Cython 3.2.0__cp39-abi3-win32.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 (333) hide show
  1. Cython/Build/BuildExecutable.py +169 -0
  2. Cython/Build/Cache.py +199 -0
  3. Cython/Build/Cythonize.py +350 -0
  4. Cython/Build/Dependencies.py +1314 -0
  5. Cython/Build/Distutils.py +1 -0
  6. Cython/Build/Inline.py +463 -0
  7. Cython/Build/IpythonMagic.py +560 -0
  8. Cython/Build/SharedModule.py +94 -0
  9. Cython/Build/Tests/TestCyCache.py +194 -0
  10. Cython/Build/Tests/TestCythonizeArgsParser.py +481 -0
  11. Cython/Build/Tests/TestDependencies.py +133 -0
  12. Cython/Build/Tests/TestInline.py +177 -0
  13. Cython/Build/Tests/TestIpythonMagic.py +287 -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 +984 -0
  24. Cython/Compiler/CmdLine.py +263 -0
  25. Cython/Compiler/Code.pxd +149 -0
  26. Cython/Compiler/Code.py +3746 -0
  27. Cython/Compiler/Code.pyd +0 -0
  28. Cython/Compiler/CodeGeneration.py +33 -0
  29. Cython/Compiler/CythonScope.py +191 -0
  30. Cython/Compiler/Dataclass.py +864 -0
  31. Cython/Compiler/DebugFlags.py +24 -0
  32. Cython/Compiler/Errors.py +297 -0
  33. Cython/Compiler/ExprNodes.py +15562 -0
  34. Cython/Compiler/FlowControl.pxd +97 -0
  35. Cython/Compiler/FlowControl.py +1451 -0
  36. Cython/Compiler/FlowControl.pyd +0 -0
  37. Cython/Compiler/FusedNode.py +971 -0
  38. Cython/Compiler/FusedNode.pyd +0 -0
  39. Cython/Compiler/Future.py +16 -0
  40. Cython/Compiler/Interpreter.py +57 -0
  41. Cython/Compiler/Lexicon.py +421 -0
  42. Cython/Compiler/LineTable.py +114 -0
  43. Cython/Compiler/LineTable.pyd +0 -0
  44. Cython/Compiler/Main.py +857 -0
  45. Cython/Compiler/MatchCaseNodes.py +259 -0
  46. Cython/Compiler/MemoryView.py +905 -0
  47. Cython/Compiler/ModuleNode.py +4235 -0
  48. Cython/Compiler/Naming.py +363 -0
  49. Cython/Compiler/Nodes.py +10831 -0
  50. Cython/Compiler/Optimize.py +5288 -0
  51. Cython/Compiler/Options.py +843 -0
  52. Cython/Compiler/ParseTreeTransforms.pxd +78 -0
  53. Cython/Compiler/ParseTreeTransforms.py +4638 -0
  54. Cython/Compiler/Parsing.pxd +9 -0
  55. Cython/Compiler/Parsing.py +4775 -0
  56. Cython/Compiler/Parsing.pyd +0 -0
  57. Cython/Compiler/Pipeline.py +439 -0
  58. Cython/Compiler/PyrexTypes.py +5870 -0
  59. Cython/Compiler/Pythran.py +232 -0
  60. Cython/Compiler/Scanning.pxd +48 -0
  61. Cython/Compiler/Scanning.py +701 -0
  62. Cython/Compiler/Scanning.pyd +0 -0
  63. Cython/Compiler/StringEncoding.py +298 -0
  64. Cython/Compiler/Symtab.py +3073 -0
  65. Cython/Compiler/Tests/TestBuffer.py +105 -0
  66. Cython/Compiler/Tests/TestBuiltin.py +72 -0
  67. Cython/Compiler/Tests/TestCmdLine.py +586 -0
  68. Cython/Compiler/Tests/TestCode.py +144 -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 +134 -0
  74. Cython/Compiler/Tests/TestSignatureMatching.py +73 -0
  75. Cython/Compiler/Tests/TestStringEncoding.py +21 -0
  76. Cython/Compiler/Tests/TestTreeFragment.py +63 -0
  77. Cython/Compiler/Tests/TestTreePath.py +103 -0
  78. Cython/Compiler/Tests/TestTypes.py +75 -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 +591 -0
  86. Cython/Compiler/TypeSlots.py +1174 -0
  87. Cython/Compiler/UFuncs.py +311 -0
  88. Cython/Compiler/UtilNodes.py +389 -0
  89. Cython/Compiler/UtilityCode.py +344 -0
  90. Cython/Compiler/Version.py +8 -0
  91. Cython/Compiler/Visitor.pxd +53 -0
  92. Cython/Compiler/Visitor.py +861 -0
  93. Cython/Compiler/Visitor.pyd +0 -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 +275 -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 +578 -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 +178 -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 +187 -0
  127. Cython/Includes/cpython/exc.pxd +263 -0
  128. Cython/Includes/cpython/fileobject.pxd +57 -0
  129. Cython/Includes/cpython/float.pxd +47 -0
  130. Cython/Includes/cpython/function.pxd +65 -0
  131. Cython/Includes/cpython/genobject.pxd +25 -0
  132. Cython/Includes/cpython/getargs.pxd +12 -0
  133. Cython/Includes/cpython/instance.pxd +25 -0
  134. Cython/Includes/cpython/iterator.pxd +36 -0
  135. Cython/Includes/cpython/iterobject.pxd +24 -0
  136. Cython/Includes/cpython/list.pxd +92 -0
  137. Cython/Includes/cpython/long.pxd +149 -0
  138. Cython/Includes/cpython/longintrepr.pxd +14 -0
  139. Cython/Includes/cpython/mapping.pxd +63 -0
  140. Cython/Includes/cpython/marshal.pxd +66 -0
  141. Cython/Includes/cpython/mem.pxd +120 -0
  142. Cython/Includes/cpython/memoryview.pxd +50 -0
  143. Cython/Includes/cpython/method.pxd +49 -0
  144. Cython/Includes/cpython/module.pxd +208 -0
  145. Cython/Includes/cpython/number.pxd +258 -0
  146. Cython/Includes/cpython/object.pxd +433 -0
  147. Cython/Includes/cpython/pycapsule.pxd +143 -0
  148. Cython/Includes/cpython/pylifecycle.pxd +68 -0
  149. Cython/Includes/cpython/pyport.pxd +8 -0
  150. Cython/Includes/cpython/pystate.pxd +95 -0
  151. Cython/Includes/cpython/pythread.pxd +53 -0
  152. Cython/Includes/cpython/ref.pxd +141 -0
  153. Cython/Includes/cpython/sequence.pxd +134 -0
  154. Cython/Includes/cpython/set.pxd +119 -0
  155. Cython/Includes/cpython/slice.pxd +70 -0
  156. Cython/Includes/cpython/time.pxd +129 -0
  157. Cython/Includes/cpython/tuple.pxd +72 -0
  158. Cython/Includes/cpython/type.pxd +53 -0
  159. Cython/Includes/cpython/unicode.pxd +639 -0
  160. Cython/Includes/cpython/version.pxd +32 -0
  161. Cython/Includes/cpython/weakref.pxd +78 -0
  162. Cython/Includes/libc/__init__.pxd +1 -0
  163. Cython/Includes/libc/complex.pxd +35 -0
  164. Cython/Includes/libc/errno.pxd +127 -0
  165. Cython/Includes/libc/float.pxd +43 -0
  166. Cython/Includes/libc/limits.pxd +28 -0
  167. Cython/Includes/libc/locale.pxd +46 -0
  168. Cython/Includes/libc/math.pxd +209 -0
  169. Cython/Includes/libc/setjmp.pxd +10 -0
  170. Cython/Includes/libc/signal.pxd +64 -0
  171. Cython/Includes/libc/stddef.pxd +9 -0
  172. Cython/Includes/libc/stdint.pxd +105 -0
  173. Cython/Includes/libc/stdio.pxd +80 -0
  174. Cython/Includes/libc/stdlib.pxd +72 -0
  175. Cython/Includes/libc/string.pxd +50 -0
  176. Cython/Includes/libc/threads.pxd +234 -0
  177. Cython/Includes/libc/time.pxd +52 -0
  178. Cython/Includes/libcpp/__init__.pxd +4 -0
  179. Cython/Includes/libcpp/algorithm.pxd +320 -0
  180. Cython/Includes/libcpp/any.pxd +16 -0
  181. Cython/Includes/libcpp/atomic.pxd +59 -0
  182. Cython/Includes/libcpp/barrier.pxd +22 -0
  183. Cython/Includes/libcpp/bit.pxd +29 -0
  184. Cython/Includes/libcpp/cast.pxd +12 -0
  185. Cython/Includes/libcpp/cmath.pxd +518 -0
  186. Cython/Includes/libcpp/complex.pxd +106 -0
  187. Cython/Includes/libcpp/condition_variable.pxd +322 -0
  188. Cython/Includes/libcpp/deque.pxd +165 -0
  189. Cython/Includes/libcpp/exception.pxd +86 -0
  190. Cython/Includes/libcpp/execution.pxd +15 -0
  191. Cython/Includes/libcpp/forward_list.pxd +63 -0
  192. Cython/Includes/libcpp/functional.pxd +26 -0
  193. Cython/Includes/libcpp/future.pxd +103 -0
  194. Cython/Includes/libcpp/iterator.pxd +34 -0
  195. Cython/Includes/libcpp/latch.pxd +17 -0
  196. Cython/Includes/libcpp/limits.pxd +61 -0
  197. Cython/Includes/libcpp/list.pxd +117 -0
  198. Cython/Includes/libcpp/map.pxd +252 -0
  199. Cython/Includes/libcpp/memory.pxd +115 -0
  200. Cython/Includes/libcpp/mutex.pxd +387 -0
  201. Cython/Includes/libcpp/numbers.pxd +15 -0
  202. Cython/Includes/libcpp/numeric.pxd +131 -0
  203. Cython/Includes/libcpp/optional.pxd +34 -0
  204. Cython/Includes/libcpp/pair.pxd +1 -0
  205. Cython/Includes/libcpp/queue.pxd +25 -0
  206. Cython/Includes/libcpp/random.pxd +166 -0
  207. Cython/Includes/libcpp/semaphore.pxd +43 -0
  208. Cython/Includes/libcpp/set.pxd +228 -0
  209. Cython/Includes/libcpp/shared_mutex.pxd +96 -0
  210. Cython/Includes/libcpp/span.pxd +87 -0
  211. Cython/Includes/libcpp/stack.pxd +11 -0
  212. Cython/Includes/libcpp/stop_token.pxd +117 -0
  213. Cython/Includes/libcpp/string.pxd +355 -0
  214. Cython/Includes/libcpp/string_view.pxd +183 -0
  215. Cython/Includes/libcpp/typeindex.pxd +15 -0
  216. Cython/Includes/libcpp/typeinfo.pxd +10 -0
  217. Cython/Includes/libcpp/unordered_map.pxd +193 -0
  218. Cython/Includes/libcpp/unordered_set.pxd +152 -0
  219. Cython/Includes/libcpp/utility.pxd +30 -0
  220. Cython/Includes/libcpp/vector.pxd +186 -0
  221. Cython/Includes/numpy/math.pxd +150 -0
  222. Cython/Includes/openmp.pxd +50 -0
  223. Cython/Includes/posix/__init__.pxd +1 -0
  224. Cython/Includes/posix/dlfcn.pxd +14 -0
  225. Cython/Includes/posix/fcntl.pxd +86 -0
  226. Cython/Includes/posix/ioctl.pxd +4 -0
  227. Cython/Includes/posix/mman.pxd +101 -0
  228. Cython/Includes/posix/resource.pxd +57 -0
  229. Cython/Includes/posix/select.pxd +21 -0
  230. Cython/Includes/posix/signal.pxd +73 -0
  231. Cython/Includes/posix/stat.pxd +98 -0
  232. Cython/Includes/posix/stdio.pxd +37 -0
  233. Cython/Includes/posix/stdlib.pxd +29 -0
  234. Cython/Includes/posix/strings.pxd +9 -0
  235. Cython/Includes/posix/time.pxd +71 -0
  236. Cython/Includes/posix/types.pxd +30 -0
  237. Cython/Includes/posix/uio.pxd +26 -0
  238. Cython/Includes/posix/unistd.pxd +271 -0
  239. Cython/Includes/posix/wait.pxd +38 -0
  240. Cython/Plex/Actions.pxd +24 -0
  241. Cython/Plex/Actions.py +119 -0
  242. Cython/Plex/Actions.pyd +0 -0
  243. Cython/Plex/DFA.pxd +14 -0
  244. Cython/Plex/DFA.py +164 -0
  245. Cython/Plex/DFA.pyd +0 -0
  246. Cython/Plex/Errors.py +48 -0
  247. Cython/Plex/Lexicons.py +178 -0
  248. Cython/Plex/Machines.pxd +36 -0
  249. Cython/Plex/Machines.py +238 -0
  250. Cython/Plex/Machines.pyd +0 -0
  251. Cython/Plex/Regexps.py +535 -0
  252. Cython/Plex/Scanners.pxd +45 -0
  253. Cython/Plex/Scanners.py +328 -0
  254. Cython/Plex/Scanners.pyd +0 -0
  255. Cython/Plex/Transitions.pxd +14 -0
  256. Cython/Plex/Transitions.py +239 -0
  257. Cython/Plex/Transitions.pyd +0 -0
  258. Cython/Plex/__init__.py +34 -0
  259. Cython/Runtime/__init__.py +1 -0
  260. Cython/Runtime/refnanny.pyd +0 -0
  261. Cython/Runtime/refnanny.pyx +237 -0
  262. Cython/Shadow.py +690 -0
  263. Cython/Shadow.pyi +521 -0
  264. Cython/StringIOTree.py +170 -0
  265. Cython/StringIOTree.pyd +0 -0
  266. Cython/Tempita/__init__.py +4 -0
  267. Cython/Tempita/_looper.py +154 -0
  268. Cython/Tempita/_tempita.py +1091 -0
  269. Cython/Tempita/_tempita.pyd +0 -0
  270. Cython/TestUtils.py +422 -0
  271. Cython/Tests/TestCodeWriter.py +128 -0
  272. Cython/Tests/TestCythonUtils.py +202 -0
  273. Cython/Tests/TestJediTyper.py +223 -0
  274. Cython/Tests/TestShadow.py +114 -0
  275. Cython/Tests/TestStringIOTree.py +67 -0
  276. Cython/Tests/TestTestUtils.py +90 -0
  277. Cython/Tests/__init__.py +1 -0
  278. Cython/Tests/xmlrunner.py +390 -0
  279. Cython/Utility/AsyncGen.c +1031 -0
  280. Cython/Utility/Buffer.c +865 -0
  281. Cython/Utility/BufferFormatFromTypeInfo.pxd +2 -0
  282. Cython/Utility/Builtins.c +810 -0
  283. Cython/Utility/CConvert.pyx +134 -0
  284. Cython/Utility/CMath.c +104 -0
  285. Cython/Utility/CommonStructures.c +226 -0
  286. Cython/Utility/Complex.c +378 -0
  287. Cython/Utility/Coroutine.c +2300 -0
  288. Cython/Utility/CpdefEnums.pyx +103 -0
  289. Cython/Utility/CppConvert.pyx +282 -0
  290. Cython/Utility/CppSupport.cpp +151 -0
  291. Cython/Utility/CythonFunction.c +1832 -0
  292. Cython/Utility/Dataclasses.c +101 -0
  293. Cython/Utility/Embed.c +121 -0
  294. Cython/Utility/Exceptions.c +1016 -0
  295. Cython/Utility/ExtensionTypes.c +996 -0
  296. Cython/Utility/FunctionArguments.c +1043 -0
  297. Cython/Utility/FusedFunction.pyx +44 -0
  298. Cython/Utility/ImportExport.c +907 -0
  299. Cython/Utility/MemoryView.pxd +188 -0
  300. Cython/Utility/MemoryView.pyx +1482 -0
  301. Cython/Utility/MemoryView_C.c +927 -0
  302. Cython/Utility/ModuleSetupCode.c +3203 -0
  303. Cython/Utility/NumpyImportArray.c +46 -0
  304. Cython/Utility/ObjectHandling.c +3273 -0
  305. Cython/Utility/Optimize.c +1603 -0
  306. Cython/Utility/Overflow.c +384 -0
  307. Cython/Utility/Printing.c +86 -0
  308. Cython/Utility/Profile.c +732 -0
  309. Cython/Utility/StringTools.c +1379 -0
  310. Cython/Utility/Synchronization.c +399 -0
  311. Cython/Utility/TString.c +356 -0
  312. Cython/Utility/TestCyUtilityLoader.pyx +8 -0
  313. Cython/Utility/TestCythonScope.pyx +75 -0
  314. Cython/Utility/TestUtilityLoader.c +12 -0
  315. Cython/Utility/TypeConversion.c +1385 -0
  316. Cython/Utility/UFuncs.pyx +50 -0
  317. Cython/Utility/UFuncs_C.c +89 -0
  318. Cython/Utility/__init__.py +28 -0
  319. Cython/Utility/arrayarray.h +167 -0
  320. Cython/Utils.py +687 -0
  321. Cython/Utils.pyd +0 -0
  322. Cython/__init__.py +10 -0
  323. Cython/__init__.pyi +7 -0
  324. Cython/py.typed +0 -0
  325. cython-3.2.0.dist-info/METADATA +85 -0
  326. cython-3.2.0.dist-info/RECORD +333 -0
  327. cython-3.2.0.dist-info/WHEEL +5 -0
  328. cython-3.2.0.dist-info/entry_points.txt +4 -0
  329. cython-3.2.0.dist-info/top_level.txt +3 -0
  330. cython.py +29 -0
  331. pyximport/__init__.py +4 -0
  332. pyximport/pyxbuild.py +160 -0
  333. pyximport/pyximport.py +482 -0
@@ -0,0 +1,1548 @@
1
+ """
2
+ GDB extension that adds Cython support.
3
+ """
4
+
5
+
6
+ import sys
7
+ import textwrap
8
+ import functools
9
+ import itertools
10
+ import collections
11
+
12
+ import gdb
13
+
14
+ try:
15
+ from lxml import etree
16
+ have_lxml = True
17
+ except ImportError:
18
+ from xml.etree import ElementTree as etree
19
+ have_lxml = False
20
+
21
+ try:
22
+ import pygments.lexers
23
+ import pygments.formatters
24
+ except ImportError:
25
+ pygments = None
26
+ sys.stderr.write("Install pygments for colorized source code.\n")
27
+
28
+ if hasattr(gdb, 'string_to_argv'):
29
+ from gdb import string_to_argv
30
+ else:
31
+ from shlex import split as string_to_argv
32
+
33
+ from Cython.Debugger import libpython
34
+
35
+ # C or Python type
36
+ CObject = 'CObject'
37
+ PythonObject = 'PythonObject'
38
+
39
+ _data_types = dict(CObject=CObject, PythonObject=PythonObject)
40
+ _filesystemencoding = sys.getfilesystemencoding() or 'UTF-8'
41
+
42
+
43
+ # decorators
44
+
45
+ def default_selected_gdb_frame(err=True):
46
+ def decorator(function):
47
+ @functools.wraps(function)
48
+ def wrapper(self, frame=None, *args, **kwargs):
49
+ try:
50
+ frame = frame or gdb.selected_frame()
51
+ except RuntimeError:
52
+ raise gdb.GdbError("No frame is currently selected.")
53
+
54
+ if err and frame.name() is None:
55
+ raise NoFunctionNameInFrameError()
56
+
57
+ return function(self, frame, *args, **kwargs)
58
+ return wrapper
59
+ return decorator
60
+
61
+
62
+ def require_cython_frame(function):
63
+ @functools.wraps(function)
64
+ @require_running_program
65
+ def wrapper(self, *args, **kwargs):
66
+ frame = kwargs.get('frame') or gdb.selected_frame()
67
+ if not self.is_cython_function(frame):
68
+ raise gdb.GdbError('Selected frame does not correspond with a '
69
+ 'Cython function we know about.')
70
+ return function(self, *args, **kwargs)
71
+ return wrapper
72
+
73
+
74
+ def dispatch_on_frame(c_command, python_command=None):
75
+ def decorator(function):
76
+ @functools.wraps(function)
77
+ def wrapper(self, *args, **kwargs):
78
+ is_cy = self.is_cython_function()
79
+ is_py = self.is_python_function()
80
+
81
+ if is_cy or (is_py and not python_command):
82
+ function(self, *args, **kwargs)
83
+ elif is_py:
84
+ gdb.execute(python_command)
85
+ elif self.is_relevant_function():
86
+ gdb.execute(c_command)
87
+ else:
88
+ raise gdb.GdbError("Not a function cygdb knows about. "
89
+ "Use the normal GDB commands instead.")
90
+
91
+ return wrapper
92
+ return decorator
93
+
94
+
95
+ def require_running_program(function):
96
+ @functools.wraps(function)
97
+ def wrapper(*args, **kwargs):
98
+ try:
99
+ gdb.selected_frame()
100
+ except RuntimeError:
101
+ raise gdb.GdbError("No frame is currently selected.")
102
+
103
+ return function(*args, **kwargs)
104
+ return wrapper
105
+
106
+
107
+ def gdb_function_value_to_unicode(function):
108
+ @functools.wraps(function)
109
+ def wrapper(self, string, *args, **kwargs):
110
+ if isinstance(string, gdb.Value):
111
+ string = string.string()
112
+
113
+ return function(self, string, *args, **kwargs)
114
+ return wrapper
115
+
116
+
117
+ # Classes that represent the debug information
118
+ # Don't rename the parameters of these classes, they come directly from the XML
119
+
120
+ def simple_repr(self, renamed=None, state=True):
121
+ """Prints out all instance variables needed to recreate an object.
122
+
123
+ Following the python convention for __repr__, this function prints all the
124
+ information stored in an instance as opposed to its class. The working
125
+ assumption is that most initialization arguments are stored as a property
126
+ using the same name.
127
+
128
+ The object contents are displayed as the initialization call followed by,
129
+ optionally, the value of each of the instance's properties in the form:
130
+ ```
131
+ ClassName(
132
+ init_arg_1 = "repr of some example str",
133
+ ...
134
+ )
135
+ self.state_based_property = ...
136
+ ```
137
+
138
+ Function arguments:
139
+ self Instance to be represented
140
+
141
+ renamed Dictionary of initialization arguments that are stored under a
142
+ different property name in the form { argument: property }
143
+
144
+ state Boolean representing whether properties outside the
145
+ initialization parameters should be printed (self.prop = ...).
146
+ Using `False` may make the class more amenable to recursive repr
147
+ """
148
+ import inspect
149
+ init_arg_names = tuple(inspect.signature(self.__init__).parameters)
150
+ init_attrs = [renamed.get(arg, arg) for arg in init_arg_names] \
151
+ if renamed else init_arg_names
152
+ state_repr = ()
153
+ if state:
154
+ instance_attrs = sorted(vars(self).keys())
155
+ state_repr = [attr for attr in instance_attrs if attr not in init_attrs]
156
+
157
+ def names_and_values(prefix, attrs, args=None):
158
+ for attr, arg in zip(attrs, args or attrs):
159
+ param = repr(getattr(self, attr)).replace("\n", "\n\t\t")
160
+ yield f'{prefix}{arg} = {param}'
161
+
162
+ return "".join([
163
+ self.__class__.__qualname__, "(",
164
+ ",".join(names_and_values("\n\t\t", init_attrs, init_arg_names)),
165
+ "\n\t)", *names_and_values("\nself.", state_repr)
166
+ ])
167
+
168
+
169
+ class CythonModule:
170
+ def __init__(self, module_name, filename, c_filename):
171
+ self.name = module_name
172
+ self.filename = filename
173
+ self.c_filename = c_filename
174
+ self.globals = {}
175
+ # {cython_lineno: min(c_linenos)}
176
+ self.lineno_cy2c = {}
177
+ # {c_lineno: cython_lineno}
178
+ self.lineno_c2cy = {}
179
+ self.functions = {}
180
+
181
+ def __repr__(self):
182
+ return simple_repr(self, renamed={"module_name": "name"}, state=False)
183
+
184
+
185
+ class CythonVariable:
186
+
187
+ def __init__(self, name, cname, qualified_name, type, lineno):
188
+ self.name = name
189
+ self.cname = cname
190
+ self.qualified_name = qualified_name
191
+ self.type = type
192
+ self.lineno = int(lineno)
193
+
194
+ def __repr__(self):
195
+ return simple_repr(self)
196
+
197
+
198
+ class CythonFunction(CythonVariable):
199
+ def __init__(self,
200
+ module,
201
+ name,
202
+ cname,
203
+ pf_cname,
204
+ qualified_name,
205
+ lineno,
206
+ type=CObject,
207
+ is_initmodule_function="False"):
208
+ super().__init__(name,
209
+ cname,
210
+ qualified_name,
211
+ type,
212
+ lineno)
213
+ self.module = module
214
+ self.pf_cname = pf_cname
215
+ self.is_initmodule_function = is_initmodule_function == "True"
216
+ self.locals = {}
217
+ self.arguments = []
218
+ self.step_into_functions = set()
219
+
220
+
221
+ # General purpose classes
222
+
223
+ frame_repr_whitelist = {
224
+ "Frame.is_valid",
225
+ "Frame.name",
226
+ "Frame.architecture",
227
+ "Frame.type",
228
+ "Frame.pc",
229
+ "Frame.block",
230
+ "Frame.function",
231
+ "Frame.older",
232
+ "Frame.newer",
233
+ "Frame.find_sal",
234
+ "Frame.select",
235
+ "Frame.static_link",
236
+ "Frame.level",
237
+ "Frame.language",
238
+ "Symbol.is_valid",
239
+ "Symbol.value",
240
+ "Symtab_and_line.is_valid",
241
+ "Symtab.is_valid",
242
+ "Symtab.fullname",
243
+ "Symtab.global_block",
244
+ "Symtab.static_block",
245
+ "Symtab.linetable",
246
+ }
247
+
248
+ def frame_repr(frame):
249
+ """Returns a string representing the internal state of a provided GDB frame
250
+ https://sourceware.org/gdb/current/onlinedocs/gdb.html/Frames-In-Python.html
251
+
252
+ Created to serve as GDB.Frame.__repr__ for debugging purposes. GDB has many
253
+ layers of abstraction separating the state of the debugger from the
254
+ corresponding source code. This prints a tree of instance properties,
255
+ expanding the values for Symtab_and_line, Symbol, and Symtab.
256
+
257
+ Most of these properties require computation to determine, meaning much of
258
+ relevant info is behind a monad, a subset of which are evaluated.
259
+
260
+ Arguments
261
+ frame The GDB.Frame instance to be represented as a string
262
+ """
263
+ res = f"{frame}\n"
264
+ for attribute in sorted(dir(frame)):
265
+ if attribute.startswith("__"):
266
+ continue
267
+ value = getattr(frame, attribute)
268
+ if callable(value) and value.__qualname__ in frame_repr_whitelist:
269
+ value = value()
270
+
271
+ if type(value) in [gdb.Symtab_and_line, gdb.Symbol, gdb.Symtab]:
272
+ # strip last line since it will get added on at the end of the loop
273
+ value = frame_repr(value).rstrip("\n").replace("\n", "\n\t")
274
+ res += f"{attribute}: " + (
275
+ f"{value:x}\n" if isinstance(value, int) and attribute != "line"
276
+ else f"{value}\n")
277
+ return res
278
+
279
+ class CythonBase:
280
+
281
+ @default_selected_gdb_frame(err=False)
282
+ def is_cython_function(self, frame):
283
+ return frame.name() in self.cy.functions_by_cname
284
+
285
+ @default_selected_gdb_frame(err=False)
286
+ def is_python_function(self, frame):
287
+ """
288
+ Tells if a frame is associated with a Python function.
289
+ If we can't read the Python frame information, don't regard it as such.
290
+ """
291
+ if frame.name() == 'PyEval_EvalFrameEx':
292
+ pyframe = libpython.Frame(frame).get_pyop()
293
+ return pyframe and not pyframe.is_optimized_out()
294
+ return False
295
+
296
+ @default_selected_gdb_frame()
297
+ def get_c_function_name(self, frame):
298
+ return frame.name()
299
+
300
+ @default_selected_gdb_frame()
301
+ def get_c_lineno(self, frame):
302
+ return frame.find_sal().line
303
+
304
+ @default_selected_gdb_frame()
305
+ def get_cython_function(self, frame):
306
+ result = self.cy.functions_by_cname.get(frame.name())
307
+ if result is None:
308
+ raise NoCythonFunctionInFrameError()
309
+
310
+ return result
311
+
312
+ @default_selected_gdb_frame()
313
+ def get_cython_lineno(self, frame):
314
+ """
315
+ Get the current Cython line number. Returns ("<no filename>", 0) if there is no
316
+ correspondence between the C and Cython code.
317
+ """
318
+ cyfunc = self.get_cython_function(frame)
319
+ return cyfunc.module.lineno_c2cy.get(self.get_c_lineno(frame), ("<no filename>", 0))
320
+
321
+ @default_selected_gdb_frame()
322
+ def get_source_desc(self, frame):
323
+ filename = lineno = lexer = None
324
+ if self.is_cython_function(frame):
325
+ filename = self.get_cython_function(frame).module.filename
326
+ filename_and_lineno = self.get_cython_lineno(frame)
327
+ assert filename == filename_and_lineno[0]
328
+ lineno = filename_and_lineno[1]
329
+ if pygments:
330
+ lexer = pygments.lexers.CythonLexer(stripall=False)
331
+ elif self.is_python_function(frame):
332
+ pyframeobject = libpython.Frame(frame).get_pyop()
333
+
334
+ if not pyframeobject:
335
+ raise gdb.GdbError(
336
+ 'Unable to read information on python frame')
337
+
338
+ filename = pyframeobject.filename()
339
+ lineno = pyframeobject.current_line_num()
340
+
341
+ if pygments:
342
+ lexer = pygments.lexers.PythonLexer(stripall=False)
343
+ else:
344
+ symbol_and_line_obj = frame.find_sal()
345
+ if not symbol_and_line_obj or not symbol_and_line_obj.symtab:
346
+ filename = None
347
+ lineno = 0
348
+ else:
349
+ filename = symbol_and_line_obj.symtab.fullname()
350
+ lineno = symbol_and_line_obj.line
351
+ if pygments:
352
+ lexer = pygments.lexers.CLexer(stripall=False)
353
+
354
+ return SourceFileDescriptor(filename, lexer), lineno
355
+
356
+ @default_selected_gdb_frame()
357
+ def get_source_line(self, frame):
358
+ source_desc, lineno = self.get_source_desc()
359
+ return source_desc.get_source(lineno)
360
+
361
+ @default_selected_gdb_frame()
362
+ def is_relevant_function(self, frame):
363
+ """
364
+ returns whether we care about a frame on the user-level when debugging
365
+ Cython code
366
+ """
367
+ name = frame.name()
368
+ older_frame = frame.older()
369
+ if self.is_cython_function(frame) or self.is_python_function(frame):
370
+ return True
371
+ elif older_frame and self.is_cython_function(older_frame):
372
+ # check for direct C function call from a Cython function
373
+ cython_func = self.get_cython_function(older_frame)
374
+ return name in cython_func.step_into_functions
375
+
376
+ return False
377
+
378
+ @default_selected_gdb_frame(err=False)
379
+ def print_stackframe(self, frame, index, is_c=False):
380
+ """
381
+ Print a C, Cython or Python stack frame and the line of source code
382
+ if available.
383
+ """
384
+ # do this to prevent the require_cython_frame decorator from
385
+ # raising GdbError when calling self.cy.cy_cvalue.invoke()
386
+ selected_frame = gdb.selected_frame()
387
+ frame.select()
388
+
389
+ try:
390
+ source_desc, lineno = self.get_source_desc(frame)
391
+ except NoFunctionNameInFrameError:
392
+ print('#%-2d Unknown Frame (compile with -g)' % index)
393
+ return
394
+
395
+ if not is_c and self.is_python_function(frame):
396
+ pyframe = libpython.Frame(frame).get_pyop()
397
+ if pyframe is None or pyframe.is_optimized_out():
398
+ # print this python function as a C function
399
+ return self.print_stackframe(frame, index, is_c=True)
400
+
401
+ func_name = pyframe.co_name
402
+ func_cname = 'PyEval_EvalFrameEx'
403
+ func_args = []
404
+ elif self.is_cython_function(frame):
405
+ cyfunc = self.get_cython_function(frame)
406
+ f = lambda arg: self.cy.cy_cvalue.invoke(arg, frame=frame)
407
+
408
+ func_name = cyfunc.name
409
+ func_cname = cyfunc.cname
410
+ func_args = [] # [(arg, f(arg)) for arg in cyfunc.arguments]
411
+ else:
412
+ source_desc, lineno = self.get_source_desc(frame)
413
+ func_name = frame.name()
414
+ func_cname = func_name
415
+ func_args = []
416
+
417
+ try:
418
+ gdb_value = gdb.parse_and_eval(func_cname)
419
+ except RuntimeError:
420
+ func_address = 0
421
+ else:
422
+ func_address = gdb_value.address
423
+ if not isinstance(func_address, int):
424
+ # Seriously? Why is the address not an int?
425
+ if not isinstance(func_address, (str, bytes)):
426
+ func_address = str(func_address)
427
+ func_address = int(func_address.split()[0], 0)
428
+
429
+ a = ', '.join('%s=%s' % (name, val) for name, val in func_args)
430
+ sys.stdout.write('#%-2d 0x%016x in %s(%s)' % (index, func_address, func_name, a))
431
+
432
+ if source_desc.filename is not None:
433
+ sys.stdout.write(' at %s:%s' % (source_desc.filename, lineno))
434
+
435
+ sys.stdout.write('\n')
436
+
437
+ try:
438
+ sys.stdout.write(f' {source_desc.get_source(lineno)}\n')
439
+ except gdb.GdbError:
440
+ pass
441
+
442
+ selected_frame.select()
443
+
444
+ def get_remote_cython_globals_dict(self):
445
+ m = gdb.parse_and_eval('__pyx_m')
446
+
447
+ try:
448
+ PyModuleObject = gdb.lookup_type('PyModuleObject')
449
+ except RuntimeError:
450
+ raise gdb.GdbError(textwrap.dedent("""\
451
+ Unable to lookup type PyModuleObject, did you compile python
452
+ with debugging support (-g)?"""))
453
+
454
+ m = m.cast(PyModuleObject.pointer())
455
+ return m['md_dict']
456
+
457
+
458
+ def get_cython_globals_dict(self):
459
+ """
460
+ Get the Cython globals dict where the remote names are turned into
461
+ local strings.
462
+ """
463
+ remote_dict = self.get_remote_cython_globals_dict()
464
+ pyobject_dict = libpython.PyObjectPtr.from_pyobject_ptr(remote_dict)
465
+
466
+ result = {}
467
+ seen = set()
468
+ for k, v in pyobject_dict.iteritems():
469
+ result[k.proxyval(seen)] = v
470
+
471
+ return result
472
+
473
+ def print_gdb_value(self, name, value, max_name_length=None, prefix=''):
474
+ if libpython.pretty_printer_lookup(value):
475
+ typename = ''
476
+ else:
477
+ typename = '(%s) ' % (value.type,)
478
+
479
+ if max_name_length is None:
480
+ print('%s%s = %s%s' % (prefix, name, typename, value))
481
+ else:
482
+ print('%s%-*s = %s%s' % (prefix, max_name_length, name, typename, value))
483
+
484
+ def is_initialized(self, cython_func, local_name):
485
+ cyvar = cython_func.locals[local_name]
486
+ cur_lineno = self.get_cython_lineno()[1]
487
+
488
+ if '->' in cyvar.cname:
489
+ # Closed over free variable
490
+ if cur_lineno > cython_func.lineno:
491
+ if cyvar.type == PythonObject:
492
+ return int(gdb.parse_and_eval(cyvar.cname))
493
+ return True
494
+ return False
495
+
496
+ return cur_lineno > cyvar.lineno
497
+
498
+
499
+ class SourceFileDescriptor:
500
+ def __init__(self, filename, lexer, formatter=None):
501
+ self.filename = filename
502
+ self.lexer = lexer
503
+ self.formatter = formatter
504
+
505
+ def valid(self):
506
+ return self.filename is not None
507
+
508
+ def lex(self, code):
509
+ if pygments and self.lexer and parameters.colorize_code:
510
+ bg = parameters.terminal_background.value
511
+ if self.formatter is None:
512
+ formatter = pygments.formatters.TerminalFormatter(bg=bg)
513
+ else:
514
+ formatter = self.formatter
515
+
516
+ return pygments.highlight(code, self.lexer, formatter)
517
+
518
+ return code
519
+
520
+ def _get_source(self, start, stop, lex_source, mark_line, lex_entire):
521
+ with open(self.filename) as f:
522
+ # to provide "correct" colouring, the entire code needs to be
523
+ # lexed. However, this makes a lot of things terribly slow, so
524
+ # we decide not to. Besides, it's unlikely to matter.
525
+
526
+ if lex_source and lex_entire:
527
+ f = self.lex(f.read()).splitlines()
528
+
529
+ slice = itertools.islice(f, start - 1, stop - 1)
530
+
531
+ for idx, line in enumerate(slice):
532
+ if start + idx == mark_line:
533
+ prefix = '>'
534
+ else:
535
+ prefix = ' '
536
+
537
+ if lex_source and not lex_entire:
538
+ line = self.lex(line)
539
+
540
+ yield '%s %4d %s' % (prefix, start + idx, line.rstrip())
541
+
542
+ def get_source(self, start, stop=None, lex_source=True, mark_line=0,
543
+ lex_entire=False):
544
+ exc = gdb.GdbError('Unable to retrieve source code')
545
+
546
+ if not self.filename:
547
+ raise exc
548
+
549
+ start = max(start, 1)
550
+ if stop is None:
551
+ stop = start + 1
552
+
553
+ try:
554
+ return '\n'.join(
555
+ self._get_source(start, stop, lex_source, mark_line, lex_entire))
556
+ except OSError:
557
+ raise exc
558
+
559
+
560
+ # Errors
561
+
562
+ class CyGDBError(gdb.GdbError):
563
+ """
564
+ Base class for Cython-command related errors
565
+ """
566
+
567
+ def __init__(self, *args):
568
+ args = args or (self.msg,)
569
+ super().__init__(*args)
570
+
571
+
572
+ class NoCythonFunctionInFrameError(CyGDBError):
573
+ """
574
+ raised when the user requests the current cython function, which is
575
+ unavailable
576
+ """
577
+ msg = "Current function is a function cygdb doesn't know about"
578
+
579
+
580
+ class NoFunctionNameInFrameError(NoCythonFunctionInFrameError):
581
+ """
582
+ raised when the name of the C function could not be determined
583
+ in the current C stack frame
584
+ """
585
+ msg = ('C function name could not be determined in the current C stack '
586
+ 'frame')
587
+
588
+
589
+ # Parameters
590
+
591
+ class CythonParameter(gdb.Parameter):
592
+ """
593
+ Base class for cython parameters
594
+ """
595
+
596
+ def __init__(self, name, command_class, parameter_class, default=None):
597
+ self.show_doc = self.set_doc = self.__class__.__doc__
598
+ super().__init__(name, command_class,
599
+ parameter_class)
600
+ if default is not None:
601
+ self.value = default
602
+
603
+ def __bool__(self):
604
+ return bool(self.value)
605
+
606
+ __nonzero__ = __bool__ # Python 2
607
+
608
+
609
+
610
+ class CompleteUnqualifiedFunctionNames(CythonParameter):
611
+ """
612
+ Have 'cy break' complete unqualified function or method names.
613
+ """
614
+
615
+
616
+ class ColorizeSourceCode(CythonParameter):
617
+ """
618
+ Tell cygdb whether to colorize source code.
619
+ """
620
+
621
+
622
+ class TerminalBackground(CythonParameter):
623
+ """
624
+ Tell cygdb about the user's terminal background (light or dark).
625
+ """
626
+
627
+
628
+ class CythonParameters:
629
+ """
630
+ Simple container class that might get more functionality in the distant
631
+ future (mostly to remind us that we're dealing with parameters).
632
+ """
633
+
634
+ def __init__(self):
635
+ self.complete_unqualified = CompleteUnqualifiedFunctionNames(
636
+ 'cy_complete_unqualified',
637
+ gdb.COMMAND_BREAKPOINTS,
638
+ gdb.PARAM_BOOLEAN,
639
+ True)
640
+ self.colorize_code = ColorizeSourceCode(
641
+ 'cy_colorize_code',
642
+ gdb.COMMAND_FILES,
643
+ gdb.PARAM_BOOLEAN,
644
+ True)
645
+ self.terminal_background = TerminalBackground(
646
+ 'cy_terminal_background_color',
647
+ gdb.COMMAND_FILES,
648
+ gdb.PARAM_STRING,
649
+ "dark")
650
+
651
+ parameters = CythonParameters()
652
+
653
+
654
+ # Commands
655
+
656
+ class CythonCommand(gdb.Command, CythonBase):
657
+ """
658
+ Base class for Cython commands
659
+ """
660
+
661
+ command_class = gdb.COMMAND_NONE
662
+
663
+ @classmethod
664
+ def _register(cls, clsname, args, kwargs):
665
+ if not hasattr(cls, 'completer_class'):
666
+ return cls(clsname, cls.command_class, *args, **kwargs)
667
+ else:
668
+ return cls(clsname, cls.command_class, cls.completer_class,
669
+ *args, **kwargs)
670
+
671
+ @classmethod
672
+ def register(cls, *args, **kwargs):
673
+ alias = getattr(cls, 'alias', None)
674
+ if alias:
675
+ cls._register(cls.alias, args, kwargs)
676
+
677
+ return cls._register(cls.name, args, kwargs)
678
+
679
+
680
+ class CyCy(CythonCommand):
681
+ """
682
+ Invoke a Cython command. Available commands are:
683
+
684
+ cy import
685
+ cy break
686
+ cy step
687
+ cy next
688
+ cy run
689
+ cy cont
690
+ cy finish
691
+ cy up
692
+ cy down
693
+ cy select
694
+ cy bt / cy backtrace
695
+ cy list
696
+ cy print
697
+ cy set
698
+ cy locals
699
+ cy globals
700
+ cy exec
701
+ """
702
+
703
+ name = 'cy'
704
+ command_class = gdb.COMMAND_NONE
705
+ completer_class = gdb.COMPLETE_COMMAND
706
+
707
+ def __init__(self, name, command_class, completer_class):
708
+ # keep the signature 2.5 compatible (i.e. do not use f(*a, k=v)
709
+ super(CythonCommand, self).__init__(name, command_class,
710
+ completer_class, prefix=True)
711
+
712
+ commands = dict(
713
+ # GDB commands
714
+ import_ = CyImport.register(),
715
+ break_ = CyBreak.register(),
716
+ step = CyStep.register(),
717
+ next = CyNext.register(),
718
+ run = CyRun.register(),
719
+ cont = CyCont.register(),
720
+ finish = CyFinish.register(),
721
+ up = CyUp.register(),
722
+ down = CyDown.register(),
723
+ select = CySelect.register(),
724
+ bt = CyBacktrace.register(),
725
+ list = CyList.register(),
726
+ print_ = CyPrint.register(),
727
+ locals = CyLocals.register(),
728
+ globals = CyGlobals.register(),
729
+ exec_ = libpython.FixGdbCommand('cy exec', '-cy-exec'),
730
+ _exec = CyExec.register(),
731
+ set = CySet.register(),
732
+
733
+ # GDB functions
734
+ cy_cname = CyCName('cy_cname'),
735
+ cy_cvalue = CyCValue('cy_cvalue'),
736
+ cy_lineno = CyLine('cy_lineno'),
737
+ cy_eval = CyEval('cy_eval'),
738
+ )
739
+
740
+ for command_name, command in commands.items():
741
+ command.cy = self
742
+ setattr(self, command_name, command)
743
+
744
+ self.cy = self
745
+
746
+ # Cython module namespace
747
+ self.cython_namespace = {}
748
+
749
+ # maps (unique) qualified function names (e.g.
750
+ # cythonmodule.ClassName.method_name) to the CythonFunction object
751
+ self.functions_by_qualified_name = {}
752
+
753
+ # unique cnames of Cython functions
754
+ self.functions_by_cname = {}
755
+
756
+ # map function names like method_name to a list of all such
757
+ # CythonFunction objects
758
+ self.functions_by_name = collections.defaultdict(list)
759
+
760
+
761
+ class CyImport(CythonCommand):
762
+ """
763
+ Import debug information outputted by the Cython compiler
764
+ Example: cy import FILE...
765
+ """
766
+
767
+ name = 'cy import'
768
+ command_class = gdb.COMMAND_STATUS
769
+ completer_class = gdb.COMPLETE_FILENAME
770
+
771
+ @libpython.dont_suppress_errors
772
+ def invoke(self, args, from_tty):
773
+ if isinstance(args, bytes):
774
+ args = args.decode(_filesystemencoding)
775
+ for arg in string_to_argv(args):
776
+ try:
777
+ f = open(arg)
778
+ except OSError as e:
779
+ raise gdb.GdbError('Unable to open file %r: %s' % (args, e.args[1]))
780
+
781
+ t = etree.parse(f)
782
+
783
+ for module in t.getroot():
784
+ cython_module = CythonModule(**module.attrib)
785
+ self.cy.cython_namespace[cython_module.name] = cython_module
786
+
787
+ for variable in module.find('Globals'):
788
+ d = variable.attrib
789
+ cython_module.globals[d['name']] = CythonVariable(**d)
790
+
791
+ for function in module.find('Functions'):
792
+ cython_function = CythonFunction(module=cython_module,
793
+ **function.attrib)
794
+
795
+ # update the global function mappings
796
+ name = cython_function.name
797
+ qname = cython_function.qualified_name
798
+
799
+ self.cy.functions_by_name[name].append(cython_function)
800
+ self.cy.functions_by_qualified_name[
801
+ cython_function.qualified_name] = cython_function
802
+ self.cy.functions_by_cname[
803
+ cython_function.cname] = cython_function
804
+
805
+ d = cython_module.functions[qname] = cython_function
806
+
807
+ for local in function.find('Locals'):
808
+ d = local.attrib
809
+ cython_function.locals[d['name']] = CythonVariable(**d)
810
+
811
+ for step_into_func in function.find('StepIntoFunctions'):
812
+ d = step_into_func.attrib
813
+ cython_function.step_into_functions.add(d['name'])
814
+
815
+ cython_function.arguments.extend(
816
+ funcarg.tag for funcarg in function.find('Arguments'))
817
+
818
+ for marker in module.find('LineNumberMapping'):
819
+ src_lineno = int(marker.attrib['src_lineno'])
820
+ src_path = marker.attrib['src_path']
821
+ c_linenos = list(map(int, marker.attrib['c_linenos'].split()))
822
+ cython_module.lineno_cy2c[src_path, src_lineno] = min(c_linenos)
823
+ for c_lineno in c_linenos:
824
+ cython_module.lineno_c2cy[c_lineno] = (src_path, src_lineno)
825
+
826
+
827
+ class CyBreak(CythonCommand):
828
+ """
829
+ Set a breakpoint for Cython code using Cython qualified name notation, e.g.:
830
+
831
+ cy break cython_modulename.ClassName.method_name...
832
+
833
+ or normal notation:
834
+
835
+ cy break function_or_method_name...
836
+
837
+ or for a line number:
838
+
839
+ cy break cython_module:lineno...
840
+
841
+ Set a Python breakpoint:
842
+ Break on any function or method named 'func' in module 'modname'
843
+
844
+ cy break -p modname.func...
845
+
846
+ Break on any function or method named 'func'
847
+
848
+ cy break -p func...
849
+ """
850
+
851
+ name = 'cy break'
852
+ command_class = gdb.COMMAND_BREAKPOINTS
853
+
854
+ def _break_pyx(self, name):
855
+ modulename, _, lineno = name.partition(':')
856
+ lineno = int(lineno)
857
+ if modulename:
858
+ cython_module = self.cy.cython_namespace[modulename]
859
+ else:
860
+ cython_module = self.get_cython_function().module
861
+
862
+ if (cython_module.filename, lineno) in cython_module.lineno_cy2c:
863
+ c_lineno = cython_module.lineno_cy2c[cython_module.filename, lineno]
864
+ breakpoint = '%s:%s' % (cython_module.c_filename, c_lineno)
865
+ gdb.execute('break ' + breakpoint)
866
+ else:
867
+ raise gdb.GdbError("Not a valid line number. "
868
+ "Does it contain actual code?")
869
+
870
+ def _break_funcname(self, funcname):
871
+ func = self.cy.functions_by_qualified_name.get(funcname)
872
+
873
+ if func and func.is_initmodule_function:
874
+ func = None
875
+
876
+ break_funcs = [func]
877
+
878
+ if not func:
879
+ funcs = self.cy.functions_by_name.get(funcname) or []
880
+ funcs = [f for f in funcs if not f.is_initmodule_function]
881
+
882
+ if not funcs:
883
+ gdb.execute('break ' + funcname)
884
+ return
885
+
886
+ if len(funcs) > 1:
887
+ # multiple functions, let the user pick one
888
+ print('There are multiple such functions:')
889
+ for idx, func in enumerate(funcs):
890
+ print('%3d) %s' % (idx, func.qualified_name))
891
+
892
+ while True:
893
+ try:
894
+ result = input(
895
+ "Select a function, press 'a' for all "
896
+ "functions or press 'q' or '^D' to quit: ")
897
+ except EOFError:
898
+ return
899
+ else:
900
+ if result.lower() == 'q':
901
+ return
902
+ elif result.lower() == 'a':
903
+ break_funcs = funcs
904
+ break
905
+ elif (result.isdigit() and
906
+ 0 <= int(result) < len(funcs)):
907
+ break_funcs = [funcs[int(result)]]
908
+ break
909
+ else:
910
+ print('Not understood...')
911
+ else:
912
+ break_funcs = [funcs[0]]
913
+
914
+ for func in break_funcs:
915
+ gdb.execute('break %s' % func.cname)
916
+ if func.pf_cname:
917
+ gdb.execute('break %s' % func.pf_cname)
918
+
919
+ @libpython.dont_suppress_errors
920
+ def invoke(self, function_names, from_tty):
921
+ if isinstance(function_names, bytes):
922
+ function_names = function_names.decode(_filesystemencoding)
923
+ argv = string_to_argv(function_names)
924
+ if function_names.startswith('-p'):
925
+ argv = argv[1:]
926
+ python_breakpoints = True
927
+ else:
928
+ python_breakpoints = False
929
+
930
+ for funcname in argv:
931
+ if python_breakpoints:
932
+ gdb.execute('py-break %s' % funcname)
933
+ elif ':' in funcname:
934
+ self._break_pyx(funcname)
935
+ else:
936
+ self._break_funcname(funcname)
937
+
938
+ @libpython.dont_suppress_errors
939
+ def complete(self, text, word):
940
+ # https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gdb/python/py-cmd.c;h=7143c1c5f7fdce9316a8c41fc2246bc6a07630d4;hb=HEAD#l140
941
+ word = word or ""
942
+ # Filter init-module functions (breakpoints can be set using
943
+ # modulename:linenumber).
944
+ names = [n for n, L in self.cy.functions_by_name.items()
945
+ if any(not f.is_initmodule_function for f in L)]
946
+ qnames = [n for n, f in self.cy.functions_by_qualified_name.items()
947
+ if not f.is_initmodule_function]
948
+
949
+ if parameters.complete_unqualified:
950
+ all_names = itertools.chain(qnames, names)
951
+ else:
952
+ all_names = qnames
953
+
954
+ words = text.strip().split()
955
+ if not words or '.' not in words[-1]:
956
+ # complete unqualified
957
+ seen = set(text[:-len(word)].split())
958
+ return [n for n in all_names
959
+ if n.startswith(word) and n not in seen]
960
+
961
+ # complete qualified name
962
+ lastword = words[-1]
963
+ compl = [n for n in qnames if n.startswith(lastword)]
964
+
965
+ if len(lastword) > len(word):
966
+ # readline sees something (e.g. a '.') as a word boundary, so don't
967
+ # "recomplete" this prefix
968
+ strip_prefix_length = len(lastword) - len(word)
969
+ compl = [n[strip_prefix_length:] for n in compl]
970
+
971
+ return compl
972
+
973
+
974
+ class CythonInfo(CythonBase, libpython.PythonInfo):
975
+ """
976
+ Implementation of the interface dictated by libpython.LanguageInfo.
977
+ """
978
+
979
+ def lineno(self, frame):
980
+ # Take care of the Python and Cython levels. We need to care for both
981
+ # as we can't simply dispatch to 'py-step', since that would work for
982
+ # stepping through Python code, but it would not step back into Cython-
983
+ # related code. The C level should be dispatched to the 'step' command.
984
+ if self.is_cython_function(frame):
985
+ return self.get_cython_lineno(frame)[1]
986
+ return super().lineno(frame)
987
+
988
+ def get_source_line(self, frame):
989
+ try:
990
+ line = super().get_source_line(frame)
991
+ except gdb.GdbError:
992
+ return None
993
+ else:
994
+ return line.strip() or None
995
+
996
+ def exc_info(self, frame):
997
+ if self.is_python_function:
998
+ return super().exc_info(frame)
999
+
1000
+ def runtime_break_functions(self):
1001
+ if self.is_cython_function():
1002
+ return self.get_cython_function().step_into_functions
1003
+ return ()
1004
+
1005
+ def static_break_functions(self):
1006
+ result = ['PyEval_EvalFrameEx']
1007
+ result.extend(self.cy.functions_by_cname)
1008
+ return result
1009
+
1010
+
1011
+ class CythonExecutionControlCommand(CythonCommand,
1012
+ libpython.ExecutionControlCommandBase):
1013
+
1014
+ @classmethod
1015
+ def register(cls):
1016
+ return cls(cls.name, cython_info)
1017
+
1018
+
1019
+ class CyStep(CythonExecutionControlCommand, libpython.PythonStepperMixin):
1020
+ "Step through Cython, Python or C code."
1021
+
1022
+ name = 'cy -step'
1023
+ stepinto = True
1024
+
1025
+ @libpython.dont_suppress_errors
1026
+ def invoke(self, args, from_tty):
1027
+ if self.is_python_function():
1028
+ self.python_step(self.stepinto)
1029
+ elif not self.is_cython_function():
1030
+ if self.stepinto:
1031
+ command = 'step'
1032
+ else:
1033
+ command = 'next'
1034
+
1035
+ self.finish_executing(gdb.execute(command, to_string=True))
1036
+ else:
1037
+ self.step(stepinto=self.stepinto)
1038
+
1039
+
1040
+ class CyNext(CyStep):
1041
+ "Step-over Cython, Python or C code."
1042
+
1043
+ name = 'cy -next'
1044
+ stepinto = False
1045
+
1046
+
1047
+ class CyRun(CythonExecutionControlCommand):
1048
+ """
1049
+ Run a Cython program. This is like the 'run' command, except that it
1050
+ displays Cython or Python source lines as well
1051
+ """
1052
+
1053
+ name = 'cy run'
1054
+
1055
+ invoke = libpython.dont_suppress_errors(CythonExecutionControlCommand.run)
1056
+
1057
+
1058
+ class CyCont(CythonExecutionControlCommand):
1059
+ """
1060
+ Continue a Cython program. This is like the 'run' command, except that it
1061
+ displays Cython or Python source lines as well.
1062
+ """
1063
+
1064
+ name = 'cy cont'
1065
+ invoke = libpython.dont_suppress_errors(CythonExecutionControlCommand.cont)
1066
+
1067
+
1068
+ class CyFinish(CythonExecutionControlCommand):
1069
+ """
1070
+ Execute until the function returns.
1071
+ """
1072
+ name = 'cy finish'
1073
+
1074
+ invoke = libpython.dont_suppress_errors(CythonExecutionControlCommand.finish)
1075
+
1076
+
1077
+ class CyUp(CythonCommand):
1078
+ """
1079
+ Go up a Cython, Python or relevant C frame.
1080
+ """
1081
+ name = 'cy up'
1082
+ _command = 'up'
1083
+
1084
+ @libpython.dont_suppress_errors
1085
+ def invoke(self, *args):
1086
+ try:
1087
+ gdb.execute(self._command, to_string=True)
1088
+ while not self.is_relevant_function(gdb.selected_frame()):
1089
+ gdb.execute(self._command, to_string=True)
1090
+ except RuntimeError as e:
1091
+ raise gdb.GdbError(*e.args)
1092
+
1093
+ frame = gdb.selected_frame()
1094
+ index = 0
1095
+ while frame:
1096
+ frame = frame.older()
1097
+ index += 1
1098
+
1099
+ self.print_stackframe(index=index - 1)
1100
+
1101
+
1102
+ class CyDown(CyUp):
1103
+ """
1104
+ Go down a Cython, Python or relevant C frame.
1105
+ """
1106
+
1107
+ name = 'cy down'
1108
+ _command = 'down'
1109
+
1110
+
1111
+ class CySelect(CythonCommand):
1112
+ """
1113
+ Select a frame. Use frame numbers as listed in `cy backtrace`.
1114
+ This command is useful because `cy backtrace` prints a reversed backtrace.
1115
+ """
1116
+
1117
+ name = 'cy select'
1118
+
1119
+ @libpython.dont_suppress_errors
1120
+ def invoke(self, stackno, from_tty):
1121
+ try:
1122
+ stackno = int(stackno)
1123
+ except ValueError:
1124
+ raise gdb.GdbError("Not a valid number: %r" % (stackno,))
1125
+
1126
+ frame = gdb.selected_frame()
1127
+ while frame.newer():
1128
+ frame = frame.newer()
1129
+
1130
+ stackdepth = libpython.stackdepth(frame)
1131
+
1132
+ try:
1133
+ gdb.execute('select %d' % (stackdepth - stackno - 1,))
1134
+ except RuntimeError as e:
1135
+ raise gdb.GdbError(*e.args)
1136
+
1137
+
1138
+ class CyBacktrace(CythonCommand):
1139
+ 'Print the Cython stack'
1140
+
1141
+ name = 'cy bt'
1142
+ alias = 'cy backtrace'
1143
+ command_class = gdb.COMMAND_STACK
1144
+ completer_class = gdb.COMPLETE_NONE
1145
+
1146
+ @libpython.dont_suppress_errors
1147
+ @require_running_program
1148
+ def invoke(self, args, from_tty):
1149
+ # get the first frame
1150
+ frame = gdb.selected_frame()
1151
+ while frame.older():
1152
+ frame = frame.older()
1153
+
1154
+ print_all = args == '-a'
1155
+
1156
+ index = 0
1157
+ while frame:
1158
+ try:
1159
+ is_relevant = self.is_relevant_function(frame)
1160
+ except CyGDBError:
1161
+ is_relevant = False
1162
+
1163
+ if print_all or is_relevant:
1164
+ self.print_stackframe(frame, index)
1165
+
1166
+ index += 1
1167
+ frame = frame.newer()
1168
+
1169
+
1170
+ class CyList(CythonCommand):
1171
+ """
1172
+ List Cython source code. To disable to customize colouring see the cy_*
1173
+ parameters.
1174
+ """
1175
+
1176
+ name = 'cy list'
1177
+ command_class = gdb.COMMAND_FILES
1178
+ completer_class = gdb.COMPLETE_NONE
1179
+
1180
+ @libpython.dont_suppress_errors
1181
+ # @dispatch_on_frame(c_command='list')
1182
+ def invoke(self, _, from_tty):
1183
+ sd, lineno = self.get_source_desc()
1184
+ source = sd.get_source(lineno - 5, lineno + 5, mark_line=lineno,
1185
+ lex_entire=True)
1186
+ print(source)
1187
+
1188
+
1189
+ class CyPrint(CythonCommand):
1190
+ """
1191
+ Print a Cython variable using 'cy-print x' or 'cy-print module.function.x'
1192
+ """
1193
+
1194
+ name = 'cy print'
1195
+ command_class = gdb.COMMAND_DATA
1196
+
1197
+ @libpython.dont_suppress_errors
1198
+ def invoke(self, name, from_tty):
1199
+ global_python_dict = self.get_cython_globals_dict()
1200
+ module_globals = self.get_cython_function().module.globals
1201
+
1202
+ if name in global_python_dict:
1203
+ value = global_python_dict[name].get_truncated_repr(libpython.MAX_OUTPUT_LEN)
1204
+ print('%s = %s' % (name, value))
1205
+ #This also would work, but because the output of cy exec is not captured in gdb.execute, TestPrint would fail
1206
+ #self.cy.exec_.invoke("print('"+name+"','=', type(" + name + "), "+name+", flush=True )", from_tty)
1207
+ elif name in module_globals:
1208
+ cname = module_globals[name].cname
1209
+ try:
1210
+ value = gdb.parse_and_eval(cname)
1211
+ except RuntimeError:
1212
+ print("unable to get value of %s" % name)
1213
+ else:
1214
+ if not value.is_optimized_out:
1215
+ self.print_gdb_value(name, value)
1216
+ else:
1217
+ print("%s is optimized out" % name)
1218
+ elif self.is_python_function():
1219
+ return gdb.execute('py-print ' + name)
1220
+ elif self.is_cython_function():
1221
+ value = self.cy.cy_cvalue.invoke(name.lstrip('*'))
1222
+ for c in name:
1223
+ if c == '*':
1224
+ value = value.dereference()
1225
+ else:
1226
+ break
1227
+
1228
+ self.print_gdb_value(name, value)
1229
+ else:
1230
+ gdb.execute('print ' + name)
1231
+
1232
+ def complete(self):
1233
+ if self.is_cython_function():
1234
+ f = self.get_cython_function()
1235
+ return list(itertools.chain(f.locals, f.globals))
1236
+ else:
1237
+ return []
1238
+
1239
+
1240
+ sortkey = lambda item: item[0].lower()
1241
+
1242
+
1243
+ class CyLocals(CythonCommand):
1244
+ """
1245
+ List the locals from the current Cython frame.
1246
+ """
1247
+
1248
+ name = 'cy locals'
1249
+ command_class = gdb.COMMAND_STACK
1250
+ completer_class = gdb.COMPLETE_NONE
1251
+
1252
+ @libpython.dont_suppress_errors
1253
+ @dispatch_on_frame(c_command='info locals', python_command='py-locals')
1254
+ def invoke(self, args, from_tty):
1255
+ cython_function = self.get_cython_function()
1256
+
1257
+ if cython_function.is_initmodule_function:
1258
+ self.cy.globals.invoke(args, from_tty)
1259
+ return
1260
+
1261
+ local_cython_vars = cython_function.locals
1262
+ max_name_length = len(max(local_cython_vars, key=len))
1263
+ for name, cyvar in sorted(local_cython_vars.items(), key=sortkey):
1264
+ if self.is_initialized(self.get_cython_function(), cyvar.name):
1265
+ value = gdb.parse_and_eval(cyvar.cname)
1266
+ if not value.is_optimized_out:
1267
+ self.print_gdb_value(cyvar.name, value,
1268
+ max_name_length, '')
1269
+
1270
+
1271
+ class CyGlobals(CyLocals):
1272
+ """
1273
+ List the globals from the current Cython module.
1274
+ """
1275
+
1276
+ name = 'cy globals'
1277
+ command_class = gdb.COMMAND_STACK
1278
+ completer_class = gdb.COMPLETE_NONE
1279
+
1280
+ @libpython.dont_suppress_errors
1281
+ @dispatch_on_frame(c_command='info variables', python_command='py-globals')
1282
+ def invoke(self, args, from_tty):
1283
+ global_python_dict = self.get_cython_globals_dict()
1284
+ module_globals = self.get_cython_function().module.globals
1285
+
1286
+ max_globals_len = 0
1287
+ max_globals_dict_len = 0
1288
+ if module_globals:
1289
+ max_globals_len = len(max(module_globals, key=len))
1290
+ if global_python_dict:
1291
+ max_globals_dict_len = len(max(global_python_dict))
1292
+
1293
+ max_name_length = max(max_globals_len, max_globals_dict_len)
1294
+
1295
+ seen = set()
1296
+ print('Python globals:')
1297
+
1298
+ for k, v in sorted(global_python_dict.items(), key=sortkey):
1299
+ v = v.get_truncated_repr(libpython.MAX_OUTPUT_LEN)
1300
+ seen.add(k)
1301
+ print(' %-*s = %s' % (max_name_length, k, v))
1302
+
1303
+ print('C globals:')
1304
+ for name, cyvar in sorted(module_globals.items(), key=sortkey):
1305
+ if name not in seen:
1306
+ try:
1307
+ value = gdb.parse_and_eval(cyvar.cname)
1308
+ except RuntimeError:
1309
+ pass
1310
+ else:
1311
+ if not value.is_optimized_out:
1312
+ self.print_gdb_value(cyvar.name, value,
1313
+ max_name_length, ' ')
1314
+
1315
+
1316
+ class EvaluateOrExecuteCodeMixin:
1317
+ """
1318
+ Evaluate or execute Python code in a Cython or Python frame. The 'evalcode'
1319
+ method evaluations Python code, prints a traceback if an exception went
1320
+ uncaught, and returns any return value as a gdb.Value (NULL on exception).
1321
+ """
1322
+
1323
+ def _fill_locals_dict(self, executor, local_dict_pointer):
1324
+ "Fill a remotely allocated dict with values from the Cython C stack"
1325
+ cython_func = self.get_cython_function()
1326
+
1327
+ for name, cyvar in cython_func.locals.items():
1328
+ if (cyvar.type == PythonObject
1329
+ and self.is_initialized(cython_func, name)):
1330
+
1331
+ try:
1332
+ val = gdb.parse_and_eval(cyvar.cname)
1333
+ except RuntimeError:
1334
+ continue
1335
+ else:
1336
+ if val.is_optimized_out:
1337
+ continue
1338
+
1339
+ pystringp = executor.alloc_pystring(name)
1340
+ code = '''
1341
+ (PyObject *) PyDict_SetItem(
1342
+ (PyObject *) %d,
1343
+ (PyObject *) %d,
1344
+ (PyObject *) %s)
1345
+ ''' % (local_dict_pointer, pystringp, cyvar.cname)
1346
+
1347
+ try:
1348
+ if gdb.parse_and_eval(code) < 0:
1349
+ gdb.parse_and_eval('PyErr_Print()')
1350
+ raise gdb.GdbError("Unable to execute Python code.")
1351
+ finally:
1352
+ # PyDict_SetItem doesn't steal our reference
1353
+ executor.xdecref(pystringp)
1354
+
1355
+ def _find_first_cython_or_python_frame(self):
1356
+ frame = gdb.selected_frame()
1357
+ while frame:
1358
+ if (self.is_cython_function(frame)
1359
+ or self.is_python_function(frame)):
1360
+ frame.select()
1361
+ return frame
1362
+
1363
+ frame = frame.older()
1364
+
1365
+ raise gdb.GdbError("There is no Cython or Python frame on the stack.")
1366
+
1367
+ def _evalcode_cython(self, executor, code, input_type):
1368
+ with libpython.FetchAndRestoreError():
1369
+ # get the dict of Cython globals and construct a dict in the
1370
+ # inferior with Cython locals
1371
+ global_dict = gdb.parse_and_eval(
1372
+ '(PyObject *) PyModule_GetDict(__pyx_m)')
1373
+ local_dict = gdb.parse_and_eval('(PyObject *) PyDict_New()')
1374
+
1375
+ try:
1376
+ self._fill_locals_dict(executor,
1377
+ libpython.pointervalue(local_dict))
1378
+ result = executor.evalcode(code, input_type, global_dict,
1379
+ local_dict)
1380
+ finally:
1381
+ executor.xdecref(libpython.pointervalue(local_dict))
1382
+
1383
+ return result
1384
+
1385
+ def evalcode(self, code, input_type):
1386
+ """
1387
+ Evaluate `code` in a Python or Cython stack frame using the given
1388
+ `input_type`.
1389
+ """
1390
+ frame = self._find_first_cython_or_python_frame()
1391
+ executor = libpython.PythonCodeExecutor()
1392
+ if self.is_python_function(frame):
1393
+ return libpython._evalcode_python(executor, code, input_type)
1394
+ return self._evalcode_cython(executor, code, input_type)
1395
+
1396
+
1397
+ class CyExec(CythonCommand, libpython.PyExec, EvaluateOrExecuteCodeMixin):
1398
+ """
1399
+ Execute Python code in the nearest Python or Cython frame.
1400
+ """
1401
+
1402
+ name = '-cy-exec'
1403
+ command_class = gdb.COMMAND_STACK
1404
+ completer_class = gdb.COMPLETE_NONE
1405
+
1406
+ @libpython.dont_suppress_errors
1407
+ def invoke(self, expr, from_tty):
1408
+ expr, input_type = self.readcode(expr)
1409
+ executor = libpython.PythonCodeExecutor()
1410
+ executor.xdecref(self.evalcode(expr, executor.Py_file_input))
1411
+
1412
+
1413
+ class CySet(CythonCommand):
1414
+ """
1415
+ Set a Cython variable to a certain value
1416
+
1417
+ cy set my_cython_c_variable = 10
1418
+ cy set my_cython_py_variable = $cy_eval("{'doner': 'kebab'}")
1419
+
1420
+ This is equivalent to
1421
+
1422
+ set $cy_value("my_cython_variable") = 10
1423
+ """
1424
+
1425
+ name = 'cy set'
1426
+ command_class = gdb.COMMAND_DATA
1427
+ completer_class = gdb.COMPLETE_NONE
1428
+
1429
+ @libpython.dont_suppress_errors
1430
+ @require_cython_frame
1431
+ def invoke(self, expr, from_tty):
1432
+ name_and_expr = expr.split('=', 1)
1433
+ if len(name_and_expr) != 2:
1434
+ raise gdb.GdbError("Invalid expression. Use 'cy set var = expr'.")
1435
+
1436
+ varname, expr = name_and_expr
1437
+ cname = self.cy.cy_cname.invoke(varname.strip())
1438
+ gdb.execute("set %s = %s" % (cname, expr))
1439
+
1440
+
1441
+ # Functions
1442
+
1443
+ class CyCName(gdb.Function, CythonBase):
1444
+ """
1445
+ Get the C name of a Cython variable in the current context.
1446
+ Examples:
1447
+
1448
+ print $cy_cname("function")
1449
+ print $cy_cname("Class.method")
1450
+ print $cy_cname("module.function")
1451
+ """
1452
+
1453
+ @libpython.dont_suppress_errors
1454
+ @require_cython_frame
1455
+ @gdb_function_value_to_unicode
1456
+ def invoke(self, cyname, frame=None):
1457
+ frame = frame or gdb.selected_frame()
1458
+ cname = None
1459
+
1460
+ if self.is_cython_function(frame):
1461
+ cython_function = self.get_cython_function(frame)
1462
+ if cyname in cython_function.locals:
1463
+ cname = cython_function.locals[cyname].cname
1464
+ elif cyname in cython_function.module.globals:
1465
+ cname = cython_function.module.globals[cyname].cname
1466
+ else:
1467
+ qname = '%s.%s' % (cython_function.module.name, cyname)
1468
+ if qname in cython_function.module.functions:
1469
+ cname = cython_function.module.functions[qname].cname
1470
+
1471
+ if not cname:
1472
+ cname = self.cy.functions_by_qualified_name.get(cyname)
1473
+
1474
+ if not cname:
1475
+ raise gdb.GdbError('No such Cython variable: %s' % cyname)
1476
+
1477
+ return cname
1478
+
1479
+
1480
+ class CyCValue(CyCName):
1481
+ """
1482
+ Get the value of a Cython variable.
1483
+ """
1484
+
1485
+ @libpython.dont_suppress_errors
1486
+ @require_cython_frame
1487
+ @gdb_function_value_to_unicode
1488
+ def invoke(self, cyname, frame=None):
1489
+ globals_dict = self.get_cython_globals_dict()
1490
+ cython_function = self.get_cython_function(frame)
1491
+
1492
+ if self.is_initialized(cython_function, cyname):
1493
+ cname = super().invoke(cyname, frame=frame)
1494
+ return gdb.parse_and_eval(cname)
1495
+ elif cyname in globals_dict:
1496
+ return globals_dict[cyname]._gdbval
1497
+ else:
1498
+ raise gdb.GdbError("Variable %s is not initialized." % cyname)
1499
+
1500
+
1501
+ class CyLine(gdb.Function, CythonBase):
1502
+ """
1503
+ Get the current Cython line.
1504
+ """
1505
+
1506
+ @libpython.dont_suppress_errors
1507
+ @require_cython_frame
1508
+ def invoke(self):
1509
+ return self.get_cython_lineno()[1]
1510
+
1511
+
1512
+ class CyEval(gdb.Function, CythonBase, EvaluateOrExecuteCodeMixin):
1513
+ """
1514
+ Evaluate Python code in the nearest Python or Cython frame and return
1515
+ """
1516
+
1517
+ @libpython.dont_suppress_errors
1518
+ @gdb_function_value_to_unicode
1519
+ def invoke(self, python_expression):
1520
+ input_type = libpython.PythonCodeExecutor.Py_eval_input
1521
+ return self.evalcode(python_expression, input_type)
1522
+
1523
+
1524
+ cython_info = CythonInfo()
1525
+ cy = CyCy.register()
1526
+ cython_info.cy = cy
1527
+
1528
+
1529
+ def register_defines():
1530
+ libpython.source_gdb_script(textwrap.dedent("""\
1531
+ define cy step
1532
+ cy -step
1533
+ end
1534
+
1535
+ define cy next
1536
+ cy -next
1537
+ end
1538
+
1539
+ document cy step
1540
+ %s
1541
+ end
1542
+
1543
+ document cy next
1544
+ %s
1545
+ end
1546
+ """) % (CyStep.__doc__, CyNext.__doc__))
1547
+
1548
+ register_defines()