Cython 3.3.0a1__cp315-cp315-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (335) hide show
  1. Cython/Build/BuildExecutable.py +156 -0
  2. Cython/Build/Cache.py +199 -0
  3. Cython/Build/Cythonize.py +349 -0
  4. Cython/Build/Dependencies.py +1276 -0
  5. Cython/Build/Distutils.py +1 -0
  6. Cython/Build/Inline.py +467 -0
  7. Cython/Build/IpythonMagic.py +559 -0
  8. Cython/Build/SharedModule.py +84 -0
  9. Cython/Build/Tests/TestCyCache.py +195 -0
  10. Cython/Build/Tests/TestCythonizeArgsParser.py +480 -0
  11. Cython/Build/Tests/TestDependencies.py +133 -0
  12. Cython/Build/Tests/TestInline.py +177 -0
  13. Cython/Build/Tests/TestIpythonMagic.py +303 -0
  14. Cython/Build/Tests/TestRecythonize.py +212 -0
  15. Cython/Build/Tests/TestStripLiterals.py +155 -0
  16. Cython/Build/Tests/__init__.py +1 -0
  17. Cython/Build/__init__.py +11 -0
  18. Cython/CodeWriter.py +815 -0
  19. Cython/Compiler/AnalysedTreeTransforms.py +97 -0
  20. Cython/Compiler/Annotate.py +328 -0
  21. Cython/Compiler/AutoDocTransforms.py +320 -0
  22. Cython/Compiler/Buffer.py +680 -0
  23. Cython/Compiler/Builtin.py +997 -0
  24. Cython/Compiler/CmdLine.py +263 -0
  25. Cython/Compiler/Code.cp315-win_amd64.pyd +0 -0
  26. Cython/Compiler/Code.pxd +152 -0
  27. Cython/Compiler/Code.py +3907 -0
  28. Cython/Compiler/CodeGeneration.py +33 -0
  29. Cython/Compiler/CythonScope.py +194 -0
  30. Cython/Compiler/Dataclass.py +890 -0
  31. Cython/Compiler/DebugFlags.py +24 -0
  32. Cython/Compiler/Errors.py +310 -0
  33. Cython/Compiler/ExprNodes.py +15983 -0
  34. Cython/Compiler/FlowControl.cp315-win_amd64.pyd +0 -0
  35. Cython/Compiler/FlowControl.pxd +99 -0
  36. Cython/Compiler/FlowControl.py +1571 -0
  37. Cython/Compiler/FusedNode.cp315-win_amd64.pyd +0 -0
  38. Cython/Compiler/FusedNode.py +976 -0
  39. Cython/Compiler/Future.py +16 -0
  40. Cython/Compiler/Interpreter.py +57 -0
  41. Cython/Compiler/Lexicon.py +422 -0
  42. Cython/Compiler/LineTable.cp315-win_amd64.pyd +0 -0
  43. Cython/Compiler/LineTable.py +114 -0
  44. Cython/Compiler/Main.py +856 -0
  45. Cython/Compiler/MatchCaseNodes.py +2197 -0
  46. Cython/Compiler/MemoryView.py +930 -0
  47. Cython/Compiler/ModuleNode.py +4517 -0
  48. Cython/Compiler/Naming.py +367 -0
  49. Cython/Compiler/Nodes.py +10941 -0
  50. Cython/Compiler/Optimize.py +5455 -0
  51. Cython/Compiler/Options.py +838 -0
  52. Cython/Compiler/ParseTreeTransforms.pxd +79 -0
  53. Cython/Compiler/ParseTreeTransforms.py +4744 -0
  54. Cython/Compiler/Parsing.cp315-win_amd64.pyd +0 -0
  55. Cython/Compiler/Parsing.pxd +9 -0
  56. Cython/Compiler/Parsing.py +4792 -0
  57. Cython/Compiler/Pipeline.py +439 -0
  58. Cython/Compiler/PyrexTypes.py +6111 -0
  59. Cython/Compiler/Pythran.py +232 -0
  60. Cython/Compiler/Scanning.cp315-win_amd64.pyd +0 -0
  61. Cython/Compiler/Scanning.pxd +70 -0
  62. Cython/Compiler/Scanning.py +720 -0
  63. Cython/Compiler/StringEncoding.py +297 -0
  64. Cython/Compiler/Symtab.py +3092 -0
  65. Cython/Compiler/Tests/TestBuffer.py +105 -0
  66. Cython/Compiler/Tests/TestBuiltin.py +117 -0
  67. Cython/Compiler/Tests/TestCmdLine.py +587 -0
  68. Cython/Compiler/Tests/TestCode.py +145 -0
  69. Cython/Compiler/Tests/TestFlowControl.py +65 -0
  70. Cython/Compiler/Tests/TestGrammar.py +202 -0
  71. Cython/Compiler/Tests/TestMemView.py +71 -0
  72. Cython/Compiler/Tests/TestParseTreeTransforms.py +285 -0
  73. Cython/Compiler/Tests/TestScanning.py +132 -0
  74. Cython/Compiler/Tests/TestSignatureMatching.py +73 -0
  75. Cython/Compiler/Tests/TestStringEncoding.py +20 -0
  76. Cython/Compiler/Tests/TestTreeFragment.py +63 -0
  77. Cython/Compiler/Tests/TestTreePath.py +103 -0
  78. Cython/Compiler/Tests/TestTypes.py +118 -0
  79. Cython/Compiler/Tests/TestUtilityLoad.py +112 -0
  80. Cython/Compiler/Tests/TestVisitor.py +61 -0
  81. Cython/Compiler/Tests/Utils.py +36 -0
  82. Cython/Compiler/Tests/__init__.py +1 -0
  83. Cython/Compiler/TreeFragment.py +278 -0
  84. Cython/Compiler/TreePath.py +303 -0
  85. Cython/Compiler/TypeInference.py +611 -0
  86. Cython/Compiler/TypeSlots.py +1329 -0
  87. Cython/Compiler/UFuncs.py +311 -0
  88. Cython/Compiler/UtilNodes.py +413 -0
  89. Cython/Compiler/UtilityCode.py +348 -0
  90. Cython/Compiler/Version.py +8 -0
  91. Cython/Compiler/Visitor.cp315-win_amd64.pyd +0 -0
  92. Cython/Compiler/Visitor.pxd +53 -0
  93. Cython/Compiler/Visitor.py +864 -0
  94. Cython/Compiler/__init__.py +1 -0
  95. Cython/Coverage.py +448 -0
  96. Cython/Debugger/Cygdb.py +177 -0
  97. Cython/Debugger/DebugWriter.py +82 -0
  98. Cython/Debugger/Tests/TestLibCython.py +280 -0
  99. Cython/Debugger/Tests/__init__.py +1 -0
  100. Cython/Debugger/Tests/cfuncs.c +8 -0
  101. Cython/Debugger/Tests/codefile +49 -0
  102. Cython/Debugger/Tests/test_libcython_in_gdb.py +580 -0
  103. Cython/Debugger/Tests/test_libpython_in_gdb.py +90 -0
  104. Cython/Debugger/__init__.py +1 -0
  105. Cython/Debugger/libcython.py +1548 -0
  106. Cython/Debugger/libpython.py +2821 -0
  107. Cython/Debugging.py +20 -0
  108. Cython/Distutils/__init__.py +2 -0
  109. Cython/Distutils/build_ext.py +139 -0
  110. Cython/Distutils/extension.py +96 -0
  111. Cython/Distutils/old_build_ext.py +351 -0
  112. Cython/Includes/cpython/__init__.pxd +173 -0
  113. Cython/Includes/cpython/array.pxd +152 -0
  114. Cython/Includes/cpython/bool.pxd +37 -0
  115. Cython/Includes/cpython/buffer.pxd +112 -0
  116. Cython/Includes/cpython/bytearray.pxd +33 -0
  117. Cython/Includes/cpython/bytes.pxd +200 -0
  118. Cython/Includes/cpython/cellobject.pxd +35 -0
  119. Cython/Includes/cpython/ceval.pxd +8 -0
  120. Cython/Includes/cpython/codecs.pxd +121 -0
  121. Cython/Includes/cpython/complex.pxd +60 -0
  122. Cython/Includes/cpython/contextvars.pxd +145 -0
  123. Cython/Includes/cpython/conversion.pxd +36 -0
  124. Cython/Includes/cpython/datetime.pxd +395 -0
  125. Cython/Includes/cpython/descr.pxd +26 -0
  126. Cython/Includes/cpython/dict.pxd +268 -0
  127. Cython/Includes/cpython/exc.pxd +263 -0
  128. Cython/Includes/cpython/fileobject.pxd +57 -0
  129. Cython/Includes/cpython/float.pxd +56 -0
  130. Cython/Includes/cpython/frozendict.pxd +37 -0
  131. Cython/Includes/cpython/function.pxd +65 -0
  132. Cython/Includes/cpython/genobject.pxd +25 -0
  133. Cython/Includes/cpython/getargs.pxd +12 -0
  134. Cython/Includes/cpython/instance.pxd +25 -0
  135. Cython/Includes/cpython/iterator.pxd +36 -0
  136. Cython/Includes/cpython/iterobject.pxd +24 -0
  137. Cython/Includes/cpython/list.pxd +144 -0
  138. Cython/Includes/cpython/long.pxd +180 -0
  139. Cython/Includes/cpython/longintrepr.pxd +14 -0
  140. Cython/Includes/cpython/mapping.pxd +63 -0
  141. Cython/Includes/cpython/marshal.pxd +66 -0
  142. Cython/Includes/cpython/mem.pxd +120 -0
  143. Cython/Includes/cpython/memoryview.pxd +50 -0
  144. Cython/Includes/cpython/method.pxd +49 -0
  145. Cython/Includes/cpython/module.pxd +208 -0
  146. Cython/Includes/cpython/number.pxd +258 -0
  147. Cython/Includes/cpython/object.pxd +430 -0
  148. Cython/Includes/cpython/pycapsule.pxd +143 -0
  149. Cython/Includes/cpython/pylifecycle.pxd +68 -0
  150. Cython/Includes/cpython/pyport.pxd +8 -0
  151. Cython/Includes/cpython/pystate.pxd +95 -0
  152. Cython/Includes/cpython/pythread.pxd +53 -0
  153. Cython/Includes/cpython/ref.pxd +141 -0
  154. Cython/Includes/cpython/sentinel.pxd +17 -0
  155. Cython/Includes/cpython/sequence.pxd +134 -0
  156. Cython/Includes/cpython/set.pxd +119 -0
  157. Cython/Includes/cpython/slice.pxd +70 -0
  158. Cython/Includes/cpython/time.pxd +129 -0
  159. Cython/Includes/cpython/tuple.pxd +72 -0
  160. Cython/Includes/cpython/type.pxd +146 -0
  161. Cython/Includes/cpython/unicode.pxd +639 -0
  162. Cython/Includes/cpython/version.pxd +32 -0
  163. Cython/Includes/cpython/weakref.pxd +78 -0
  164. Cython/Includes/libc/__init__.pxd +1 -0
  165. Cython/Includes/libc/complex.pxd +35 -0
  166. Cython/Includes/libc/errno.pxd +127 -0
  167. Cython/Includes/libc/float.pxd +43 -0
  168. Cython/Includes/libc/limits.pxd +28 -0
  169. Cython/Includes/libc/locale.pxd +46 -0
  170. Cython/Includes/libc/math.pxd +209 -0
  171. Cython/Includes/libc/setjmp.pxd +10 -0
  172. Cython/Includes/libc/signal.pxd +64 -0
  173. Cython/Includes/libc/stddef.pxd +9 -0
  174. Cython/Includes/libc/stdint.pxd +105 -0
  175. Cython/Includes/libc/stdio.pxd +80 -0
  176. Cython/Includes/libc/stdlib.pxd +72 -0
  177. Cython/Includes/libc/string.pxd +50 -0
  178. Cython/Includes/libc/threads.pxd +234 -0
  179. Cython/Includes/libc/time.pxd +52 -0
  180. Cython/Includes/libcpp/__init__.pxd +4 -0
  181. Cython/Includes/libcpp/algorithm.pxd +320 -0
  182. Cython/Includes/libcpp/any.pxd +16 -0
  183. Cython/Includes/libcpp/atomic.pxd +59 -0
  184. Cython/Includes/libcpp/barrier.pxd +22 -0
  185. Cython/Includes/libcpp/bit.pxd +29 -0
  186. Cython/Includes/libcpp/cast.pxd +12 -0
  187. Cython/Includes/libcpp/cmath.pxd +518 -0
  188. Cython/Includes/libcpp/complex.pxd +106 -0
  189. Cython/Includes/libcpp/condition_variable.pxd +322 -0
  190. Cython/Includes/libcpp/deque.pxd +165 -0
  191. Cython/Includes/libcpp/exception.pxd +216 -0
  192. Cython/Includes/libcpp/execution.pxd +15 -0
  193. Cython/Includes/libcpp/forward_list.pxd +63 -0
  194. Cython/Includes/libcpp/functional.pxd +26 -0
  195. Cython/Includes/libcpp/future.pxd +103 -0
  196. Cython/Includes/libcpp/iterator.pxd +34 -0
  197. Cython/Includes/libcpp/latch.pxd +17 -0
  198. Cython/Includes/libcpp/limits.pxd +61 -0
  199. Cython/Includes/libcpp/list.pxd +117 -0
  200. Cython/Includes/libcpp/map.pxd +252 -0
  201. Cython/Includes/libcpp/memory.pxd +115 -0
  202. Cython/Includes/libcpp/mutex.pxd +387 -0
  203. Cython/Includes/libcpp/numbers.pxd +15 -0
  204. Cython/Includes/libcpp/numeric.pxd +131 -0
  205. Cython/Includes/libcpp/optional.pxd +34 -0
  206. Cython/Includes/libcpp/pair.pxd +1 -0
  207. Cython/Includes/libcpp/queue.pxd +25 -0
  208. Cython/Includes/libcpp/random.pxd +166 -0
  209. Cython/Includes/libcpp/semaphore.pxd +43 -0
  210. Cython/Includes/libcpp/set.pxd +228 -0
  211. Cython/Includes/libcpp/shared_mutex.pxd +96 -0
  212. Cython/Includes/libcpp/span.pxd +87 -0
  213. Cython/Includes/libcpp/stack.pxd +11 -0
  214. Cython/Includes/libcpp/stop_token.pxd +117 -0
  215. Cython/Includes/libcpp/string.pxd +355 -0
  216. Cython/Includes/libcpp/string_view.pxd +183 -0
  217. Cython/Includes/libcpp/typeindex.pxd +15 -0
  218. Cython/Includes/libcpp/typeinfo.pxd +10 -0
  219. Cython/Includes/libcpp/unordered_map.pxd +193 -0
  220. Cython/Includes/libcpp/unordered_set.pxd +152 -0
  221. Cython/Includes/libcpp/utility.pxd +30 -0
  222. Cython/Includes/libcpp/vector.pxd +186 -0
  223. Cython/Includes/numpy/math.pxd +150 -0
  224. Cython/Includes/openmp.pxd +50 -0
  225. Cython/Includes/posix/__init__.pxd +1 -0
  226. Cython/Includes/posix/dlfcn.pxd +14 -0
  227. Cython/Includes/posix/fcntl.pxd +86 -0
  228. Cython/Includes/posix/ioctl.pxd +4 -0
  229. Cython/Includes/posix/mman.pxd +101 -0
  230. Cython/Includes/posix/resource.pxd +57 -0
  231. Cython/Includes/posix/select.pxd +21 -0
  232. Cython/Includes/posix/signal.pxd +73 -0
  233. Cython/Includes/posix/stat.pxd +98 -0
  234. Cython/Includes/posix/stdio.pxd +37 -0
  235. Cython/Includes/posix/stdlib.pxd +29 -0
  236. Cython/Includes/posix/strings.pxd +9 -0
  237. Cython/Includes/posix/time.pxd +71 -0
  238. Cython/Includes/posix/types.pxd +30 -0
  239. Cython/Includes/posix/uio.pxd +26 -0
  240. Cython/Includes/posix/unistd.pxd +271 -0
  241. Cython/Includes/posix/wait.pxd +38 -0
  242. Cython/LZSS.py +170 -0
  243. Cython/Plex/Actions.cp315-win_amd64.pyd +0 -0
  244. Cython/Plex/Actions.pxd +24 -0
  245. Cython/Plex/Actions.py +119 -0
  246. Cython/Plex/DFA.cp315-win_amd64.pyd +0 -0
  247. Cython/Plex/DFA.pxd +14 -0
  248. Cython/Plex/DFA.py +164 -0
  249. Cython/Plex/Errors.py +48 -0
  250. Cython/Plex/Lexicons.py +178 -0
  251. Cython/Plex/Machines.cp315-win_amd64.pyd +0 -0
  252. Cython/Plex/Machines.pxd +36 -0
  253. Cython/Plex/Machines.py +238 -0
  254. Cython/Plex/Regexps.py +535 -0
  255. Cython/Plex/Scanners.cp315-win_amd64.pyd +0 -0
  256. Cython/Plex/Scanners.pxd +45 -0
  257. Cython/Plex/Scanners.py +328 -0
  258. Cython/Plex/Transitions.cp315-win_amd64.pyd +0 -0
  259. Cython/Plex/Transitions.pxd +14 -0
  260. Cython/Plex/Transitions.py +239 -0
  261. Cython/Plex/__init__.py +34 -0
  262. Cython/Runtime/__init__.py +1 -0
  263. Cython/Runtime/refnanny.cp315-win_amd64.pyd +0 -0
  264. Cython/Runtime/refnanny.pyx +237 -0
  265. Cython/Shadow.py +1167 -0
  266. Cython/StringIOTree.cp315-win_amd64.pyd +0 -0
  267. Cython/StringIOTree.py +169 -0
  268. Cython/Tempita/__init__.py +4 -0
  269. Cython/Tempita/_looper.py +154 -0
  270. Cython/Tempita/_tempita.cp315-win_amd64.pyd +0 -0
  271. Cython/Tempita/_tempita.py +1087 -0
  272. Cython/TestUtils.py +464 -0
  273. Cython/Tests/TestCodeWriter.py +128 -0
  274. Cython/Tests/TestCythonUtils.py +202 -0
  275. Cython/Tests/TestJediTyper.py +223 -0
  276. Cython/Tests/TestShadow.py +110 -0
  277. Cython/Tests/TestStringIOTree.py +68 -0
  278. Cython/Tests/TestTestUtils.py +89 -0
  279. Cython/Tests/__init__.py +1 -0
  280. Cython/Tests/xmlrunner.py +390 -0
  281. Cython/Utility/AsyncGen.c +1073 -0
  282. Cython/Utility/Buffer.c +866 -0
  283. Cython/Utility/BufferFormatFromTypeInfo.pxd +2 -0
  284. Cython/Utility/Builtins.c +933 -0
  285. Cython/Utility/CConvert.pyx +149 -0
  286. Cython/Utility/CMath.c +104 -0
  287. Cython/Utility/CommonStructures.c +244 -0
  288. Cython/Utility/Complex.c +378 -0
  289. Cython/Utility/Coroutine.c +2337 -0
  290. Cython/Utility/CpdefEnums.pyx +107 -0
  291. Cython/Utility/CppConvert.pyx +282 -0
  292. Cython/Utility/CppSupport.cpp +151 -0
  293. Cython/Utility/CythonFunction.c +2072 -0
  294. Cython/Utility/Dataclasses.c +101 -0
  295. Cython/Utility/Embed.c +129 -0
  296. Cython/Utility/Exceptions.c +1038 -0
  297. Cython/Utility/ExtensionTypes.c +1158 -0
  298. Cython/Utility/FunctionArguments.c +1045 -0
  299. Cython/Utility/FusedFunction.pyx +44 -0
  300. Cython/Utility/ImportExport.c +930 -0
  301. Cython/Utility/MatchCase.c +979 -0
  302. Cython/Utility/MatchCase_Cy.pyx +12 -0
  303. Cython/Utility/MemoryView.pxd +108 -0
  304. Cython/Utility/MemoryView.pyx +1499 -0
  305. Cython/Utility/MemoryView_C.c +1056 -0
  306. Cython/Utility/ModuleSetupCode.c +3352 -0
  307. Cython/Utility/NumpyImportArray.c +46 -0
  308. Cython/Utility/ObjectHandling.c +3372 -0
  309. Cython/Utility/Optimize.c +2563 -0
  310. Cython/Utility/Overflow.c +378 -0
  311. Cython/Utility/Profile.c +736 -0
  312. Cython/Utility/StringTools.c +1414 -0
  313. Cython/Utility/Synchronization.c +438 -0
  314. Cython/Utility/TString.c +369 -0
  315. Cython/Utility/TestCyUtilityLoader.pyx +8 -0
  316. Cython/Utility/TestCythonScope.pyx +75 -0
  317. Cython/Utility/TestUtilityLoader.c +12 -0
  318. Cython/Utility/TypeConversion.c +1556 -0
  319. Cython/Utility/UFuncs.pyx +50 -0
  320. Cython/Utility/UFuncs_C.c +89 -0
  321. Cython/Utility/__init__.py +28 -0
  322. Cython/Utility/arrayarray.h +172 -0
  323. Cython/Utils.cp315-win_amd64.pyd +0 -0
  324. Cython/Utils.py +677 -0
  325. Cython/__init__.py +12 -0
  326. Cython/py.typed +0 -0
  327. cython-3.3.0a1.dist-info/METADATA +394 -0
  328. cython-3.3.0a1.dist-info/RECORD +335 -0
  329. cython-3.3.0a1.dist-info/WHEEL +5 -0
  330. cython-3.3.0a1.dist-info/entry_points.txt +4 -0
  331. cython-3.3.0a1.dist-info/top_level.txt +3 -0
  332. cython.py +29 -0
  333. pyximport/__init__.py +4 -0
  334. pyximport/pyxbuild.py +160 -0
  335. pyximport/pyximport.py +482 -0
@@ -0,0 +1,156 @@
1
+ """
2
+ Compile a Python script into an executable that embeds CPython.
3
+ Requires CPython to be built as a shared library ('libpythonX.Y').
4
+
5
+ Basic usage:
6
+
7
+ python -m Cython.Build.BuildExecutable [ARGS] somefile.py
8
+ """
9
+
10
+
11
+ DEBUG = True
12
+
13
+ import sys
14
+ import os
15
+ import sysconfig
16
+
17
+
18
+ def get_config_var(name, default=''):
19
+ return sysconfig.get_config_var(name) or default
20
+
21
+ INCDIR = sysconfig.get_path('include')
22
+ LIBDIR1 = get_config_var('LIBDIR')
23
+ LIBDIR2 = get_config_var('LIBPL')
24
+ PYLIB = get_config_var('LIBRARY')
25
+ PYLIB_DYN = get_config_var('LDLIBRARY')
26
+ if PYLIB_DYN == PYLIB:
27
+ # no shared library
28
+ PYLIB_DYN = ''
29
+ else:
30
+ PYLIB_DYN = os.path.splitext(PYLIB_DYN[3:])[0] # 'lib(XYZ).so' -> XYZ
31
+
32
+ CC = get_config_var('CC', os.environ.get('CC', ''))
33
+ CFLAGS = get_config_var('CFLAGS') + ' ' + os.environ.get('CFLAGS', '')
34
+ LINKCC = get_config_var('LINKCC', os.environ.get('LINKCC', CC))
35
+ LINKFORSHARED = get_config_var('LINKFORSHARED')
36
+ LIBS = get_config_var('LIBS')
37
+ SYSLIBS = get_config_var('SYSLIBS')
38
+ EXE_EXT = sysconfig.get_config_var('EXE')
39
+
40
+
41
+ def _debug(msg, *args):
42
+ if DEBUG:
43
+ if args:
44
+ msg = msg % args
45
+ sys.stderr.write(msg + '\n')
46
+
47
+
48
+ def dump_config():
49
+ _debug('INCDIR: %s', INCDIR)
50
+ _debug('LIBDIR1: %s', LIBDIR1)
51
+ _debug('LIBDIR2: %s', LIBDIR2)
52
+ _debug('PYLIB: %s', PYLIB)
53
+ _debug('PYLIB_DYN: %s', PYLIB_DYN)
54
+ _debug('CC: %s', CC)
55
+ _debug('CFLAGS: %s', CFLAGS)
56
+ _debug('LINKCC: %s', LINKCC)
57
+ _debug('LINKFORSHARED: %s', LINKFORSHARED)
58
+ _debug('LIBS: %s', LIBS)
59
+ _debug('SYSLIBS: %s', SYSLIBS)
60
+ _debug('EXE_EXT: %s', EXE_EXT)
61
+
62
+
63
+ def _parse_args(args):
64
+ cy_args = []
65
+ last_arg = None
66
+ for i, arg in enumerate(args):
67
+ if arg.startswith('-'):
68
+ cy_args.append(arg)
69
+ elif last_arg in ('-X', '--directive'):
70
+ cy_args.append(arg)
71
+ else:
72
+ input_file = arg
73
+ args = args[i+1:]
74
+ break
75
+ last_arg = arg
76
+ else:
77
+ raise ValueError('no input file provided')
78
+
79
+ return input_file, cy_args, args
80
+
81
+
82
+ def runcmd(cmd, shell=True):
83
+ if shell:
84
+ cmd = ' '.join(cmd)
85
+ _debug(cmd)
86
+ else:
87
+ _debug(' '.join(cmd))
88
+
89
+ import subprocess
90
+ returncode = subprocess.call(cmd, shell=shell)
91
+
92
+ if returncode:
93
+ sys.exit(returncode)
94
+
95
+
96
+ def clink(basename):
97
+ runcmd([LINKCC, '-o', basename + EXE_EXT, basename+'.o', '-L'+LIBDIR1, '-L'+LIBDIR2]
98
+ + [PYLIB_DYN and ('-l'+PYLIB_DYN) or os.path.join(LIBDIR1, PYLIB)]
99
+ + LIBS.split() + SYSLIBS.split() + LINKFORSHARED.split())
100
+
101
+
102
+ def ccompile(basename):
103
+ runcmd([CC, '-c', '-o', basename+'.o', basename+'.c', '-I' + INCDIR] + CFLAGS.split())
104
+
105
+
106
+ def cycompile(input_file, options=()):
107
+ from ..Compiler import Version, CmdLine, Main
108
+ options, sources = CmdLine.parse_command_line(list(options or ()) + ['--embed', input_file])
109
+ _debug('Using Cython %s to compile %s', Version.version, input_file)
110
+ result = Main.compile(sources, options)
111
+ if result.num_errors > 0:
112
+ sys.exit(1)
113
+
114
+
115
+ def exec_file(program_name, args=()):
116
+ runcmd([os.path.abspath(program_name)] + list(args), shell=False)
117
+
118
+
119
+ def build(input_file, compiler_args=(), force=False):
120
+ """
121
+ Build an executable program from a Cython module.
122
+
123
+ Returns the name of the executable file.
124
+ """
125
+ basename = os.path.splitext(input_file)[0]
126
+ exe_file = basename + EXE_EXT
127
+ if not force and os.path.abspath(exe_file) == os.path.abspath(input_file):
128
+ raise ValueError("Input and output file names are the same, refusing to overwrite")
129
+ if (not force and os.path.exists(exe_file) and os.path.exists(input_file)
130
+ and os.path.getmtime(input_file) <= os.path.getmtime(exe_file)):
131
+ _debug("File is up to date, not regenerating %s", exe_file)
132
+ return exe_file
133
+ cycompile(input_file, compiler_args)
134
+ ccompile(basename)
135
+ clink(basename)
136
+ return exe_file
137
+
138
+
139
+ def build_and_run(args):
140
+ """
141
+ Build an executable program from a Cython module and run it.
142
+
143
+ Arguments after the module name will be passed verbatimly to the program.
144
+ """
145
+ program_name, args = _build(args)
146
+ exec_file(program_name, args)
147
+
148
+
149
+ def _build(args):
150
+ input_file, cy_args, args = _parse_args(args)
151
+ program_name = build(input_file, cy_args)
152
+ return program_name, args
153
+
154
+
155
+ if __name__ == '__main__':
156
+ _build(sys.argv[1:])
Cython/Build/Cache.py ADDED
@@ -0,0 +1,199 @@
1
+ from dataclasses import dataclass
2
+ import sys
3
+ import os
4
+ import hashlib
5
+ import shutil
6
+ import subprocess
7
+ from ..Utils import safe_makedirs, cached_function
8
+ import zipfile
9
+ from .. import __version__
10
+
11
+ try:
12
+ import zlib
13
+
14
+ zipfile_compression_mode = zipfile.ZIP_DEFLATED
15
+ except ImportError:
16
+ zipfile_compression_mode = zipfile.ZIP_STORED
17
+
18
+ try:
19
+ import gzip
20
+
21
+ gzip_open = gzip.open
22
+ gzip_ext = ".gz"
23
+ except ImportError:
24
+ gzip_open = open
25
+ gzip_ext = ""
26
+
27
+ zip_ext = ".zip"
28
+
29
+ MAX_CACHE_SIZE = 1024 * 1024 * 100
30
+
31
+ join_path = cached_function(os.path.join)
32
+
33
+
34
+ @cached_function
35
+ def file_hash(filename):
36
+ path = os.path.normpath(filename)
37
+ prefix = ("%d:%s" % (len(path), path)).encode("UTF-8")
38
+ m = hashlib.sha256(prefix)
39
+ with open(path, "rb") as f:
40
+ data = f.read(65000)
41
+ while data:
42
+ m.update(data)
43
+ data = f.read(65000)
44
+ return m.hexdigest()
45
+
46
+
47
+ @cached_function
48
+ def get_cython_cache_dir():
49
+ r"""
50
+ Return the base directory containing Cython's caches.
51
+
52
+ Priority:
53
+
54
+ 1. CYTHON_CACHE_DIR
55
+ 2. (OS X): ~/Library/Caches/Cython
56
+ (posix not OS X): XDG_CACHE_HOME/cython if XDG_CACHE_HOME defined
57
+ 3. ~/.cython
58
+
59
+ """
60
+ if "CYTHON_CACHE_DIR" in os.environ:
61
+ return os.environ["CYTHON_CACHE_DIR"]
62
+
63
+ parent = None
64
+ if os.name == "posix":
65
+ if sys.platform == "darwin":
66
+ parent = os.path.expanduser("~/Library/Caches")
67
+ else:
68
+ # this could fallback on ~/.cache
69
+ parent = os.environ.get("XDG_CACHE_HOME")
70
+
71
+ if parent and os.path.isdir(parent):
72
+ return join_path(parent, "cython")
73
+
74
+ # last fallback: ~/.cython
75
+ return os.path.expanduser(join_path("~", ".cython"))
76
+
77
+
78
+ @dataclass
79
+ class FingerprintFlags:
80
+ language: str = "c"
81
+ py_limited_api: bool = False
82
+ np_pythran: bool = False
83
+
84
+ def get_fingerprint(self):
85
+ return str((self.language, self.py_limited_api, self.np_pythran))
86
+
87
+
88
+ class Cache:
89
+ def __init__(self, path, cache_size=None):
90
+ if path is None:
91
+ self.path = join_path(get_cython_cache_dir(), "compiler")
92
+ else:
93
+ self.path = path
94
+ self.cache_size = cache_size if cache_size is not None else MAX_CACHE_SIZE
95
+ if not os.path.exists(self.path):
96
+ os.makedirs(self.path)
97
+
98
+ def transitive_fingerprint(
99
+ self, filename, dependencies, compilation_options, flags=FingerprintFlags()
100
+ ):
101
+ r"""
102
+ Return a fingerprint of a cython file that is about to be cythonized.
103
+
104
+ Fingerprints are looked up in future compilations. If the fingerprint
105
+ is found, the cythonization can be skipped. The fingerprint must
106
+ incorporate everything that has an influence on the generated code.
107
+ """
108
+ try:
109
+ m = hashlib.sha256(__version__.encode("UTF-8"))
110
+ m.update(file_hash(filename).encode("UTF-8"))
111
+ for x in sorted(dependencies):
112
+ if os.path.splitext(x)[1] not in (".c", ".cpp", ".h"):
113
+ m.update(file_hash(x).encode("UTF-8"))
114
+ # Include the module attributes that change the compilation result
115
+ # in the fingerprint. We do not iterate over module.__dict__ and
116
+ # include almost everything here as users might extend Extension
117
+ # with arbitrary (random) attributes that would lead to cache
118
+ # misses.
119
+ m.update(flags.get_fingerprint().encode("UTF-8"))
120
+ m.update(compilation_options.get_fingerprint().encode("UTF-8"))
121
+ return m.hexdigest()
122
+ except OSError:
123
+ return None
124
+
125
+ def fingerprint_file(self, cfile, fingerprint, ext):
126
+ return (
127
+ join_path(self.path, "%s-%s" % (os.path.basename(cfile), fingerprint)) + ext
128
+ )
129
+
130
+ def lookup_cache(self, c_file, fingerprint):
131
+ # Cython-generated c files are highly compressible.
132
+ # (E.g. a compression ratio of about 10 for Sage).
133
+ if not os.path.exists(self.path):
134
+ safe_makedirs(self.path)
135
+ gz_fingerprint_file = self.fingerprint_file(c_file, fingerprint, gzip_ext)
136
+ if os.path.exists(gz_fingerprint_file):
137
+ return gz_fingerprint_file
138
+ zip_fingerprint_file = self.fingerprint_file(c_file, fingerprint, zip_ext)
139
+ if os.path.exists(zip_fingerprint_file):
140
+ return zip_fingerprint_file
141
+ return None
142
+
143
+ def load_from_cache(self, c_file, cached):
144
+ ext = os.path.splitext(cached)[1]
145
+ if ext == gzip_ext:
146
+ os.utime(cached, None)
147
+ with gzip_open(cached, "rb") as g:
148
+ with open(c_file, "wb") as f:
149
+ shutil.copyfileobj(g, f)
150
+ elif ext == zip_ext:
151
+ os.utime(cached, None)
152
+ dirname = os.path.dirname(c_file)
153
+ with zipfile.ZipFile(cached) as z:
154
+ for artifact in z.namelist():
155
+ z.extract(artifact, dirname)
156
+ else:
157
+ raise ValueError(f"Unsupported cache file extension: {ext}")
158
+
159
+ def store_to_cache(self, c_file, fingerprint, compilation_result):
160
+ artifacts = compilation_result.get_generated_source_files()
161
+ if len(artifacts) == 1:
162
+ fingerprint_file = self.fingerprint_file(c_file, fingerprint, gzip_ext)
163
+ with open(c_file, "rb") as f:
164
+ with gzip_open(fingerprint_file + ".tmp", "wb") as g:
165
+ shutil.copyfileobj(f, g)
166
+ else:
167
+ fingerprint_file = self.fingerprint_file(c_file, fingerprint, zip_ext)
168
+ with zipfile.ZipFile(
169
+ fingerprint_file + ".tmp", "w", zipfile_compression_mode
170
+ ) as zip:
171
+ for artifact in artifacts:
172
+ zip.write(artifact, os.path.basename(artifact))
173
+ os.rename(fingerprint_file + ".tmp", fingerprint_file)
174
+
175
+ def cleanup_cache(self, ratio=0.85):
176
+ try:
177
+ completed_process = subprocess.run(
178
+ ["du", "-s", "-k", os.path.abspath(self.path)], stdout=subprocess.PIPE
179
+ )
180
+ stdout = completed_process.stdout
181
+ if completed_process.returncode == 0:
182
+ total_size = 1024 * int(stdout.strip().split()[0])
183
+ if total_size < self.cache_size:
184
+ return
185
+ except (OSError, ValueError):
186
+ pass
187
+ total_size = 0
188
+ all = []
189
+ for file in os.listdir(self.path):
190
+ path = join_path(self.path, file)
191
+ s = os.stat(path)
192
+ total_size += s.st_size
193
+ all.append((s.st_atime, s.st_size, path))
194
+ if total_size > self.cache_size:
195
+ for time, size, file in reversed(sorted(all)):
196
+ os.unlink(file)
197
+ total_size -= size
198
+ if total_size < self.cache_size * ratio:
199
+ break
@@ -0,0 +1,349 @@
1
+ import concurrent.futures
2
+ import os
3
+ import shutil
4
+ import sys
5
+ import tempfile
6
+ from collections import defaultdict
7
+ from contextlib import contextmanager
8
+
9
+ from .Dependencies import cythonize, extended_iglob
10
+ from ..Utils import is_package_dir
11
+ from ..Compiler import Options
12
+
13
+ try:
14
+ import multiprocessing
15
+ except ImportError:
16
+ multiprocessing = None
17
+
18
+
19
+ def find_package_base(path):
20
+ base_dir, package_path = os.path.split(path)
21
+ while is_package_dir(base_dir):
22
+ base_dir, parent = os.path.split(base_dir)
23
+ package_path = '%s/%s' % (parent, package_path)
24
+ return base_dir, package_path
25
+
26
+
27
+ def cython_compile(path_pattern, options):
28
+ all_paths = map(os.path.abspath, extended_iglob(path_pattern))
29
+ ext_modules_by_basedir = _cython_compile_files(all_paths, options)
30
+ _build(list(ext_modules_by_basedir.items()), options.parallel)
31
+
32
+
33
+ def _cython_compile_files(all_paths, options) -> dict:
34
+ ext_modules_to_build = defaultdict(list)
35
+
36
+ for path in all_paths:
37
+ if options.build_inplace:
38
+ base_dir = path
39
+ while not os.path.isdir(base_dir) or is_package_dir(base_dir):
40
+ base_dir = os.path.dirname(base_dir)
41
+ else:
42
+ base_dir = None
43
+
44
+ if os.path.isdir(path):
45
+ # recursively compiling a package
46
+ paths = [os.path.join(path, '**', '*.{py,pyx}')]
47
+ else:
48
+ # assume it's a file(-like thing)
49
+ paths = [path]
50
+
51
+ ext_modules = cythonize(
52
+ paths,
53
+ nthreads=options.parallel,
54
+ exclude_failures=options.keep_going,
55
+ exclude=options.excludes,
56
+ compiler_directives=options.directives,
57
+ compile_time_env=options.compile_time_env,
58
+ force=options.force,
59
+ quiet=options.quiet,
60
+ depfile=options.depfile,
61
+ language=options.language,
62
+ **options.options)
63
+
64
+ if ext_modules and options.build:
65
+ ext_modules_to_build[base_dir].extend(ext_modules)
66
+
67
+ return dict(ext_modules_to_build)
68
+
69
+
70
+ @contextmanager
71
+ def _interruptible_pool(pool_cm):
72
+ with pool_cm as proc_pool:
73
+ try:
74
+ yield proc_pool
75
+ except KeyboardInterrupt:
76
+ proc_pool.terminate_workers()
77
+ proc_pool.shutdown(cancel_futures=True)
78
+ raise
79
+
80
+
81
+ def _build(ext_modules, parallel):
82
+ modcount = sum(len(modules) for _, modules in ext_modules)
83
+ if not modcount:
84
+ return
85
+
86
+ serial_execution_mode = modcount == 1 or (
87
+ parallel is not None and parallel < 2)
88
+
89
+ try:
90
+ pool_cm = (
91
+ None if serial_execution_mode
92
+ else concurrent.futures.ProcessPoolExecutor(max_workers=parallel)
93
+ )
94
+ except (OSError, ImportError):
95
+ # `OSError` is a historic exception in `multiprocessing`
96
+ # `ImportError` happens e.g. under pyodide (`ModuleNotFoundError`)
97
+ serial_execution_mode = True
98
+
99
+ if serial_execution_mode:
100
+ for ext in ext_modules:
101
+ run_distutils(ext)
102
+ return
103
+
104
+ with _interruptible_pool(pool_cm) as proc_pool:
105
+ compiler_tasks = [
106
+ proc_pool.submit(run_distutils, (base_dir, [ext]))
107
+ for base_dir, modules in ext_modules
108
+ for ext in modules
109
+ ]
110
+
111
+ concurrent.futures.wait(compiler_tasks, return_when=concurrent.futures.FIRST_EXCEPTION)
112
+
113
+ worker_exceptions = []
114
+ for task in compiler_tasks: # discover any crashes
115
+ try:
116
+ task.result()
117
+ except BaseException as proc_err: # could be SystemExit
118
+ worker_exceptions.append(proc_err)
119
+
120
+ if worker_exceptions:
121
+ exc_msg = 'Compiling Cython modules failed with these errors:\n\n'
122
+ exc_msg += '\n\t* '.join(('', *map(str, worker_exceptions)))
123
+ exc_msg += '\n\n'
124
+
125
+ non_base_exceptions = [
126
+ exc for exc in worker_exceptions
127
+ if isinstance(exc, Exception)
128
+ ]
129
+ if sys.version_info[:2] >= (3, 11) and non_base_exceptions:
130
+ raise ExceptionGroup(exc_msg, non_base_exceptions)
131
+ else:
132
+ raise RuntimeError(exc_msg) from worker_exceptions[0]
133
+
134
+
135
+ def run_distutils(args):
136
+ try:
137
+ from distutils.core import setup
138
+ except ImportError:
139
+ try:
140
+ from setuptools import setup
141
+ except ImportError:
142
+ raise ImportError("'distutils' is not available. Please install 'setuptools' for binary builds.")
143
+
144
+ base_dir, ext_modules = args
145
+ script_args = ['build_ext', '-i']
146
+ cwd = os.getcwd()
147
+ temp_dir = None
148
+ try:
149
+ if base_dir:
150
+ os.chdir(base_dir)
151
+ temp_dir = tempfile.mkdtemp(dir=base_dir)
152
+ script_args.extend(['--build-temp', temp_dir])
153
+ setup(
154
+ script_name='setup.py',
155
+ script_args=script_args,
156
+ ext_modules=ext_modules,
157
+ )
158
+ finally:
159
+ if base_dir:
160
+ os.chdir(cwd)
161
+ if temp_dir and os.path.isdir(temp_dir):
162
+ shutil.rmtree(temp_dir)
163
+
164
+
165
+ def benchmark(code, setup_code=None, import_module=None, directives=None):
166
+ from Cython.Build.Inline import cymeit
167
+
168
+ timings, number = cymeit(code, setup_code, import_module, directives, repeat=9)
169
+
170
+ # Based on 'timeit.main()' in CPython 3.13.
171
+ units = {"nsec": 1e-9, "usec": 1e-6, "msec": 1e-3, "sec": 1.0}
172
+ scales = [(scale, unit) for unit, scale in reversed(units.items())] # biggest first
173
+
174
+ def format_time(t):
175
+ for scale, unit in scales:
176
+ if t >= scale:
177
+ break
178
+ else:
179
+ raise RuntimeError("Timing is below nanoseconds: {t:f}")
180
+ return f"{t / scale :.3f} {unit}"
181
+
182
+ timings.sort()
183
+ assert len(timings) & 1 == 1 # odd number of timings, for median position
184
+ fastest, median, slowest = timings[0], timings[len(timings) // 2], timings[-1]
185
+
186
+ print(f"{number} loops, best of {len(timings)}: {format_time(fastest)} per loop (median: {format_time(median)})")
187
+
188
+ if slowest > fastest * 4:
189
+ print(
190
+ "The timings are likely unreliable. "
191
+ f"The worst time ({format_time(slowest)}) was more than four times "
192
+ f"slower than the best time ({format_time(fastest)}).")
193
+
194
+
195
+ def create_args_parser():
196
+ from argparse import ArgumentParser, RawDescriptionHelpFormatter
197
+ from ..Compiler.CmdLine import ParseDirectivesAction, ParseOptionsAction, ParseCompileTimeEnvAction
198
+
199
+ parser = ArgumentParser(
200
+ formatter_class=RawDescriptionHelpFormatter,
201
+ epilog="""\
202
+ Environment variables:
203
+ CYTHON_FORCE_REGEN: if set to 1, forces cythonize to regenerate the output files regardless
204
+ of modification times and changes.
205
+ CYTHON_CACHE_DIR: the base directory containing Cython's caches.
206
+ Environment variables accepted by setuptools are supported to configure the C compiler and build:
207
+ https://setuptools.pypa.io/en/latest/userguide/ext_modules.html#compiler-and-linker-options"""
208
+ )
209
+
210
+ parser.add_argument('-X', '--directive', metavar='NAME=VALUE,...',
211
+ dest='directives', default={}, type=str,
212
+ action=ParseDirectivesAction,
213
+ help='set a compiler directive')
214
+ parser.add_argument('-E', '--compile-time-env', metavar='NAME=VALUE,...',
215
+ dest='compile_time_env', default={}, type=str,
216
+ action=ParseCompileTimeEnvAction,
217
+ help='set a compile time environment variable')
218
+ parser.add_argument('-s', '--option', metavar='NAME=VALUE',
219
+ dest='options', default={}, type=str,
220
+ action=ParseOptionsAction,
221
+ help='set a cythonize option')
222
+ parser.add_argument('-2', dest='language_level', action='store_const', const=2, default=None,
223
+ help='use Python 2 syntax mode by default')
224
+ parser.add_argument('-3', dest='language_level', action='store_const', const=3,
225
+ help='use Python 3 syntax mode by default')
226
+ parser.add_argument('--3str', dest='language_level', action='store_const', const=3,
227
+ help='use Python 3 syntax mode by default (deprecated alias for -3)')
228
+ parser.add_argument('-+', '--cplus', dest='language', action='store_const', const='c++', default=None,
229
+ help='Compile as C++ rather than C')
230
+ parser.add_argument('-a', '--annotate', action='store_const', const='default', dest='annotate',
231
+ help='Produce a colorized HTML version of the source.')
232
+ parser.add_argument('--annotate-fullc', action='store_const', const='fullc', dest='annotate',
233
+ help='Produce a colorized HTML version of the source '
234
+ 'which includes entire generated C/C++-code.')
235
+ parser.add_argument('-x', '--exclude', metavar='PATTERN', dest='excludes',
236
+ action='append', default=[],
237
+ help='exclude certain file patterns from the compilation')
238
+
239
+ parser.add_argument('-b', '--build', dest='build', action='store_true', default=None,
240
+ help='build extension modules using distutils/setuptools')
241
+ parser.add_argument('-i', '--inplace', dest='build_inplace', action='store_true', default=None,
242
+ help='build extension modules in place using distutils/setuptools (implies -b)')
243
+
244
+ parser.add_argument('--timeit', dest='benchmark', metavar="CODESTRING", type=str, default=None,
245
+ help="build in place, then compile+run CODESTRING as benchmark in first module's namespace (implies -i)")
246
+ parser.add_argument('--setup', dest='benchmark_setup', metavar="CODESTRING", type=str, default=None,
247
+ help="use CODESTRING as pre-benchmark setup code for --bench")
248
+
249
+ parser.add_argument('-j', '--parallel', dest='parallel', metavar='N',
250
+ type=int, default=None,
251
+ help='run builds in N parallel jobs (default: CPU count)')
252
+ parser.add_argument('-f', '--force', dest='force', action='store_true', default=None,
253
+ help='force recompilation')
254
+ parser.add_argument('-q', '--quiet', dest='quiet', action='store_true', default=None,
255
+ help='be less verbose during compilation')
256
+
257
+ parser.add_argument('--lenient', dest='lenient', action='store_true', default=None,
258
+ help='increase Python compatibility by ignoring some compile time errors')
259
+ parser.add_argument('-k', '--keep-going', dest='keep_going', action='store_true', default=None,
260
+ help='compile as much as possible, ignore compilation failures')
261
+ parser.add_argument('--no-docstrings', dest='no_docstrings', action='store_true', default=None,
262
+ help='strip docstrings')
263
+ parser.add_argument('-M', '--depfile', action='store_true', help='produce depfiles for the sources')
264
+ parser.add_argument('sources', nargs='*')
265
+ return parser
266
+
267
+
268
+ def parse_args_raw(parser, args):
269
+ options, unknown = parser.parse_known_args(args)
270
+ sources = options.sources
271
+ # if positional arguments were interspersed
272
+ # some of them are in unknown
273
+ for option in unknown:
274
+ if option.startswith('-'):
275
+ parser.error("unknown option "+option)
276
+ else:
277
+ sources.append(option)
278
+ del options.sources
279
+ return (options, sources)
280
+
281
+
282
+ def parse_args(args):
283
+ parser = create_args_parser()
284
+ options, args = parse_args_raw(parser, args)
285
+
286
+ if options.benchmark is not None:
287
+ options.build_inplace = True
288
+ elif not args:
289
+ parser.error("no source files provided")
290
+
291
+ if options.build_inplace:
292
+ options.build = True
293
+ if multiprocessing is None:
294
+ options.parallel = 0
295
+ if options.language_level:
296
+ assert options.language_level in (2, 3, '3str')
297
+ options.options['language_level'] = options.language_level
298
+
299
+ if options.lenient:
300
+ # increase Python compatibility by ignoring compile time errors
301
+ Options.error_on_unknown_names = False
302
+ Options.error_on_uninitialized = False
303
+
304
+ if options.annotate:
305
+ Options.annotate = options.annotate
306
+
307
+ if options.no_docstrings:
308
+ Options.docstrings = False
309
+
310
+ return options, args
311
+
312
+
313
+ def main(args=None):
314
+ options, paths = parse_args(args)
315
+
316
+ all_paths = []
317
+ for path in paths:
318
+ expanded_path = [os.path.abspath(p) for p in extended_iglob(path)]
319
+ if not expanded_path:
320
+ print("{}: No such file or directory: '{}'".format(sys.argv[0], path), file=sys.stderr)
321
+ sys.exit(1)
322
+ all_paths.extend(expanded_path)
323
+
324
+ ext_modules_by_basedir = _cython_compile_files(all_paths, options)
325
+
326
+ if ext_modules_by_basedir and options.build:
327
+ _build(list(ext_modules_by_basedir.items()), options.parallel)
328
+
329
+ if options.benchmark is not None:
330
+ base_dir = import_module = None
331
+ if ext_modules_by_basedir:
332
+ base_dir, first_extensions = ext_modules_by_basedir.popitem()
333
+ if first_extensions:
334
+ import_module = first_extensions[0].name
335
+
336
+ if base_dir is not None:
337
+ sys.path.insert(0, base_dir)
338
+
339
+ benchmark(
340
+ options.benchmark, options.benchmark_setup,
341
+ import_module=import_module,
342
+ )
343
+
344
+ if base_dir is not None:
345
+ sys.path.remove(base_dir)
346
+
347
+
348
+ if __name__ == '__main__':
349
+ main()