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,1329 @@
1
+ #
2
+ # Tables describing slots in the CPython type object
3
+ # and associated know-how.
4
+ #
5
+
6
+
7
+ from . import Naming
8
+ from . import PyrexTypes
9
+ from .Errors import error, warn_once
10
+
11
+ import copy
12
+ import enum
13
+
14
+ invisible = ['__cinit__', '__dealloc__', '__richcmp__',
15
+ '__nonzero__', '__bool__']
16
+
17
+ richcmp_special_methods = ['__eq__', '__ne__', '__lt__', '__gt__', '__le__', '__ge__']
18
+
19
+
20
+ class Signature:
21
+ # Method slot signature descriptor.
22
+ #
23
+ # has_dummy_arg boolean
24
+ # has_generic_args boolean
25
+ # fixed_arg_format string
26
+ # ret_format string
27
+ # error_value string
28
+ # use_fastcall FastcallUsed enum
29
+ #
30
+ # The formats are strings made up of the following
31
+ # characters:
32
+ #
33
+ # 'O' Python object
34
+ # 'T' Python object of the type of 'self'
35
+ # 'v' void
36
+ # 'p' void *
37
+ # 'P' void **
38
+ # 'i' int
39
+ # 'b' bint
40
+ # 'I' int *
41
+ # 'l' long
42
+ # 'f' float
43
+ # 'd' double
44
+ # 'h' Py_hash_t
45
+ # 'z' Py_ssize_t
46
+ # 'Z' Py_ssize_t *
47
+ # 's' char *
48
+ # 'S' char **
49
+ # 'r' int used only to signal exception
50
+ # 'B' Py_buffer *
51
+ # '-' dummy 'self' argument (not used)
52
+ # '*' rest of args passed as generic Python
53
+ # arg tuple and kw dict (must be last
54
+ # char in format string)
55
+ # '?' optional object arg (currently for pow only)
56
+
57
+ format_map = {
58
+ 'O': PyrexTypes.py_object_type,
59
+ 'v': PyrexTypes.c_void_type,
60
+ 'p': PyrexTypes.c_void_ptr_type,
61
+ 'P': PyrexTypes.c_void_ptr_ptr_type,
62
+ 'i': PyrexTypes.c_int_type,
63
+ 'b': PyrexTypes.c_bint_type,
64
+ 'I': PyrexTypes.c_int_ptr_type,
65
+ 'l': PyrexTypes.c_long_type,
66
+ 'f': PyrexTypes.c_float_type,
67
+ 'd': PyrexTypes.c_double_type,
68
+ 'h': PyrexTypes.c_py_hash_t_type,
69
+ 'z': PyrexTypes.c_py_ssize_t_type,
70
+ 'Z': PyrexTypes.c_py_ssize_t_ptr_type,
71
+ 's': PyrexTypes.c_char_ptr_type,
72
+ 'S': PyrexTypes.c_char_ptr_ptr_type,
73
+ 'r': PyrexTypes.c_returncode_type,
74
+ 'B': PyrexTypes.c_py_buffer_ptr_type,
75
+ '?': PyrexTypes.py_object_type
76
+ # 'T', '-' and '*' are handled otherwise
77
+ # and are not looked up in here
78
+ }
79
+
80
+ type_to_format_map = {type_: format_ for format_, type_ in format_map.items()}
81
+
82
+ error_value_map = {
83
+ 'O': "NULL",
84
+ 'T': "NULL",
85
+ 'i': "-1",
86
+ 'b': "-1",
87
+ 'l': "-1",
88
+ 'r': "-1",
89
+ 'h': "-1",
90
+ 'z': "-1",
91
+ }
92
+
93
+ # Describes whether to use fastcall, and what macro
94
+ # to use the guard the use of fastcall.
95
+ class FastcallUsed(enum.IntEnum):
96
+ NO = 0
97
+ YES = 1 # guarded by CYTHON_FASTCALL
98
+ TP_NEW = 2 # guarded by CYTHON_FASTCALL_TPNEW
99
+
100
+ # Use METH_FASTCALL instead of METH_VARARGS
101
+ use_fastcall = FastcallUsed.NO
102
+
103
+ def __init__(self, arg_format, ret_format, nogil=False):
104
+ self.has_dummy_arg = False
105
+ self.has_generic_args = False
106
+ self.optional_object_arg_count = 0
107
+ if arg_format[:1] == '-':
108
+ self.has_dummy_arg = True
109
+ arg_format = arg_format[1:]
110
+ if arg_format[-1:] == '*':
111
+ self.has_generic_args = True
112
+ arg_format = arg_format[:-1]
113
+ if arg_format[-1:] == '?':
114
+ self.optional_object_arg_count += 1
115
+ self.fixed_arg_format = arg_format
116
+ self.ret_format = ret_format
117
+ self.error_value = self.error_value_map.get(ret_format, None)
118
+ self.exception_check = ret_format != 'r' and self.error_value is not None
119
+ self.is_staticmethod = False
120
+ self.nogil = nogil
121
+
122
+ def __repr__(self):
123
+ return '<Signature[%s(%s%s)]>' % (
124
+ self.ret_format,
125
+ ', '.join(self.fixed_arg_format),
126
+ '*' if self.has_generic_args else '')
127
+
128
+ def min_num_fixed_args(self):
129
+ return self.max_num_fixed_args() - self.optional_object_arg_count
130
+
131
+ def max_num_fixed_args(self):
132
+ return len(self.fixed_arg_format)
133
+
134
+ def is_self_arg(self, i):
135
+ # argument is 'self' for methods or 'class' for classmethods
136
+ return self.fixed_arg_format[i] == 'T'
137
+
138
+ def returns_self_type(self):
139
+ # return type is same as 'self' argument type
140
+ return self.ret_format == 'T'
141
+
142
+ def fixed_arg_type(self, i):
143
+ return self.format_map[self.fixed_arg_format[i]]
144
+
145
+ def return_type(self):
146
+ return self.format_map[self.ret_format]
147
+
148
+ def format_from_type(self, arg_type):
149
+ if arg_type.is_pyobject:
150
+ arg_type = PyrexTypes.py_object_type
151
+ return self.type_to_format_map[arg_type]
152
+
153
+ def exception_value(self):
154
+ return self.error_value_map.get(self.ret_format)
155
+
156
+ def function_type(self, self_arg_override=None):
157
+ # Construct a C function type descriptor for this signature
158
+ args = []
159
+ for i in range(self.max_num_fixed_args()):
160
+ if self_arg_override is not None and self.is_self_arg(i):
161
+ assert isinstance(self_arg_override, PyrexTypes.CFuncTypeArg)
162
+ args.append(self_arg_override)
163
+ else:
164
+ arg_type = self.fixed_arg_type(i)
165
+ args.append(PyrexTypes.CFuncTypeArg("", arg_type, None))
166
+ if self_arg_override is not None and self.returns_self_type():
167
+ ret_type = self_arg_override.type
168
+ else:
169
+ ret_type = self.return_type()
170
+ exc_value = self.exception_value()
171
+ return PyrexTypes.CFuncType(
172
+ ret_type, args, exception_value=exc_value,
173
+ exception_check=self.exception_check,
174
+ nogil=self.nogil)
175
+
176
+ def method_flags(self):
177
+ if self.ret_format == "O":
178
+ full_args = self.fixed_arg_format
179
+ if self.has_dummy_arg:
180
+ full_args = "O" + full_args
181
+ if full_args in ["O", "T"]:
182
+ if not self.has_generic_args:
183
+ return [method_noargs]
184
+ elif self.use_fastcall:
185
+ return [method_fastcall, method_keywords]
186
+ else:
187
+ return [method_varargs, method_keywords]
188
+ elif full_args in ["OO", "TO"] and not self.has_generic_args:
189
+ return [method_onearg]
190
+
191
+ if self.is_staticmethod:
192
+ if self.use_fastcall:
193
+ return [method_fastcall, method_keywords]
194
+ else:
195
+ return [method_varargs, method_keywords]
196
+ return None
197
+
198
+ def method_function_type(self):
199
+ # Return the C function type
200
+ mflags = self.method_flags()
201
+ kw = "WithKeywords" if (method_keywords in mflags) else ""
202
+ for m in mflags:
203
+ if m == method_noargs or m == method_onearg:
204
+ return "PyCFunction"
205
+ if m == method_varargs:
206
+ return "PyCFunction" + kw
207
+ if m == method_fastcall:
208
+ return "__Pyx_PyCFunction_FastCall" + kw
209
+ return None
210
+
211
+ def with_fastcall(self, fastcall_type=FastcallUsed.YES):
212
+ # Return a copy of this Signature with use_fastcall=True
213
+ sig = copy.copy(self)
214
+ sig.use_fastcall = fastcall_type
215
+ return sig
216
+
217
+ @property
218
+ def fastvar(self):
219
+ # Used to select variants of functions, one dealing with METH_VARARGS
220
+ # and one dealing with __Pyx_METH_FASTCALL
221
+ if self.use_fastcall == self.FastcallUsed.YES:
222
+ return "FASTCALL"
223
+ elif self.use_fastcall == self.FastcallUsed.TP_NEW:
224
+ return "FASTCALL_TPNEW"
225
+ else:
226
+ return "VARARGS"
227
+
228
+ @property
229
+ def fastcall_guard(self):
230
+ if self.use_fastcall == self.FastcallUsed.YES:
231
+ return "CYTHON_VECTORCALL"
232
+ elif self.use_fastcall == self.FastcallUsed.TP_NEW:
233
+ return "CYTHON_VECTORCALL_TPNEW"
234
+ else:
235
+ return "1"
236
+
237
+
238
+ class SlotDescriptor:
239
+ # Abstract base class for type slot descriptors.
240
+ #
241
+ # slot_name string Member name of the slot in the type object
242
+ # is_initialised_dynamically Is initialised by code in the module init function
243
+ # is_inherited Is inherited by subtypes (see PyType_Ready())
244
+ # ifdef Full #ifdef string that slot is wrapped in. Using this causes flags to be ignored.
245
+ # used_ifdef Full #ifdef string that the slot value is wrapped in (otherwise it is assigned NULL)
246
+ # Unlike "ifdef" the slot is defined and this just controls if it receives a value
247
+
248
+ def __init__(self, slot_name, dynamic=False, inherited=False,
249
+ ifdef=None, is_binop=False,
250
+ used_ifdef=None):
251
+ self.slot_name = slot_name
252
+ self.is_initialised_dynamically = dynamic
253
+ self.is_inherited = inherited
254
+ self.ifdef = ifdef
255
+ self.used_ifdef = used_ifdef
256
+ self.is_binop = is_binop
257
+
258
+ def slot_code(self, scope):
259
+ raise NotImplementedError()
260
+
261
+ def spec_value(self, scope):
262
+ return self.slot_code(scope)
263
+
264
+ def preprocessor_guard_code(self):
265
+ ifdef = self.ifdef
266
+ guard = None
267
+ if ifdef:
268
+ guard = "#if %s" % ifdef
269
+ return guard
270
+
271
+ def generate_spec(self, scope, code):
272
+ if self.is_initialised_dynamically:
273
+ return
274
+ value = self.spec_value(scope)
275
+ if value == "0":
276
+ return
277
+ preprocessor_guard = self.preprocessor_guard_code()
278
+ if not preprocessor_guard:
279
+ if self.slot_name.startswith(('bf_', 'am_')):
280
+ # The buffer protocol requires Limited API 3.11 and 'am_send' requires 3.10,
281
+ # so check if the spec slots are available.
282
+ preprocessor_guard = "#if defined(Py_%s)" % self.slot_name
283
+ if preprocessor_guard:
284
+ code.putln(preprocessor_guard)
285
+ if self.used_ifdef:
286
+ # different from preprocessor guard - this defines if we *want* to define it,
287
+ # rather than if the slot exists
288
+ code.putln(f"#if {self.used_ifdef}")
289
+ code.putln("{Py_%s, (void *)%s}," % (self.slot_name, value))
290
+ if self.used_ifdef:
291
+ code.putln("#endif")
292
+ if preprocessor_guard:
293
+ code.putln("#endif")
294
+
295
+ def generate(self, scope, code):
296
+ preprocessor_guard = self.preprocessor_guard_code()
297
+ if preprocessor_guard:
298
+ code.putln(preprocessor_guard)
299
+
300
+ end_pypy_guard = False
301
+ if self.is_initialised_dynamically:
302
+ value = "0"
303
+ else:
304
+ value = self.slot_code(scope)
305
+ if value == "0" and self.is_inherited:
306
+ # PyPy currently has a broken PyType_Ready() that fails to
307
+ # inherit some slots. To work around this, we explicitly
308
+ # set inherited slots here, but only in PyPy since CPython
309
+ # handles this better than we do (except for buffer slots in type specs).
310
+ inherited_value = value
311
+ current_scope = scope
312
+ while (inherited_value == "0"
313
+ and current_scope.parent_type
314
+ and current_scope.parent_type.base_type
315
+ and current_scope.parent_type.base_type.scope):
316
+ current_scope = current_scope.parent_type.base_type.scope
317
+ inherited_value = self.slot_code(current_scope)
318
+ if inherited_value != "0":
319
+ # we always need inherited buffer slots for the type spec
320
+ is_buffer_slot = int(self.slot_name in ("bf_getbuffer", "bf_releasebuffer"))
321
+ code.putln("#if CYTHON_COMPILING_IN_PYPY || %d" % is_buffer_slot)
322
+ code.putln("%s, /*%s*/" % (inherited_value, self.slot_name))
323
+ code.putln("#else")
324
+ end_pypy_guard = True
325
+
326
+ if self.used_ifdef:
327
+ code.putln("#if %s" % self.used_ifdef)
328
+ code.putln("%s, /*%s*/" % (value, self.slot_name))
329
+ if self.used_ifdef:
330
+ code.putln("#else")
331
+ code.putln("NULL, /*%s*/" % self.slot_name)
332
+ code.putln("#endif")
333
+
334
+ if end_pypy_guard:
335
+ code.putln("#endif")
336
+
337
+ if preprocessor_guard:
338
+ code.putln("#endif")
339
+
340
+ # Some C implementations have trouble statically
341
+ # initialising a global with a pointer to an extern
342
+ # function, so we initialise some of the type slots
343
+ # in the module init function instead.
344
+
345
+ def generate_dynamic_init_code(self, scope, code):
346
+ if self.is_initialised_dynamically:
347
+ self.generate_set_slot_code(
348
+ self.slot_code(scope), scope, code)
349
+
350
+ def generate_set_slot_code(self, value, scope, code):
351
+ if value == "0":
352
+ return
353
+
354
+ if scope.parent_type.typeptr_cname:
355
+ target = "%s->%s" % (
356
+ code.typeptr_cname_in_module_state(scope.parent_type), self.slot_name)
357
+ else:
358
+ assert scope.parent_type.typeobj_cname
359
+ target = "%s.%s" % (
360
+ code.name_in_module_state(scope.parent_type.typeobj_cname), self.slot_name)
361
+
362
+ code.putln("%s = %s;" % (target, value))
363
+
364
+
365
+ class FixedSlot(SlotDescriptor):
366
+ # Descriptor for a type slot with a fixed value.
367
+ #
368
+ # value string
369
+
370
+ def __init__(self, slot_name, value, ifdef=None):
371
+ SlotDescriptor.__init__(self, slot_name, ifdef=ifdef)
372
+ self.value = value
373
+
374
+ def slot_code(self, scope):
375
+ return self.value
376
+
377
+
378
+ class EmptySlot(FixedSlot):
379
+ # Descriptor for a type slot whose value is always 0.
380
+
381
+ def __init__(self, slot_name, ifdef=None):
382
+ FixedSlot.__init__(self, slot_name, "0", ifdef=ifdef)
383
+
384
+
385
+ class MethodSlot(SlotDescriptor):
386
+ # Type slot descriptor for a user-definable method.
387
+ #
388
+ # signature Signature
389
+ # method_name string The __xxx__ name of the method
390
+ # alternatives [string] Alternative list of __xxx__ names for the method
391
+
392
+ def __init__(self, signature, slot_name, method_name, method_name_to_slot,
393
+ fallback=None, ifdef=None, inherited=True):
394
+ SlotDescriptor.__init__(self, slot_name,
395
+ ifdef=ifdef, inherited=inherited)
396
+ self.signature = signature
397
+ self.slot_name = slot_name
398
+ self.method_name = method_name
399
+ self.alternatives = []
400
+ method_name_to_slot[method_name] = self
401
+ #
402
+ if fallback:
403
+ self.alternatives.append(fallback)
404
+
405
+ def slot_code(self, scope):
406
+ entry = scope.lookup_here(self.method_name)
407
+ if entry and entry.is_special and entry.func_cname:
408
+ for method_name in self.alternatives:
409
+ alt_entry = scope.lookup_here(method_name)
410
+ if alt_entry:
411
+ warn_once(alt_entry.pos,
412
+ f"{method_name} was removed in Python 3; ignoring it and using {self.method_name} instead",
413
+ 2)
414
+ return entry.func_cname
415
+ for method_name in self.alternatives:
416
+ entry = scope.lookup_here(method_name)
417
+ if entry and entry.is_special and entry.func_cname:
418
+ warn_once(entry.pos,
419
+ f"{method_name} was removed in Python 3; use {self.method_name} instead",
420
+ 2)
421
+ return entry.func_cname
422
+ return "0"
423
+
424
+
425
+ class InternalMethodSlot(SlotDescriptor):
426
+ # Type slot descriptor for a method which is always
427
+ # synthesized by Cython.
428
+ #
429
+ # slot_name string Member name of the slot in the type object
430
+
431
+ def __init__(self, slot_name, **kargs):
432
+ SlotDescriptor.__init__(self, slot_name, **kargs)
433
+
434
+ def slot_code(self, scope):
435
+ return scope.mangle_internal(self.slot_name)
436
+
437
+
438
+ class GCDependentSlot(InternalMethodSlot):
439
+ # Descriptor for a slot whose value depends on whether
440
+ # the type participates in GC.
441
+
442
+ def __init__(self, slot_name, **kargs):
443
+ InternalMethodSlot.__init__(self, slot_name, **kargs)
444
+
445
+ def slot_code(self, scope):
446
+ # We treat external types as needing gc, but don't generate a slot code
447
+ # because we don't know it to be able to call it directly.
448
+ if not scope.needs_gc() or scope.parent_type.is_external:
449
+ return "0"
450
+ if not scope.has_cyclic_pyobject_attrs:
451
+ # if the type does not have GC relevant object attributes, it can
452
+ # delegate GC methods to its parent - iff the parent functions
453
+ # are defined in the same module
454
+ parent_type_scope = scope.parent_type.base_type.scope
455
+ if scope.parent_scope is parent_type_scope.parent_scope:
456
+ entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
457
+ if entry.visibility != 'extern':
458
+ return self.slot_code(parent_type_scope)
459
+ return InternalMethodSlot.slot_code(self, scope)
460
+
461
+
462
+ class GCClearReferencesSlot(GCDependentSlot):
463
+
464
+ def slot_code(self, scope):
465
+ if scope.needs_tp_clear():
466
+ return GCDependentSlot.slot_code(self, scope)
467
+ return "0"
468
+
469
+
470
+ class ConstructorSlot(InternalMethodSlot):
471
+ # Descriptor for tp_new and tp_dealloc.
472
+
473
+ def __init__(self, slot_name, method=None, **kargs):
474
+ InternalMethodSlot.__init__(self, slot_name, **kargs)
475
+ self.method = method
476
+
477
+ def to_vectorcall_slot(self):
478
+ # Return a dummy slot used to implement tp_vectorcall.
479
+ # It has the same rules about when to generate it as tp_new.
480
+ assert self.slot_name == "tp_new"
481
+ self_copy = copy.copy(self)
482
+ self_copy.slot_name = "tp_new_vectorcall"
483
+ return self_copy
484
+
485
+ def _needs_own(self, scope):
486
+ if (scope.parent_type.base_type
487
+ and not scope.has_pyobject_attrs
488
+ and not scope.has_memoryview_attrs
489
+ and not scope.has_explicitly_constructable_attrs
490
+ and not (self.slot_name in ('tp_new', 'tp_new_vectorcall') and scope.parent_type.vtabslot_cname)):
491
+ entry = scope.lookup_here(self.method) if self.method else None
492
+ if not (entry and entry.is_special):
493
+ return False
494
+ # Unless we can safely delegate to the parent, all types need a tp_new().
495
+ return True
496
+
497
+ def _parent_slot_function(self, scope):
498
+ parent_type_scope = scope.parent_type.base_type.scope
499
+ if scope.parent_scope is parent_type_scope.parent_scope:
500
+ entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
501
+ if entry.visibility != 'extern':
502
+ return self.slot_code(parent_type_scope)
503
+ return None
504
+
505
+ def slot_code(self, scope):
506
+ if not self._needs_own(scope):
507
+ # if the type does not have object attributes, it can
508
+ # delegate GC methods to its parent - iff the parent
509
+ # functions are defined in the same module
510
+ slot_code = self._parent_slot_function(scope)
511
+ if slot_code is not None:
512
+ return slot_code
513
+ return InternalMethodSlot.slot_code(self, scope)
514
+
515
+ def generate_dynamic_init_code(self, scope, code):
516
+ if self.slot_code(scope) != '0':
517
+ return
518
+ # If we don't have our own slot function and don't know the
519
+ # parent function statically, copy it dynamically.
520
+ base_type = scope.parent_type.base_type
521
+ if base_type.typeptr_cname:
522
+ base_typeptr_cname = code.typeptr_cname_in_module_state(base_type)
523
+ src = '%s->%s' % (base_typeptr_cname, self.slot_name)
524
+ elif base_type.is_extension_type and base_type.typeobj_cname:
525
+ src = '%s.%s' % (code.typeptr_cname_in_module_state(base_type), self.slot_name)
526
+ else:
527
+ return
528
+
529
+ self.generate_set_slot_code(src, scope, code)
530
+
531
+
532
+ class TpVectorcallSlot(ConstructorSlot):
533
+ def _needs_own(self, scope):
534
+ return True # never inherited
535
+
536
+ def slot_code(self, scope):
537
+ tp = scope.parent_type
538
+ seen_init = False
539
+ while tp:
540
+ if not tp.is_extension_type:
541
+ return "0"
542
+ if tp.is_external:
543
+ return "0"
544
+ if tp.scope.parent_scope is not scope.parent_scope:
545
+ # In a pxd file. We don't have enough visibility to make this work.
546
+ return "0"
547
+ if tp.multiple_bases:
548
+ return "0" # Can't reason about __init__
549
+ # If we don't have the second overloaded alternative for __cinit__ or __init__
550
+ # this means the signature was wrong and so we haven't generated code for the
551
+ # vectorcall wrappers in DefNode.analyse_declarations
552
+ cinit_entry = tp.scope.lookup_here("__cinit__")
553
+ if cinit_entry and not (cinit_entry.is_special and cinit_entry.tp_new_can_be_vectorcall):
554
+ return "0"
555
+ if not seen_init and (init_entry := tp.scope.lookup_here("__init__")):
556
+ if not (init_entry.is_special and init_entry.tp_new_can_be_vectorcall):
557
+ return "0"
558
+ seen_init = True
559
+ tp = tp.base_type
560
+ return super().slot_code(scope)
561
+
562
+ def generate_dynamic_init_code(self, scope, code):
563
+ return # never do anything dynamic here
564
+
565
+
566
+ class SyntheticSlot(InternalMethodSlot):
567
+ # Type slot descriptor for a synthesized method which
568
+ # dispatches to one or more user-defined methods depending
569
+ # on its arguments. If none of the relevant methods are
570
+ # defined, the method will not be synthesized and an
571
+ # alternative default value will be placed in the type
572
+ # slot.
573
+
574
+ def __init__(self, slot_name, user_methods, default_value, **kargs):
575
+ InternalMethodSlot.__init__(self, slot_name, **kargs)
576
+ self.user_methods = user_methods
577
+ self.default_value = default_value
578
+
579
+ def slot_code(self, scope):
580
+ if scope.defines_any_special(self.user_methods):
581
+ return InternalMethodSlot.slot_code(self, scope)
582
+ else:
583
+ return self.default_value
584
+
585
+ def spec_value(self, scope):
586
+ return self.slot_code(scope)
587
+
588
+
589
+ class SubscriptSlot(SyntheticSlot):
590
+ """
591
+ Slot descriptor that implements the functionally overlapping sequence/mapping slots.
592
+ """
593
+ def __init__(self, slot_name, user_methods):
594
+ super().__init__(slot_name, user_methods, "0")
595
+
596
+ _slot_methods = {
597
+ 'sq_item': ['__getitem__'],
598
+ 'sq_ass_item': ['__setitem__', '__delitem__'],
599
+ 'mp_subscript': ['__getitem__'],
600
+ 'mp_ass_subscript': ['__setitem__', '__delitem__'],
601
+ }
602
+
603
+ @staticmethod
604
+ def find_special_method(scope, method_name):
605
+ while True:
606
+ entry = scope.lookup_here(method_name)
607
+ if entry is not None:
608
+ return entry if entry.is_special else None
609
+ base_type = scope.parent_type.base_type
610
+ if base_type is None or base_type.is_external:
611
+ return None
612
+ scope = base_type.scope
613
+
614
+ @classmethod
615
+ def implements_slot(cls, scope, slot_name):
616
+ scope_implements_methods = False
617
+ is_sequence_impl = True
618
+ for method_name in cls._slot_methods[slot_name]:
619
+ entry = cls.find_special_method(scope, method_name)
620
+ if entry is None:
621
+ continue
622
+ if entry.scope is scope:
623
+ scope_implements_methods = True
624
+ if entry.signature != sequence_subscript_signatures[method_name]:
625
+ is_sequence_impl = False
626
+
627
+ if not scope_implements_methods:
628
+ return False
629
+
630
+ if slot_name.startswith('mp_') and scope.parent_type.base_type is not None:
631
+ # Even when implementing the sequence protocol, a base class might have chosen to
632
+ # implement the mapping protocol (or may choose to do so in the future),
633
+ # and that would unfortunately take precedence.
634
+ return True
635
+
636
+ collection_type = scope.directives.get('collection_type')
637
+ if collection_type == 'mapping':
638
+ if slot_name.startswith('mp_'):
639
+ return True
640
+ # Implementing the Sequence slot doesn't hurt because the Mapping protocol takes precedence.
641
+ elif collection_type == 'sequence':
642
+ if slot_name.startswith('sq_'):
643
+ return True
644
+ elif is_sequence_impl:
645
+ # Mapping slot in a Sequence, implemented with sequence signature.
646
+ # By not implementing it, we allow callers to see that it would be inefficient to use.
647
+ return False
648
+
649
+ return True
650
+
651
+ def slot_code(self, scope):
652
+ if self.implements_slot(scope, self.slot_name):
653
+ return InternalMethodSlot.slot_code(self, scope)
654
+ else:
655
+ return self.default_value
656
+
657
+
658
+ class BinopSlot(SyntheticSlot):
659
+ def __init__(self, signature, slot_name, left_method, method_name_to_slot, **kargs):
660
+ assert left_method.startswith('__')
661
+ right_method = '__r' + left_method[2:]
662
+ SyntheticSlot.__init__(
663
+ self, slot_name, [left_method, right_method], "0", is_binop=True, **kargs)
664
+ # MethodSlot causes special method registration.
665
+ self.left_slot = MethodSlot(signature, "", left_method, method_name_to_slot, **kargs)
666
+ self.right_slot = MethodSlot(signature, "", right_method, method_name_to_slot, **kargs)
667
+
668
+
669
+ class InitSlot(MethodSlot):
670
+ def slot_code(self, scope):
671
+ super_slot_code = super().slot_code(scope)
672
+ if super_slot_code != "0":
673
+ entry = scope.lookup(self.method_name)
674
+ if entry and entry.is_special and entry.signature.use_fastcall:
675
+ # we need a wrapper
676
+ return InternalMethodSlot.slot_code(self, scope)
677
+ return super_slot_code
678
+
679
+
680
+ class RichcmpSlot(MethodSlot):
681
+ def slot_code(self, scope):
682
+ entry = scope.lookup_here(self.method_name)
683
+ if entry and entry.is_special and entry.func_cname:
684
+ return entry.func_cname
685
+ elif scope.defines_any_special(richcmp_special_methods):
686
+ return scope.mangle_internal(self.slot_name)
687
+ else:
688
+ return "0"
689
+
690
+
691
+ class TypeFlagsSlot(SlotDescriptor):
692
+ # Descriptor for the type flags slot.
693
+
694
+ def slot_code(self, scope):
695
+ value = "Py_TPFLAGS_DEFAULT"
696
+ if scope.directives['type_version_tag']:
697
+ # No longer used since Py3.11.
698
+ value += "|Py_TPFLAGS_HAVE_VERSION_TAG"
699
+ else:
700
+ # Used to be in 'Py_TPFLAGS_DEFAULT' up to Py3.10.
701
+ value = f"({value}&~Py_TPFLAGS_HAVE_VERSION_TAG)"
702
+ if not scope.parent_type.is_final_type:
703
+ value += "|Py_TPFLAGS_BASETYPE"
704
+ if scope.needs_gc():
705
+ value += "|Py_TPFLAGS_HAVE_GC"
706
+ if scope.parent_type.has_sequence_flag:
707
+ value += "|Py_TPFLAGS_SEQUENCE"
708
+ if scope.parent_type.has_mapping_flag:
709
+ assert not scope.parent_type.has_sequence_flag
710
+ value += "|Py_TPFLAGS_MAPPING"
711
+ return value
712
+
713
+ def generate_spec(self, scope, code):
714
+ # Flags are stored in the PyType_Spec, not in a PyType_Slot.
715
+ return
716
+
717
+
718
+ class DocStringSlot(SlotDescriptor):
719
+ # Descriptor for the docstring slot.
720
+
721
+ def slot_code(self, scope):
722
+ doc = scope.doc
723
+ if doc is None:
724
+ return "0"
725
+ if doc.is_unicode:
726
+ doc = doc.as_utf8_string()
727
+ return "PyDoc_STR(%s)" % doc.as_c_string_literal()
728
+
729
+
730
+ class SuiteSlot(SlotDescriptor):
731
+ # Descriptor for a substructure of the type object.
732
+ #
733
+ # sub_slots [SlotDescriptor]
734
+
735
+ def __init__(self, sub_slots, slot_type, slot_name, substructures, ifdef=None, cast_cname=None):
736
+ SlotDescriptor.__init__(self, slot_name, ifdef=ifdef)
737
+ self.sub_slots = sub_slots
738
+ self.slot_type = slot_type
739
+ self.cast_cname = cast_cname
740
+ substructures.append(self)
741
+
742
+ def is_empty(self, scope):
743
+ for slot in self.sub_slots:
744
+ if slot.slot_code(scope) != "0":
745
+ return False
746
+ return True
747
+
748
+ def substructure_cname(self, scope):
749
+ return "%s%s_%s" % (Naming.pyrex_prefix, self.slot_name, scope.class_name)
750
+
751
+ def slot_code(self, scope):
752
+ if not self.is_empty(scope):
753
+ cast = ""
754
+ if self.cast_cname:
755
+ cast = f"({self.cast_cname}*)"
756
+ return f"{cast}&{self.substructure_cname(scope)}"
757
+ return "0"
758
+
759
+ def generate_substructure(self, scope, code):
760
+ if not self.is_empty(scope):
761
+ code.putln("")
762
+ if self.ifdef:
763
+ code.putln("#if %s" % self.ifdef)
764
+ code.putln(
765
+ "static %s %s = {" % (
766
+ self.slot_type,
767
+ self.substructure_cname(scope)))
768
+ for slot in self.sub_slots:
769
+ slot.generate(scope, code)
770
+ code.putln("};")
771
+ if self.ifdef:
772
+ code.putln("#endif")
773
+
774
+ def generate_spec(self, scope, code):
775
+ for slot in self.sub_slots:
776
+ slot.generate_spec(scope, code)
777
+
778
+ class MethodTableSlot(SlotDescriptor):
779
+ # Slot descriptor for the method table.
780
+
781
+ def slot_code(self, scope):
782
+ if scope.pyfunc_entries:
783
+ return scope.method_table_cname
784
+ else:
785
+ return "0"
786
+
787
+
788
+ class MemberTableSlot(SlotDescriptor):
789
+ # Slot descriptor for the table of Python-accessible attributes.
790
+
791
+ def slot_code(self, scope):
792
+ # Only used in specs.
793
+ return "0"
794
+
795
+ def get_member_specs(self, scope):
796
+ return [
797
+ get_slot_by_name("tp_dictoffset", scope.directives).members_slot_value(scope),
798
+ #get_slot_by_name("tp_weaklistoffset").spec_value(scope),
799
+ ]
800
+
801
+ def is_empty(self, scope):
802
+ for member_entry in self.get_member_specs(scope):
803
+ if member_entry:
804
+ return False
805
+ return True
806
+
807
+ def substructure_cname(self, scope):
808
+ return "%s%s_%s" % (Naming.pyrex_prefix, self.slot_name, scope.class_name)
809
+
810
+ def generate_substructure_spec(self, scope, code):
811
+ if self.is_empty(scope):
812
+ return
813
+ from .Code import UtilityCode
814
+ code.globalstate.use_utility_code(UtilityCode.load_cached("IncludeStructmemberH", "ModuleSetupCode.c"))
815
+
816
+ code.putln("static struct PyMemberDef %s[] = {" % self.substructure_cname(scope))
817
+ for member_entry in self.get_member_specs(scope):
818
+ if member_entry:
819
+ code.putln(member_entry)
820
+ code.putln("{NULL, 0, 0, 0, NULL}")
821
+ code.putln("};")
822
+
823
+ def spec_value(self, scope):
824
+ if self.is_empty(scope):
825
+ return "0"
826
+ return self.substructure_cname(scope)
827
+
828
+
829
+ class GetSetSlot(SlotDescriptor):
830
+ # Slot descriptor for the table of attribute get & set methods.
831
+
832
+ def slot_code(self, scope):
833
+ if scope.property_entries:
834
+ return scope.getset_table_cname
835
+ else:
836
+ return "0"
837
+
838
+
839
+ class BaseClassSlot(SlotDescriptor):
840
+ # Slot descriptor for the base class slot.
841
+
842
+ def __init__(self, name):
843
+ SlotDescriptor.__init__(self, name, dynamic=True)
844
+
845
+ def generate_dynamic_init_code(self, scope, code):
846
+ base_type = scope.parent_type.base_type
847
+ if base_type:
848
+ base_typeptr_cname = code.typeptr_cname_in_module_state(base_type)
849
+ code.putln("%s->%s = %s;" % (
850
+ code.typeptr_cname_in_module_state(scope.parent_type),
851
+ self.slot_name,
852
+ base_typeptr_cname))
853
+
854
+
855
+ class DictOffsetSlot(SlotDescriptor):
856
+ # Slot descriptor for a class' dict offset, for dynamic attributes.
857
+
858
+ def slot_code(self, scope):
859
+ dict_entry = scope.lookup_here("__dict__") if not scope.is_closure_class_scope else None
860
+ if dict_entry and dict_entry.is_variable:
861
+ if dict_entry.is_inherited:
862
+ return "0"
863
+ if not dict_entry.type.is_pydict_type:
864
+ error(dict_entry.pos, "__dict__ slot must be of type 'dict'")
865
+ return "0"
866
+ type = scope.parent_type
867
+ if type.typedef_flag:
868
+ objstruct = type.objstruct_cname
869
+ else:
870
+ objstruct = "struct %s" % type.objstruct_cname
871
+ return ("offsetof(%s, %s)" % (
872
+ objstruct,
873
+ dict_entry.cname))
874
+ else:
875
+ return "0"
876
+
877
+ def members_slot_value(self, scope):
878
+ dict_offset = self.slot_code(scope)
879
+ if dict_offset == "0":
880
+ return None
881
+ return '{"__dictoffset__", T_PYSSIZET, %s, READONLY, NULL},' % dict_offset
882
+
883
+ ## The following slots are (or could be) initialised with an
884
+ ## extern function pointer.
885
+ #
886
+ #slots_initialised_from_extern = (
887
+ # "tp_free",
888
+ #)
889
+
890
+ #------------------------------------------------------------------------------------------
891
+ #
892
+ # Utility functions for accessing slot table data structures
893
+ #
894
+ #------------------------------------------------------------------------------------------
895
+
896
+
897
+ def get_property_accessor_signature(name):
898
+ # Return signature of accessor for an extension type
899
+ # property, else None.
900
+ return property_accessor_signatures.get(name)
901
+
902
+
903
+ def get_base_slot_function(scope, slot):
904
+ # Returns the function implementing this slot in the baseclass.
905
+ # This is useful for enabling the compiler to optimize calls
906
+ # that recursively climb the class hierarchy.
907
+ base_type = scope.parent_type.base_type
908
+ if base_type and scope.parent_scope is base_type.scope.parent_scope:
909
+ parent_slot = slot.slot_code(base_type.scope)
910
+ if parent_slot != '0':
911
+ entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
912
+ if entry.visibility != 'extern':
913
+ return parent_slot
914
+ return None
915
+
916
+
917
+ def get_slot_function(scope, slot):
918
+ # Returns the function implementing this slot in the baseclass.
919
+ # This is useful for enabling the compiler to optimize calls
920
+ # that recursively climb the class hierarchy.
921
+ slot_code = slot.slot_code(scope)
922
+ if slot_code != '0':
923
+ entry = scope.parent_scope.lookup_here(scope.parent_type.name)
924
+ if entry.visibility != 'extern':
925
+ return slot_code
926
+ return None
927
+
928
+
929
+ def get_slot_by_name(slot_name, compiler_directives):
930
+ # For now, only search the type struct, no referenced sub-structs.
931
+ for slot in get_slot_table(compiler_directives).slot_table:
932
+ if slot.slot_name == slot_name:
933
+ return slot
934
+ assert False, "Slot not found: %s" % slot_name
935
+
936
+
937
+ def get_slot_code_by_name(scope, slot_name):
938
+ slot = get_slot_by_name(slot_name, scope.directives)
939
+ return slot.slot_code(scope)
940
+
941
+ def is_binop_number_slot(name):
942
+ """
943
+ Tries to identify __add__/__radd__ and friends (so the METH_COEXIST flag can be applied).
944
+
945
+ There's no great consequence if it inadvertently identifies a few other methods
946
+ so just use a simple rule rather than an exact list.
947
+ """
948
+ slot_table = get_slot_table(None)
949
+ for meth in get_slot_table(None).PyNumberMethods:
950
+ if meth.is_binop and name in meth.user_methods:
951
+ return True
952
+ return False
953
+
954
+
955
+ #------------------------------------------------------------------------------------------
956
+ #
957
+ # Signatures for generic Python functions and methods.
958
+ #
959
+ #------------------------------------------------------------------------------------------
960
+
961
+ pyfunction_signature = Signature("-*", "O")
962
+ pymethod_signature = Signature("T*", "O")
963
+
964
+ #------------------------------------------------------------------------------------------
965
+ #
966
+ # Signatures for simple Python functions.
967
+ #
968
+ #------------------------------------------------------------------------------------------
969
+
970
+ pyfunction_noargs = Signature("-", "O")
971
+ pyfunction_onearg = Signature("-O", "O")
972
+
973
+ #------------------------------------------------------------------------------------------
974
+ #
975
+ # Signatures for the various kinds of function that
976
+ # can appear in the type object and its substructures.
977
+ #
978
+ #------------------------------------------------------------------------------------------
979
+
980
+ unaryfunc = Signature("T", "O") # typedef PyObject * (*unaryfunc)(PyObject *);
981
+ binaryfunc = Signature("OO", "O") # typedef PyObject * (*binaryfunc)(PyObject *, PyObject *);
982
+ ibinaryfunc = Signature("TO", "O") # typedef PyObject * (*binaryfunc)(PyObject *, PyObject *);
983
+ powternaryfunc = Signature("OO?", "O") # typedef PyObject * (*ternaryfunc)(PyObject *, PyObject *, PyObject *);
984
+ ipowternaryfunc = Signature("TO?", "O") # typedef PyObject * (*ternaryfunc)(PyObject *, PyObject *, PyObject *);
985
+ callfunc = Signature("T*", "O") # typedef PyObject * (*ternaryfunc)(PyObject *, PyObject *, PyObject *);
986
+ inquiry = Signature("T", "i") # typedef int (*inquiry)(PyObject *);
987
+ lenfunc = Signature("T", "z") # typedef Py_ssize_t (*lenfunc)(PyObject *);
988
+
989
+ # typedef int (*coercion)(PyObject **, PyObject **);
990
+ intargfunc = Signature("Ti", "O") # typedef PyObject *(*intargfunc)(PyObject *, int);
991
+ ssizeargfunc = Signature("Tz", "O") # typedef PyObject *(*ssizeargfunc)(PyObject *, Py_ssize_t);
992
+ intintargfunc = Signature("Tii", "O") # typedef PyObject *(*intintargfunc)(PyObject *, int, int);
993
+ ssizessizeargfunc = Signature("Tzz", "O") # typedef PyObject *(*ssizessizeargfunc)(PyObject *, Py_ssize_t, Py_ssize_t);
994
+ ssizeargproc = Signature("Tz", "r") # typedef int(*ssizeargfunc)(PyObject *, Py_ssize_t);
995
+ intobjargproc = Signature("TiO", 'r') # typedef int(*intobjargproc)(PyObject *, int, PyObject *);
996
+ ssizeobjargproc = Signature("TzO", 'r') # typedef int(*ssizeobjargproc)(PyObject *, Py_ssize_t, PyObject *);
997
+ intintobjargproc = Signature("TiiO", 'r') # typedef int(*intintobjargproc)(PyObject *, int, int, PyObject *);
998
+ ssizessizeobjargproc = Signature("TzzO", 'r') # typedef int(*ssizessizeobjargproc)(PyObject *, Py_ssize_t, Py_ssize_t, PyObject *);
999
+
1000
+ intintargproc = Signature("Tii", 'r')
1001
+ ssizessizeargproc = Signature("Tzz", 'r')
1002
+ objargfunc = Signature("TO", "O")
1003
+ objobjargproc = Signature("TOO", 'r') # typedef int (*objobjargproc)(PyObject *, PyObject *, PyObject *);
1004
+ readbufferproc = Signature("TzP", "z") # typedef Py_ssize_t (*readbufferproc)(PyObject *, Py_ssize_t, void **);
1005
+ writebufferproc = Signature("TzP", "z") # typedef Py_ssize_t (*writebufferproc)(PyObject *, Py_ssize_t, void **);
1006
+ segcountproc = Signature("TZ", "z") # typedef Py_ssize_t (*segcountproc)(PyObject *, Py_ssize_t *);
1007
+ charbufferproc = Signature("TzS", "z") # typedef Py_ssize_t (*charbufferproc)(PyObject *, Py_ssize_t, char **);
1008
+ objargproc = Signature("TO", 'r') # typedef int (*objobjproc)(PyObject *, PyObject *);
1009
+ # typedef int (*visitproc)(PyObject *, void *);
1010
+ # typedef int (*traverseproc)(PyObject *, visitproc, void *);
1011
+
1012
+ destructor = Signature("T", "v") # typedef void (*destructor)(PyObject *);
1013
+ # printfunc = Signature("TFi", 'r') # typedef int (*printfunc)(PyObject *, FILE *, int);
1014
+ # typedef PyObject *(*getattrfunc)(PyObject *, char *);
1015
+ getattrofunc = Signature("TO", "O") # typedef PyObject *(*getattrofunc)(PyObject *, PyObject *);
1016
+ # typedef int (*setattrfunc)(PyObject *, char *, PyObject *);
1017
+ setattrofunc = Signature("TOO", 'r') # typedef int (*setattrofunc)(PyObject *, PyObject *, PyObject *);
1018
+ delattrofunc = Signature("TO", 'r')
1019
+ cmpfunc = Signature("TO", "i") # typedef int (*cmpfunc)(PyObject *, PyObject *);
1020
+ reprfunc = Signature("T", "O") # typedef PyObject *(*reprfunc)(PyObject *);
1021
+ hashfunc = Signature("T", "h") # typedef Py_hash_t (*hashfunc)(PyObject *);
1022
+ richcmpfunc = Signature("TOi", "O") # typedef PyObject *(*richcmpfunc) (PyObject *, PyObject *, int);
1023
+ getiterfunc = Signature("T", "O") # typedef PyObject *(*getiterfunc) (PyObject *);
1024
+ iternextfunc = Signature("T", "O") # typedef PyObject *(*iternextfunc) (PyObject *);
1025
+ descrgetfunc = Signature("TOO", "O") # typedef PyObject *(*descrgetfunc) (PyObject *, PyObject *, PyObject *);
1026
+ descrsetfunc = Signature("TOO", 'r') # typedef int (*descrsetfunc) (PyObject *, PyObject *, PyObject *);
1027
+ descrdelfunc = Signature("TO", 'r')
1028
+ initproc = Signature("T*", 'r') # typedef int (*initproc)(PyObject *, PyObject *, PyObject *);
1029
+ # typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *);
1030
+ # typedef PyObject *(*allocfunc)(struct _typeobject *, int);
1031
+
1032
+ getbufferproc = Signature("TBi", "r") # typedef int (*getbufferproc)(PyObject *, Py_buffer *, int);
1033
+ releasebufferproc = Signature("TB", "v") # typedef void (*releasebufferproc)(PyObject *, Py_buffer *);
1034
+
1035
+ # typedef PySendResult (*sendfunc)(PyObject* iter, PyObject* value, PyObject** result);
1036
+ sendfunc = PyrexTypes.CPtrType(PyrexTypes.CFuncType(
1037
+ return_type=PyrexTypes.PySendResult_type,
1038
+ args=[
1039
+ PyrexTypes.CFuncTypeArg("iter", PyrexTypes.py_object_type),
1040
+ PyrexTypes.CFuncTypeArg("value", PyrexTypes.py_object_type),
1041
+ PyrexTypes.CFuncTypeArg("result", PyrexTypes.CPtrType(PyrexTypes.py_objptr_type)),
1042
+ ],
1043
+ exception_value="PYGEN_ERROR",
1044
+ exception_check=True, # we allow returning PYGEN_ERROR without GeneratorExit / StopIteration
1045
+ ))
1046
+
1047
+ sequence_subscript_signatures = {
1048
+ '__getitem__': ssizeargfunc,
1049
+ '__setitem__': ssizeobjargproc,
1050
+ '__delitem__': ssizeargproc,
1051
+ }
1052
+
1053
+
1054
+ #------------------------------------------------------------------------------------------
1055
+ #
1056
+ # Signatures for accessor methods of properties.
1057
+ #
1058
+ #------------------------------------------------------------------------------------------
1059
+
1060
+ property_accessor_signatures = {
1061
+ '__get__': Signature("T", "O"),
1062
+ '__set__': Signature("TO", 'r'),
1063
+ '__del__': Signature("T", 'r')
1064
+ }
1065
+
1066
+ #------------------------------------------------------------------------------------------
1067
+ #
1068
+ # The main slot table. This table contains descriptors for all the
1069
+ # top-level type slots, beginning with tp_dealloc, in the order they
1070
+ # appear in the type object.
1071
+ #
1072
+ # It depends on some compiler directives (currently c_api_binop_methods), so the
1073
+ # slot tables for each set of compiler directives are generated lazily and put in
1074
+ # the _slot_table_dict
1075
+ #
1076
+ #------------------------------------------------------------------------------------------
1077
+
1078
+ class SlotTable:
1079
+ def __init__(self, old_binops):
1080
+ # The following dictionary maps __xxx__ method names to slot descriptors.
1081
+ method_name_to_slot = {}
1082
+ self._get_slot_by_method_name = method_name_to_slot.get
1083
+ self.substructures = [] # List of all SuiteSlot instances
1084
+
1085
+ bf = binaryfunc if old_binops else ibinaryfunc
1086
+ ptf = powternaryfunc if old_binops else ipowternaryfunc
1087
+
1088
+ # Descriptor tables for the slots of the various type object
1089
+ # substructures, in the order they appear in the structure.
1090
+ self.PyNumberMethods = (
1091
+ BinopSlot(bf, "nb_add", "__add__", method_name_to_slot),
1092
+ BinopSlot(bf, "nb_subtract", "__sub__", method_name_to_slot),
1093
+ BinopSlot(bf, "nb_multiply", "__mul__", method_name_to_slot),
1094
+ BinopSlot(bf, "nb_remainder", "__mod__", method_name_to_slot),
1095
+ BinopSlot(bf, "nb_divmod", "__divmod__", method_name_to_slot),
1096
+ BinopSlot(ptf, "nb_power", "__pow__", method_name_to_slot),
1097
+ MethodSlot(unaryfunc, "nb_negative", "__neg__", method_name_to_slot),
1098
+ MethodSlot(unaryfunc, "nb_positive", "__pos__", method_name_to_slot),
1099
+ MethodSlot(unaryfunc, "nb_absolute", "__abs__", method_name_to_slot),
1100
+ MethodSlot(inquiry, "nb_bool", "__bool__", method_name_to_slot,
1101
+ fallback="__nonzero__"),
1102
+ MethodSlot(unaryfunc, "nb_invert", "__invert__", method_name_to_slot),
1103
+ BinopSlot(bf, "nb_lshift", "__lshift__", method_name_to_slot),
1104
+ BinopSlot(bf, "nb_rshift", "__rshift__", method_name_to_slot),
1105
+ BinopSlot(bf, "nb_and", "__and__", method_name_to_slot),
1106
+ BinopSlot(bf, "nb_xor", "__xor__", method_name_to_slot),
1107
+ BinopSlot(bf, "nb_or", "__or__", method_name_to_slot),
1108
+ MethodSlot(unaryfunc, "nb_int", "__int__", method_name_to_slot, fallback="__long__"),
1109
+ EmptySlot("nb_long (reserved)"),
1110
+ MethodSlot(unaryfunc, "nb_float", "__float__", method_name_to_slot),
1111
+
1112
+ # Added in release 2.0
1113
+ MethodSlot(ibinaryfunc, "nb_inplace_add", "__iadd__", method_name_to_slot),
1114
+ MethodSlot(ibinaryfunc, "nb_inplace_subtract", "__isub__", method_name_to_slot),
1115
+ MethodSlot(ibinaryfunc, "nb_inplace_multiply", "__imul__", method_name_to_slot),
1116
+ MethodSlot(ibinaryfunc, "nb_inplace_remainder", "__imod__", method_name_to_slot),
1117
+ MethodSlot(ptf, "nb_inplace_power", "__ipow__", method_name_to_slot),
1118
+ MethodSlot(ibinaryfunc, "nb_inplace_lshift", "__ilshift__", method_name_to_slot),
1119
+ MethodSlot(ibinaryfunc, "nb_inplace_rshift", "__irshift__", method_name_to_slot),
1120
+ MethodSlot(ibinaryfunc, "nb_inplace_and", "__iand__", method_name_to_slot),
1121
+ MethodSlot(ibinaryfunc, "nb_inplace_xor", "__ixor__", method_name_to_slot),
1122
+ MethodSlot(ibinaryfunc, "nb_inplace_or", "__ior__", method_name_to_slot),
1123
+
1124
+ # Added in release 2.2
1125
+ # The following require the Py_TPFLAGS_HAVE_CLASS flag
1126
+ BinopSlot(bf, "nb_floor_divide", "__floordiv__", method_name_to_slot),
1127
+ BinopSlot(bf, "nb_true_divide", "__truediv__", method_name_to_slot),
1128
+ MethodSlot(ibinaryfunc, "nb_inplace_floor_divide", "__ifloordiv__", method_name_to_slot),
1129
+ MethodSlot(ibinaryfunc, "nb_inplace_true_divide", "__itruediv__", method_name_to_slot),
1130
+
1131
+ # Added in release 2.5
1132
+ MethodSlot(unaryfunc, "nb_index", "__index__", method_name_to_slot),
1133
+
1134
+ # Added in release 3.5
1135
+ BinopSlot(bf, "nb_matrix_multiply", "__matmul__", method_name_to_slot),
1136
+ MethodSlot(ibinaryfunc, "nb_inplace_matrix_multiply", "__imatmul__", method_name_to_slot),
1137
+ )
1138
+
1139
+ self.PySequenceMethods = (
1140
+ MethodSlot(lenfunc, "sq_length", "__len__", method_name_to_slot),
1141
+ EmptySlot("sq_concat"), # nb_add used instead
1142
+ EmptySlot("sq_repeat"), # nb_multiply used instead
1143
+ SubscriptSlot("sq_item", ["__getitem__"]),
1144
+ EmptySlot("sq_slice"),
1145
+ SubscriptSlot("sq_ass_item", ["__setitem__", "__delitem__"]),
1146
+ EmptySlot("sq_ass_slice"),
1147
+ MethodSlot(cmpfunc, "sq_contains", "__contains__", method_name_to_slot),
1148
+ EmptySlot("sq_inplace_concat"), # nb_inplace_add used instead
1149
+ EmptySlot("sq_inplace_repeat"), # nb_inplace_multiply used instead
1150
+ )
1151
+
1152
+ self.PyMappingMethods = (
1153
+ MethodSlot(lenfunc, "mp_length", "__len__", method_name_to_slot),
1154
+ SubscriptSlot("mp_subscript", ["__getitem__"]),
1155
+ SubscriptSlot("mp_ass_subscript", ["__setitem__", "__delitem__"]),
1156
+ )
1157
+
1158
+ self.PyBufferProcs = (
1159
+ MethodSlot(getbufferproc, "bf_getbuffer", "__getbuffer__", method_name_to_slot),
1160
+ MethodSlot(releasebufferproc, "bf_releasebuffer", "__releasebuffer__", method_name_to_slot)
1161
+ )
1162
+
1163
+ self.PyAsyncMethods = (
1164
+ MethodSlot(unaryfunc, "am_await", "__await__", method_name_to_slot),
1165
+ MethodSlot(unaryfunc, "am_aiter", "__aiter__", method_name_to_slot),
1166
+ MethodSlot(unaryfunc, "am_anext", "__anext__", method_name_to_slot),
1167
+ # We should not map arbitrary .send() methods to an async slot.
1168
+ #MethodSlot(sendfunc, "am_send", "send", method_name_to_slot),
1169
+ EmptySlot("am_send"),
1170
+ )
1171
+
1172
+ self.slot_table = (
1173
+ ConstructorSlot("tp_dealloc", '__dealloc__'),
1174
+ EmptySlot("tp_vectorcall_offset"),
1175
+ EmptySlot("tp_getattr"),
1176
+ EmptySlot("tp_setattr"),
1177
+
1178
+ SuiteSlot(self. PyAsyncMethods, "__Pyx_PyAsyncMethodsStruct", "tp_as_async",
1179
+ self.substructures, cast_cname="PyAsyncMethods"),
1180
+
1181
+ MethodSlot(reprfunc, "tp_repr", "__repr__", method_name_to_slot),
1182
+
1183
+ SuiteSlot(self.PyNumberMethods, "PyNumberMethods", "tp_as_number", self.substructures),
1184
+ SuiteSlot(self.PySequenceMethods, "PySequenceMethods", "tp_as_sequence", self.substructures),
1185
+ SuiteSlot(self.PyMappingMethods, "PyMappingMethods", "tp_as_mapping", self.substructures),
1186
+
1187
+ MethodSlot(hashfunc, "tp_hash", "__hash__", method_name_to_slot,
1188
+ inherited=False), # Py3 checks for __richcmp__
1189
+ MethodSlot(callfunc, "tp_call", "__call__", method_name_to_slot),
1190
+ MethodSlot(reprfunc, "tp_str", "__str__", method_name_to_slot),
1191
+
1192
+ SyntheticSlot("tp_getattro", ["__getattr__","__getattribute__"], "0"), #"PyObject_GenericGetAttr"),
1193
+ SyntheticSlot("tp_setattro", ["__setattr__", "__delattr__"], "0"), #"PyObject_GenericSetAttr"),
1194
+
1195
+ SuiteSlot(self.PyBufferProcs, "PyBufferProcs", "tp_as_buffer", self.substructures),
1196
+
1197
+ TypeFlagsSlot("tp_flags"),
1198
+ DocStringSlot("tp_doc"),
1199
+
1200
+ GCDependentSlot("tp_traverse"),
1201
+ GCClearReferencesSlot("tp_clear"),
1202
+
1203
+ RichcmpSlot(richcmpfunc, "tp_richcompare", "__richcmp__", method_name_to_slot,
1204
+ inherited=False), # Py3 checks for __hash__
1205
+
1206
+ EmptySlot("tp_weaklistoffset"),
1207
+
1208
+ MethodSlot(getiterfunc, "tp_iter", "__iter__", method_name_to_slot),
1209
+ MethodSlot(iternextfunc, "tp_iternext", "__next__", method_name_to_slot),
1210
+
1211
+ MethodTableSlot("tp_methods"),
1212
+ MemberTableSlot("tp_members"),
1213
+ GetSetSlot("tp_getset"),
1214
+
1215
+ BaseClassSlot("tp_base"), #EmptySlot("tp_base"),
1216
+ EmptySlot("tp_dict"),
1217
+
1218
+ SyntheticSlot("tp_descr_get", ["__get__"], "0"),
1219
+ SyntheticSlot("tp_descr_set", ["__set__", "__delete__"], "0"),
1220
+
1221
+ DictOffsetSlot("tp_dictoffset", ifdef="!CYTHON_USE_TYPE_SPECS"), # otherwise set via "__dictoffset__" member
1222
+
1223
+ InitSlot(initproc, "tp_init", "__init__", method_name_to_slot),
1224
+ EmptySlot("tp_alloc"), #FixedSlot("tp_alloc", "PyType_GenericAlloc"),
1225
+ ConstructorSlot("tp_new", "__cinit__"),
1226
+ EmptySlot("tp_free"),
1227
+
1228
+ EmptySlot("tp_is_gc"),
1229
+ EmptySlot("tp_bases"),
1230
+ EmptySlot("tp_mro"),
1231
+ EmptySlot("tp_cache"),
1232
+ EmptySlot("tp_subclasses"),
1233
+ EmptySlot("tp_weaklist"),
1234
+ EmptySlot("tp_del"),
1235
+ EmptySlot("tp_version_tag"),
1236
+ SyntheticSlot("tp_finalize", ["__del__"], "0",
1237
+ used_ifdef="CYTHON_USE_TP_FINALIZE"),
1238
+ TpVectorcallSlot("tp_vectorcall",
1239
+ ifdef="(!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) && "
1240
+ "(!CYTHON_COMPILING_IN_LIMITED_API || __PYX_LIMITED_VERSION_HEX >= 0x030E0000)",
1241
+ used_ifdef="CYTHON_VECTORCALL_TPNEW"),
1242
+ EmptySlot("tp_print", ifdef="__PYX_NEED_TP_PRINT_SLOT == 1"),
1243
+ EmptySlot("tp_watched", ifdef="PY_VERSION_HEX >= 0x030C0000"),
1244
+ EmptySlot("tp_versions_used", ifdef="PY_VERSION_HEX >= 0x030d00A4"),
1245
+ # PyPy specific extension - only here to avoid C compiler warnings.
1246
+ EmptySlot("tp_pypy_flags", ifdef="CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x030a0000"),
1247
+ )
1248
+
1249
+ #------------------------------------------------------------------------------------------
1250
+ #
1251
+ # Descriptors for special methods which don't appear directly
1252
+ # in the type object or its substructures. These methods are
1253
+ # called from slot functions synthesized by Cython.
1254
+ #
1255
+ #------------------------------------------------------------------------------------------
1256
+
1257
+ MethodSlot(initproc, "", "__cinit__", method_name_to_slot)
1258
+ MethodSlot(destructor, "", "__dealloc__", method_name_to_slot)
1259
+ MethodSlot(destructor, "", "__del__", method_name_to_slot)
1260
+ MethodSlot(objargfunc, "", "__getitem__", method_name_to_slot)
1261
+ MethodSlot(objobjargproc, "", "__setitem__", method_name_to_slot)
1262
+ MethodSlot(objargproc, "", "__delitem__", method_name_to_slot)
1263
+ MethodSlot(ssizessizeobjargproc, "", "__setslice__", method_name_to_slot)
1264
+ MethodSlot(ssizessizeargproc, "", "__delslice__", method_name_to_slot)
1265
+ MethodSlot(getattrofunc, "", "__getattr__", method_name_to_slot)
1266
+ MethodSlot(getattrofunc, "", "__getattribute__", method_name_to_slot)
1267
+ MethodSlot(setattrofunc, "", "__setattr__", method_name_to_slot)
1268
+ MethodSlot(delattrofunc, "", "__delattr__", method_name_to_slot)
1269
+ MethodSlot(descrgetfunc, "", "__get__", method_name_to_slot)
1270
+ MethodSlot(descrsetfunc, "", "__set__", method_name_to_slot)
1271
+ MethodSlot(descrdelfunc, "", "__delete__", method_name_to_slot)
1272
+
1273
+ #-------------------------------------------------------------------------
1274
+ #
1275
+ # Legacy "fallback" Py2 slots. Don't appear in the generated slot table,
1276
+ # but match the "fallback" argument of a slot that does
1277
+ #
1278
+ #-------------------------------------------------------------------------
1279
+ MethodSlot(inquiry, "", "__nonzero__", method_name_to_slot)
1280
+ MethodSlot(unaryfunc, "", "__long__", method_name_to_slot)
1281
+
1282
+ def get_special_method_signature(self, name):
1283
+ # Given a method name, if it is a special method,
1284
+ # return its signature, else return None.
1285
+ slot = self._get_slot_by_method_name(name)
1286
+ if slot:
1287
+ return slot.signature
1288
+ elif name in richcmp_special_methods:
1289
+ return ibinaryfunc
1290
+ else:
1291
+ return None
1292
+
1293
+ def get_slot_by_method_name(self, method_name):
1294
+ # For now, only search the type struct, no referenced sub-structs.
1295
+ return self._get_slot_by_method_name(method_name)
1296
+
1297
+ def __iter__(self):
1298
+ # make it easier to iterate over all the slots
1299
+ return iter(self.slot_table)
1300
+
1301
+
1302
+ _slot_table_dict = {}
1303
+
1304
+ def get_slot_table(compiler_directives):
1305
+ if not compiler_directives:
1306
+ # fetch default directives here since the builtin type classes don't have
1307
+ # directives set
1308
+ from .Options import get_directive_defaults
1309
+ compiler_directives = get_directive_defaults()
1310
+
1311
+ old_binops = compiler_directives['c_api_binop_methods']
1312
+ key = (old_binops,)
1313
+ if key not in _slot_table_dict:
1314
+ _slot_table_dict[key] = SlotTable(old_binops=old_binops)
1315
+ return _slot_table_dict[key]
1316
+
1317
+
1318
+ # Populate "special_method_names" based on the default directives (so it can always be accessed quickly).
1319
+ special_method_names = set(get_slot_table(compiler_directives=None))
1320
+
1321
+
1322
+ # Method flags for python-exposed methods.
1323
+
1324
+ method_noargs = "METH_NOARGS"
1325
+ method_onearg = "METH_O"
1326
+ method_varargs = "METH_VARARGS"
1327
+ method_fastcall = "__Pyx_METH_FASTCALL" # Actually VARARGS on versions < 3.7
1328
+ method_keywords = "METH_KEYWORDS"
1329
+ method_coexist = "METH_COEXIST"