summaryrefslogtreecommitdiff
path: root/Cython/Build/Cythonize.py
diff options
context:
space:
mode:
Diffstat (limited to 'Cython/Build/Cythonize.py')
-rw-r--r--Cython/Build/Cythonize.py154
1 files changed, 86 insertions, 68 deletions
diff --git a/Cython/Build/Cythonize.py b/Cython/Build/Cythonize.py
index c85b6eaba..179c04060 100644
--- a/Cython/Build/Cythonize.py
+++ b/Cython/Build/Cythonize.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
-from __future__ import absolute_import
+from __future__ import absolute_import, print_function
import os
import shutil
@@ -38,46 +38,19 @@ class _FakePool(object):
pass
-def parse_directives(option, name, value, parser):
- dest = option.dest
- old_directives = dict(getattr(parser.values, dest,
- Options.get_directive_defaults()))
- directives = Options.parse_directive_list(
- value, relaxed_bool=True, current_settings=old_directives)
- setattr(parser.values, dest, directives)
-
-
-def parse_options(option, name, value, parser):
- dest = option.dest
- options = dict(getattr(parser.values, dest, {}))
- for opt in value.split(','):
- if '=' in opt:
- n, v = opt.split('=', 1)
- v = v.lower() not in ('false', 'f', '0', 'no')
- else:
- n, v = opt, True
- options[n] = v
- setattr(parser.values, dest, options)
-
-
-def parse_compile_time_env(option, name, value, parser):
- dest = option.dest
- old_env = dict(getattr(parser.values, dest, {}))
- new_env = Options.parse_compile_time_env(value, current_settings=old_env)
- setattr(parser.values, dest, new_env)
-
-
def find_package_base(path):
base_dir, package_path = os.path.split(path)
- while os.path.isfile(os.path.join(base_dir, '__init__.py')):
+ while is_package_dir(base_dir):
base_dir, parent = os.path.split(base_dir)
package_path = '%s/%s' % (parent, package_path)
return base_dir, package_path
-
def cython_compile(path_pattern, options):
- pool = None
all_paths = map(os.path.abspath, extended_iglob(path_pattern))
+ _cython_compile_files(all_paths, options)
+
+def _cython_compile_files(all_paths, options):
+ pool = None
try:
for path in all_paths:
if options.build_inplace:
@@ -149,55 +122,89 @@ def run_distutils(args):
shutil.rmtree(temp_dir)
-def parse_args(args):
- from optparse import OptionParser
- parser = OptionParser(usage='%prog [options] [sources and packages]+')
+def create_args_parser():
+ from argparse import ArgumentParser, RawDescriptionHelpFormatter
+ from ..Compiler.CmdLine import ParseDirectivesAction, ParseOptionsAction, ParseCompileTimeEnvAction
- parser.add_option('-X', '--directive', metavar='NAME=VALUE,...',
- dest='directives', default={}, type="str",
- action='callback', callback=parse_directives,
+ parser = ArgumentParser(
+ formatter_class=RawDescriptionHelpFormatter,
+ epilog="""\
+Environment variables:
+ CYTHON_FORCE_REGEN: if set to 1, forces cythonize to regenerate the output files regardless
+ of modification times and changes.
+ Environment variables accepted by setuptools are supported to configure the C compiler and build:
+ https://setuptools.pypa.io/en/latest/userguide/ext_modules.html#compiler-and-linker-options"""
+ )
+
+ parser.add_argument('-X', '--directive', metavar='NAME=VALUE,...',
+ dest='directives', default={}, type=str,
+ action=ParseDirectivesAction,
help='set a compiler directive')
- parser.add_option('-E', '--compile-time-env', metavar='NAME=VALUE,...',
- dest='compile_time_env', default={}, type="str",
- action='callback', callback=parse_compile_time_env,
+ parser.add_argument('-E', '--compile-time-env', metavar='NAME=VALUE,...',
+ dest='compile_time_env', default={}, type=str,
+ action=ParseCompileTimeEnvAction,
help='set a compile time environment variable')
- parser.add_option('-s', '--option', metavar='NAME=VALUE',
- dest='options', default={}, type="str",
- action='callback', callback=parse_options,
+ parser.add_argument('-s', '--option', metavar='NAME=VALUE',
+ dest='options', default={}, type=str,
+ action=ParseOptionsAction,
help='set a cythonize option')
- parser.add_option('-2', dest='language_level', action='store_const', const=2, default=None,
+ parser.add_argument('-2', dest='language_level', action='store_const', const=2, default=None,
help='use Python 2 syntax mode by default')
- parser.add_option('-3', dest='language_level', action='store_const', const=3,
+ parser.add_argument('-3', dest='language_level', action='store_const', const=3,
help='use Python 3 syntax mode by default')
- parser.add_option('--3str', dest='language_level', action='store_const', const='3str',
+ parser.add_argument('--3str', dest='language_level', action='store_const', const='3str',
help='use Python 3 syntax mode by default')
- parser.add_option('-a', '--annotate', dest='annotate', action='store_true',
- help='generate annotated HTML page for source files')
-
- parser.add_option('-x', '--exclude', metavar='PATTERN', dest='excludes',
+ parser.add_argument('-a', '--annotate', action='store_const', const='default', dest='annotate',
+ help='Produce a colorized HTML version of the source.')
+ parser.add_argument('--annotate-fullc', action='store_const', const='fullc', dest='annotate',
+ help='Produce a colorized HTML version of the source '
+ 'which includes entire generated C/C++-code.')
+ parser.add_argument('-x', '--exclude', metavar='PATTERN', dest='excludes',
action='append', default=[],
help='exclude certain file patterns from the compilation')
- parser.add_option('-b', '--build', dest='build', action='store_true',
+ parser.add_argument('-b', '--build', dest='build', action='store_true', default=None,
help='build extension modules using distutils')
- parser.add_option('-i', '--inplace', dest='build_inplace', action='store_true',
+ parser.add_argument('-i', '--inplace', dest='build_inplace', action='store_true', default=None,
help='build extension modules in place using distutils (implies -b)')
- parser.add_option('-j', '--parallel', dest='parallel', metavar='N',
+ parser.add_argument('-j', '--parallel', dest='parallel', metavar='N',
type=int, default=parallel_compiles,
help=('run builds in N parallel jobs (default: %d)' %
parallel_compiles or 1))
- parser.add_option('-f', '--force', dest='force', action='store_true',
+ parser.add_argument('-f', '--force', dest='force', action='store_true', default=None,
help='force recompilation')
- parser.add_option('-q', '--quiet', dest='quiet', action='store_true',
+ parser.add_argument('-q', '--quiet', dest='quiet', action='store_true', default=None,
help='be less verbose during compilation')
- parser.add_option('--lenient', dest='lenient', action='store_true',
+ parser.add_argument('--lenient', dest='lenient', action='store_true', default=None,
help='increase Python compatibility by ignoring some compile time errors')
- parser.add_option('-k', '--keep-going', dest='keep_going', action='store_true',
+ parser.add_argument('-k', '--keep-going', dest='keep_going', action='store_true', default=None,
help='compile as much as possible, ignore compilation failures')
- parser.add_option('-M', '--depfile', action='store_true', help='produce depfiles for the sources')
+ parser.add_argument('--no-docstrings', dest='no_docstrings', action='store_true', default=None,
+ help='strip docstrings')
+ parser.add_argument('-M', '--depfile', action='store_true', help='produce depfiles for the sources')
+ parser.add_argument('sources', nargs='*')
+ return parser
+
+
+def parse_args_raw(parser, args):
+ options, unknown = parser.parse_known_args(args)
+ sources = options.sources
+ # if positional arguments were interspersed
+ # some of them are in unknown
+ for option in unknown:
+ if option.startswith('-'):
+ parser.error("unknown option "+option)
+ else:
+ sources.append(option)
+ del options.sources
+ return (options, sources)
+
+
+def parse_args(args):
+ parser = create_args_parser()
+ options, args = parse_args_raw(parser, args)
- options, args = parser.parse_args(args)
if not args:
parser.error("no source files provided")
if options.build_inplace:
@@ -207,11 +214,6 @@ def parse_args(args):
if options.language_level:
assert options.language_level in (2, 3, '3str')
options.options['language_level'] = options.language_level
- return options, args
-
-
-def main(args=None):
- options, paths = parse_args(args)
if options.lenient:
# increase Python compatibility by ignoring compile time errors
@@ -219,10 +221,26 @@ def main(args=None):
Options.error_on_uninitialized = False
if options.annotate:
- Options.annotate = True
+ Options.annotate = options.annotate
+
+ if options.no_docstrings:
+ Options.docstrings = False
+
+ return options, args
+
+
+def main(args=None):
+ options, paths = parse_args(args)
+ all_paths = []
for path in paths:
- cython_compile(path, options)
+ expanded_path = [os.path.abspath(p) for p in extended_iglob(path)]
+ if not expanded_path:
+ import sys
+ print("{}: No such file or directory: '{}'".format(sys.argv[0], path), file=sys.stderr)
+ sys.exit(1)
+ all_paths.extend(expanded_path)
+ _cython_compile_files(all_paths, options)
if __name__ == '__main__':