Commit cedeb1a6 authored by Stefan Behnel's avatar Stefan Behnel

Merge branch 'master' of git+ssh://github.com/cython/cython

parents f59f6193 2a1ec5e7
...@@ -38,35 +38,6 @@ class _FakePool(object): ...@@ -38,35 +38,6 @@ class _FakePool(object):
pass 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): def find_package_base(path):
base_dir, package_path = os.path.split(path) base_dir, package_path = os.path.split(path)
while is_package_dir(base_dir): while is_package_dir(base_dir):
...@@ -148,56 +119,93 @@ def run_distutils(args): ...@@ -148,56 +119,93 @@ def run_distutils(args):
shutil.rmtree(temp_dir) shutil.rmtree(temp_dir)
def parse_args(args): def create_args_parser():
from optparse import OptionParser from argparse import ArgumentParser, Action
parser = OptionParser(usage='%prog [options] [sources and packages]+')
parser.add_option('-X', '--directive', metavar='NAME=VALUE,...', class ParseDirectivesAction(Action):
dest='directives', default={}, type="str", def __call__(self, parser, namespace, values, option_string=None):
action='callback', callback=parse_directives, old_directives = dict(getattr(namespace, self.dest,
Options.get_directive_defaults()))
directives = Options.parse_directive_list(
values, relaxed_bool=True, current_settings=old_directives)
setattr(namespace, self.dest, directives)
class ParseOptionsAction(Action):
def __call__(self, parser, namespace, values, option_string=None):
options = dict(getattr(namespace, self.dest, {}))
for opt in values.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(namespace, self.dest, options)
class ParseCompileTimeEnvAction(Action):
def __call__(self, parser, namespace, values, option_string=None):
old_env = dict(getattr(namespace, self.dest, {}))
new_env = Options.parse_compile_time_env(values, current_settings=old_env)
setattr(namespace, self.dest, new_env)
parser = ArgumentParser()
parser.add_argument('-X', '--directive', metavar='NAME=VALUE,...',
dest='directives', default={}, type=str,
action=ParseDirectivesAction,
help='set a compiler directive') help='set a compiler directive')
parser.add_option('-E', '--compile-time-env', metavar='NAME=VALUE,...', parser.add_argument('-E', '--compile-time-env', metavar='NAME=VALUE,...',
dest='compile_time_env', default={}, type="str", dest='compile_time_env', default={}, type=str,
action='callback', callback=parse_compile_time_env, action=ParseCompileTimeEnvAction,
help='set a compile time environment variable') help='set a compile time environment variable')
parser.add_option('-s', '--option', metavar='NAME=VALUE', parser.add_argument('-s', '--option', metavar='NAME=VALUE',
dest='options', default={}, type="str", dest='options', default={}, type=str,
action='callback', callback=parse_options, action=ParseOptionsAction,
help='set a cythonize option') 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') 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') 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') help='use Python 3 syntax mode by default')
parser.add_option('-a', '--annotate', dest='annotate', action='store_true', parser.add_argument('-a', '--annotate', dest='annotate', action='store_true', default=None,
help='generate annotated HTML page for source files') help='generate annotated HTML page for source files')
parser.add_option('-x', '--exclude', metavar='PATTERN', dest='excludes', parser.add_argument('-x', '--exclude', metavar='PATTERN', dest='excludes',
action='append', default=[], action='append', default=[],
help='exclude certain file patterns from the compilation') 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') 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)') 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, type=int, default=parallel_compiles,
help=('run builds in N parallel jobs (default: %d)' % help=('run builds in N parallel jobs (default: %d)' %
parallel_compiles or 1)) 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') 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') 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') 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') help='compile as much as possible, ignore compilation failures')
parser.add_option('--no-docstrings', dest='no_docstrings', action='store_true', parser.add_argument('--no-docstrings', dest='no_docstrings', action='store_true', default=None,
help='strip docstrings') help='strip docstrings')
parser.add_argument('sources', nargs='*')
return parser
options, args = parser.parse_args(args) def parse_args_raw(parser, args):
options = parser.parse_args(args)
return (options, options.sources)
def parse_args(args):
parser = create_args_parser()
options, args = parse_args_raw(parser, args)
if not args: if not args:
parser.error("no source files provided") parser.error("no source files provided")
if options.build_inplace: if options.build_inplace:
......
from Cython.Build.Cythonize import create_args_parser, parse_args_raw, parse_args
from unittest import TestCase
class TestCythonizeArgsParser(TestCase):
def setUp(self):
TestCase.setUp(self)
self.parse_args = lambda x, parser=create_args_parser() : parse_args_raw(parser, x)
def are_default(self, options, skip):
# empty containers
empty_containers = ['directives', 'compile_time_env', 'options', 'excludes']
are_none = ['language_level', 'annotate', 'build', 'build_inplace', 'force', 'quiet', 'lenient', 'keep_going', 'no_docstrings']
for opt_name in empty_containers:
if len(getattr(options, opt_name))!=0 and (not opt_name in skip):
self.assertEqual(opt_name,"")
return False
for opt_name in are_none:
if (getattr(options, opt_name) is not None) and (not opt_name in skip):
self.assertEqual(opt_name,"")
return False
if options.parallel!=3 and (not 'parallel' in skip):
return False
return True
# testing directives:
def test_directive_short(self):
options, args = self.parse_args(['-X', 'cdivision=True'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['directives']))
self.assertEqual(options.directives['cdivision'], True)
def test_directive_long(self):
options, args = self.parse_args(['--directive', 'cdivision=True'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['directives']))
self.assertEqual(options.directives['cdivision'], True)
def test_directive_multiple(self):
options, args = self.parse_args(['-X', 'cdivision=True', '-X', 'c_string_type=bytes'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['directives']))
self.assertEqual(options.directives['cdivision'], True)
self.assertEqual(options.directives['c_string_type'], 'bytes')
def test_directive_multiple_v2(self):
options, args = self.parse_args(['-X', 'cdivision=True,c_string_type=bytes'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['directives']))
self.assertEqual(options.directives['cdivision'], True)
self.assertEqual(options.directives['c_string_type'], 'bytes')
def test_directive_value_yes(self):
options, args = self.parse_args(['-X', 'cdivision=YeS'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['directives']))
self.assertEqual(options.directives['cdivision'], True)
def test_directive_value_no(self):
options, args = self.parse_args(['-X', 'cdivision=no'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['directives']))
self.assertEqual(options.directives['cdivision'], False)
def test_directive_value_invalid(self):
with self.assertRaises(ValueError) as context:
options, args = self.parse_args(['-X', 'cdivision=sadfasd'])
def test_directive_key_invalid(self):
with self.assertRaises(ValueError) as context:
options, args = self.parse_args(['-X', 'abracadabra'])
def test_directive_no_value(self):
with self.assertRaises(ValueError) as context:
options, args = self.parse_args(['-X', 'cdivision'])
def test_directives_types(self):
directives = {
'auto_pickle': True,
'c_string_type': 'bytearray',
'c_string_type': 'bytes',
'c_string_type': 'str',
'c_string_type': 'bytearray',
'c_string_type': 'unicode',
'c_string_encoding' : 'ascii',
'language_level' : 2,
'language_level' : 3,
'language_level' : '3str',
'set_initial_path' : 'my_initial_path',
}
for key, value in directives.items():
cmd = '{key}={value}'.format(key=key, value=str(value))
options, args = self.parse_args(['-X', cmd])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['directives']), msg = "Error for option: "+cmd)
self.assertEqual(options.directives[key], value, msg = "Error for option: "+cmd)
def test_directives_wrong(self):
directives = {
'auto_pickle': 42, # for bool type
'auto_pickle': 'NONONO', # for bool type
'c_string_type': 'bites',
#'c_string_encoding' : 'a',
#'language_level' : 4,
}
for key, value in directives.items():
cmd = '{key}={value}'.format(key=key, value=str(value))
with self.assertRaises(ValueError, msg = "Error for option: "+cmd) as context:
options, args = self.parse_args(['-X', cmd])
def test_compile_time_env_short(self):
options, args = self.parse_args(['-E', 'MYSIZE=10'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['compile_time_env']))
self.assertEqual(options.compile_time_env['MYSIZE'], 10)
def test_compile_time_env_long(self):
options, args = self.parse_args(['--compile-time-env', 'MYSIZE=10'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['compile_time_env']))
self.assertEqual(options.compile_time_env['MYSIZE'], 10)
def test_compile_time_env_multiple(self):
options, args = self.parse_args(['-E', 'MYSIZE=10', '-E', 'ARRSIZE=11'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['compile_time_env']))
self.assertEqual(options.compile_time_env['MYSIZE'], 10)
self.assertEqual(options.compile_time_env['ARRSIZE'], 11)
def test_compile_time_env_multiple_v2(self):
options, args = self.parse_args(['-E', 'MYSIZE=10,ARRSIZE=11'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['compile_time_env']))
self.assertEqual(options.compile_time_env['MYSIZE'], 10)
self.assertEqual(options.compile_time_env['ARRSIZE'], 11)
#testing options
def test_option_short(self):
options, args = self.parse_args(['-s', 'docstrings=True'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], True)
def test_option_long(self):
options, args = self.parse_args(['--option', 'docstrings=True'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], True)
def test_option_multiple(self):
options, args = self.parse_args(['-s', 'docstrings=True', '-s', 'buffer_max_dims=8'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], True)
self.assertEqual(options.options['buffer_max_dims'], True) # really?
def test_option_multiple_v2(self):
options, args = self.parse_args(['-s', 'docstrings=True,buffer_max_dims=8'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], True)
self.assertEqual(options.options['buffer_max_dims'], True) # really?
def test_option_value_yes(self):
options, args = self.parse_args(['-s', 'docstrings=YeS'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], True)
def test_option_value_4242(self):
options, args = self.parse_args(['-s', 'docstrings=4242'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], True)
def test_option_value_0(self):
options, args = self.parse_args(['-s', 'docstrings=0'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], False)
def test_option_value_emptystr(self):
options, args = self.parse_args(['-s', 'docstrings='])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], True)
def test_option_value_a_str(self):
options, args = self.parse_args(['-s', 'docstrings=BB'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], True)
def test_option_value_no(self):
options, args = self.parse_args(['-s', 'docstrings=nO'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], False)
def test_option_no_value(self):
options, args = self.parse_args(['-s', 'docstrings'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['docstrings'], True)
def test_option_any_key(self):
options, args = self.parse_args(['-s', 'abracadabra'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['options']))
self.assertEqual(options.options['abracadabra'], True)
def test_language_level_2(self):
options, args = self.parse_args(['-2'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['language_level']))
self.assertEqual(options.language_level, 2)
def test_language_level_3(self):
options, args = self.parse_args(['-3'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['language_level']))
self.assertEqual(options.language_level, 3)
def test_language_level_3str(self):
options, args = self.parse_args(['--3str'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['language_level']))
self.assertEqual(options.language_level, '3str')
def test_annotate_short(self):
options, args = self.parse_args(['-a'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['annotate']))
self.assertEqual(options.annotate, True)
def test_annotate_long(self):
options, args = self.parse_args(['--annotate'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['annotate']))
self.assertEqual(options.annotate, True)
def test_exclude_short(self):
options, args = self.parse_args(['-x', '*.pyx'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['excludes']))
self.assertTrue('*.pyx' in options.excludes)
def test_exclude_long(self):
options, args = self.parse_args(['--exclude', '*.pyx'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['excludes']))
self.assertTrue('*.pyx' in options.excludes)
def test_exclude_multiple(self):
options, args = self.parse_args(['--exclude', '*.pyx', '--exclude', '*.py', ])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['excludes']))
self.assertEqual(options.excludes, ['*.pyx', '*.py'])
def test_build_short(self):
options, args = self.parse_args(['-b'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['build']))
self.assertEqual(options.build, True)
def test_build_long(self):
options, args = self.parse_args(['--build'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['build']))
self.assertEqual(options.build, True)
def test_inplace_short(self):
options, args = self.parse_args(['-i'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['build_inplace']))
self.assertEqual(options.build_inplace, True)
def test_inplace_long(self):
options, args = self.parse_args(['--inplace'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['build_inplace']))
self.assertEqual(options.build_inplace, True)
def test_parallel_short(self):
options, args = self.parse_args(['-j', '42'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['parallel']))
self.assertEqual(options.parallel, 42)
def test_parallel_long(self):
options, args = self.parse_args(['--parallel', '42'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['parallel']))
self.assertEqual(options.parallel, 42)
def test_force_short(self):
options, args = self.parse_args(['-f'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['force']))
self.assertEqual(options.force, True)
def test_force_long(self):
options, args = self.parse_args(['--force'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['force']))
self.assertEqual(options.force, True)
def test_quite_short(self):
options, args = self.parse_args(['-q'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['quiet']))
self.assertEqual(options.quiet, True)
def test_quite_long(self):
options, args = self.parse_args(['--quiet'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['quiet']))
self.assertEqual(options.quiet, True)
def test_lenient_long(self):
options, args = self.parse_args(['--lenient'])
self.assertTrue(self.are_default(options, ['lenient']))
self.assertFalse(args)
self.assertEqual(options.lenient, True)
def test_keep_going_short(self):
options, args = self.parse_args(['-k'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['keep_going']))
self.assertEqual(options.keep_going, True)
def test_keep_going_long(self):
options, args = self.parse_args(['--keep-going'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['keep_going']))
self.assertEqual(options.keep_going, True)
def test_no_docstrings_long(self):
options, args = self.parse_args(['--no-docstrings'])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['no_docstrings']))
self.assertEqual(options.no_docstrings, True)
def test_file_name(self):
options, args = self.parse_args(['file1.pyx', 'file2.pyx'])
self.assertEqual(len(args), 2)
self.assertEqual(args[0], 'file1.pyx')
self.assertEqual(args[1], 'file2.pyx')
self.assertTrue(self.are_default(options, []))
def test_option_first(self):
options, args = self.parse_args(['-i', 'file.pyx'])
self.assertEqual(args, ['file.pyx'])
self.assertEqual(options.build_inplace, True)
self.assertTrue(self.are_default(options, ['build_inplace']))
def test_file_inbetween(self):
options, args = self.parse_args(['-i', 'file.pyx', '-a'])
self.assertEqual(args, ['file.pyx'])
self.assertEqual(options.build_inplace, True)
self.assertEqual(options.annotate, True)
self.assertTrue(self.are_default(options, ['build_inplace', 'annotate']))
def test_option_trailing(self):
options, args = self.parse_args(['file.pyx', '-i'])
self.assertEqual(args, ['file.pyx'])
self.assertEqual(options.build_inplace, True)
self.assertTrue(self.are_default(options, ['build_inplace']))
class TestParseArgs(TestCase):
def test_build_set_for_inplace(self):
options, args = parse_args(['foo.pyx', '-i'])
self.assertEqual(options.build, True)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment