|
|
|
|
|
|
|
|
|
|
|
|
|
|
from __future__ import absolute_import |
|
|
|
|
|
|
|
|
class ShouldBeFromDirective(object): |
|
|
|
|
|
known_directives = [] |
|
|
|
|
|
def __init__(self, options_name, directive_name=None, disallow=False): |
|
|
self.options_name = options_name |
|
|
self.directive_name = directive_name or options_name |
|
|
self.disallow = disallow |
|
|
self.known_directives.append(self) |
|
|
|
|
|
def __nonzero__(self): |
|
|
self._bad_access() |
|
|
|
|
|
def __int__(self): |
|
|
self._bad_access() |
|
|
|
|
|
def _bad_access(self): |
|
|
raise RuntimeError(repr(self)) |
|
|
|
|
|
def __repr__(self): |
|
|
return ( |
|
|
"Illegal access of '%s' from Options module rather than directive '%s'" |
|
|
% (self.options_name, self.directive_name)) |
|
|
|
|
|
|
|
|
""" |
|
|
The members of this module are documented using autodata in |
|
|
Cython/docs/src/reference/compilation.rst. |
|
|
See http://www.sphinx-doc.org/en/master/ext/autodoc.html#directive-autoattribute |
|
|
for how autodata works. |
|
|
Descriptions of those members should start with a #: |
|
|
Donc forget to keep the docs in sync by removing and adding |
|
|
the members in both this file and the .rst file. |
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docstrings = True |
|
|
|
|
|
|
|
|
embed_pos_in_docstring = False |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
emit_code_comments = True |
|
|
|
|
|
|
|
|
pre_import = None |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
generate_cleanup_code = False |
|
|
|
|
|
|
|
|
clear_to_none = True |
|
|
|
|
|
|
|
|
|
|
|
annotate = False |
|
|
|
|
|
|
|
|
|
|
|
annotate_coverage_xml = None |
|
|
|
|
|
|
|
|
|
|
|
fast_fail = False |
|
|
|
|
|
|
|
|
warning_errors = False |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
error_on_unknown_names = True |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
error_on_uninitialized = True |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
convert_range = True |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cache_builtins = True |
|
|
|
|
|
|
|
|
gcc_branch_hints = True |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lookup_module_cpdef = False |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
embed = None |
|
|
|
|
|
|
|
|
|
|
|
old_style_globals = ShouldBeFromDirective('old_style_globals') |
|
|
|
|
|
|
|
|
cimport_from_pyx = False |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
buffer_max_dims = 8 |
|
|
|
|
|
|
|
|
closure_freelist_size = 8 |
|
|
|
|
|
|
|
|
def get_directive_defaults(): |
|
|
|
|
|
|
|
|
|
|
|
for old_option in ShouldBeFromDirective.known_directives: |
|
|
value = globals().get(old_option.options_name) |
|
|
assert old_option.directive_name in _directive_defaults |
|
|
if not isinstance(value, ShouldBeFromDirective): |
|
|
if old_option.disallow: |
|
|
raise RuntimeError( |
|
|
"Option '%s' must be set from directive '%s'" % ( |
|
|
old_option.option_name, old_option.directive_name)) |
|
|
else: |
|
|
|
|
|
_directive_defaults[old_option.directive_name] = value |
|
|
return _directive_defaults |
|
|
|
|
|
|
|
|
_directive_defaults = { |
|
|
'boundscheck' : True, |
|
|
'nonecheck' : False, |
|
|
'initializedcheck' : True, |
|
|
'embedsignature' : False, |
|
|
'auto_cpdef': False, |
|
|
'auto_pickle': None, |
|
|
'cdivision': False, |
|
|
'cdivision_warnings': False, |
|
|
'c_api_binop_methods': True, |
|
|
'overflowcheck': False, |
|
|
'overflowcheck.fold': True, |
|
|
'always_allow_keywords': False, |
|
|
'allow_none_for_extension_args': True, |
|
|
'wraparound' : True, |
|
|
'ccomplex' : False, |
|
|
'callspec' : "", |
|
|
'nogil' : False, |
|
|
'profile': False, |
|
|
'linetrace': False, |
|
|
'emit_code_comments': True, |
|
|
'annotation_typing': True, |
|
|
'infer_types': None, |
|
|
'infer_types.verbose': False, |
|
|
'autotestdict': True, |
|
|
'autotestdict.cdef': False, |
|
|
'autotestdict.all': False, |
|
|
'language_level': None, |
|
|
'fast_getattr': False, |
|
|
'py2_import': False, |
|
|
'preliminary_late_includes_cy28': False, |
|
|
'iterable_coroutine': False, |
|
|
'c_string_type': 'bytes', |
|
|
'c_string_encoding': '', |
|
|
'type_version_tag': True, |
|
|
'unraisable_tracebacks': True, |
|
|
'old_style_globals': False, |
|
|
'np_pythran': False, |
|
|
'fast_gil': False, |
|
|
|
|
|
|
|
|
'set_initial_path' : None, |
|
|
|
|
|
'warn': None, |
|
|
'warn.undeclared': False, |
|
|
'warn.unreachable': True, |
|
|
'warn.maybe_uninitialized': False, |
|
|
'warn.unused': False, |
|
|
'warn.unused_arg': False, |
|
|
'warn.unused_result': False, |
|
|
'warn.multiple_declarators': True, |
|
|
|
|
|
|
|
|
'optimize.inline_defnode_calls': True, |
|
|
'optimize.unpack_method_calls': True, |
|
|
'optimize.unpack_method_calls_in_pyinit': False, |
|
|
'optimize.use_switch': True, |
|
|
|
|
|
|
|
|
'remove_unreachable': True, |
|
|
|
|
|
|
|
|
'control_flow.dot_output': "", |
|
|
'control_flow.dot_annotate_defs': False, |
|
|
|
|
|
|
|
|
'test_assert_path_exists' : [], |
|
|
'test_fail_if_path_exists' : [], |
|
|
|
|
|
|
|
|
'binding': None, |
|
|
|
|
|
'formal_grammar': False, |
|
|
} |
|
|
|
|
|
|
|
|
extra_warnings = { |
|
|
'warn.maybe_uninitialized': True, |
|
|
'warn.unreachable': True, |
|
|
'warn.unused': True, |
|
|
} |
|
|
|
|
|
def one_of(*args): |
|
|
def validate(name, value): |
|
|
if value not in args: |
|
|
raise ValueError("%s directive must be one of %s, got '%s'" % ( |
|
|
name, args, value)) |
|
|
else: |
|
|
return value |
|
|
return validate |
|
|
|
|
|
|
|
|
def normalise_encoding_name(option_name, encoding): |
|
|
""" |
|
|
>>> normalise_encoding_name('c_string_encoding', 'ascii') |
|
|
'ascii' |
|
|
>>> normalise_encoding_name('c_string_encoding', 'AsCIi') |
|
|
'ascii' |
|
|
>>> normalise_encoding_name('c_string_encoding', 'us-ascii') |
|
|
'ascii' |
|
|
>>> normalise_encoding_name('c_string_encoding', 'utF8') |
|
|
'utf8' |
|
|
>>> normalise_encoding_name('c_string_encoding', 'utF-8') |
|
|
'utf8' |
|
|
>>> normalise_encoding_name('c_string_encoding', 'deFAuLT') |
|
|
'default' |
|
|
>>> normalise_encoding_name('c_string_encoding', 'default') |
|
|
'default' |
|
|
>>> normalise_encoding_name('c_string_encoding', 'SeriousLyNoSuch--Encoding') |
|
|
'SeriousLyNoSuch--Encoding' |
|
|
""" |
|
|
if not encoding: |
|
|
return '' |
|
|
if encoding.lower() in ('default', 'ascii', 'utf8'): |
|
|
return encoding.lower() |
|
|
import codecs |
|
|
try: |
|
|
decoder = codecs.getdecoder(encoding) |
|
|
except LookupError: |
|
|
return encoding |
|
|
for name in ('ascii', 'utf8'): |
|
|
if codecs.getdecoder(name) == decoder: |
|
|
return name |
|
|
return encoding |
|
|
|
|
|
|
|
|
|
|
|
directive_types = { |
|
|
'language_level': str, |
|
|
'auto_pickle': bool, |
|
|
'locals': dict, |
|
|
'final' : bool, |
|
|
'nogil' : bool, |
|
|
'internal' : bool, |
|
|
'infer_types' : bool, |
|
|
'binding' : bool, |
|
|
'cfunc' : None, |
|
|
'ccall' : None, |
|
|
'inline' : None, |
|
|
'staticmethod' : None, |
|
|
'cclass' : None, |
|
|
'no_gc_clear' : bool, |
|
|
'no_gc' : bool, |
|
|
'returns' : type, |
|
|
'exceptval': type, |
|
|
'set_initial_path': str, |
|
|
'freelist': int, |
|
|
'c_string_type': one_of('bytes', 'bytearray', 'str', 'unicode'), |
|
|
'c_string_encoding': normalise_encoding_name, |
|
|
} |
|
|
|
|
|
for key, val in _directive_defaults.items(): |
|
|
if key not in directive_types: |
|
|
directive_types[key] = type(val) |
|
|
|
|
|
directive_scopes = { |
|
|
|
|
|
'auto_pickle': ('module', 'cclass'), |
|
|
'final' : ('cclass', 'function'), |
|
|
'nogil' : ('function', 'with statement'), |
|
|
'inline' : ('function',), |
|
|
'cfunc' : ('function', 'with statement'), |
|
|
'ccall' : ('function', 'with statement'), |
|
|
'returns' : ('function',), |
|
|
'exceptval' : ('function',), |
|
|
'locals' : ('function',), |
|
|
'staticmethod' : ('function',), |
|
|
'no_gc_clear' : ('cclass',), |
|
|
'no_gc' : ('cclass',), |
|
|
'internal' : ('cclass',), |
|
|
'cclass' : ('class', 'cclass', 'with statement'), |
|
|
'autotestdict' : ('module',), |
|
|
'autotestdict.all' : ('module',), |
|
|
'autotestdict.cdef' : ('module',), |
|
|
'set_initial_path' : ('module',), |
|
|
'test_assert_path_exists' : ('function', 'class', 'cclass'), |
|
|
'test_fail_if_path_exists' : ('function', 'class', 'cclass'), |
|
|
'freelist': ('cclass',), |
|
|
'emit_code_comments': ('module',), |
|
|
'annotation_typing': ('module',), |
|
|
|
|
|
'c_string_type': ('module',), |
|
|
'c_string_encoding': ('module',), |
|
|
'type_version_tag': ('module', 'cclass'), |
|
|
'language_level': ('module',), |
|
|
|
|
|
|
|
|
'old_style_globals': ('module',), |
|
|
'np_pythran': ('module',), |
|
|
'fast_gil': ('module',), |
|
|
'iterable_coroutine': ('module', 'function'), |
|
|
} |
|
|
|
|
|
|
|
|
def parse_directive_value(name, value, relaxed_bool=False): |
|
|
""" |
|
|
Parses value as an option value for the given name and returns |
|
|
the interpreted value. None is returned if the option does not exist. |
|
|
|
|
|
>>> print(parse_directive_value('nonexisting', 'asdf asdfd')) |
|
|
None |
|
|
>>> parse_directive_value('boundscheck', 'True') |
|
|
True |
|
|
>>> parse_directive_value('boundscheck', 'true') |
|
|
Traceback (most recent call last): |
|
|
... |
|
|
ValueError: boundscheck directive must be set to True or False, got 'true' |
|
|
|
|
|
>>> parse_directive_value('c_string_encoding', 'us-ascii') |
|
|
'ascii' |
|
|
>>> parse_directive_value('c_string_type', 'str') |
|
|
'str' |
|
|
>>> parse_directive_value('c_string_type', 'bytes') |
|
|
'bytes' |
|
|
>>> parse_directive_value('c_string_type', 'bytearray') |
|
|
'bytearray' |
|
|
>>> parse_directive_value('c_string_type', 'unicode') |
|
|
'unicode' |
|
|
>>> parse_directive_value('c_string_type', 'unnicode') |
|
|
Traceback (most recent call last): |
|
|
ValueError: c_string_type directive must be one of ('bytes', 'bytearray', 'str', 'unicode'), got 'unnicode' |
|
|
""" |
|
|
type = directive_types.get(name) |
|
|
if not type: |
|
|
return None |
|
|
orig_value = value |
|
|
if type is bool: |
|
|
value = str(value) |
|
|
if value == 'True': |
|
|
return True |
|
|
if value == 'False': |
|
|
return False |
|
|
if relaxed_bool: |
|
|
value = value.lower() |
|
|
if value in ("true", "yes"): |
|
|
return True |
|
|
elif value in ("false", "no"): |
|
|
return False |
|
|
raise ValueError("%s directive must be set to True or False, got '%s'" % ( |
|
|
name, orig_value)) |
|
|
elif type is int: |
|
|
try: |
|
|
return int(value) |
|
|
except ValueError: |
|
|
raise ValueError("%s directive must be set to an integer, got '%s'" % ( |
|
|
name, orig_value)) |
|
|
elif type is str: |
|
|
return str(value) |
|
|
elif callable(type): |
|
|
return type(name, value) |
|
|
else: |
|
|
assert False |
|
|
|
|
|
|
|
|
def parse_directive_list(s, relaxed_bool=False, ignore_unknown=False, |
|
|
current_settings=None): |
|
|
""" |
|
|
Parses a comma-separated list of pragma options. Whitespace |
|
|
is not considered. |
|
|
|
|
|
>>> parse_directive_list(' ') |
|
|
{} |
|
|
>>> (parse_directive_list('boundscheck=True') == |
|
|
... {'boundscheck': True}) |
|
|
True |
|
|
>>> parse_directive_list(' asdf') |
|
|
Traceback (most recent call last): |
|
|
... |
|
|
ValueError: Expected "=" in option "asdf" |
|
|
>>> parse_directive_list('boundscheck=hey') |
|
|
Traceback (most recent call last): |
|
|
... |
|
|
ValueError: boundscheck directive must be set to True or False, got 'hey' |
|
|
>>> parse_directive_list('unknown=True') |
|
|
Traceback (most recent call last): |
|
|
... |
|
|
ValueError: Unknown option: "unknown" |
|
|
>>> warnings = parse_directive_list('warn.all=True') |
|
|
>>> len(warnings) > 1 |
|
|
True |
|
|
>>> sum(warnings.values()) == len(warnings) # all true. |
|
|
True |
|
|
""" |
|
|
if current_settings is None: |
|
|
result = {} |
|
|
else: |
|
|
result = current_settings |
|
|
for item in s.split(','): |
|
|
item = item.strip() |
|
|
if not item: |
|
|
continue |
|
|
if '=' not in item: |
|
|
raise ValueError('Expected "=" in option "%s"' % item) |
|
|
name, value = [s.strip() for s in item.strip().split('=', 1)] |
|
|
if name not in _directive_defaults: |
|
|
found = False |
|
|
if name.endswith('.all'): |
|
|
prefix = name[:-3] |
|
|
for directive in _directive_defaults: |
|
|
if directive.startswith(prefix): |
|
|
found = True |
|
|
parsed_value = parse_directive_value(directive, value, relaxed_bool=relaxed_bool) |
|
|
result[directive] = parsed_value |
|
|
if not found and not ignore_unknown: |
|
|
raise ValueError('Unknown option: "%s"' % name) |
|
|
else: |
|
|
parsed_value = parse_directive_value(name, value, relaxed_bool=relaxed_bool) |
|
|
result[name] = parsed_value |
|
|
return result |
|
|
|
|
|
|
|
|
def parse_variable_value(value): |
|
|
""" |
|
|
Parses value as an option value for the given name and returns |
|
|
the interpreted value. |
|
|
|
|
|
>>> parse_variable_value('True') |
|
|
True |
|
|
>>> parse_variable_value('true') |
|
|
'true' |
|
|
>>> parse_variable_value('us-ascii') |
|
|
'us-ascii' |
|
|
>>> parse_variable_value('str') |
|
|
'str' |
|
|
>>> parse_variable_value('123') |
|
|
123 |
|
|
>>> parse_variable_value('1.23') |
|
|
1.23 |
|
|
|
|
|
""" |
|
|
if value == "True": |
|
|
return True |
|
|
elif value == "False": |
|
|
return False |
|
|
elif value == "None": |
|
|
return None |
|
|
elif value.isdigit(): |
|
|
return int(value) |
|
|
else: |
|
|
try: |
|
|
value = float(value) |
|
|
except Exception: |
|
|
|
|
|
pass |
|
|
return value |
|
|
|
|
|
|
|
|
def parse_compile_time_env(s, current_settings=None): |
|
|
""" |
|
|
Parses a comma-separated list of pragma options. Whitespace |
|
|
is not considered. |
|
|
|
|
|
>>> parse_compile_time_env(' ') |
|
|
{} |
|
|
>>> (parse_compile_time_env('HAVE_OPENMP=True') == |
|
|
... {'HAVE_OPENMP': True}) |
|
|
True |
|
|
>>> parse_compile_time_env(' asdf') |
|
|
Traceback (most recent call last): |
|
|
... |
|
|
ValueError: Expected "=" in option "asdf" |
|
|
>>> parse_compile_time_env('NUM_THREADS=4') == {'NUM_THREADS': 4} |
|
|
True |
|
|
>>> parse_compile_time_env('unknown=anything') == {'unknown': 'anything'} |
|
|
True |
|
|
""" |
|
|
if current_settings is None: |
|
|
result = {} |
|
|
else: |
|
|
result = current_settings |
|
|
for item in s.split(','): |
|
|
item = item.strip() |
|
|
if not item: |
|
|
continue |
|
|
if '=' not in item: |
|
|
raise ValueError('Expected "=" in option "%s"' % item) |
|
|
name, value = [s.strip() for s in item.split('=', 1)] |
|
|
result[name] = parse_variable_value(value) |
|
|
return result |
|
|
|