• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#
2#  Cython - Compilation-wide options and pragma declarations
3#
4
5# Perform lookups on builtin names only once, at module initialisation
6# time.  This will prevent the module from getting imported if a
7# builtin name that it uses cannot be found during initialisation.
8cache_builtins = True
9
10embed_pos_in_docstring = False
11gcc_branch_hints = True
12
13pre_import = None
14docstrings = True
15
16# Decref global variables in this module on exit for garbage collection.
17# 0: None, 1+: interned objects, 2+: cdef globals, 3+: types objects
18# Mostly for reducing noise for Valgrind, only executes at process exit
19# (when all memory will be reclaimed anyways).
20generate_cleanup_code = False
21
22annotate = False
23
24# This will abort the compilation on the first error occured rather than trying
25# to keep going and printing further error messages.
26fast_fail = False
27
28# Make all warnings into errors.
29warning_errors = False
30
31# Make unknown names an error.  Python raises a NameError when
32# encountering unknown names at runtime, whereas this option makes
33# them a compile time error.  If you want full Python compatibility,
34# you should disable this option and also 'cache_builtins'.
35error_on_unknown_names = True
36
37# Make uninitialized local variable reference a compile time error.
38# Python raises UnboundLocalError at runtime, whereas this option makes
39# them a compile time error. Note that this option affects only variables
40# of "python object" type.
41error_on_uninitialized = True
42
43# This will convert statements of the form "for i in range(...)"
44# to "for i from ..." when i is a cdef'd integer type, and the direction
45# (i.e. sign of step) can be determined.
46# WARNING: This may change the semantics if the range causes assignment to
47# i to overflow. Specifically, if this option is set, an error will be
48# raised before the loop is entered, wheras without this option the loop
49# will execute until an overflowing value is encountered.
50convert_range = True
51
52# Enable this to allow one to write your_module.foo = ... to overwrite the
53# definition if the cpdef function foo, at the cost of an extra dictionary
54# lookup on every call.
55# If this is 0 it simply creates a wrapper.
56lookup_module_cpdef = False
57
58# Whether or not to embed the Python interpreter, for use in making a
59# standalone executable or calling from external libraries.
60# This will provide a method which initalizes the interpreter and
61# executes the body of this module.
62embed = None
63
64# In previous iterations of Cython, globals() gave the first non-Cython module
65# globals in the call stack.  Sage relies on this behavior for variable injection.
66old_style_globals = False
67
68# Allows cimporting from a pyx file without a pxd file.
69cimport_from_pyx = False
70
71# max # of dims for buffers -- set lower than number of dimensions in numpy, as
72# slices are passed by value and involve a lot of copying
73buffer_max_dims = 8
74
75# Number of function closure instances to keep in a freelist (0: no freelists)
76closure_freelist_size = 8
77
78# Should tp_clear() set object fields to None instead of clearing them to NULL?
79clear_to_none = True
80
81
82# Declare compiler directives
83directive_defaults = {
84    'boundscheck' : True,
85    'nonecheck' : False,
86    'initializedcheck' : True,
87    'embedsignature' : False,
88    'locals' : {},
89    'auto_cpdef': False,
90    'cdivision': False, # was True before 0.12
91    'cdivision_warnings': False,
92    'overflowcheck': False,
93    'overflowcheck.fold': True,
94    'always_allow_keywords': False,
95    'allow_none_for_extension_args': True,
96    'wraparound' : True,
97    'ccomplex' : False, # use C99/C++ for complex types and arith
98    'callspec' : "",
99    'final' : False,
100    'internal' : False,
101    'profile': False,
102    'no_gc_clear': False,
103    'linetrace': False,
104    'infer_types': None,
105    'infer_types.verbose': False,
106    'autotestdict': True,
107    'autotestdict.cdef': False,
108    'autotestdict.all': False,
109    'language_level': 2,
110    'fast_getattr': False, # Undocumented until we come up with a better way to handle this everywhere.
111    'py2_import': False, # For backward compatibility of Cython's source code in Py3 source mode
112    'c_string_type': 'bytes',
113    'c_string_encoding': '',
114    'type_version_tag': True,   # enables Py_TPFLAGS_HAVE_VERSION_TAG on extension types
115    'unraisable_tracebacks': False,
116
117    # set __file__ and/or __path__ to known source/target path at import time (instead of not having them available)
118    'set_initial_path' : None,  # SOURCEFILE or "/full/path/to/module"
119
120    'warn': None,
121    'warn.undeclared': False,
122    'warn.unreachable': True,
123    'warn.maybe_uninitialized': False,
124    'warn.unused': False,
125    'warn.unused_arg': False,
126    'warn.unused_result': False,
127    'warn.multiple_declarators': True,
128
129# optimizations
130    'optimize.inline_defnode_calls': True,
131
132# remove unreachable code
133    'remove_unreachable': True,
134
135# control flow debug directives
136    'control_flow.dot_output': "", # Graphviz output filename
137    'control_flow.dot_annotate_defs': False, # Annotate definitions
138
139# test support
140    'test_assert_path_exists' : [],
141    'test_fail_if_path_exists' : [],
142
143# experimental, subject to change
144    'binding': None,
145    'freelist': 0,
146}
147
148# Extra warning directives
149extra_warnings = {
150    'warn.maybe_uninitialized': True,
151    'warn.unreachable': True,
152    'warn.unused': True,
153}
154
155def one_of(*args):
156    def validate(name, value):
157        if value not in args:
158            raise ValueError("%s directive must be one of %s, got '%s'" % (
159                name, args, value))
160        else:
161            return value
162    return validate
163
164
165def normalise_encoding_name(option_name, encoding):
166    """
167    >>> normalise_encoding_name('c_string_encoding', 'ascii')
168    'ascii'
169    >>> normalise_encoding_name('c_string_encoding', 'AsCIi')
170    'ascii'
171    >>> normalise_encoding_name('c_string_encoding', 'us-ascii')
172    'ascii'
173    >>> normalise_encoding_name('c_string_encoding', 'utF8')
174    'utf8'
175    >>> normalise_encoding_name('c_string_encoding', 'utF-8')
176    'utf8'
177    >>> normalise_encoding_name('c_string_encoding', 'deFAuLT')
178    'default'
179    >>> normalise_encoding_name('c_string_encoding', 'default')
180    'default'
181    >>> normalise_encoding_name('c_string_encoding', 'SeriousLyNoSuch--Encoding')
182    'SeriousLyNoSuch--Encoding'
183    """
184    if not encoding:
185        return ''
186    if encoding.lower() in ('default', 'ascii', 'utf8'):
187        return encoding.lower()
188    import codecs
189    try:
190        decoder = codecs.getdecoder(encoding)
191    except LookupError:
192        return encoding  # may exists at runtime ...
193    for name in ('ascii', 'utf8'):
194        if codecs.getdecoder(name) == decoder:
195            return name
196    return encoding
197
198
199# Override types possibilities above, if needed
200directive_types = {
201    'final' : bool,  # final cdef classes and methods
202    'internal' : bool,  # cdef class visibility in the module dict
203    'infer_types' : bool, # values can be True/None/False
204    'binding' : bool,
205    'cfunc' : None, # decorators do not take directive value
206    'ccall' : None,
207    'cclass' : None,
208    'returns' : type,
209    'set_initial_path': str,
210    'freelist': int,
211    'c_string_type': one_of('bytes', 'bytearray', 'str', 'unicode'),
212    'c_string_encoding': normalise_encoding_name,
213}
214
215for key, val in directive_defaults.items():
216    if key not in directive_types:
217        directive_types[key] = type(val)
218
219directive_scopes = { # defaults to available everywhere
220    # 'module', 'function', 'class', 'with statement'
221    'final' : ('cclass', 'function'),
222    'no_gc_clear' : ('cclass',),
223    'internal' : ('cclass',),
224    'autotestdict' : ('module',),
225    'autotestdict.all' : ('module',),
226    'autotestdict.cdef' : ('module',),
227    'set_initial_path' : ('module',),
228    'test_assert_path_exists' : ('function', 'class', 'cclass'),
229    'test_fail_if_path_exists' : ('function', 'class', 'cclass'),
230    'freelist': ('cclass',),
231    # Avoid scope-specific to/from_py_functions for c_string.
232    'c_string_type': ('module',),
233    'c_string_encoding': ('module',),
234    'type_version_tag': ('module', 'cclass'),
235}
236
237def parse_directive_value(name, value, relaxed_bool=False):
238    """
239    Parses value as an option value for the given name and returns
240    the interpreted value. None is returned if the option does not exist.
241
242    >>> print parse_directive_value('nonexisting', 'asdf asdfd')
243    None
244    >>> parse_directive_value('boundscheck', 'True')
245    True
246    >>> parse_directive_value('boundscheck', 'true')
247    Traceback (most recent call last):
248       ...
249    ValueError: boundscheck directive must be set to True or False, got 'true'
250
251    >>> parse_directive_value('c_string_encoding', 'us-ascii')
252    'ascii'
253    >>> parse_directive_value('c_string_type', 'str')
254    'str'
255    >>> parse_directive_value('c_string_type', 'bytes')
256    'bytes'
257    >>> parse_directive_value('c_string_type', 'bytearray')
258    'bytearray'
259    >>> parse_directive_value('c_string_type', 'unicode')
260    'unicode'
261    >>> parse_directive_value('c_string_type', 'unnicode')
262    Traceback (most recent call last):
263    ValueError: c_string_type directive must be one of ('bytes', 'bytearray', 'str', 'unicode'), got 'unnicode'
264    """
265    type = directive_types.get(name)
266    if not type: return None
267    orig_value = value
268    if type is bool:
269        value = str(value)
270        if value == 'True': return True
271        if value == 'False': return False
272        if relaxed_bool:
273            value = value.lower()
274            if value in ("true", "yes"): return True
275            elif value in ("false", "no"): return False
276        raise ValueError("%s directive must be set to True or False, got '%s'" % (
277            name, orig_value))
278    elif type is int:
279        try:
280            return int(value)
281        except ValueError:
282            raise ValueError("%s directive must be set to an integer, got '%s'" % (
283                name, orig_value))
284    elif type is str:
285        return str(value)
286    elif callable(type):
287        return type(name, value)
288    else:
289        assert False
290
291def parse_directive_list(s, relaxed_bool=False, ignore_unknown=False,
292                         current_settings=None):
293    """
294    Parses a comma-separated list of pragma options. Whitespace
295    is not considered.
296
297    >>> parse_directive_list('      ')
298    {}
299    >>> (parse_directive_list('boundscheck=True') ==
300    ... {'boundscheck': True})
301    True
302    >>> parse_directive_list('  asdf')
303    Traceback (most recent call last):
304       ...
305    ValueError: Expected "=" in option "asdf"
306    >>> parse_directive_list('boundscheck=hey')
307    Traceback (most recent call last):
308       ...
309    ValueError: boundscheck directive must be set to True or False, got 'hey'
310    >>> parse_directive_list('unknown=True')
311    Traceback (most recent call last):
312       ...
313    ValueError: Unknown option: "unknown"
314    >>> warnings = parse_directive_list('warn.all=True')
315    >>> len(warnings) > 1
316    True
317    >>> sum(warnings.values()) == len(warnings)  # all true.
318    True
319    """
320    if current_settings is None:
321        result = {}
322    else:
323        result = current_settings
324    for item in s.split(','):
325        item = item.strip()
326        if not item: continue
327        if not '=' in item: raise ValueError('Expected "=" in option "%s"' % item)
328        name, value = [ s.strip() for s in item.strip().split('=', 1) ]
329        if name not in directive_defaults:
330            found = False
331            if name.endswith('.all'):
332                prefix = name[:-3]
333                for directive in directive_defaults:
334                    if directive.startswith(prefix):
335                        found = True
336                        parsed_value = parse_directive_value(directive, value, relaxed_bool=relaxed_bool)
337                        result[directive] = parsed_value
338            if not found and not ignore_unknown:
339                raise ValueError('Unknown option: "%s"' % name)
340        else:
341            parsed_value = parse_directive_value(name, value, relaxed_bool=relaxed_bool)
342            result[name] = parsed_value
343    return result
344