1# 2# Cython - Compilation-wide options and pragma declarations 3# 4 5from __future__ import absolute_import 6 7 8class ShouldBeFromDirective(object): 9 10 known_directives = [] 11 12 def __init__(self, options_name, directive_name=None, disallow=False): 13 self.options_name = options_name 14 self.directive_name = directive_name or options_name 15 self.disallow = disallow 16 self.known_directives.append(self) 17 18 def __nonzero__(self): 19 self._bad_access() 20 21 def __int__(self): 22 self._bad_access() 23 24 def _bad_access(self): 25 raise RuntimeError(repr(self)) 26 27 def __repr__(self): 28 return ( 29 "Illegal access of '%s' from Options module rather than directive '%s'" 30 % (self.options_name, self.directive_name)) 31 32 33""" 34The members of this module are documented using autodata in 35Cython/docs/src/reference/compilation.rst. 36See http://www.sphinx-doc.org/en/master/ext/autodoc.html#directive-autoattribute 37for how autodata works. 38Descriptions of those members should start with a #: 39Donc forget to keep the docs in sync by removing and adding 40the members in both this file and the .rst file. 41""" 42 43#: Whether or not to include docstring in the Python extension. If False, the binary size 44#: will be smaller, but the ``__doc__`` attribute of any class or function will be an 45#: empty string. 46docstrings = True 47 48#: Embed the source code position in the docstrings of functions and classes. 49embed_pos_in_docstring = False 50 51#: Copy the original source code line by line into C code comments 52#: in the generated code file to help with understanding the output. 53#: This is also required for coverage analysis. 54emit_code_comments = True 55 56# undocumented 57pre_import = None 58 59#: Decref global variables in each module on exit for garbage collection. 60#: 0: None, 1+: interned objects, 2+: cdef globals, 3+: types objects 61#: Mostly for reducing noise in Valgrind as it typically executes at process exit 62#: (when all memory will be reclaimed anyways). 63#: Note that directly or indirectly executed cleanup code that makes use of global 64#: variables or types may no longer be safe when enabling the respective level since 65#: there is no guaranteed order in which the (reference counted) objects will 66#: be cleaned up. The order can change due to live references and reference cycles. 67generate_cleanup_code = False 68 69#: Should tp_clear() set object fields to None instead of clearing them to NULL? 70clear_to_none = True 71 72#: Generate an annotated HTML version of the input source files for debugging and optimisation purposes. 73#: This has the same effect as the ``annotate`` argument in :func:`cythonize`. 74annotate = False 75 76# When annotating source files in HTML, include coverage information from 77# this file. 78annotate_coverage_xml = None 79 80#: This will abort the compilation on the first error occurred rather than trying 81#: to keep going and printing further error messages. 82fast_fail = False 83 84#: Turn all warnings into errors. 85warning_errors = False 86 87#: Make unknown names an error. Python raises a NameError when 88#: encountering unknown names at runtime, whereas this option makes 89#: them a compile time error. If you want full Python compatibility, 90#: you should disable this option and also 'cache_builtins'. 91error_on_unknown_names = True 92 93#: Make uninitialized local variable reference a compile time error. 94#: Python raises UnboundLocalError at runtime, whereas this option makes 95#: them a compile time error. Note that this option affects only variables 96#: of "python object" type. 97error_on_uninitialized = True 98 99#: This will convert statements of the form ``for i in range(...)`` 100#: to ``for i from ...`` when ``i`` is a C integer type, and the direction 101#: (i.e. sign of step) can be determined. 102#: WARNING: This may change the semantics if the range causes assignment to 103#: i to overflow. Specifically, if this option is set, an error will be 104#: raised before the loop is entered, whereas without this option the loop 105#: will execute until an overflowing value is encountered. 106convert_range = True 107 108#: Perform lookups on builtin names only once, at module initialisation 109#: time. This will prevent the module from getting imported if a 110#: builtin name that it uses cannot be found during initialisation. 111#: Default is True. 112#: Note that some legacy builtins are automatically remapped 113#: from their Python 2 names to their Python 3 names by Cython 114#: when building in Python 3.x, 115#: so that they do not get in the way even if this option is enabled. 116cache_builtins = True 117 118#: Generate branch prediction hints to speed up error handling etc. 119gcc_branch_hints = True 120 121#: Enable this to allow one to write ``your_module.foo = ...`` to overwrite the 122#: definition if the cpdef function foo, at the cost of an extra dictionary 123#: lookup on every call. 124#: If this is false it generates only the Python wrapper and no override check. 125lookup_module_cpdef = False 126 127#: Whether or not to embed the Python interpreter, for use in making a 128#: standalone executable or calling from external libraries. 129#: This will provide a C function which initialises the interpreter and 130#: executes the body of this module. 131#: See `this demo <https://github.com/cython/cython/tree/master/Demos/embed>`_ 132#: for a concrete example. 133#: If true, the initialisation function is the C main() function, but 134#: this option can also be set to a non-empty string to provide a function name explicitly. 135#: Default is False. 136embed = None 137 138# In previous iterations of Cython, globals() gave the first non-Cython module 139# globals in the call stack. Sage relies on this behavior for variable injection. 140old_style_globals = ShouldBeFromDirective('old_style_globals') 141 142#: Allows cimporting from a pyx file without a pxd file. 143cimport_from_pyx = False 144 145#: Maximum number of dimensions for buffers -- set lower than number of 146#: dimensions in numpy, as 147#: slices are passed by value and involve a lot of copying. 148buffer_max_dims = 8 149 150#: Number of function closure instances to keep in a freelist (0: no freelists) 151closure_freelist_size = 8 152 153 154def get_directive_defaults(): 155 # To add an item to this list, all accesses should be changed to use the new 156 # directive, and the global option itself should be set to an instance of 157 # ShouldBeFromDirective. 158 for old_option in ShouldBeFromDirective.known_directives: 159 value = globals().get(old_option.options_name) 160 assert old_option.directive_name in _directive_defaults 161 if not isinstance(value, ShouldBeFromDirective): 162 if old_option.disallow: 163 raise RuntimeError( 164 "Option '%s' must be set from directive '%s'" % ( 165 old_option.option_name, old_option.directive_name)) 166 else: 167 # Warn? 168 _directive_defaults[old_option.directive_name] = value 169 return _directive_defaults 170 171# Declare compiler directives 172_directive_defaults = { 173 'boundscheck' : True, 174 'nonecheck' : False, 175 'initializedcheck' : True, 176 'embedsignature' : False, 177 'auto_cpdef': False, 178 'auto_pickle': None, 179 'cdivision': False, # was True before 0.12 180 'cdivision_warnings': False, 181 'c_api_binop_methods': True, 182 'overflowcheck': False, 183 'overflowcheck.fold': True, 184 'always_allow_keywords': False, 185 'allow_none_for_extension_args': True, 186 'wraparound' : True, 187 'ccomplex' : False, # use C99/C++ for complex types and arith 188 'callspec' : "", 189 'nogil' : False, 190 'profile': False, 191 'linetrace': False, 192 'emit_code_comments': True, # copy original source code into C code comments 193 'annotation_typing': True, # read type declarations from Python function annotations 194 'infer_types': None, 195 'infer_types.verbose': False, 196 'autotestdict': True, 197 'autotestdict.cdef': False, 198 'autotestdict.all': False, 199 'language_level': None, 200 'fast_getattr': False, # Undocumented until we come up with a better way to handle this everywhere. 201 'py2_import': False, # For backward compatibility of Cython's source code in Py3 source mode 202 'preliminary_late_includes_cy28': False, # Temporary directive in 0.28, to be removed in a later version (see GH#2079). 203 'iterable_coroutine': False, # Make async coroutines backwards compatible with the old asyncio yield-from syntax. 204 'c_string_type': 'bytes', 205 'c_string_encoding': '', 206 'type_version_tag': True, # enables Py_TPFLAGS_HAVE_VERSION_TAG on extension types 207 'unraisable_tracebacks': True, 208 'old_style_globals': False, 209 'np_pythran': False, 210 'fast_gil': False, 211 212 # set __file__ and/or __path__ to known source/target path at import time (instead of not having them available) 213 'set_initial_path' : None, # SOURCEFILE or "/full/path/to/module" 214 215 'warn': None, 216 'warn.undeclared': False, 217 'warn.unreachable': True, 218 'warn.maybe_uninitialized': False, 219 'warn.unused': False, 220 'warn.unused_arg': False, 221 'warn.unused_result': False, 222 'warn.multiple_declarators': True, 223 224# optimizations 225 'optimize.inline_defnode_calls': True, 226 'optimize.unpack_method_calls': True, # increases code size when True 227 'optimize.unpack_method_calls_in_pyinit': False, # uselessly increases code size when True 228 'optimize.use_switch': True, 229 230# remove unreachable code 231 'remove_unreachable': True, 232 233# control flow debug directives 234 'control_flow.dot_output': "", # Graphviz output filename 235 'control_flow.dot_annotate_defs': False, # Annotate definitions 236 237# test support 238 'test_assert_path_exists' : [], 239 'test_fail_if_path_exists' : [], 240 241# experimental, subject to change 242 'binding': None, 243 244 'formal_grammar': False, 245} 246 247# Extra warning directives 248extra_warnings = { 249 'warn.maybe_uninitialized': True, 250 'warn.unreachable': True, 251 'warn.unused': True, 252} 253 254def one_of(*args): 255 def validate(name, value): 256 if value not in args: 257 raise ValueError("%s directive must be one of %s, got '%s'" % ( 258 name, args, value)) 259 else: 260 return value 261 return validate 262 263 264def normalise_encoding_name(option_name, encoding): 265 """ 266 >>> normalise_encoding_name('c_string_encoding', 'ascii') 267 'ascii' 268 >>> normalise_encoding_name('c_string_encoding', 'AsCIi') 269 'ascii' 270 >>> normalise_encoding_name('c_string_encoding', 'us-ascii') 271 'ascii' 272 >>> normalise_encoding_name('c_string_encoding', 'utF8') 273 'utf8' 274 >>> normalise_encoding_name('c_string_encoding', 'utF-8') 275 'utf8' 276 >>> normalise_encoding_name('c_string_encoding', 'deFAuLT') 277 'default' 278 >>> normalise_encoding_name('c_string_encoding', 'default') 279 'default' 280 >>> normalise_encoding_name('c_string_encoding', 'SeriousLyNoSuch--Encoding') 281 'SeriousLyNoSuch--Encoding' 282 """ 283 if not encoding: 284 return '' 285 if encoding.lower() in ('default', 'ascii', 'utf8'): 286 return encoding.lower() 287 import codecs 288 try: 289 decoder = codecs.getdecoder(encoding) 290 except LookupError: 291 return encoding # may exists at runtime ... 292 for name in ('ascii', 'utf8'): 293 if codecs.getdecoder(name) == decoder: 294 return name 295 return encoding 296 297 298# Override types possibilities above, if needed 299directive_types = { 300 'language_level': str, # values can be None/2/3/'3str', where None == 2+warning 301 'auto_pickle': bool, 302 'locals': dict, 303 'final' : bool, # final cdef classes and methods 304 'nogil' : bool, 305 'internal' : bool, # cdef class visibility in the module dict 306 'infer_types' : bool, # values can be True/None/False 307 'binding' : bool, 308 'cfunc' : None, # decorators do not take directive value 309 'ccall' : None, 310 'inline' : None, 311 'staticmethod' : None, 312 'cclass' : None, 313 'no_gc_clear' : bool, 314 'no_gc' : bool, 315 'returns' : type, 316 'exceptval': type, # actually (type, check=True/False), but has its own parser 317 'set_initial_path': str, 318 'freelist': int, 319 'c_string_type': one_of('bytes', 'bytearray', 'str', 'unicode'), 320 'c_string_encoding': normalise_encoding_name, 321} 322 323for key, val in _directive_defaults.items(): 324 if key not in directive_types: 325 directive_types[key] = type(val) 326 327directive_scopes = { # defaults to available everywhere 328 # 'module', 'function', 'class', 'with statement' 329 'auto_pickle': ('module', 'cclass'), 330 'final' : ('cclass', 'function'), 331 'nogil' : ('function', 'with statement'), 332 'inline' : ('function',), 333 'cfunc' : ('function', 'with statement'), 334 'ccall' : ('function', 'with statement'), 335 'returns' : ('function',), 336 'exceptval' : ('function',), 337 'locals' : ('function',), 338 'staticmethod' : ('function',), # FIXME: analysis currently lacks more specific function scope 339 'no_gc_clear' : ('cclass',), 340 'no_gc' : ('cclass',), 341 'internal' : ('cclass',), 342 'cclass' : ('class', 'cclass', 'with statement'), 343 'autotestdict' : ('module',), 344 'autotestdict.all' : ('module',), 345 'autotestdict.cdef' : ('module',), 346 'set_initial_path' : ('module',), 347 'test_assert_path_exists' : ('function', 'class', 'cclass'), 348 'test_fail_if_path_exists' : ('function', 'class', 'cclass'), 349 'freelist': ('cclass',), 350 'emit_code_comments': ('module',), 351 'annotation_typing': ('module',), # FIXME: analysis currently lacks more specific function scope 352 # Avoid scope-specific to/from_py_functions for c_string. 353 'c_string_type': ('module',), 354 'c_string_encoding': ('module',), 355 'type_version_tag': ('module', 'cclass'), 356 'language_level': ('module',), 357 # globals() could conceivably be controlled at a finer granularity, 358 # but that would complicate the implementation 359 'old_style_globals': ('module',), 360 'np_pythran': ('module',), 361 'fast_gil': ('module',), 362 'iterable_coroutine': ('module', 'function'), 363} 364 365 366def parse_directive_value(name, value, relaxed_bool=False): 367 """ 368 Parses value as an option value for the given name and returns 369 the interpreted value. None is returned if the option does not exist. 370 371 >>> print(parse_directive_value('nonexisting', 'asdf asdfd')) 372 None 373 >>> parse_directive_value('boundscheck', 'True') 374 True 375 >>> parse_directive_value('boundscheck', 'true') 376 Traceback (most recent call last): 377 ... 378 ValueError: boundscheck directive must be set to True or False, got 'true' 379 380 >>> parse_directive_value('c_string_encoding', 'us-ascii') 381 'ascii' 382 >>> parse_directive_value('c_string_type', 'str') 383 'str' 384 >>> parse_directive_value('c_string_type', 'bytes') 385 'bytes' 386 >>> parse_directive_value('c_string_type', 'bytearray') 387 'bytearray' 388 >>> parse_directive_value('c_string_type', 'unicode') 389 'unicode' 390 >>> parse_directive_value('c_string_type', 'unnicode') 391 Traceback (most recent call last): 392 ValueError: c_string_type directive must be one of ('bytes', 'bytearray', 'str', 'unicode'), got 'unnicode' 393 """ 394 type = directive_types.get(name) 395 if not type: 396 return None 397 orig_value = value 398 if type is bool: 399 value = str(value) 400 if value == 'True': 401 return True 402 if value == 'False': 403 return False 404 if relaxed_bool: 405 value = value.lower() 406 if value in ("true", "yes"): 407 return True 408 elif value in ("false", "no"): 409 return False 410 raise ValueError("%s directive must be set to True or False, got '%s'" % ( 411 name, orig_value)) 412 elif type is int: 413 try: 414 return int(value) 415 except ValueError: 416 raise ValueError("%s directive must be set to an integer, got '%s'" % ( 417 name, orig_value)) 418 elif type is str: 419 return str(value) 420 elif callable(type): 421 return type(name, value) 422 else: 423 assert False 424 425 426def parse_directive_list(s, relaxed_bool=False, ignore_unknown=False, 427 current_settings=None): 428 """ 429 Parses a comma-separated list of pragma options. Whitespace 430 is not considered. 431 432 >>> parse_directive_list(' ') 433 {} 434 >>> (parse_directive_list('boundscheck=True') == 435 ... {'boundscheck': True}) 436 True 437 >>> parse_directive_list(' asdf') 438 Traceback (most recent call last): 439 ... 440 ValueError: Expected "=" in option "asdf" 441 >>> parse_directive_list('boundscheck=hey') 442 Traceback (most recent call last): 443 ... 444 ValueError: boundscheck directive must be set to True or False, got 'hey' 445 >>> parse_directive_list('unknown=True') 446 Traceback (most recent call last): 447 ... 448 ValueError: Unknown option: "unknown" 449 >>> warnings = parse_directive_list('warn.all=True') 450 >>> len(warnings) > 1 451 True 452 >>> sum(warnings.values()) == len(warnings) # all true. 453 True 454 """ 455 if current_settings is None: 456 result = {} 457 else: 458 result = current_settings 459 for item in s.split(','): 460 item = item.strip() 461 if not item: 462 continue 463 if '=' not in item: 464 raise ValueError('Expected "=" in option "%s"' % item) 465 name, value = [s.strip() for s in item.strip().split('=', 1)] 466 if name not in _directive_defaults: 467 found = False 468 if name.endswith('.all'): 469 prefix = name[:-3] 470 for directive in _directive_defaults: 471 if directive.startswith(prefix): 472 found = True 473 parsed_value = parse_directive_value(directive, value, relaxed_bool=relaxed_bool) 474 result[directive] = parsed_value 475 if not found and not ignore_unknown: 476 raise ValueError('Unknown option: "%s"' % name) 477 else: 478 parsed_value = parse_directive_value(name, value, relaxed_bool=relaxed_bool) 479 result[name] = parsed_value 480 return result 481 482 483def parse_variable_value(value): 484 """ 485 Parses value as an option value for the given name and returns 486 the interpreted value. 487 488 >>> parse_variable_value('True') 489 True 490 >>> parse_variable_value('true') 491 'true' 492 >>> parse_variable_value('us-ascii') 493 'us-ascii' 494 >>> parse_variable_value('str') 495 'str' 496 >>> parse_variable_value('123') 497 123 498 >>> parse_variable_value('1.23') 499 1.23 500 501 """ 502 if value == "True": 503 return True 504 elif value == "False": 505 return False 506 elif value == "None": 507 return None 508 elif value.isdigit(): 509 return int(value) 510 else: 511 try: 512 value = float(value) 513 except Exception: 514 # Not a float 515 pass 516 return value 517 518 519def parse_compile_time_env(s, current_settings=None): 520 """ 521 Parses a comma-separated list of pragma options. Whitespace 522 is not considered. 523 524 >>> parse_compile_time_env(' ') 525 {} 526 >>> (parse_compile_time_env('HAVE_OPENMP=True') == 527 ... {'HAVE_OPENMP': True}) 528 True 529 >>> parse_compile_time_env(' asdf') 530 Traceback (most recent call last): 531 ... 532 ValueError: Expected "=" in option "asdf" 533 >>> parse_compile_time_env('NUM_THREADS=4') == {'NUM_THREADS': 4} 534 True 535 >>> parse_compile_time_env('unknown=anything') == {'unknown': 'anything'} 536 True 537 """ 538 if current_settings is None: 539 result = {} 540 else: 541 result = current_settings 542 for item in s.split(','): 543 item = item.strip() 544 if not item: 545 continue 546 if '=' not in item: 547 raise ValueError('Expected "=" in option "%s"' % item) 548 name, value = [s.strip() for s in item.split('=', 1)] 549 result[name] = parse_variable_value(value) 550 return result 551