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