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,97 @@
1
+ from .Visitor import ScopeTrackingTransform
2
+ from .Nodes import StatListNode, SingleAssignmentNode, CFuncDefNode, DefNode
3
+ from .ExprNodes import DictNode, DictItemNode, NameNode, UnicodeNode
4
+ from .PyrexTypes import py_object_type
5
+ from .StringEncoding import EncodedString
6
+ from . import Symtab
7
+
8
+ class AutoTestDictTransform(ScopeTrackingTransform):
9
+ # Handles autotestdict directive
10
+
11
+ excludelist = ['__cinit__', '__dealloc__', '__richcmp__',
12
+ '__nonzero__', '__bool__',
13
+ '__len__', '__contains__']
14
+
15
+ def visit_ModuleNode(self, node):
16
+ if node.is_pxd:
17
+ return node
18
+ self.scope_type = 'module'
19
+ self.scope_node = node
20
+
21
+ if not self.current_directives['autotestdict']:
22
+ return node
23
+ self.all_docstrings = self.current_directives['autotestdict.all']
24
+ self.cdef_docstrings = self.all_docstrings or self.current_directives['autotestdict.cdef']
25
+
26
+ assert isinstance(node.body, StatListNode)
27
+
28
+ # First see if __test__ is already created
29
+ if '__test__' in node.scope.entries:
30
+ # Do nothing
31
+ return node
32
+
33
+ pos = node.pos
34
+
35
+ self.tests = []
36
+ self.testspos = node.pos
37
+
38
+ test_dict_entry = node.scope.declare_var(EncodedString('__test__'),
39
+ py_object_type,
40
+ pos,
41
+ visibility='public')
42
+ create_test_dict_assignment = SingleAssignmentNode(pos,
43
+ lhs=NameNode(pos, name=EncodedString('__test__'),
44
+ entry=test_dict_entry),
45
+ rhs=DictNode(pos, key_value_pairs=self.tests))
46
+ self.visitchildren(node)
47
+ node.body.stats.append(create_test_dict_assignment)
48
+ return node
49
+
50
+ def add_test(self, testpos, path, doctest):
51
+ pos = self.testspos
52
+ keystr = EncodedString(f'{path} (line {testpos[1]:d})')
53
+ key = UnicodeNode(pos, value=keystr)
54
+ value = UnicodeNode(pos, value=doctest)
55
+ self.tests.append(DictItemNode(pos, key=key, value=value))
56
+
57
+ def visit_ExprNode(self, node):
58
+ # expressions cannot contain functions and lambda expressions
59
+ # do not have a docstring
60
+ return node
61
+
62
+ def visit_FuncDefNode(self, node):
63
+ if not node.doc or (isinstance(node, DefNode) and node.fused_py_func):
64
+ return node
65
+ if not self.cdef_docstrings:
66
+ if isinstance(node, CFuncDefNode) and not node.py_func:
67
+ return node
68
+ if not self.all_docstrings and '>>>' not in node.doc:
69
+ return node
70
+
71
+ pos = self.testspos
72
+ if self.scope_type == 'module':
73
+ path = node.entry.name
74
+ elif self.scope_type in ('pyclass', 'cclass'):
75
+ if isinstance(node, CFuncDefNode):
76
+ if node.py_func is not None:
77
+ name = node.py_func.name
78
+ else:
79
+ name = node.entry.name
80
+ else:
81
+ name = node.name
82
+ if self.scope_type == 'cclass' and name in self.excludelist:
83
+ return node
84
+ if self.scope_type == 'pyclass':
85
+ class_name = self.scope_node.name
86
+ else:
87
+ class_name = self.scope_node.class_name
88
+ if isinstance(node.entry.scope, Symtab.PropertyScope):
89
+ property_method_name = node.entry.scope.name
90
+ path = "%s.%s.%s" % (class_name, node.entry.scope.name,
91
+ node.entry.name)
92
+ else:
93
+ path = "%s.%s" % (class_name, node.entry.name)
94
+ else:
95
+ assert False
96
+ self.add_test(node.pos, path, node.doc)
97
+ return node
@@ -0,0 +1,328 @@
1
+ # Note: Work in progress
2
+
3
+
4
+ import os
5
+ import os.path
6
+ import re
7
+ import textwrap
8
+ from datetime import datetime
9
+ from functools import partial
10
+ from collections import defaultdict
11
+ from xml.sax.saxutils import escape as html_escape
12
+ from io import StringIO
13
+
14
+ from . import Version
15
+ from .Code import CCodeWriter
16
+ from .. import Utils
17
+
18
+
19
+ class AnnotationCCodeWriter(CCodeWriter):
20
+
21
+ # also used as marker for detection of complete code emission in tests
22
+ COMPLETE_CODE_TITLE = "Complete cythonized code"
23
+
24
+ def __init__(self, create_from=None, buffer=None, copy_formatting=True, show_entire_c_code=False, source_desc=None):
25
+ CCodeWriter.__init__(self, create_from, buffer, copy_formatting=copy_formatting)
26
+ self.show_entire_c_code = show_entire_c_code
27
+ if create_from is None:
28
+ self.annotation_buffer = StringIO()
29
+ self.last_annotated_pos = None
30
+ # annotations[filename][line] -> [(column, AnnotationItem)*]
31
+ self.annotations = defaultdict(partial(defaultdict, list))
32
+ # code[filename][line] -> str
33
+ self.code = defaultdict(partial(defaultdict, str))
34
+ # scopes[filename][line] -> set(scopes)
35
+ self.scopes = defaultdict(partial(defaultdict, set))
36
+ else:
37
+ # When creating an insertion point, keep references to the same database
38
+ self.annotation_buffer = create_from.annotation_buffer
39
+ self.annotations = create_from.annotations
40
+ self.code = create_from.code
41
+ self.scopes = create_from.scopes
42
+ self.last_annotated_pos = create_from.last_annotated_pos
43
+
44
+ def create_new(self, create_from, buffer, copy_formatting):
45
+ return AnnotationCCodeWriter(create_from, buffer, copy_formatting)
46
+
47
+ def _write_to_buffer(self, s):
48
+ self.buffer.write(s)
49
+ self.annotation_buffer.write(s)
50
+
51
+ def mark_pos(self, pos, trace=True):
52
+ if pos is not None:
53
+ CCodeWriter.mark_pos(self, pos, trace)
54
+ if self.funcstate and self.funcstate.scope:
55
+ # lambdas and genexprs can result in multiple scopes per line => keep them in a set
56
+ self.scopes[pos[0].filename][pos[1]].add(self.funcstate.scope)
57
+ if self.last_annotated_pos:
58
+ source_desc, line, _ = self.last_annotated_pos
59
+ pos_code = self.code[source_desc.filename]
60
+ pos_code[line] += self.annotation_buffer.getvalue()
61
+ self.annotation_buffer = StringIO()
62
+ self.last_annotated_pos = pos
63
+
64
+ def annotate(self, pos, item):
65
+ self.annotations[pos[0].filename][pos[1]].append((pos[2], item))
66
+
67
+ def _css(self):
68
+ """css template will later allow to choose a colormap"""
69
+ css = [self._css_template]
70
+ for i in range(255):
71
+ color_shade = int(255.0 // (1.0 + i/10.0))
72
+ css.append(f'.cython.score-{i:d} {{background-color: #FFFF{color_shade:02x};}}')
73
+ try:
74
+ from pygments.formatters import HtmlFormatter
75
+ except ImportError:
76
+ pass
77
+ else:
78
+ css.append(HtmlFormatter().get_style_defs('.cython'))
79
+ return '\n'.join(css)
80
+
81
+ _css_template = textwrap.dedent("""
82
+ body.cython { font-family: courier; font-size: 12; }
83
+
84
+ .cython.tag { }
85
+ .cython.line { color: #000000; margin: 0em }
86
+ .cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 8px; border-left: 8px none; }
87
+
88
+ .cython.line .run { background-color: #B0FFB0; }
89
+ .cython.line .mis { background-color: #FFB0B0; }
90
+ .cython.code.run { border-left: 8px solid #B0FFB0; }
91
+ .cython.code.mis { border-left: 8px solid #FFB0B0; }
92
+
93
+ .cython.code .py_c_api { color: red; }
94
+ .cython.code .py_macro_api { color: #FF7000; }
95
+ .cython.code .pyx_c_api { color: #FF3000; }
96
+ .cython.code .pyx_macro_api { color: #FF7000; }
97
+ .cython.code .refnanny { color: #FFA000; }
98
+ .cython.code .trace { color: #FFA000; }
99
+ .cython.code .error_goto { color: #FFA000; }
100
+
101
+ .cython.code .coerce { color: #008000; border: 1px dotted #008000 }
102
+ .cython.code .py_attr { color: #FF0000; font-weight: bold; }
103
+ .cython.code .c_attr { color: #0000FF; }
104
+ .cython.code .py_call { color: #FF0000; font-weight: bold; }
105
+ .cython.code .c_call { color: #0000FF; }
106
+ """)
107
+
108
+ # on-click toggle function to show/hide C source code
109
+ _onclick_attr = ' onclick="{}"'.format((
110
+ # Use local JS variables by declaring them as function arguments.
111
+ "(function(f, s, c) {"
112
+ " c = f.nodeValue == '+';"
113
+ " s.display = c ? 'block' : 'none';"
114
+ " f.nodeValue = c ? '−' : '+'"
115
+ "})(this.firstChild, this.nextElementSibling.style)"
116
+ ).replace(' ', '') # poor dev's JS minification
117
+ )
118
+
119
+ def save_annotation(self, source_filename, target_filename, coverage_xml=None):
120
+ with Utils.open_source_file(source_filename) as f:
121
+ code = f.read()
122
+ generated_code = self.code.get(source_filename, {})
123
+ c_file = Utils.decode_filename(os.path.basename(target_filename))
124
+ html_filename = os.path.splitext(target_filename)[0] + ".html"
125
+
126
+ with open(html_filename, "w", encoding="UTF-8") as out_buffer:
127
+ out_buffer.write(self._save_annotation(code, generated_code, c_file, source_filename, coverage_xml))
128
+
129
+ def _save_annotation_header(self, c_file, source_filename, coverage_timestamp=None):
130
+ coverage_info = ''
131
+ if coverage_timestamp:
132
+ coverage_info = ' with coverage data from {timestamp}'.format(
133
+ timestamp=datetime.fromtimestamp(int(coverage_timestamp) // 1000))
134
+
135
+ outlist = [
136
+ textwrap.dedent('''\
137
+ <!DOCTYPE html>
138
+ <!-- Generated by Cython {watermark} -->
139
+ <html>
140
+ <head>
141
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
142
+ <title>Cython: {filename}</title>
143
+ <style type="text/css">
144
+ {css}
145
+ </style>
146
+ </head>
147
+ <body class="cython">
148
+ <p><span style="border-bottom: solid 1px grey;">Generated by Cython {watermark}</span>{more_info}</p>
149
+ <p>
150
+ <span style="background-color: #FFFF00">Yellow lines</span> hint at Python interaction.<br />
151
+ Click on a line that starts with a "<code>+</code>" to see the C code that Cython generated for it.
152
+ </p>
153
+ ''').format(css=self._css(), watermark=Version.watermark,
154
+ filename=os.path.basename(source_filename) if source_filename else '',
155
+ more_info=coverage_info)
156
+ ]
157
+ if c_file:
158
+ outlist.append('<p>Raw output: <a href="%s">%s</a></p>\n' % (c_file, c_file))
159
+ return outlist
160
+
161
+ def _save_annotation_footer(self):
162
+ return ('</body></html>\n',)
163
+
164
+ def _save_annotation(self, code, generated_code, c_file=None, source_filename=None, coverage_xml=None):
165
+ """
166
+ lines : original cython source code split by lines
167
+ generated_code : generated c code keyed by line number in original file
168
+ target filename : name of the file in which to store the generated html
169
+ c_file : filename in which the c_code has been written
170
+ """
171
+ if coverage_xml is not None and source_filename:
172
+ coverage_timestamp = coverage_xml.get('timestamp', '').strip()
173
+ covered_lines = self._get_line_coverage(coverage_xml, source_filename)
174
+ else:
175
+ coverage_timestamp = covered_lines = None
176
+ annotation_items = dict(self.annotations[source_filename])
177
+ scopes = dict(self.scopes[source_filename])
178
+
179
+ outlist = []
180
+ outlist.extend(self._save_annotation_header(c_file, source_filename, coverage_timestamp))
181
+ outlist.extend(self._save_annotation_body(code, generated_code, annotation_items, scopes, covered_lines))
182
+ outlist.extend(self._save_annotation_footer())
183
+ return ''.join(outlist)
184
+
185
+ def _get_line_coverage(self, coverage_xml, source_filename):
186
+ coverage_data = None
187
+ for entry in coverage_xml.iterfind('.//class'):
188
+ if not entry.get('filename'):
189
+ continue
190
+ if (entry.get('filename') == source_filename or
191
+ os.path.abspath(entry.get('filename')) == source_filename):
192
+ coverage_data = entry
193
+ break
194
+ elif source_filename.endswith(entry.get('filename')):
195
+ coverage_data = entry # but we might still find a better match...
196
+ if coverage_data is None:
197
+ return None
198
+ return {
199
+ int(line.get('number')): int(line.get('hits'))
200
+ for line in coverage_data.iterfind('lines/line')
201
+ }
202
+
203
+ def _htmlify_code(self, code, language):
204
+ try:
205
+ from pygments import highlight
206
+ from pygments.lexers import CythonLexer, CppLexer
207
+ from pygments.formatters import HtmlFormatter
208
+ except ImportError:
209
+ # no Pygments, just escape the code
210
+ return html_escape(code)
211
+
212
+ if language == "cython":
213
+ lexer = CythonLexer(stripnl=False, stripall=False)
214
+ elif language == "c/cpp":
215
+ lexer = CppLexer(stripnl=False, stripall=False)
216
+ else:
217
+ # unknown language, use fallback
218
+ return html_escape(code)
219
+ html_code = highlight(
220
+ code, lexer,
221
+ HtmlFormatter(nowrap=True))
222
+ return html_code
223
+
224
+ def _save_annotation_body(self, cython_code, generated_code, annotation_items, scopes, covered_lines=None):
225
+ outlist = ['<div class="cython">']
226
+ pos_comment_marker = '/* \N{HORIZONTAL ELLIPSIS} */\n'
227
+ new_calls_map = {
228
+ name: 0 for name in
229
+ 'refnanny trace py_macro_api py_c_api pyx_macro_api pyx_c_api error_goto'.split()
230
+ }.copy
231
+
232
+ self.mark_pos(None)
233
+
234
+ def annotate(match):
235
+ group_name = match.lastgroup
236
+ calls[group_name] += 1
237
+ return f"<span class='{group_name}'>{match.group(group_name)}</span>"
238
+
239
+ lines = self._htmlify_code(cython_code, "cython").splitlines()
240
+ lineno_width = len(str(len(lines)))
241
+ if not covered_lines:
242
+ covered_lines = None
243
+
244
+ for k, line in enumerate(lines, 1):
245
+ try:
246
+ c_code = generated_code[k]
247
+ except KeyError:
248
+ c_code = ''
249
+ else:
250
+ c_code = _replace_pos_comment(pos_comment_marker, c_code)
251
+ if c_code.startswith(pos_comment_marker):
252
+ c_code = c_code[len(pos_comment_marker):]
253
+ c_code = html_escape(c_code)
254
+
255
+ calls = new_calls_map()
256
+ c_code = _parse_code(annotate, c_code)
257
+ score = (5 * calls['py_c_api'] + 2 * calls['pyx_c_api'] +
258
+ calls['py_macro_api'] + calls['pyx_macro_api'])
259
+
260
+ if c_code:
261
+ onclick = self._onclick_attr
262
+ expandsymbol = '+'
263
+ else:
264
+ onclick = ''
265
+ expandsymbol = '&#xA0;'
266
+
267
+ covered = ''
268
+ if covered_lines is not None and k in covered_lines:
269
+ hits = covered_lines[k]
270
+ if hits is not None:
271
+ covered = 'run' if hits else 'mis'
272
+
273
+ outlist.append(
274
+ f'<pre class="cython line score-{score}"{onclick}>'
275
+ # generate line number with expand symbol in front,
276
+ # and the right number of digit
277
+ f'{expandsymbol}<span class="{covered}">{k:0{lineno_width}d}</span>: {line.rstrip()}</pre>\n'
278
+ )
279
+ if c_code:
280
+ outlist.append(f"<pre class='cython code score-{score} {covered}'>{c_code}</pre>")
281
+ outlist.append("</div>")
282
+
283
+ # now the whole c-code if needed:
284
+ if self.show_entire_c_code:
285
+ complete_code_as_html = self._htmlify_code(self.buffer.getvalue(), "c/cpp")
286
+ outlist.append(
287
+ '<p><div class="cython">'
288
+ f"<pre class='cython line'{self._onclick_attr}>+ {AnnotationCCodeWriter.COMPLETE_CODE_TITLE}</pre>\n"
289
+ f"<pre class='cython code'>{complete_code_as_html}</pre>"
290
+ "</div></p>"
291
+ )
292
+
293
+ return outlist
294
+
295
+
296
+ _parse_code = re.compile((
297
+ br'(?P<refnanny>__Pyx_X?(?:GOT|GIVE)REF|__Pyx_RefNanny[A-Za-z]+)|'
298
+ br'(?P<trace>__Pyx_Trace[A-Za-z]+)|'
299
+ br'(?:'
300
+ br'(?P<pyx_macro_api>__Pyx_[A-Z][A-Z_]+)|'
301
+ br'(?P<pyx_c_api>(?:__Pyx_[A-Z][a-z_][A-Za-z_]*)|__pyx_convert_[A-Za-z_]*)|'
302
+ br'(?P<py_macro_api>Py[A-Z][a-z]+_[A-Z][A-Z_]+)|'
303
+ br'(?P<py_c_api>Py[A-Z][a-z]+_[A-Z][a-z][A-Za-z_]*)'
304
+ br')(?=\()|' # look-ahead to exclude subsequent '(' from replacement
305
+ br'(?P<error_goto>(?:(?<=;) *if [^;]* +)?__PYX_ERR\([^)]+\))'
306
+ ).decode('ascii')).sub
307
+
308
+
309
+ _replace_pos_comment = re.compile(
310
+ # this matches what Cython generates as code line marker comment
311
+ br'^\s*/\*(?:(?:[^*]|\*[^/])*\n)+\s*\*/\s*\n'.decode('ascii'),
312
+ re.M
313
+ ).sub
314
+
315
+
316
+ class AnnotationItem:
317
+
318
+ def __init__(self, style, text, tag="", size=0):
319
+ self.style = style
320
+ self.text = text
321
+ self.tag = tag
322
+ self.size = size
323
+
324
+ def start(self):
325
+ return "<span class='cython tag %s' title='%s'>%s" % (self.style, self.text, self.tag)
326
+
327
+ def end(self):
328
+ return self.size, "</span>"