Cython 3.3.0__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 (339) 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 +1281 -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 +165 -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 +825 -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 +679 -0
  23. Cython/Compiler/Builtin.py +1102 -0
  24. Cython/Compiler/CmdLine.py +373 -0
  25. Cython/Compiler/Code.cp315-win_amd64.pyd +0 -0
  26. Cython/Compiler/Code.pxd +154 -0
  27. Cython/Compiler/Code.py +3760 -0
  28. Cython/Compiler/CodeGeneration.py +33 -0
  29. Cython/Compiler/CythonScope.py +208 -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 +16273 -0
  34. Cython/Compiler/FlowControl.cp315-win_amd64.pyd +0 -0
  35. Cython/Compiler/FlowControl.pxd +112 -0
  36. Cython/Compiler/FlowControl.py +1573 -0
  37. Cython/Compiler/FusedNode.cp315-win_amd64.pyd +0 -0
  38. Cython/Compiler/FusedNode.py +978 -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 +2200 -0
  46. Cython/Compiler/MemoryView.py +930 -0
  47. Cython/Compiler/ModuleNode.py +4548 -0
  48. Cython/Compiler/Naming.py +370 -0
  49. Cython/Compiler/Nodes.py +11304 -0
  50. Cython/Compiler/Optimize.py +5564 -0
  51. Cython/Compiler/Options.py +840 -0
  52. Cython/Compiler/ParseTreeTransforms.pxd +80 -0
  53. Cython/Compiler/ParseTreeTransforms.py +4808 -0
  54. Cython/Compiler/Parsing.cp315-win_amd64.pyd +0 -0
  55. Cython/Compiler/Parsing.pxd +9 -0
  56. Cython/Compiler/Parsing.py +4809 -0
  57. Cython/Compiler/Pipeline.py +439 -0
  58. Cython/Compiler/PyrexTypes.py +6588 -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.cp315-win_amd64.pyd +0 -0
  64. Cython/Compiler/StringEncoding.py +354 -0
  65. Cython/Compiler/Symtab.py +3121 -0
  66. Cython/Compiler/Tests/TestBuffer.py +105 -0
  67. Cython/Compiler/Tests/TestBuiltin.py +196 -0
  68. Cython/Compiler/Tests/TestCmdLine.py +652 -0
  69. Cython/Compiler/Tests/TestCode.py +145 -0
  70. Cython/Compiler/Tests/TestFlowControl.py +65 -0
  71. Cython/Compiler/Tests/TestGrammar.py +202 -0
  72. Cython/Compiler/Tests/TestMemView.py +71 -0
  73. Cython/Compiler/Tests/TestParseTreeTransforms.py +285 -0
  74. Cython/Compiler/Tests/TestScanning.py +132 -0
  75. Cython/Compiler/Tests/TestSignatureMatching.py +73 -0
  76. Cython/Compiler/Tests/TestStringEncoding.py +20 -0
  77. Cython/Compiler/Tests/TestTreeFragment.py +63 -0
  78. Cython/Compiler/Tests/TestTreePath.py +103 -0
  79. Cython/Compiler/Tests/TestTypes.py +119 -0
  80. Cython/Compiler/Tests/TestUtilityLoad.py +112 -0
  81. Cython/Compiler/Tests/TestVisitor.py +119 -0
  82. Cython/Compiler/Tests/Utils.py +36 -0
  83. Cython/Compiler/Tests/__init__.py +1 -0
  84. Cython/Compiler/TreeFragment.py +279 -0
  85. Cython/Compiler/TreePath.py +303 -0
  86. Cython/Compiler/TypeInference.py +611 -0
  87. Cython/Compiler/TypeSlots.py +1329 -0
  88. Cython/Compiler/UFuncs.py +317 -0
  89. Cython/Compiler/UtilNodes.py +389 -0
  90. Cython/Compiler/UtilityCode.py +354 -0
  91. Cython/Compiler/Version.py +8 -0
  92. Cython/Compiler/Visitor.cp315-win_amd64.pyd +0 -0
  93. Cython/Compiler/Visitor.pxd +52 -0
  94. Cython/Compiler/Visitor.py +914 -0
  95. Cython/Compiler/__init__.py +1 -0
  96. Cython/Coverage.py +448 -0
  97. Cython/Debugger/Cygdb.py +214 -0
  98. Cython/Debugger/DebugWriter.py +82 -0
  99. Cython/Debugger/Tests/TestLibCython.py +280 -0
  100. Cython/Debugger/Tests/__init__.py +1 -0
  101. Cython/Debugger/Tests/cfuncs.c +8 -0
  102. Cython/Debugger/Tests/codefile +49 -0
  103. Cython/Debugger/Tests/test_libcython_in_gdb.py +580 -0
  104. Cython/Debugger/Tests/test_libpython_in_gdb.py +90 -0
  105. Cython/Debugger/__init__.py +1 -0
  106. Cython/Debugger/libcython.py +1548 -0
  107. Cython/Debugger/libpython.py +2821 -0
  108. Cython/Debugging.py +20 -0
  109. Cython/Distutils/__init__.py +2 -0
  110. Cython/Distutils/build_ext.py +143 -0
  111. Cython/Distutils/extension.py +96 -0
  112. Cython/Distutils/old_build_ext.py +351 -0
  113. Cython/Includes/cpython/__init__.pxd +173 -0
  114. Cython/Includes/cpython/array.pxd +152 -0
  115. Cython/Includes/cpython/bool.pxd +37 -0
  116. Cython/Includes/cpython/buffer.pxd +112 -0
  117. Cython/Includes/cpython/bytearray.pxd +33 -0
  118. Cython/Includes/cpython/bytes.pxd +200 -0
  119. Cython/Includes/cpython/cellobject.pxd +35 -0
  120. Cython/Includes/cpython/ceval.pxd +8 -0
  121. Cython/Includes/cpython/codecs.pxd +121 -0
  122. Cython/Includes/cpython/complex.pxd +60 -0
  123. Cython/Includes/cpython/contextvars.pxd +145 -0
  124. Cython/Includes/cpython/conversion.pxd +36 -0
  125. Cython/Includes/cpython/datetime.pxd +395 -0
  126. Cython/Includes/cpython/descr.pxd +26 -0
  127. Cython/Includes/cpython/dict.pxd +268 -0
  128. Cython/Includes/cpython/exc.pxd +263 -0
  129. Cython/Includes/cpython/fileobject.pxd +57 -0
  130. Cython/Includes/cpython/float.pxd +56 -0
  131. Cython/Includes/cpython/frozendict.pxd +37 -0
  132. Cython/Includes/cpython/function.pxd +65 -0
  133. Cython/Includes/cpython/genobject.pxd +25 -0
  134. Cython/Includes/cpython/getargs.pxd +12 -0
  135. Cython/Includes/cpython/instance.pxd +25 -0
  136. Cython/Includes/cpython/iterator.pxd +36 -0
  137. Cython/Includes/cpython/iterobject.pxd +24 -0
  138. Cython/Includes/cpython/list.pxd +144 -0
  139. Cython/Includes/cpython/long.pxd +180 -0
  140. Cython/Includes/cpython/longintrepr.pxd +14 -0
  141. Cython/Includes/cpython/mapping.pxd +63 -0
  142. Cython/Includes/cpython/marshal.pxd +66 -0
  143. Cython/Includes/cpython/mem.pxd +120 -0
  144. Cython/Includes/cpython/memoryview.pxd +50 -0
  145. Cython/Includes/cpython/method.pxd +49 -0
  146. Cython/Includes/cpython/module.pxd +208 -0
  147. Cython/Includes/cpython/number.pxd +258 -0
  148. Cython/Includes/cpython/object.pxd +430 -0
  149. Cython/Includes/cpython/pycapsule.pxd +143 -0
  150. Cython/Includes/cpython/pylifecycle.pxd +68 -0
  151. Cython/Includes/cpython/pyport.pxd +8 -0
  152. Cython/Includes/cpython/pystate.pxd +95 -0
  153. Cython/Includes/cpython/pythread.pxd +53 -0
  154. Cython/Includes/cpython/ref.pxd +141 -0
  155. Cython/Includes/cpython/sentinel.pxd +17 -0
  156. Cython/Includes/cpython/sequence.pxd +134 -0
  157. Cython/Includes/cpython/set.pxd +119 -0
  158. Cython/Includes/cpython/slice.pxd +70 -0
  159. Cython/Includes/cpython/time.pxd +129 -0
  160. Cython/Includes/cpython/tuple.pxd +72 -0
  161. Cython/Includes/cpython/type.pxd +146 -0
  162. Cython/Includes/cpython/unicode.pxd +639 -0
  163. Cython/Includes/cpython/version.pxd +32 -0
  164. Cython/Includes/cpython/weakref.pxd +78 -0
  165. Cython/Includes/libc/__init__.pxd +1 -0
  166. Cython/Includes/libc/complex.pxd +35 -0
  167. Cython/Includes/libc/errno.pxd +127 -0
  168. Cython/Includes/libc/float.pxd +43 -0
  169. Cython/Includes/libc/limits.pxd +28 -0
  170. Cython/Includes/libc/locale.pxd +46 -0
  171. Cython/Includes/libc/math.pxd +209 -0
  172. Cython/Includes/libc/setjmp.pxd +10 -0
  173. Cython/Includes/libc/signal.pxd +64 -0
  174. Cython/Includes/libc/stddef.pxd +9 -0
  175. Cython/Includes/libc/stdint.pxd +105 -0
  176. Cython/Includes/libc/stdio.pxd +80 -0
  177. Cython/Includes/libc/stdlib.pxd +72 -0
  178. Cython/Includes/libc/string.pxd +50 -0
  179. Cython/Includes/libc/threads.pxd +234 -0
  180. Cython/Includes/libc/time.pxd +52 -0
  181. Cython/Includes/libcpp/__init__.pxd +4 -0
  182. Cython/Includes/libcpp/algorithm.pxd +320 -0
  183. Cython/Includes/libcpp/any.pxd +16 -0
  184. Cython/Includes/libcpp/atomic.pxd +59 -0
  185. Cython/Includes/libcpp/barrier.pxd +22 -0
  186. Cython/Includes/libcpp/bit.pxd +29 -0
  187. Cython/Includes/libcpp/cast.pxd +12 -0
  188. Cython/Includes/libcpp/cmath.pxd +518 -0
  189. Cython/Includes/libcpp/complex.pxd +106 -0
  190. Cython/Includes/libcpp/condition_variable.pxd +322 -0
  191. Cython/Includes/libcpp/deque.pxd +165 -0
  192. Cython/Includes/libcpp/exception.pxd +216 -0
  193. Cython/Includes/libcpp/execution.pxd +15 -0
  194. Cython/Includes/libcpp/forward_list.pxd +63 -0
  195. Cython/Includes/libcpp/functional.pxd +26 -0
  196. Cython/Includes/libcpp/future.pxd +103 -0
  197. Cython/Includes/libcpp/iterator.pxd +34 -0
  198. Cython/Includes/libcpp/latch.pxd +17 -0
  199. Cython/Includes/libcpp/limits.pxd +61 -0
  200. Cython/Includes/libcpp/list.pxd +117 -0
  201. Cython/Includes/libcpp/map.pxd +252 -0
  202. Cython/Includes/libcpp/memory.pxd +115 -0
  203. Cython/Includes/libcpp/mutex.pxd +387 -0
  204. Cython/Includes/libcpp/numbers.pxd +15 -0
  205. Cython/Includes/libcpp/numeric.pxd +131 -0
  206. Cython/Includes/libcpp/optional.pxd +34 -0
  207. Cython/Includes/libcpp/pair.pxd +1 -0
  208. Cython/Includes/libcpp/queue.pxd +25 -0
  209. Cython/Includes/libcpp/random.pxd +166 -0
  210. Cython/Includes/libcpp/semaphore.pxd +43 -0
  211. Cython/Includes/libcpp/set.pxd +228 -0
  212. Cython/Includes/libcpp/shared_mutex.pxd +96 -0
  213. Cython/Includes/libcpp/span.pxd +87 -0
  214. Cython/Includes/libcpp/stack.pxd +11 -0
  215. Cython/Includes/libcpp/stop_token.pxd +117 -0
  216. Cython/Includes/libcpp/string.pxd +355 -0
  217. Cython/Includes/libcpp/string_view.pxd +183 -0
  218. Cython/Includes/libcpp/typeindex.pxd +15 -0
  219. Cython/Includes/libcpp/typeinfo.pxd +10 -0
  220. Cython/Includes/libcpp/unordered_map.pxd +193 -0
  221. Cython/Includes/libcpp/unordered_set.pxd +152 -0
  222. Cython/Includes/libcpp/utility.pxd +30 -0
  223. Cython/Includes/libcpp/vector.pxd +186 -0
  224. Cython/Includes/numpy/math.pxd +150 -0
  225. Cython/Includes/openmp.pxd +50 -0
  226. Cython/Includes/posix/__init__.pxd +1 -0
  227. Cython/Includes/posix/dlfcn.pxd +14 -0
  228. Cython/Includes/posix/fcntl.pxd +86 -0
  229. Cython/Includes/posix/ioctl.pxd +4 -0
  230. Cython/Includes/posix/mman.pxd +101 -0
  231. Cython/Includes/posix/resource.pxd +57 -0
  232. Cython/Includes/posix/select.pxd +21 -0
  233. Cython/Includes/posix/signal.pxd +73 -0
  234. Cython/Includes/posix/stat.pxd +98 -0
  235. Cython/Includes/posix/stdio.pxd +37 -0
  236. Cython/Includes/posix/stdlib.pxd +29 -0
  237. Cython/Includes/posix/strings.pxd +9 -0
  238. Cython/Includes/posix/time.pxd +71 -0
  239. Cython/Includes/posix/types.pxd +30 -0
  240. Cython/Includes/posix/uio.pxd +26 -0
  241. Cython/Includes/posix/unistd.pxd +271 -0
  242. Cython/Includes/posix/wait.pxd +38 -0
  243. Cython/LZSS.cp315-win_amd64.pyd +0 -0
  244. Cython/LZSS.py +184 -0
  245. Cython/Plex/Actions.cp315-win_amd64.pyd +0 -0
  246. Cython/Plex/Actions.pxd +24 -0
  247. Cython/Plex/Actions.py +119 -0
  248. Cython/Plex/DFA.cp315-win_amd64.pyd +0 -0
  249. Cython/Plex/DFA.pxd +14 -0
  250. Cython/Plex/DFA.py +164 -0
  251. Cython/Plex/Errors.py +48 -0
  252. Cython/Plex/Lexicons.py +178 -0
  253. Cython/Plex/Machines.cp315-win_amd64.pyd +0 -0
  254. Cython/Plex/Machines.pxd +36 -0
  255. Cython/Plex/Machines.py +238 -0
  256. Cython/Plex/Regexps.py +535 -0
  257. Cython/Plex/Scanners.cp315-win_amd64.pyd +0 -0
  258. Cython/Plex/Scanners.pxd +45 -0
  259. Cython/Plex/Scanners.py +328 -0
  260. Cython/Plex/Transitions.cp315-win_amd64.pyd +0 -0
  261. Cython/Plex/Transitions.pxd +14 -0
  262. Cython/Plex/Transitions.py +239 -0
  263. Cython/Plex/__init__.py +34 -0
  264. Cython/Runtime/__init__.py +1 -0
  265. Cython/Runtime/refnanny.cp315-win_amd64.pyd +0 -0
  266. Cython/Runtime/refnanny.pyx +237 -0
  267. Cython/Shadow.py +1174 -0
  268. Cython/StringIOTree.cp315-win_amd64.pyd +0 -0
  269. Cython/StringIOTree.py +169 -0
  270. Cython/Tempita/__init__.py +4 -0
  271. Cython/Tempita/_looper.py +154 -0
  272. Cython/Tempita/_tempita.cp315-win_amd64.pyd +0 -0
  273. Cython/Tempita/_tempita.py +1087 -0
  274. Cython/TestUtils.py +472 -0
  275. Cython/Tests/TestCodeWriter.py +128 -0
  276. Cython/Tests/TestCythonUtils.py +202 -0
  277. Cython/Tests/TestJediTyper.py +223 -0
  278. Cython/Tests/TestShadow.py +125 -0
  279. Cython/Tests/TestStringIOTree.py +68 -0
  280. Cython/Tests/TestTestUtils.py +89 -0
  281. Cython/Tests/__init__.py +1 -0
  282. Cython/Tests/xmlrunner.py +390 -0
  283. Cython/Utility/AsyncGen.c +1152 -0
  284. Cython/Utility/Buffer.c +866 -0
  285. Cython/Utility/BufferFormatFromTypeInfo.pxd +2 -0
  286. Cython/Utility/Builtins.c +1068 -0
  287. Cython/Utility/CConvert.pyx +153 -0
  288. Cython/Utility/CMath.c +104 -0
  289. Cython/Utility/CommonStructures.c +244 -0
  290. Cython/Utility/Complex.c +378 -0
  291. Cython/Utility/Coroutine.c +2344 -0
  292. Cython/Utility/CpdefEnums.pyx +119 -0
  293. Cython/Utility/CppConvert.pyx +282 -0
  294. Cython/Utility/CppSupport.cpp +151 -0
  295. Cython/Utility/CythonFunction.c +2185 -0
  296. Cython/Utility/Dataclasses.c +101 -0
  297. Cython/Utility/Embed.c +129 -0
  298. Cython/Utility/Exceptions.c +1331 -0
  299. Cython/Utility/Exceptions_Cy.pyx +109 -0
  300. Cython/Utility/ExtensionTypes.c +1199 -0
  301. Cython/Utility/FunctionArguments.c +1052 -0
  302. Cython/Utility/FusedFunction.pyx +44 -0
  303. Cython/Utility/ImportExport.c +972 -0
  304. Cython/Utility/MatchCase.c +981 -0
  305. Cython/Utility/MatchCase_Cy.pyx +12 -0
  306. Cython/Utility/MemoryView.pxd +108 -0
  307. Cython/Utility/MemoryView.pyx +1499 -0
  308. Cython/Utility/MemoryView_C.c +1056 -0
  309. Cython/Utility/ModuleSetupCode.c +3319 -0
  310. Cython/Utility/NumpyImportArray.c +46 -0
  311. Cython/Utility/ObjectHandling.c +3404 -0
  312. Cython/Utility/Optimize.c +2564 -0
  313. Cython/Utility/Overflow.c +378 -0
  314. Cython/Utility/Profile.c +736 -0
  315. Cython/Utility/StringTools.c +1534 -0
  316. Cython/Utility/Synchronization.c +438 -0
  317. Cython/Utility/TString.c +369 -0
  318. Cython/Utility/TestCyUtilityLoader.pyx +8 -0
  319. Cython/Utility/TestCythonScope.pyx +75 -0
  320. Cython/Utility/TestUtilityLoader.c +12 -0
  321. Cython/Utility/TypeConversion.c +1588 -0
  322. Cython/Utility/UFuncs.pyx +50 -0
  323. Cython/Utility/UFuncs_C.c +89 -0
  324. Cython/Utility/__init__.py +28 -0
  325. Cython/Utility/arrayarray.h +172 -0
  326. Cython/Utils.cp315-win_amd64.pyd +0 -0
  327. Cython/Utils.py +680 -0
  328. Cython/__init__.py +12 -0
  329. Cython/_shared.cp315-win_amd64.pyd +0 -0
  330. Cython/py.typed +0 -0
  331. cython-3.3.0.dist-info/METADATA +555 -0
  332. cython-3.3.0.dist-info/RECORD +339 -0
  333. cython-3.3.0.dist-info/WHEEL +5 -0
  334. cython-3.3.0.dist-info/entry_points.txt +4 -0
  335. cython-3.3.0.dist-info/top_level.txt +3 -0
  336. cython.py +29 -0
  337. pyximport/__init__.py +4 -0
  338. pyximport/pyxbuild.py +160 -0
  339. pyximport/pyximport.py +482 -0
@@ -0,0 +1,119 @@
1
+ from itertools import chain
2
+
3
+ import Cython.Compiler.PyrexTypes as PT
4
+ from ...TestUtils import TimedTest
5
+
6
+
7
+ class TestMethodDispatcherTransform(TimedTest):
8
+
9
+ def test_widest_numeric_type(self):
10
+ def assert_widest(type1, type2, widest):
11
+ self.assertEqual(widest, PT.widest_numeric_type(type1, type2))
12
+
13
+ assert_widest(PT.c_int_type, PT.c_long_type, PT.c_long_type)
14
+ assert_widest(PT.c_double_type, PT.c_long_type, PT.c_double_type)
15
+ assert_widest(PT.c_longdouble_type, PT.c_long_type, PT.c_longdouble_type)
16
+
17
+ cenum = PT.CEnumType("E", "cenum", typedef_flag=False)
18
+ assert_widest(PT.c_int_type, cenum, PT.c_int_type)
19
+
20
+
21
+ class TestBuiltinTypes(TimedTest):
22
+
23
+ BUILTIN_FLAGS_MAPPING = {
24
+ 'is_pyint_type': ['int'],
25
+ 'is_pyfloat_type': ['float'],
26
+ 'is_pybool_type': ['bool'],
27
+ 'is_pycomplex_type': ['complex'],
28
+ 'is_pylist_type': ['list'],
29
+ 'is_pytuple_type': ['tuple'],
30
+ 'is_pydict_type': ['dict'],
31
+ 'is_pyfrozendict_type': ['frozendict'],
32
+ 'is_pyanydict_type': ['dict', 'frozendict'],
33
+ 'is_pyset_type': ['set'],
34
+ 'is_pyfrozenset_type': ['frozenset'],
35
+ 'is_pyanyset_type': ['set', 'frozenset'],
36
+ 'is_pybytes_type': ['bytes'],
37
+ 'is_pystr_type': ['str'],
38
+ 'is_pybytearray_type': ['bytearray'],
39
+ 'is_pymemoryview_type': ['memoryview'],
40
+ 'is_builtin_sequence': ['list', 'tuple', 'bytes', 'str', 'bytearray'],
41
+ 'is_bytes_or_str_or_bytearray': ['bytes', 'str', 'bytearray'],
42
+ 'has_uniform_element_type': ['list', 'set', 'frozenset'],
43
+ 'supports_container_type': ['list', 'dict', 'frozendict', 'set', 'frozenset', 'dict_keys', 'dict_values', 'dict_items'],
44
+ 'is_exception_type': PT.KNOWN_EXCEPTION_NAMES,
45
+ }
46
+
47
+ def test_set_builtin_type_flags(self):
48
+ builtin_flags = set(chain.from_iterable(PT.BuiltinObjectType._builtin_type_flag_mapping.values()))
49
+ builtin_types = set(chain.from_iterable(self.BUILTIN_FLAGS_MAPPING.values()))
50
+
51
+ self.assertSetEqual(builtin_flags, set(self.BUILTIN_FLAGS_MAPPING))
52
+ self.assertSetEqual(set(PT.BuiltinObjectType._builtin_type_flag_mapping), builtin_types)
53
+
54
+ for attr in builtin_flags:
55
+ self.assertIs(getattr(PT.PyrexType, attr), False)
56
+ for type_name in self.BUILTIN_FLAGS_MAPPING[attr]:
57
+ self.assertIs(
58
+ getattr(PT.BuiltinObjectType(type_name, f'c_{type_name}'), attr),
59
+ True,
60
+ f"{attr} should be set for {type_name}"
61
+ )
62
+
63
+
64
+ class TestTypeIdentifiers(TimedTest):
65
+
66
+ TEST_DATA = [
67
+ ("char*", "char__ptr"),
68
+ ("char *", "char__ptr"),
69
+ ("char **", "char__ptr__ptr"),
70
+ ("_typedef", "_typedef"),
71
+ ("__typedef", "__dundertypedef"),
72
+ ("___typedef", "__dunder_typedef"),
73
+ ("____typedef", "__dunder__dundertypedef"),
74
+ ("_____typedef", "__dunder__dunder_typedef"),
75
+ ("const __typedef", "__const___dundertypedef"),
76
+ ("int[42]", "int__lArr42__rArr"),
77
+ ("int[:]", "int__lArr__D__rArr"),
78
+ ("int[:,:]", "int__lArr__D__comma___D__rArr"),
79
+ ("int[:,:,:]", "int__lArr__D__comma___D__comma___D__rArr"),
80
+ ("int[:,:,...]", "int__lArr__D__comma___D__comma___EL__rArr"),
81
+ ("std::vector", "std__in_vector"),
82
+ ("std::vector&&", "std__in_vector__fwref"),
83
+ ("const std::vector", "__const_std__in_vector"),
84
+ ("const std::vector&", "__const_std__in_vector__ref"),
85
+ ("const_std", "const_std"),
86
+ ]
87
+
88
+ def test_escape_special_type_characters(self):
89
+ test_func = PT._escape_special_type_characters # keep test usage visible for IDEs
90
+ function_name = "_escape_special_type_characters"
91
+ self._test_escape(function_name)
92
+
93
+ def test_type_identifier_for_declaration(self):
94
+ test_func = PT.type_identifier_from_declaration # keep test usage visible for IDEs
95
+ function_name = test_func.__name__
96
+ self._test_escape(function_name)
97
+
98
+ # differences due to whitespace removal
99
+ test_data = [
100
+ ("const &std::vector", "const__refstd__in_vector"),
101
+ ("const &std::vector<int>", "const__refstd__in_vector__lAngint__rAng"),
102
+ ("const &&std::vector", "const__fwrefstd__in_vector"),
103
+ ("const &&&std::vector", "const__fwref__refstd__in_vector"),
104
+ ("const &&std::vector", "const__fwrefstd__in_vector"),
105
+ ("void (*func)(int x, float y)",
106
+ "975d51__void__lParen__ptrfunc__rParen__lParenint__spac__etc"),
107
+ ("float ** (*func)(int x, int[:] y)",
108
+ "31883a__float__ptr__ptr__lParen__ptrfunc__rParen__lPar__etc"),
109
+ ]
110
+ self._test_escape(function_name, test_data)
111
+
112
+ def _test_escape(self, func_name, test_data=TEST_DATA):
113
+ escape = getattr(PT, func_name)
114
+ for declaration, expected in test_data:
115
+ escaped_value = escape(declaration)
116
+ self.assertEqual(escaped_value, expected, "%s('%s') == '%s' != '%s'" % (
117
+ func_name, declaration, escaped_value, expected))
118
+ # test that the length has been successfully capped
119
+ self.assertLessEqual(len(escaped_value), 64)
@@ -0,0 +1,112 @@
1
+ from Cython.Compiler import Code, UtilityCode
2
+ from ...TestUtils import TimedTest
3
+
4
+
5
+ def strip_2tup(tup):
6
+ return tup[0] and tup[0].strip(), tup[1] and tup[1].strip()
7
+
8
+
9
+ class TestUtilityLoader(TimedTest):
10
+ """
11
+ Test loading UtilityCodes
12
+ """
13
+
14
+ expected = "test {{loader}} prototype", "test {{loader}} impl"
15
+
16
+ required = "req {{loader}} proto", "req {{loader}} impl"
17
+
18
+ context = dict(loader='Loader')
19
+
20
+ name = "TestUtilityLoader"
21
+ filename = "TestUtilityLoader.c"
22
+ cls = Code.UtilityCode
23
+
24
+ def test_load_as_string(self):
25
+ got = strip_2tup(self.cls.load_as_string(self.name, self.filename))
26
+ self.assertEqual(got, self.expected)
27
+
28
+ def test_load(self):
29
+ utility = self.cls.load(self.name, from_file=self.filename)
30
+ got = strip_2tup((utility.proto, utility.impl))
31
+ self.assertEqual(got, self.expected)
32
+
33
+ required, = utility.requires
34
+ got = strip_2tup((required.proto, required.impl))
35
+ self.assertEqual(got, self.required)
36
+
37
+ utility = self.cls.load_cached(self.name, from_file=self.filename)
38
+ got = strip_2tup((utility.proto, utility.impl))
39
+ self.assertEqual(got, self.expected)
40
+
41
+
42
+ class TestTempitaUtilityLoader(TestUtilityLoader):
43
+ """
44
+ Test loading UtilityCodes with Tempita substitution
45
+ """
46
+ expected_tempita = (TestUtilityLoader.expected[0].replace('{{loader}}', 'Loader'),
47
+ TestUtilityLoader.expected[1].replace('{{loader}}', 'Loader'))
48
+
49
+ required_tempita = (TestUtilityLoader.required[0].replace('{{loader}}', 'Loader'),
50
+ TestUtilityLoader.required[1].replace('{{loader}}', 'Loader'))
51
+
52
+ cls = Code.TempitaUtilityCode
53
+
54
+ def test_load_as_string(self):
55
+ got = strip_2tup(self.cls.load_as_string(self.name, self.filename, context=self.context))
56
+ self.assertEqual(got, self.expected_tempita)
57
+
58
+ def test_load(self):
59
+ utility = self.cls.load(self.name, self.filename, context=self.context)
60
+ got = strip_2tup((utility.proto, utility.impl))
61
+ self.assertEqual(got, self.expected_tempita)
62
+
63
+ required, = utility.requires
64
+ got = strip_2tup((required.proto, required.impl))
65
+ self.assertEqual(got, self.required_tempita)
66
+
67
+ utility = self.cls.load(self.name, from_file=self.filename, context=self.context)
68
+ got = strip_2tup((utility.proto, utility.impl))
69
+ self.assertEqual(got, self.expected_tempita)
70
+
71
+
72
+ class TestCythonUtilityLoader(TestTempitaUtilityLoader):
73
+ """
74
+ Test loading CythonUtilityCodes
75
+ """
76
+
77
+ # Just change the attributes and run the same tests
78
+ expected = None, "test {{cy_loader}} impl"
79
+ expected_tempita = None, "test CyLoader impl"
80
+
81
+ required = None, "req {{cy_loader}} impl"
82
+ required_tempita = None, "req CyLoader impl"
83
+
84
+ context = dict(cy_loader='CyLoader')
85
+
86
+ name = "TestCyUtilityLoader"
87
+ filename = "TestCyUtilityLoader.pyx"
88
+ cls = UtilityCode.CythonUtilityCode
89
+
90
+ # Small hack to pass our tests above
91
+ cls.proto = None
92
+
93
+ test_load = TestUtilityLoader.test_load
94
+ test_load_tempita = TestTempitaUtilityLoader.test_load
95
+
96
+
97
+ class TestUtilityCode(TimedTest):
98
+ def test_equality(self):
99
+ c1 = Code.UtilityCode.load("NumpyImportUFunc", "NumpyImportArray.c")
100
+ c2 = Code.UtilityCode.load("NumpyImportArray", "NumpyImportArray.c")
101
+ c3 = Code.UtilityCode.load("pyunicode_strlen", "StringTools.c")
102
+ c4 = Code.UtilityCode.load("pyunicode_from_unicode", "StringTools.c")
103
+ c5 = Code.UtilityCode.load("IncludeStringH", "StringTools.c")
104
+ c6 = Code.UtilityCode.load("IncludeCppStringH", "StringTools.c")
105
+
106
+ codes = [c1, c2, c3, c4, c5, c6]
107
+ for m in range(len(codes)):
108
+ for n in range(len(codes)):
109
+ if n == m:
110
+ self.assertEqual(codes[m], codes[n])
111
+ else:
112
+ self.assertNotEqual(codes[m], codes[n])
@@ -0,0 +1,119 @@
1
+ from Cython.Compiler.ModuleNode import ModuleNode
2
+ from Cython.Compiler.Symtab import ModuleScope
3
+ from Cython.TestUtils import TransformTest, TimedTest
4
+ from Cython.Compiler.Visitor import MethodDispatcherTransform, _test_flatten_list as test_flatten_list
5
+ from Cython.Compiler.ParseTreeTransforms import (
6
+ NormalizeTree, AnalyseDeclarationsTransform,
7
+ AnalyseExpressionsTransform, InterpretCompilerDirectives)
8
+
9
+
10
+ class TestMethodDispatcherTransform(TransformTest):
11
+ _tree = None
12
+
13
+ def _build_tree(self):
14
+ if self._tree is None:
15
+ context = None
16
+
17
+ def fake_module(node):
18
+ scope = ModuleScope('test', None, None)
19
+ return ModuleNode(node.pos, doc=None, body=node,
20
+ scope=scope, full_module_name='test',
21
+ directive_comments={})
22
+ pipeline = [
23
+ fake_module,
24
+ NormalizeTree(context),
25
+ InterpretCompilerDirectives(context, {}),
26
+ AnalyseDeclarationsTransform(context),
27
+ AnalyseExpressionsTransform(context),
28
+ ]
29
+ self._tree = self.run_pipeline(pipeline, """
30
+ cdef bytes s = b'asdfg'
31
+ cdef dict d = {1:2}
32
+ x = s * 3
33
+ d.get('test')
34
+ """)
35
+ return self._tree
36
+
37
+ def test_builtin_method(self):
38
+ calls = [0]
39
+ class Test(MethodDispatcherTransform):
40
+ def _handle_simple_method_dict_get(self, node, func, args, unbound):
41
+ calls[0] += 1
42
+ return node
43
+
44
+ tree = self._build_tree()
45
+ Test(None)(tree)
46
+ self.assertEqual(1, calls[0])
47
+
48
+ def test_binop_method(self):
49
+ calls = {'bytes': 0, 'object': 0}
50
+ class Test(MethodDispatcherTransform):
51
+ def _handle_simple_method_bytes___mul__(self, node, func, args, unbound):
52
+ calls['bytes'] += 1
53
+ return node
54
+ def _handle_simple_method_object___mul__(self, node, func, args, unbound):
55
+ calls['object'] += 1
56
+ return node
57
+
58
+ tree = self._build_tree()
59
+ Test(None)(tree)
60
+ self.assertEqual(1, calls['bytes'])
61
+ self.assertEqual(0, calls['object'])
62
+
63
+
64
+ class TestVisitorTransform(TimedTest):
65
+ def test_flatten_list_unchanged(self):
66
+ for test_list in [[], [1], [1,2], [0], [0,0]]:
67
+ self.assertIs(test_flatten_list(test_list), test_list)
68
+
69
+ def test_flatten_list_unchanged_sublist(self):
70
+ for test_list in [
71
+ [[1]],
72
+ [[1,2]],
73
+ [[1,2], 3],
74
+ [[1,2], None, []],
75
+ ]:
76
+ self.assertIs(test_flatten_list(test_list), test_list[0])
77
+
78
+ for test_list in [
79
+ [None, [1]],
80
+ [[], [1,2]],
81
+ [[], [1,2], []],
82
+ [[], [1,2], None],
83
+ [[], [1,2], 3],
84
+ [None, [1,2], None, []],
85
+ [None, [1,2], None, [3]],
86
+ ]:
87
+ self.assertIs(test_flatten_list(test_list), test_list[1])
88
+
89
+ def test_flatten_list_mixed(self):
90
+ self.assertListEqual(test_flatten_list([1, []]), [1])
91
+ self.assertListEqual(test_flatten_list([[], [], []]), [])
92
+ self.assertListEqual(test_flatten_list([[], None, []]), [])
93
+ self.assertListEqual(test_flatten_list([None, [], None]), [])
94
+ self.assertListEqual(test_flatten_list([1, [2]]), [1, 2])
95
+ self.assertListEqual(test_flatten_list([[1], [2]]), [1, 2])
96
+ self.assertListEqual(test_flatten_list([[1,2], [3,4]]), [1, 2, 3, 4])
97
+ self.assertListEqual(test_flatten_list([[1,2], [0], [], 0, [4]]), [1, 2, 0, 0, 4])
98
+
99
+ def test_flatten_list_fuzzer(self):
100
+ def flatten(l):
101
+ return [
102
+ item
103
+ for item_or_list in filter(None, l)
104
+ for item in (item_or_list if type(item_or_list) is list else [item_or_list])
105
+ ]
106
+
107
+ from itertools import chain, combinations as mixer
108
+ test_items = [None, [], None, 1, [2], [], 3, None, [4], [5, 6], [], None]
109
+
110
+ from collections import defaultdict
111
+ counter = defaultdict(int)
112
+
113
+ for test_list in chain.from_iterable(mixer(test_items, length) for length in range(2, 7)):
114
+ counter[len(test_list)] += 1
115
+ test_list = list(test_list)
116
+ expected = flatten(test_list)
117
+ self.assertListEqual(test_flatten_list(test_list), expected)
118
+
119
+ #print("FUZZER TEST COUNTS:", dict(counter))
@@ -0,0 +1,36 @@
1
+ import copy
2
+
3
+ from .. import Options
4
+
5
+
6
+ def backup_Options():
7
+ backup = {}
8
+ for name, value in vars(Options).items():
9
+ # we need a deep copy of _directive_defaults, because they can be changed
10
+ if name == '_directive_defaults':
11
+ value = copy.deepcopy(value)
12
+ backup[name] = value
13
+ return backup
14
+
15
+
16
+ def restore_Options(backup):
17
+ no_value = object()
18
+ for name, orig_value in backup.items():
19
+ if getattr(Options, name, no_value) != orig_value:
20
+ setattr(Options, name, orig_value)
21
+ # strip Options from new keys that might have been added:
22
+ for name in vars(Options).keys():
23
+ if name not in backup:
24
+ delattr(Options, name)
25
+
26
+
27
+ def check_global_options(expected_options, white_list=[]):
28
+ """
29
+ returns error message of "" if check Ok
30
+ """
31
+ no_value = object()
32
+ for name, orig_value in expected_options.items():
33
+ if name not in white_list:
34
+ if getattr(Options, name, no_value) != orig_value:
35
+ return "error in option " + name
36
+ return ""
@@ -0,0 +1 @@
1
+ # empty file
@@ -0,0 +1,279 @@
1
+ #
2
+ # TreeFragments - parsing of strings to trees
3
+ #
4
+
5
+ """
6
+ Support for parsing strings into code trees.
7
+ """
8
+
9
+
10
+ import re
11
+ from io import StringIO
12
+
13
+ from .Scanning import PyrexScanner, StringSourceDescriptor
14
+ from .Symtab import ModuleScope
15
+ from . import PyrexTypes
16
+ from .Visitor import VisitorTransform
17
+ from .Nodes import Node, StatListNode
18
+ from .ExprNodes import NameNode
19
+ from . import Parsing
20
+ from . import Main
21
+ from . import UtilNodes
22
+
23
+
24
+ class StringParseContext(Main.Context):
25
+ def __init__(self, name, include_directories=None, compiler_directives=None, cpp=False, options=None):
26
+ if include_directories is None:
27
+ include_directories = []
28
+ if compiler_directives is None:
29
+ compiler_directives = {}
30
+ Main.Context.__init__(self, include_directories, compiler_directives, cpp=cpp, language_level='3', options=options)
31
+ self.module_name = name
32
+
33
+ def find_module(self, module_name, from_module=None, pos=None, need_pxd=1, absolute_fallback=True, relative_import=False):
34
+ if module_name not in (self.module_name, 'cython'):
35
+ raise AssertionError("Not yet supporting any cimports/includes from string code snippets")
36
+ return ModuleScope(module_name, parent_module=None, context=self)
37
+
38
+
39
+ def parse_from_strings(name, code, pxds=None, level=None, initial_pos=None,
40
+ context=None, allow_struct_enum_decorator=False,
41
+ in_utility_code=False):
42
+ """
43
+ Utility method to parse a (unicode) string of code. This is mostly
44
+ used for internal Cython compiler purposes (creating code snippets
45
+ that transforms should emit, as well as unit testing).
46
+
47
+ code - a unicode string containing Cython (module-level) code
48
+ name - a descriptive name for the code source (to use in error messages etc.)
49
+ in_utility_code - used to suppress some messages from utility code. False by default
50
+ because some generated code snippets like properties and dataclasses
51
+ probably want to see those messages.
52
+
53
+ RETURNS
54
+
55
+ The tree, i.e. a ModuleNode. The ModuleNode's scope attribute is
56
+ set to the scope used when parsing.
57
+ """
58
+ if context is None:
59
+ context = StringParseContext(name)
60
+ # Since source files carry an encoding, it makes sense in this context
61
+ # to use a unicode string so that code fragments don't have to bother
62
+ # with encoding. This means that test code passed in should not have an
63
+ # encoding header.
64
+ assert isinstance(code, str), "unicode code snippets only please"
65
+ encoding = "UTF-8"
66
+
67
+ module_name = name
68
+ if initial_pos is None:
69
+ initial_pos = (name, 1, 0)
70
+ code_source = StringSourceDescriptor(name, code)
71
+ if in_utility_code:
72
+ code_source.in_utility_code = True
73
+
74
+ scope = context.find_module(module_name, pos=initial_pos, need_pxd=False)
75
+
76
+ buf = StringIO(code)
77
+
78
+ scanner = PyrexScanner(buf, code_source, source_encoding = encoding,
79
+ scope = scope, context = context, initial_pos = initial_pos)
80
+ ctx = Parsing.Ctx(allow_struct_enum_decorator=allow_struct_enum_decorator)
81
+
82
+ if level is None or level in ("module", "module_pxd"):
83
+ in_pxd = (level == "module_pxd")
84
+ tree = Parsing.p_module(scanner, in_pxd, module_name, ctx=ctx)
85
+ tree.is_pxd = in_pxd
86
+ else:
87
+ scanner.parse_comments = False
88
+ tree = Parsing.p_code(scanner, level=level, ctx=ctx)
89
+
90
+ tree.scope = scope
91
+ return tree
92
+
93
+
94
+ class TreeCopier(VisitorTransform):
95
+ def visit_Node(self, node):
96
+ if node is None:
97
+ return node
98
+ else:
99
+ c = node.clone_node()
100
+ self.visitchildren(c)
101
+ return c
102
+
103
+
104
+ class ApplyPositionAndCopy(TreeCopier):
105
+ def __init__(self, pos):
106
+ super().__init__()
107
+ self.pos = pos
108
+
109
+ def visit_Node(self, node):
110
+ copy = super().visit_Node(node)
111
+ copy.pos = self.pos
112
+ return copy
113
+
114
+
115
+ class TemplateTransform(VisitorTransform):
116
+ """
117
+ Makes a copy of a template tree while doing substitutions.
118
+
119
+ A dictionary "substitutions" should be passed in when calling
120
+ the transform; mapping names to replacement nodes. Then replacement
121
+ happens like this:
122
+ - If an ExprStatNode contains a single NameNode, whose name is
123
+ a key in the substitutions dictionary, the ExprStatNode is
124
+ replaced with a copy of the tree given in the dictionary.
125
+ It is the responsibility of the caller that the replacement
126
+ node is a valid statement.
127
+ - If a single NameNode is otherwise encountered, it is replaced
128
+ if its name is listed in the substitutions dictionary in the
129
+ same way. It is the responsibility of the caller to make sure
130
+ that the replacement nodes is a valid expression.
131
+
132
+ Also a list "temps" should be passed. Any names listed will
133
+ be transformed into anonymous, temporary names.
134
+
135
+ Currently supported for tempnames is:
136
+ NameNode
137
+ (various function and class definition nodes etc. should be added to this)
138
+
139
+ Each replacement node gets the position of the substituted node
140
+ recursively applied to every member node.
141
+ """
142
+
143
+ temp_name_counter = 0
144
+
145
+ def __call__(self, node, substitutions, temps, pos):
146
+ self.substitutions = substitutions
147
+ self.pos = pos
148
+ tempmap = {}
149
+ temphandles = []
150
+ for temp in temps:
151
+ TemplateTransform.temp_name_counter += 1
152
+ handle = UtilNodes.TempHandle(PyrexTypes.py_object_type)
153
+ tempmap[temp] = handle
154
+ temphandles.append(handle)
155
+ self.tempmap = tempmap
156
+ result = super().__call__(node)
157
+ if temps:
158
+ result = UtilNodes.TempsBlockNode(self.get_pos(node),
159
+ temps=temphandles,
160
+ body=result)
161
+ return result
162
+
163
+ def get_pos(self, node):
164
+ if self.pos:
165
+ return self.pos
166
+ else:
167
+ return node.pos
168
+
169
+ def visit_Node(self, node):
170
+ if node is None:
171
+ return None
172
+ else:
173
+ c = node.clone_node()
174
+ if self.pos is not None:
175
+ c.pos = self.pos
176
+ self.visitchildren(c)
177
+ return c
178
+
179
+ def try_substitution(self, node, key):
180
+ sub = self.substitutions.get(key)
181
+ if sub is not None:
182
+ pos = self.pos
183
+ if pos is None: pos = node.pos
184
+ return ApplyPositionAndCopy(pos)(sub)
185
+ else:
186
+ return self.visit_Node(node) # make copy as usual
187
+
188
+ def visit_NameNode(self, node):
189
+ temphandle = self.tempmap.get(node.name)
190
+ if temphandle:
191
+ # Replace name with temporary
192
+ return temphandle.ref(self.get_pos(node))
193
+ else:
194
+ return self.try_substitution(node, node.name)
195
+
196
+ def visit_ExprStatNode(self, node):
197
+ # If an expression-as-statement consists of only a replaceable
198
+ # NameNode, we replace the entire statement, not only the NameNode
199
+ if isinstance(node.expr, NameNode):
200
+ return self.try_substitution(node, node.expr.name)
201
+ else:
202
+ return self.visit_Node(node)
203
+
204
+
205
+ def copy_code_tree(node):
206
+ return TreeCopier()(node)
207
+
208
+
209
+ _match_indent = re.compile("^ *").match
210
+
211
+
212
+ def strip_common_indent(lines):
213
+ """Strips empty lines and common indentation from the list of strings given in lines"""
214
+ # TODO: Facilitate textwrap.indent instead
215
+ lines = [x for x in lines if x.strip() != ""]
216
+ if lines:
217
+ minindent = min([len(_match_indent(x).group(0)) for x in lines])
218
+ lines = [x[minindent:] for x in lines]
219
+ return lines
220
+
221
+
222
+ class TreeFragment:
223
+ def __init__(self, code, name=None, pxds=None, temps=None, pipeline=None, level=None, initial_pos=None):
224
+ if pxds is None:
225
+ pxds = {}
226
+ if temps is None:
227
+ temps = []
228
+ if pipeline is None:
229
+ pipeline = []
230
+ if not name:
231
+ name = "(tree fragment)"
232
+
233
+ if isinstance(code, str):
234
+ def fmt(x): return u"\n".join(strip_common_indent(x.split(u"\n")))
235
+
236
+ fmt_code = fmt(code)
237
+ fmt_pxds = {}
238
+ for key, value in pxds.items():
239
+ fmt_pxds[key] = fmt(value)
240
+ mod = t = parse_from_strings(name, fmt_code, fmt_pxds, level=level, initial_pos=initial_pos)
241
+ if level is None or level in ("module", "module_pxd"):
242
+ t = t.body # Make sure a StatListNode is at the top
243
+ if not isinstance(t, StatListNode):
244
+ t = StatListNode(pos=mod.pos, stats=[t])
245
+ for transform in pipeline:
246
+ if transform is None:
247
+ continue
248
+ t = transform(t)
249
+ self.root = t
250
+ elif isinstance(code, Node):
251
+ if pxds:
252
+ raise NotImplementedError()
253
+ self.root = code
254
+ else:
255
+ raise ValueError("Unrecognized code format (accepts unicode and Node)")
256
+ self.temps = temps
257
+
258
+ def copy(self):
259
+ return copy_code_tree(self.root)
260
+
261
+ def substitute(self, nodes=None, temps=None, pos = None):
262
+ if nodes is None:
263
+ nodes = {}
264
+ if temps is None:
265
+ temps = []
266
+ return TemplateTransform()(self.root,
267
+ substitutions = nodes,
268
+ temps = self.temps + temps, pos = pos)
269
+
270
+
271
+ class SetPosTransform(VisitorTransform):
272
+ def __init__(self, pos):
273
+ super().__init__()
274
+ self.pos = pos
275
+
276
+ def visit_Node(self, node):
277
+ node.pos = self.pos
278
+ self.visitchildren(node)
279
+ return node