Options.py 19 KB

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