# coding: utf-8
#!/usr/bin/env python
import sys
import os
import argparse
# TODO add version
# --version show program's version number and exit
from pyccel.parser.errors import Errors
from pyccel.parser.errors import ErrorsMode
from pyccel.parser.messages import INVALID_FILE_DIRECTORY, INVALID_FILE_EXTENSION
from pyccel.parser.utilities import is_valid_filename_pyh, is_valid_filename_py
from pyccel.codegen.utilities import construct_flags
from pyccel.codegen.utilities import compile_fortran
from pyccel.codegen.utilities import execute_pyccel
[docs]class MyParser(argparse.ArgumentParser):
"""
Custom argument parser for printing help message in case of an error.
See http://stackoverflow.com/questions/4042452/display-help-message-with-python-argparse-when-script-is-called-without-any-argu
"""
[docs] def error(self, message):
sys.stderr.write('error: %s\n' % message)
self.print_help()
sys.exit(2)
def _which(program):
def is_exe(fpath):
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
fpath, fname = os.path.split(program)
if fpath:
if is_exe(program):
return program
else:
for path in os.environ["PATH"].split(os.pathsep):
path = path.strip('"')
exe_file = os.path.join(path, program)
if is_exe(exe_file):
return exe_file
return None
# TODO - remove output_dir froms args
# - remove files from args
# but quickstart and build are still calling it for the moment
[docs]def pyccel(files=None, openmp=None, openacc=None, output_dir=None, compiler='gfortran'):
"""
pyccel console command.
"""
parser = MyParser(description='pyccel command line')
parser.add_argument('files', metavar='N', type=str, nargs='+',
help='a Pyccel file')
# ... compiler syntax, semantic and codegen
group = parser.add_argument_group('Pyccel compiling stages')
group.add_argument('-x', '--syntax-only', action='store_true',
help='Using pyccel for Syntax Checking')
group.add_argument('-e', '--semantic-only', action='store_true',
help='Using pyccel for Semantic Checking')
group.add_argument('-t', '--convert-only', action='store_true',
help='Converts pyccel files only without build')
# ...
# ... backend compiler options
group = parser.add_argument_group('Backend compiler options')
group.add_argument('--compiler', type=str, \
help='Used compiler')
group.add_argument('--fflags', type=str, \
help='Fortran compiler flags.')
group.add_argument('--debug', action='store_true', \
help='compiles the code in a debug mode.')
group.add_argument('--include', type=str, \
help='path to include directory.')
group.add_argument('--libdir', type=str, \
help='path to lib directory.')
group.add_argument('--libs', type=str, \
help='list of libraries to link with.')
group.add_argument('--output', type=str, default = '',\
help='folder in which the output is stored.')
# ...
# ... Accelerators
group = parser.add_argument_group('Accelerators options')
group.add_argument('--openmp', action='store_true', \
help='uses openmp')
group.add_argument('--openacc', action='store_true', \
help='uses openacc')
# ...
# ... Other options
group = parser.add_argument_group('Other options')
group.add_argument('--verbose', action='store_true', \
help='enables verbose mode.')
group.add_argument('--developer-mode', action='store_true', \
help='shows internal messages')
# ...
# TODO move to another cmd line
parser.add_argument('--analysis', action='store_true', \
help='enables code analysis mode.')
# ...
# ...
args = parser.parse_args()
# ...
# ...
if not files:
files = args.files
if args.compiler:
compiler = args.compiler
if not openmp:
openmp = args.openmp
if not openacc:
openacc = args.openacc
if args.convert_only or args.syntax_only or args.semantic_only:
compiler = None
# ...
# ...
if not files:
raise ValueError("a python filename must be provided.")
if len(files) > 1:
raise ValueError('Expecting one single file for the moment.')
# ...
filename = files[0]
# ... report error
if os.path.isfile(filename):
# we don't use is_valid_filename_py since it uses absolute path
# file extension
ext = filename.split('.')[-1]
if not(ext in ['py', 'pyh']):
errors = Errors()
errors.report(INVALID_FILE_EXTENSION,
symbol=ext,
severity='fatal')
errors.check()
raise SystemExit(0)
else:
# we use Pyccel error manager, although we can do it in other ways
errors = Errors()
errors.report(INVALID_FILE_DIRECTORY,
symbol=filename,
severity='fatal')
errors.check()
raise SystemExit(0)
# ...
if compiler:
if _which(compiler) is None:
raise ValueError('Could not find {0}'.format(compiler))
accelerator = None
if openmp:
accelerator = "openmp"
if openacc:
accelerator = "openacc"
debug = args.debug
verbose = args.verbose
include = args.include
fflags = args.fflags
libdir = args.libdir
libs = args.libs
output_folder = args.output
if (len(output_folder)>0 and output_folder[-1]!='/'):
output_folder+='/'
if not include:
include = []
if not libdir:
libdir = []
if not libs:
libs = []
# ...
# ...
if args.developer_mode:
# this will initialize the singelton ErrorsMode
# making this settings available everywhere
err_mode = ErrorsMode()
err_mode.set_mode('developer')
# ...
# ...
from pyccel.parser import Parser
from pyccel.codegen import Codegen
if args.syntax_only:
pyccel = Parser(filename)
ast = pyccel.parse()
elif args.semantic_only:
pyccel = Parser(filename)
ast = pyccel.parse()
settings = {}
ast = pyccel.annotate(**settings)
elif args.convert_only:
pyccel = Parser(filename)
ast = pyccel.parse()
settings = {}
ast = pyccel.annotate(**settings)
name = os.path.basename(filename)
name = os.path.splitext(name)[0]
codegen = Codegen(ast, name)
code = codegen.doprint()
codegen.export(output_folder+name)
for son in pyccel.sons:
if 'print' in son.metavars.keys():
name = son.filename.split('/')[-1].strip('.py')
name = 'mod_'+name
codegen = Codegen(son.ast, name)
code = codegen.doprint()
codegen.export()
elif args.analysis:
# TODO move to another cmd line
from pyccel.complexity.arithmetic import OpComplexity
complexity = OpComplexity(filename)
print(" arithmetic cost ~ " + str(complexity.cost()))
else:
# TODO shall we add them in the cmd line?
modules = []
binary = None
execute_pyccel(filename,
compiler=compiler,
fflags=fflags,
debug=False,
verbose=verbose,
accelerator=accelerator,
include=include,
libdir=libdir,
modules=modules,
libs=libs,
binary=binary,
output=output_folder)