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
Cython/TestUtils.py ADDED
@@ -0,0 +1,464 @@
1
+ import os
2
+ import re
3
+ import unittest
4
+ import shlex
5
+ import sys
6
+ import tempfile
7
+ import textwrap
8
+ import time
9
+ from functools import partial
10
+
11
+ from .Compiler import Errors
12
+ from .CodeWriter import CodeWriter
13
+ from .Compiler.TreeFragment import TreeFragment, strip_common_indent, StringParseContext
14
+ from .Compiler.Visitor import TreeVisitor, VisitorTransform
15
+ from .Compiler import Nodes, TreePath
16
+ from .Compiler.ParseTreeTransforms import PostParse
17
+
18
+
19
+ class NodeTypeWriter(TreeVisitor):
20
+ def __init__(self):
21
+ super().__init__()
22
+ self._indents = 0
23
+ self.result = []
24
+
25
+ def visit_Node(self, node):
26
+ if not self.access_path:
27
+ name = "(root)"
28
+ else:
29
+ tip = self.access_path[-1]
30
+ if tip[2] is not None:
31
+ name = "%s[%d]" % tip[1:3]
32
+ else:
33
+ name = tip[1]
34
+
35
+ self.result.append(" " * self._indents +
36
+ "%s: %s" % (name, node.__class__.__name__))
37
+ self._indents += 1
38
+ self.visitchildren(node)
39
+ self._indents -= 1
40
+
41
+
42
+ def treetypes(root):
43
+ """Returns a string representing the tree by class names.
44
+ There's a leading and trailing whitespace so that it can be
45
+ compared by simple string comparison while still making test
46
+ cases look ok."""
47
+ w = NodeTypeWriter()
48
+ w.visit(root)
49
+ return "\n".join([""] + w.result + [""])
50
+
51
+
52
+ class TimedTest(unittest.TestCase):
53
+ # See copy in runtests.py
54
+ def setUp(self):
55
+ super().setUp()
56
+ self._start_time = time.time()
57
+
58
+ def tearDown(self):
59
+ t = time.time() - self._start_time
60
+ super().tearDown()
61
+ sys.stderr.write(f"[{self.id()}:{'' if t < .5 else ' SLOWTEST'} {t:.2f} sec] ")
62
+
63
+
64
+ class CythonTest(TimedTest):
65
+
66
+ def setUp(self):
67
+ Errors.reset()
68
+ super().setUp()
69
+
70
+ def tearDown(self):
71
+ super().tearDown()
72
+ Errors.reset()
73
+
74
+ def assertLines(self, expected, result):
75
+ "Checks that the given strings or lists of strings are equal line by line"
76
+ if not isinstance(expected, list):
77
+ expected = expected.split("\n")
78
+ if not isinstance(result, list):
79
+ result = result.split("\n")
80
+ for idx, (expected_line, result_line) in enumerate(zip(expected, result)):
81
+ self.assertEqual(expected_line, result_line,
82
+ "Line %d:\nExp: %s\nGot: %s" % (idx, expected_line, result_line))
83
+ self.assertEqual(len(expected), len(result),
84
+ "Unmatched lines. Got:\n%s\nExpected:\n%s" % ("\n".join(expected), "\n".join(result)))
85
+
86
+ def codeToLines(self, tree):
87
+ writer = CodeWriter()
88
+ writer.write(tree)
89
+ return writer.result.lines
90
+
91
+ def codeToString(self, tree):
92
+ return "\n".join(self.codeToLines(tree))
93
+
94
+ def assertCode(self, expected, result_tree):
95
+ result_lines = self.codeToLines(result_tree)
96
+
97
+ expected_lines = strip_common_indent(expected.split("\n"))
98
+
99
+ for idx, (line, expected_line) in enumerate(zip(result_lines, expected_lines)):
100
+ self.assertEqual(expected_line, line,
101
+ "Line %d:\nGot: %s\nExp: %s" % (idx, line, expected_line))
102
+ self.assertEqual(len(result_lines), len(expected_lines),
103
+ "Unmatched lines. Got:\n%s\nExpected:\n%s" % ("\n".join(result_lines), expected))
104
+
105
+ def assertNodeExists(self, path, result_tree):
106
+ self.assertNotEqual(TreePath.find_first(result_tree, path), None,
107
+ "Path '%s' not found in result tree" % path)
108
+
109
+ def fragment(self, code, pxds=None, pipeline=None):
110
+ "Simply create a tree fragment using the name of the test-case in parse errors."
111
+ if pxds is None:
112
+ pxds = {}
113
+ if pipeline is None:
114
+ pipeline = []
115
+ name = self.id()
116
+ if name.startswith("__main__."):
117
+ name = name[len("__main__."):]
118
+ name = name.replace(".", "_")
119
+
120
+ with Errors.local_errors() as errors:
121
+ fragment = TreeFragment(code, name, pxds, pipeline=pipeline)
122
+
123
+ if errors:
124
+ raise errors[0]
125
+ return fragment
126
+
127
+ def treetypes(self, root):
128
+ return treetypes(root)
129
+
130
+ def should_fail(self, func, exc_type=Exception):
131
+ """Calls "func" and fails if it doesn't raise the right exception
132
+ (any exception by default). Also returns the exception in question.
133
+ """
134
+ try:
135
+ func()
136
+ self.fail("Expected an exception of type %r" % exc_type)
137
+ except exc_type as e:
138
+ self.assertTrue(isinstance(e, exc_type))
139
+ return e
140
+
141
+ def should_not_fail(self, func):
142
+ """Calls func and succeeds if and only if no exception is raised
143
+ (i.e. converts exception raising into a failed testcase). Returns
144
+ the return value of func."""
145
+ try:
146
+ return func()
147
+ except Exception as exc:
148
+ self.fail(str(exc))
149
+
150
+
151
+ class TransformTest(CythonTest):
152
+ """
153
+ Utility base class for transform unit tests. It is based around constructing
154
+ test trees (either explicitly or by parsing a Cython code string); running
155
+ the transform, serialize it using a customized Cython serializer (with
156
+ special markup for nodes that cannot be represented in Cython),
157
+ and do a string-comparison line-by-line of the result.
158
+
159
+ To create a test case:
160
+ - Call run_pipeline. The pipeline should at least contain the transform you
161
+ are testing; pyx should be either a string (passed to the parser to
162
+ create a post-parse tree) or a node representing input to pipeline.
163
+ The result will be a transformed result.
164
+
165
+ - Check that the tree is correct. If wanted, assertCode can be used, which
166
+ takes a code string as expected, and a ModuleNode in result_tree
167
+ (it serializes the ModuleNode to a string and compares line-by-line).
168
+
169
+ All code strings are first stripped for whitespace lines and then common
170
+ indentation.
171
+
172
+ Plans: One could have a pxd dictionary parameter to run_pipeline.
173
+ """
174
+
175
+ def run_pipeline(self, pipeline, pyx, pxds=None):
176
+ if pxds is None:
177
+ pxds = {}
178
+ tree = self.fragment(pyx, pxds).root
179
+ # Run pipeline
180
+ for T in pipeline:
181
+ tree = T(tree)
182
+ return tree
183
+
184
+
185
+ # For the test C code validation, we have to take care that the test directives (and thus
186
+ # the match strings) do not just appear in (multiline) C code comments containing the original
187
+ # Cython source code. Thus, we discard the comments before matching.
188
+ # This seems a prime case for re.VERBOSE, but it seems to match some of the whitespace.
189
+ _strip_c_comments = partial(re.compile(
190
+ re.sub(r'\s+', '', r'''
191
+ /[*] (
192
+ (?: [^*\n] | [*][^/] )*
193
+ [\n]
194
+ (?: [^*] | [*][^/] )*
195
+ ) [*]/
196
+ ''')
197
+ ).sub, '')
198
+
199
+ _strip_cython_code_from_html = partial(re.compile(
200
+ re.sub(r'\s\s+', '', r'''
201
+ (?:
202
+ <pre class=["'][^"']*cython\s+line[^"']*["']\s*>
203
+ (?:[^<]|<(?!/pre))+
204
+ </pre>
205
+ )|(?:
206
+ <style[^>]*>
207
+ (?:[^<]|<(?!/style))+
208
+ </style>
209
+ )
210
+ ''')
211
+ ).sub, '')
212
+
213
+
214
+ def _parse_pattern(pattern):
215
+ start = end = None
216
+ if pattern.startswith('/'):
217
+ start, pattern = re.split(r"(?<!\\)/", pattern[1:], maxsplit=1)
218
+ pattern = pattern.strip()
219
+ if pattern.startswith(':'):
220
+ pattern = pattern[1:].strip()
221
+ if pattern.startswith("/"):
222
+ end, pattern = re.split(r"(?<!\\)/", pattern[1:], maxsplit=1)
223
+ pattern = pattern.strip()
224
+ return start, end, pattern
225
+
226
+
227
+ class TreeAssertVisitor(VisitorTransform):
228
+ # actually, a TreeVisitor would be enough, but this needs to run
229
+ # as part of the compiler pipeline
230
+
231
+ def __init__(self):
232
+ super().__init__()
233
+ self._module_pos = None
234
+ self._c_patterns = []
235
+ self._c_antipatterns = []
236
+
237
+ def create_c_file_validator(self):
238
+ patterns, antipatterns = self._c_patterns, self._c_antipatterns
239
+
240
+ def fail(pos, pattern, found, file_path):
241
+ Errors.error(pos, "Pattern '%s' %s found in %s" %(
242
+ pattern,
243
+ 'was' if found else 'was not',
244
+ file_path,
245
+ ))
246
+
247
+ def extract_section(file_path, content, start, end):
248
+ if start:
249
+ split = re.search(start, content)
250
+ if split:
251
+ content = content[split.end():]
252
+ else:
253
+ fail(self._module_pos, start, found=False, file_path=file_path)
254
+ if end:
255
+ split = re.search(end, content)
256
+ if split:
257
+ content = content[:split.start()]
258
+ else:
259
+ fail(self._module_pos, end, found=False, file_path=file_path)
260
+ return content
261
+
262
+ def validate_file_content(file_path, content):
263
+ for pattern in patterns:
264
+ #print("Searching pattern '%s'" % pattern)
265
+ start, end, pattern = _parse_pattern(pattern)
266
+ section = extract_section(file_path, content, start, end)
267
+ if not re.search(pattern, section):
268
+ fail(self._module_pos, pattern, found=False, file_path=file_path)
269
+
270
+ for antipattern in antipatterns:
271
+ #print("Searching antipattern '%s'" % antipattern)
272
+ start, end, antipattern = _parse_pattern(antipattern)
273
+ section = extract_section(file_path, content, start, end)
274
+ if re.search(antipattern, section):
275
+ fail(self._module_pos, antipattern, found=True, file_path=file_path)
276
+
277
+ def validate_c_file(result):
278
+ c_file = result.c_file
279
+ if not (patterns or antipatterns):
280
+ #print("No patterns defined for %s" % c_file)
281
+ return result
282
+
283
+ with open(c_file, encoding='utf8') as f:
284
+ content = f.read()
285
+ content = _strip_c_comments(content)
286
+ validate_file_content(c_file, content)
287
+
288
+ return validate_c_file
289
+
290
+ def _check_directives(self, node):
291
+ directives = node.directives
292
+ if 'test_assert_path_exists' in directives:
293
+ for path in directives['test_assert_path_exists']:
294
+ if TreePath.find_first(node, path) is None:
295
+ Errors.error(
296
+ node.pos,
297
+ "Expected path '%s' not found in result tree" % path)
298
+ if 'test_fail_if_path_exists' in directives:
299
+ for path in directives['test_fail_if_path_exists']:
300
+ first_node = TreePath.find_first(node, path)
301
+ if first_node is not None:
302
+ Errors.error(
303
+ first_node.pos,
304
+ "Unexpected path '%s' found in result tree" % path)
305
+ if 'test_assert_c_code_has' in directives:
306
+ self._c_patterns.extend(directives['test_assert_c_code_has'])
307
+ if 'test_fail_if_c_code_has' in directives:
308
+ self._c_antipatterns.extend(directives['test_fail_if_c_code_has'])
309
+ if 'test_body_needs_exception_handling' in directives:
310
+ value = directives['test_body_needs_exception_handling']
311
+ if value is not None:
312
+ from .Compiler.ParseTreeTransforms import HasNoExceptionHandlingVisitor
313
+ visitor = HasNoExceptionHandlingVisitor()
314
+ result = not visitor(node.body)
315
+ if value != result:
316
+ visitor(node.body)
317
+ Errors.error(
318
+ node.pos,
319
+ "Node had unexpected exception handling value"
320
+ )
321
+
322
+ def visit_ModuleNode(self, node):
323
+ self._module_pos = node.pos
324
+ self._check_directives(node)
325
+ self.visitchildren(node)
326
+ return node
327
+
328
+ def visit_CompilerDirectivesMixin(self, node):
329
+ self._check_directives(node)
330
+ self.visitchildren(node)
331
+ return node
332
+
333
+ visit_Node = VisitorTransform.recurse_to_children
334
+
335
+
336
+ def unpack_source_tree(tree_file, workdir, cython_root):
337
+ programs = {
338
+ 'PYTHON': [sys.executable],
339
+ 'CYTHON': [sys.executable, os.path.join(cython_root, 'cython.py')],
340
+ 'CYTHONIZE': [sys.executable, os.path.join(cython_root, 'cythonize.py')]
341
+ }
342
+
343
+ if workdir is None:
344
+ workdir = tempfile.mkdtemp()
345
+ header, cur_file = [], None
346
+ with open(tree_file, 'rb') as f:
347
+ try:
348
+ for line in f:
349
+ if line[:5] == b'#####':
350
+ filename = line.strip().strip(b'#').strip().decode('utf8').replace('/', os.path.sep)
351
+ path = os.path.join(workdir, filename)
352
+ if not os.path.exists(os.path.dirname(path)):
353
+ os.makedirs(os.path.dirname(path))
354
+ if cur_file is not None:
355
+ to_close, cur_file = cur_file, None
356
+ to_close.close()
357
+ cur_file = open(path, 'wb')
358
+ elif cur_file is not None:
359
+ cur_file.write(line)
360
+ elif line.strip() and not line.lstrip().startswith(b'#'):
361
+ if line.strip() not in (b'"""', b"'''"):
362
+ command = shlex.split(line.decode('utf8'))
363
+ if not command: continue
364
+ # In Python 3: prog, *args = command
365
+ prog, args = command[0], command[1:]
366
+ try:
367
+ header.append(programs[prog]+args)
368
+ except KeyError:
369
+ header.append(command)
370
+ finally:
371
+ if cur_file is not None:
372
+ cur_file.close()
373
+ return workdir, header
374
+
375
+
376
+ def write_file(file_path, content, dedent=False, encoding=None):
377
+ r"""Write some content (text or bytes) to the file
378
+ at `file_path` without translating `'\n'` into `os.linesep`.
379
+
380
+ The default encoding is `'utf-8'`.
381
+ """
382
+ if isinstance(content, bytes):
383
+ mode = "wb"
384
+
385
+ # binary mode doesn't take an encoding and newline arguments
386
+ newline = None
387
+ default_encoding = None
388
+ else:
389
+ mode = "w"
390
+
391
+ # any "\n" characters written are not translated
392
+ # to the system default line separator, os.linesep
393
+ newline = "\n"
394
+ default_encoding = "utf-8"
395
+
396
+ if encoding is None:
397
+ encoding = default_encoding
398
+
399
+ if dedent:
400
+ content = textwrap.dedent(content)
401
+
402
+ with open(file_path, mode=mode, encoding=encoding, newline=newline) as f:
403
+ f.write(content)
404
+
405
+
406
+ def write_newer_file(file_path, newer_than, content, dedent=False, encoding=None):
407
+ r"""
408
+ Write `content` to the file `file_path` without translating `'\n'`
409
+ into `os.linesep` and make sure it is newer than the file `newer_than`.
410
+
411
+ The default encoding is `'utf-8'` (same as for `write_file`).
412
+ """
413
+ write_file(file_path, content, dedent=dedent, encoding=encoding)
414
+
415
+ try:
416
+ other_time = os.path.getmtime(newer_than)
417
+ except OSError:
418
+ # Support writing a fresh file (which is always newer than a non-existent one)
419
+ other_time = None
420
+
421
+ while other_time is None or other_time >= os.path.getmtime(file_path):
422
+ write_file(file_path, content, dedent=dedent, encoding=encoding)
423
+
424
+
425
+ class DictEvalScope:
426
+ def __init__(self, namespace):
427
+ self.lookup = namespace.get
428
+
429
+ empty_eval_scope = DictEvalScope({})
430
+
431
+
432
+ def compiled_eval(code, namespace=None):
433
+ """
434
+ Parse code and evaluate it in a compile time env.
435
+ """
436
+ node = py_parse_code(code)
437
+
438
+ if isinstance(node, Nodes.StatListNode):
439
+ assert len(node.stats) == 1, node.stats
440
+ node = node.stats[0]
441
+ if isinstance(node, Nodes.ExprStatNode):
442
+ node = node.expr
443
+
444
+ return node.compile_time_value(DictEvalScope(namespace) if namespace else empty_eval_scope)
445
+
446
+
447
+ def py_parse_code(code):
448
+ """
449
+ Compiles code far enough to get errors from the parser and post-parse stage.
450
+
451
+ Is useful for checking for syntax errors, however it doesn't generate runable code.
452
+ """
453
+ context = StringParseContext("test")
454
+ # all the errors we care about are in the parsing or postparse stage
455
+ try:
456
+ with Errors.local_errors() as errors:
457
+ result = TreeFragment(code, pipeline=[PostParse(context)])
458
+ result = result.substitute()
459
+ if errors:
460
+ raise errors[0] # compile error, which should get caught below
461
+ else:
462
+ return result
463
+ except Errors.CompileError as e:
464
+ raise SyntaxError(e.message_only)
@@ -0,0 +1,128 @@
1
+ from Cython.TestUtils import CythonTest
2
+
3
+ class TestCodeWriter(CythonTest):
4
+ # CythonTest uses the CodeWriter heavily, so do some checking by
5
+ # roundtripping Cython code through the test framework.
6
+
7
+ # Note that this test is dependent upon the normal Cython parser
8
+ # to generate the input trees to the CodeWriter. This save *a lot*
9
+ # of time; better to spend that time writing other tests than perfecting
10
+ # this one...
11
+
12
+ # Whitespace is very significant in this process:
13
+ # - always newline on new block (!)
14
+ # - indent 4 spaces
15
+ # - 1 space around every operator
16
+
17
+ def t(self, codestr):
18
+ self.assertCode(codestr, self.fragment(codestr).root)
19
+
20
+ def test_print(self):
21
+ self.t("""
22
+ print(x + y ** 2)
23
+ print(x, y, z)
24
+ print(x + y, x + y * z, x * (y + z))
25
+ """)
26
+
27
+ def test_if(self):
28
+ self.t("if x:\n pass")
29
+
30
+ def test_ifelifelse(self):
31
+ self.t("""
32
+ if x:
33
+ pass
34
+ elif y:
35
+ pass
36
+ elif z + 34 ** 34 - 2:
37
+ pass
38
+ else:
39
+ pass
40
+ """)
41
+
42
+ def test_def(self):
43
+ self.t("""
44
+ def f(x, y, z):
45
+ pass
46
+ def f(x = 34, y = 54, z):
47
+ pass
48
+ """)
49
+
50
+ def test_cdef(self):
51
+ self.t("""
52
+ cdef f(x, y, z):
53
+ pass
54
+ cdef public void (x = 34, y = 54, z):
55
+ pass
56
+ cdef f(int *x, void *y, Value *z):
57
+ pass
58
+ cdef f(int **x, void **y, Value **z):
59
+ pass
60
+ cdef inline f(int &x, Value &z):
61
+ pass
62
+ """)
63
+
64
+ def test_longness_and_signedness(self):
65
+ self.t("def f(unsigned long long long long long int y):\n pass")
66
+
67
+ def test_signed_short(self):
68
+ self.t("def f(signed short int y):\n pass")
69
+
70
+ def test_typed_args(self):
71
+ self.t("def f(int x, unsigned long int y):\n pass")
72
+
73
+ def test_cdef_var(self):
74
+ self.t("""
75
+ cdef int hello
76
+ cdef int hello = 4, x = 3, y, z
77
+ """)
78
+
79
+ def test_for_loop(self):
80
+ self.t("""
81
+ for x, y, z in f(g(h(34) * 2) + 23):
82
+ print(x, y, z)
83
+ else:
84
+ print(43)
85
+ """)
86
+ self.t("""
87
+ for abc in (1, 2, 3):
88
+ print(x, y, z)
89
+ else:
90
+ print(43)
91
+ """)
92
+
93
+ def test_while_loop(self):
94
+ self.t("""
95
+ while True:
96
+ while True:
97
+ while True:
98
+ continue
99
+ """)
100
+
101
+ def test_inplace_assignment(self):
102
+ self.t("x += 43")
103
+
104
+ def test_cascaded_assignment(self):
105
+ self.t("x = y = z = abc = 43")
106
+
107
+ def test_attribute(self):
108
+ self.t("a.x")
109
+
110
+ def test_return_none(self):
111
+ self.t("""
112
+ def f(x, y, z):
113
+ return
114
+ cdef f(x, y, z):
115
+ return
116
+ def f(x, y, z):
117
+ return None
118
+ cdef f(x, y, z):
119
+ return None
120
+ def f(x, y, z):
121
+ return 1234
122
+ cdef f(x, y, z):
123
+ return 1234
124
+ """)
125
+
126
+ if __name__ == "__main__":
127
+ import unittest
128
+ unittest.main()