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.
- Cython/Build/BuildExecutable.py +156 -0
- Cython/Build/Cache.py +199 -0
- Cython/Build/Cythonize.py +349 -0
- Cython/Build/Dependencies.py +1276 -0
- Cython/Build/Distutils.py +1 -0
- Cython/Build/Inline.py +467 -0
- Cython/Build/IpythonMagic.py +559 -0
- Cython/Build/SharedModule.py +84 -0
- Cython/Build/Tests/TestCyCache.py +195 -0
- Cython/Build/Tests/TestCythonizeArgsParser.py +480 -0
- Cython/Build/Tests/TestDependencies.py +133 -0
- Cython/Build/Tests/TestInline.py +177 -0
- Cython/Build/Tests/TestIpythonMagic.py +303 -0
- Cython/Build/Tests/TestRecythonize.py +212 -0
- Cython/Build/Tests/TestStripLiterals.py +155 -0
- Cython/Build/Tests/__init__.py +1 -0
- Cython/Build/__init__.py +11 -0
- Cython/CodeWriter.py +815 -0
- Cython/Compiler/AnalysedTreeTransforms.py +97 -0
- Cython/Compiler/Annotate.py +328 -0
- Cython/Compiler/AutoDocTransforms.py +320 -0
- Cython/Compiler/Buffer.py +680 -0
- Cython/Compiler/Builtin.py +997 -0
- Cython/Compiler/CmdLine.py +263 -0
- Cython/Compiler/Code.cp315-win_amd64.pyd +0 -0
- Cython/Compiler/Code.pxd +152 -0
- Cython/Compiler/Code.py +3907 -0
- Cython/Compiler/CodeGeneration.py +33 -0
- Cython/Compiler/CythonScope.py +194 -0
- Cython/Compiler/Dataclass.py +890 -0
- Cython/Compiler/DebugFlags.py +24 -0
- Cython/Compiler/Errors.py +310 -0
- Cython/Compiler/ExprNodes.py +15983 -0
- Cython/Compiler/FlowControl.cp315-win_amd64.pyd +0 -0
- Cython/Compiler/FlowControl.pxd +99 -0
- Cython/Compiler/FlowControl.py +1571 -0
- Cython/Compiler/FusedNode.cp315-win_amd64.pyd +0 -0
- Cython/Compiler/FusedNode.py +976 -0
- Cython/Compiler/Future.py +16 -0
- Cython/Compiler/Interpreter.py +57 -0
- Cython/Compiler/Lexicon.py +422 -0
- Cython/Compiler/LineTable.cp315-win_amd64.pyd +0 -0
- Cython/Compiler/LineTable.py +114 -0
- Cython/Compiler/Main.py +856 -0
- Cython/Compiler/MatchCaseNodes.py +2197 -0
- Cython/Compiler/MemoryView.py +930 -0
- Cython/Compiler/ModuleNode.py +4517 -0
- Cython/Compiler/Naming.py +367 -0
- Cython/Compiler/Nodes.py +10941 -0
- Cython/Compiler/Optimize.py +5455 -0
- Cython/Compiler/Options.py +838 -0
- Cython/Compiler/ParseTreeTransforms.pxd +79 -0
- Cython/Compiler/ParseTreeTransforms.py +4744 -0
- Cython/Compiler/Parsing.cp315-win_amd64.pyd +0 -0
- Cython/Compiler/Parsing.pxd +9 -0
- Cython/Compiler/Parsing.py +4792 -0
- Cython/Compiler/Pipeline.py +439 -0
- Cython/Compiler/PyrexTypes.py +6111 -0
- Cython/Compiler/Pythran.py +232 -0
- Cython/Compiler/Scanning.cp315-win_amd64.pyd +0 -0
- Cython/Compiler/Scanning.pxd +70 -0
- Cython/Compiler/Scanning.py +720 -0
- Cython/Compiler/StringEncoding.py +297 -0
- Cython/Compiler/Symtab.py +3092 -0
- Cython/Compiler/Tests/TestBuffer.py +105 -0
- Cython/Compiler/Tests/TestBuiltin.py +117 -0
- Cython/Compiler/Tests/TestCmdLine.py +587 -0
- Cython/Compiler/Tests/TestCode.py +145 -0
- Cython/Compiler/Tests/TestFlowControl.py +65 -0
- Cython/Compiler/Tests/TestGrammar.py +202 -0
- Cython/Compiler/Tests/TestMemView.py +71 -0
- Cython/Compiler/Tests/TestParseTreeTransforms.py +285 -0
- Cython/Compiler/Tests/TestScanning.py +132 -0
- Cython/Compiler/Tests/TestSignatureMatching.py +73 -0
- Cython/Compiler/Tests/TestStringEncoding.py +20 -0
- Cython/Compiler/Tests/TestTreeFragment.py +63 -0
- Cython/Compiler/Tests/TestTreePath.py +103 -0
- Cython/Compiler/Tests/TestTypes.py +118 -0
- Cython/Compiler/Tests/TestUtilityLoad.py +112 -0
- Cython/Compiler/Tests/TestVisitor.py +61 -0
- Cython/Compiler/Tests/Utils.py +36 -0
- Cython/Compiler/Tests/__init__.py +1 -0
- Cython/Compiler/TreeFragment.py +278 -0
- Cython/Compiler/TreePath.py +303 -0
- Cython/Compiler/TypeInference.py +611 -0
- Cython/Compiler/TypeSlots.py +1329 -0
- Cython/Compiler/UFuncs.py +311 -0
- Cython/Compiler/UtilNodes.py +413 -0
- Cython/Compiler/UtilityCode.py +348 -0
- Cython/Compiler/Version.py +8 -0
- Cython/Compiler/Visitor.cp315-win_amd64.pyd +0 -0
- Cython/Compiler/Visitor.pxd +53 -0
- Cython/Compiler/Visitor.py +864 -0
- Cython/Compiler/__init__.py +1 -0
- Cython/Coverage.py +448 -0
- Cython/Debugger/Cygdb.py +177 -0
- Cython/Debugger/DebugWriter.py +82 -0
- Cython/Debugger/Tests/TestLibCython.py +280 -0
- Cython/Debugger/Tests/__init__.py +1 -0
- Cython/Debugger/Tests/cfuncs.c +8 -0
- Cython/Debugger/Tests/codefile +49 -0
- Cython/Debugger/Tests/test_libcython_in_gdb.py +580 -0
- Cython/Debugger/Tests/test_libpython_in_gdb.py +90 -0
- Cython/Debugger/__init__.py +1 -0
- Cython/Debugger/libcython.py +1548 -0
- Cython/Debugger/libpython.py +2821 -0
- Cython/Debugging.py +20 -0
- Cython/Distutils/__init__.py +2 -0
- Cython/Distutils/build_ext.py +139 -0
- Cython/Distutils/extension.py +96 -0
- Cython/Distutils/old_build_ext.py +351 -0
- Cython/Includes/cpython/__init__.pxd +173 -0
- Cython/Includes/cpython/array.pxd +152 -0
- Cython/Includes/cpython/bool.pxd +37 -0
- Cython/Includes/cpython/buffer.pxd +112 -0
- Cython/Includes/cpython/bytearray.pxd +33 -0
- Cython/Includes/cpython/bytes.pxd +200 -0
- Cython/Includes/cpython/cellobject.pxd +35 -0
- Cython/Includes/cpython/ceval.pxd +8 -0
- Cython/Includes/cpython/codecs.pxd +121 -0
- Cython/Includes/cpython/complex.pxd +60 -0
- Cython/Includes/cpython/contextvars.pxd +145 -0
- Cython/Includes/cpython/conversion.pxd +36 -0
- Cython/Includes/cpython/datetime.pxd +395 -0
- Cython/Includes/cpython/descr.pxd +26 -0
- Cython/Includes/cpython/dict.pxd +268 -0
- Cython/Includes/cpython/exc.pxd +263 -0
- Cython/Includes/cpython/fileobject.pxd +57 -0
- Cython/Includes/cpython/float.pxd +56 -0
- Cython/Includes/cpython/frozendict.pxd +37 -0
- Cython/Includes/cpython/function.pxd +65 -0
- Cython/Includes/cpython/genobject.pxd +25 -0
- Cython/Includes/cpython/getargs.pxd +12 -0
- Cython/Includes/cpython/instance.pxd +25 -0
- Cython/Includes/cpython/iterator.pxd +36 -0
- Cython/Includes/cpython/iterobject.pxd +24 -0
- Cython/Includes/cpython/list.pxd +144 -0
- Cython/Includes/cpython/long.pxd +180 -0
- Cython/Includes/cpython/longintrepr.pxd +14 -0
- Cython/Includes/cpython/mapping.pxd +63 -0
- Cython/Includes/cpython/marshal.pxd +66 -0
- Cython/Includes/cpython/mem.pxd +120 -0
- Cython/Includes/cpython/memoryview.pxd +50 -0
- Cython/Includes/cpython/method.pxd +49 -0
- Cython/Includes/cpython/module.pxd +208 -0
- Cython/Includes/cpython/number.pxd +258 -0
- Cython/Includes/cpython/object.pxd +430 -0
- Cython/Includes/cpython/pycapsule.pxd +143 -0
- Cython/Includes/cpython/pylifecycle.pxd +68 -0
- Cython/Includes/cpython/pyport.pxd +8 -0
- Cython/Includes/cpython/pystate.pxd +95 -0
- Cython/Includes/cpython/pythread.pxd +53 -0
- Cython/Includes/cpython/ref.pxd +141 -0
- Cython/Includes/cpython/sentinel.pxd +17 -0
- Cython/Includes/cpython/sequence.pxd +134 -0
- Cython/Includes/cpython/set.pxd +119 -0
- Cython/Includes/cpython/slice.pxd +70 -0
- Cython/Includes/cpython/time.pxd +129 -0
- Cython/Includes/cpython/tuple.pxd +72 -0
- Cython/Includes/cpython/type.pxd +146 -0
- Cython/Includes/cpython/unicode.pxd +639 -0
- Cython/Includes/cpython/version.pxd +32 -0
- Cython/Includes/cpython/weakref.pxd +78 -0
- Cython/Includes/libc/__init__.pxd +1 -0
- Cython/Includes/libc/complex.pxd +35 -0
- Cython/Includes/libc/errno.pxd +127 -0
- Cython/Includes/libc/float.pxd +43 -0
- Cython/Includes/libc/limits.pxd +28 -0
- Cython/Includes/libc/locale.pxd +46 -0
- Cython/Includes/libc/math.pxd +209 -0
- Cython/Includes/libc/setjmp.pxd +10 -0
- Cython/Includes/libc/signal.pxd +64 -0
- Cython/Includes/libc/stddef.pxd +9 -0
- Cython/Includes/libc/stdint.pxd +105 -0
- Cython/Includes/libc/stdio.pxd +80 -0
- Cython/Includes/libc/stdlib.pxd +72 -0
- Cython/Includes/libc/string.pxd +50 -0
- Cython/Includes/libc/threads.pxd +234 -0
- Cython/Includes/libc/time.pxd +52 -0
- Cython/Includes/libcpp/__init__.pxd +4 -0
- Cython/Includes/libcpp/algorithm.pxd +320 -0
- Cython/Includes/libcpp/any.pxd +16 -0
- Cython/Includes/libcpp/atomic.pxd +59 -0
- Cython/Includes/libcpp/barrier.pxd +22 -0
- Cython/Includes/libcpp/bit.pxd +29 -0
- Cython/Includes/libcpp/cast.pxd +12 -0
- Cython/Includes/libcpp/cmath.pxd +518 -0
- Cython/Includes/libcpp/complex.pxd +106 -0
- Cython/Includes/libcpp/condition_variable.pxd +322 -0
- Cython/Includes/libcpp/deque.pxd +165 -0
- Cython/Includes/libcpp/exception.pxd +216 -0
- Cython/Includes/libcpp/execution.pxd +15 -0
- Cython/Includes/libcpp/forward_list.pxd +63 -0
- Cython/Includes/libcpp/functional.pxd +26 -0
- Cython/Includes/libcpp/future.pxd +103 -0
- Cython/Includes/libcpp/iterator.pxd +34 -0
- Cython/Includes/libcpp/latch.pxd +17 -0
- Cython/Includes/libcpp/limits.pxd +61 -0
- Cython/Includes/libcpp/list.pxd +117 -0
- Cython/Includes/libcpp/map.pxd +252 -0
- Cython/Includes/libcpp/memory.pxd +115 -0
- Cython/Includes/libcpp/mutex.pxd +387 -0
- Cython/Includes/libcpp/numbers.pxd +15 -0
- Cython/Includes/libcpp/numeric.pxd +131 -0
- Cython/Includes/libcpp/optional.pxd +34 -0
- Cython/Includes/libcpp/pair.pxd +1 -0
- Cython/Includes/libcpp/queue.pxd +25 -0
- Cython/Includes/libcpp/random.pxd +166 -0
- Cython/Includes/libcpp/semaphore.pxd +43 -0
- Cython/Includes/libcpp/set.pxd +228 -0
- Cython/Includes/libcpp/shared_mutex.pxd +96 -0
- Cython/Includes/libcpp/span.pxd +87 -0
- Cython/Includes/libcpp/stack.pxd +11 -0
- Cython/Includes/libcpp/stop_token.pxd +117 -0
- Cython/Includes/libcpp/string.pxd +355 -0
- Cython/Includes/libcpp/string_view.pxd +183 -0
- Cython/Includes/libcpp/typeindex.pxd +15 -0
- Cython/Includes/libcpp/typeinfo.pxd +10 -0
- Cython/Includes/libcpp/unordered_map.pxd +193 -0
- Cython/Includes/libcpp/unordered_set.pxd +152 -0
- Cython/Includes/libcpp/utility.pxd +30 -0
- Cython/Includes/libcpp/vector.pxd +186 -0
- Cython/Includes/numpy/math.pxd +150 -0
- Cython/Includes/openmp.pxd +50 -0
- Cython/Includes/posix/__init__.pxd +1 -0
- Cython/Includes/posix/dlfcn.pxd +14 -0
- Cython/Includes/posix/fcntl.pxd +86 -0
- Cython/Includes/posix/ioctl.pxd +4 -0
- Cython/Includes/posix/mman.pxd +101 -0
- Cython/Includes/posix/resource.pxd +57 -0
- Cython/Includes/posix/select.pxd +21 -0
- Cython/Includes/posix/signal.pxd +73 -0
- Cython/Includes/posix/stat.pxd +98 -0
- Cython/Includes/posix/stdio.pxd +37 -0
- Cython/Includes/posix/stdlib.pxd +29 -0
- Cython/Includes/posix/strings.pxd +9 -0
- Cython/Includes/posix/time.pxd +71 -0
- Cython/Includes/posix/types.pxd +30 -0
- Cython/Includes/posix/uio.pxd +26 -0
- Cython/Includes/posix/unistd.pxd +271 -0
- Cython/Includes/posix/wait.pxd +38 -0
- Cython/LZSS.py +170 -0
- Cython/Plex/Actions.cp315-win_amd64.pyd +0 -0
- Cython/Plex/Actions.pxd +24 -0
- Cython/Plex/Actions.py +119 -0
- Cython/Plex/DFA.cp315-win_amd64.pyd +0 -0
- Cython/Plex/DFA.pxd +14 -0
- Cython/Plex/DFA.py +164 -0
- Cython/Plex/Errors.py +48 -0
- Cython/Plex/Lexicons.py +178 -0
- Cython/Plex/Machines.cp315-win_amd64.pyd +0 -0
- Cython/Plex/Machines.pxd +36 -0
- Cython/Plex/Machines.py +238 -0
- Cython/Plex/Regexps.py +535 -0
- Cython/Plex/Scanners.cp315-win_amd64.pyd +0 -0
- Cython/Plex/Scanners.pxd +45 -0
- Cython/Plex/Scanners.py +328 -0
- Cython/Plex/Transitions.cp315-win_amd64.pyd +0 -0
- Cython/Plex/Transitions.pxd +14 -0
- Cython/Plex/Transitions.py +239 -0
- Cython/Plex/__init__.py +34 -0
- Cython/Runtime/__init__.py +1 -0
- Cython/Runtime/refnanny.cp315-win_amd64.pyd +0 -0
- Cython/Runtime/refnanny.pyx +237 -0
- Cython/Shadow.py +1167 -0
- Cython/StringIOTree.cp315-win_amd64.pyd +0 -0
- Cython/StringIOTree.py +169 -0
- Cython/Tempita/__init__.py +4 -0
- Cython/Tempita/_looper.py +154 -0
- Cython/Tempita/_tempita.cp315-win_amd64.pyd +0 -0
- Cython/Tempita/_tempita.py +1087 -0
- Cython/TestUtils.py +464 -0
- Cython/Tests/TestCodeWriter.py +128 -0
- Cython/Tests/TestCythonUtils.py +202 -0
- Cython/Tests/TestJediTyper.py +223 -0
- Cython/Tests/TestShadow.py +110 -0
- Cython/Tests/TestStringIOTree.py +68 -0
- Cython/Tests/TestTestUtils.py +89 -0
- Cython/Tests/__init__.py +1 -0
- Cython/Tests/xmlrunner.py +390 -0
- Cython/Utility/AsyncGen.c +1073 -0
- Cython/Utility/Buffer.c +866 -0
- Cython/Utility/BufferFormatFromTypeInfo.pxd +2 -0
- Cython/Utility/Builtins.c +933 -0
- Cython/Utility/CConvert.pyx +149 -0
- Cython/Utility/CMath.c +104 -0
- Cython/Utility/CommonStructures.c +244 -0
- Cython/Utility/Complex.c +378 -0
- Cython/Utility/Coroutine.c +2337 -0
- Cython/Utility/CpdefEnums.pyx +107 -0
- Cython/Utility/CppConvert.pyx +282 -0
- Cython/Utility/CppSupport.cpp +151 -0
- Cython/Utility/CythonFunction.c +2072 -0
- Cython/Utility/Dataclasses.c +101 -0
- Cython/Utility/Embed.c +129 -0
- Cython/Utility/Exceptions.c +1038 -0
- Cython/Utility/ExtensionTypes.c +1158 -0
- Cython/Utility/FunctionArguments.c +1045 -0
- Cython/Utility/FusedFunction.pyx +44 -0
- Cython/Utility/ImportExport.c +930 -0
- Cython/Utility/MatchCase.c +979 -0
- Cython/Utility/MatchCase_Cy.pyx +12 -0
- Cython/Utility/MemoryView.pxd +108 -0
- Cython/Utility/MemoryView.pyx +1499 -0
- Cython/Utility/MemoryView_C.c +1056 -0
- Cython/Utility/ModuleSetupCode.c +3352 -0
- Cython/Utility/NumpyImportArray.c +46 -0
- Cython/Utility/ObjectHandling.c +3372 -0
- Cython/Utility/Optimize.c +2563 -0
- Cython/Utility/Overflow.c +378 -0
- Cython/Utility/Profile.c +736 -0
- Cython/Utility/StringTools.c +1414 -0
- Cython/Utility/Synchronization.c +438 -0
- Cython/Utility/TString.c +369 -0
- Cython/Utility/TestCyUtilityLoader.pyx +8 -0
- Cython/Utility/TestCythonScope.pyx +75 -0
- Cython/Utility/TestUtilityLoader.c +12 -0
- Cython/Utility/TypeConversion.c +1556 -0
- Cython/Utility/UFuncs.pyx +50 -0
- Cython/Utility/UFuncs_C.c +89 -0
- Cython/Utility/__init__.py +28 -0
- Cython/Utility/arrayarray.h +172 -0
- Cython/Utils.cp315-win_amd64.pyd +0 -0
- Cython/Utils.py +677 -0
- Cython/__init__.py +12 -0
- Cython/py.typed +0 -0
- cython-3.3.0a1.dist-info/METADATA +394 -0
- cython-3.3.0a1.dist-info/RECORD +335 -0
- cython-3.3.0a1.dist-info/WHEEL +5 -0
- cython-3.3.0a1.dist-info/entry_points.txt +4 -0
- cython-3.3.0a1.dist-info/top_level.txt +3 -0
- cython.py +29 -0
- pyximport/__init__.py +4 -0
- pyximport/pyxbuild.py +160 -0
- 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"
|