Cython 3.2.4__py3-none-any.whl → 3.2.6__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/Cache.py +1 -1
- Cython/Build/Dependencies.py +1 -1
- Cython/Build/SharedModule.py +8 -17
- Cython/Build/Tests/TestCyCache.py +1 -0
- Cython/Build/Tests/TestInline.py +1 -1
- Cython/Compiler/Code.py +20 -5
- Cython/Compiler/CythonScope.py +3 -0
- Cython/Compiler/ExprNodes.py +2 -2
- Cython/Compiler/FlowControl.py +23 -7
- Cython/Compiler/MemoryView.py +3 -0
- Cython/Compiler/ModuleNode.py +1 -0
- Cython/Compiler/Nodes.py +7 -6
- Cython/Compiler/Optimize.py +7 -2
- Cython/Compiler/PyrexTypes.py +8 -2
- Cython/Compiler/Scanning.py +9 -0
- Cython/Compiler/Tests/TestBuiltin.py +11 -1
- Cython/Compiler/TreeFragment.py +2 -2
- Cython/Compiler/UtilityCode.py +4 -1
- Cython/Includes/cpython/array.pxd +3 -29
- Cython/Includes/libcpp/mutex.pxd +6 -6
- Cython/Includes/libcpp/vector.pxd +4 -4
- Cython/Runtime/refnanny.pyx +6 -6
- Cython/Shadow.py +1 -1
- Cython/Tempita/_tempita.py +0 -3
- Cython/Utility/Builtins.c +1 -0
- Cython/Utility/Coroutine.c +26 -29
- Cython/Utility/CpdefEnums.pyx +6 -2
- Cython/Utility/CythonFunction.c +56 -6
- Cython/Utility/FunctionArguments.c +1 -1
- Cython/Utility/MemoryView.pxd +8 -9
- Cython/Utility/MemoryView.pyx +10 -105
- Cython/Utility/MemoryView_C.c +130 -4
- Cython/Utility/ObjectHandling.c +2 -2
- Cython/Utility/Optimize.c +4 -4
- Cython/Utility/StringTools.c +6 -9
- Cython/Utility/TString.c +1 -1
- Cython/Utility/arrayarray.h +6 -1
- Cython/Utils.py +2 -0
- cython-3.2.6.dist-info/METADATA +93 -0
- {cython-3.2.4.dist-info → cython-3.2.6.dist-info}/RECORD +43 -43
- {cython-3.2.4.dist-info → cython-3.2.6.dist-info}/WHEEL +1 -1
- cython-3.2.4.dist-info/METADATA +0 -158
- {cython-3.2.4.dist-info → cython-3.2.6.dist-info}/entry_points.txt +0 -0
- {cython-3.2.4.dist-info → cython-3.2.6.dist-info}/top_level.txt +0 -0
Cython/Build/Cache.py
CHANGED
|
@@ -152,7 +152,7 @@ class Cache:
|
|
|
152
152
|
dirname = os.path.dirname(c_file)
|
|
153
153
|
with zipfile.ZipFile(cached) as z:
|
|
154
154
|
for artifact in z.namelist():
|
|
155
|
-
z.extract(artifact,
|
|
155
|
+
z.extract(artifact, dirname)
|
|
156
156
|
else:
|
|
157
157
|
raise ValueError(f"Unsupported cache file extension: {ext}")
|
|
158
158
|
|
Cython/Build/Dependencies.py
CHANGED
|
@@ -52,7 +52,7 @@ def extended_iglob(pattern):
|
|
|
52
52
|
# because '/' is generally common for relative paths.
|
|
53
53
|
if '**/' in pattern or os.sep == '\\' and '**\\' in pattern:
|
|
54
54
|
seen = set()
|
|
55
|
-
first, rest = re.split(r'\*\*[%s]' % ('/\\\\' if os.sep == '\\' else '/'), pattern, 1)
|
|
55
|
+
first, rest = re.split(r'\*\*[%s]' % ('/\\\\' if os.sep == '\\' else '/'), pattern, maxsplit=1)
|
|
56
56
|
if first:
|
|
57
57
|
first = iglob(first + os.sep)
|
|
58
58
|
else:
|
Cython/Build/SharedModule.py
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import os
|
|
2
|
-
import re
|
|
3
|
-
import shutil
|
|
4
|
-
import tempfile
|
|
5
2
|
|
|
6
3
|
from Cython.Compiler import (
|
|
7
4
|
MemoryView, Code, Options, Pipeline, Errors, Main, Symtab
|
|
8
5
|
)
|
|
9
6
|
from Cython.Compiler.StringEncoding import EncodedString
|
|
10
|
-
from Cython.Compiler.Scanning import
|
|
7
|
+
from Cython.Compiler.Scanning import SharedUtilitySourceDescriptor
|
|
11
8
|
|
|
12
9
|
|
|
13
10
|
def create_shared_library_pipeline(context, scope, options, result):
|
|
@@ -72,23 +69,17 @@ def generate_shared_module(options):
|
|
|
72
69
|
Errors.open_listing_file(None)
|
|
73
70
|
|
|
74
71
|
dest_c_file = options.shared_c_file_path
|
|
72
|
+
pyx_file = os.path.splitext(dest_c_file)[0] + '.pyx'
|
|
75
73
|
module_name = os.path.splitext(os.path.basename(dest_c_file))[0]
|
|
76
74
|
|
|
77
75
|
context = Main.Context.from_options(options)
|
|
78
76
|
scope = Symtab.ModuleScope('MemoryView', parent_module = None, context = context, is_package=False)
|
|
79
77
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
comp_src = Main.CompilationSource(source_desc, EncodedString(module_name), os.getcwd())
|
|
87
|
-
result = Main.create_default_resultobj(comp_src, options)
|
|
88
|
-
|
|
89
|
-
pipeline = create_shared_library_pipeline(context, scope, options, result)
|
|
90
|
-
err, enddata = Pipeline.run_pipeline(pipeline, comp_src)
|
|
91
|
-
if err is None:
|
|
92
|
-
shutil.copy(c_file, dest_c_file)
|
|
78
|
+
source_desc = SharedUtilitySourceDescriptor(pyx_file)
|
|
79
|
+
comp_src = Main.CompilationSource(source_desc, EncodedString(module_name), os.getcwd())
|
|
80
|
+
result = Main.create_default_resultobj(comp_src, options)
|
|
81
|
+
|
|
82
|
+
pipeline = create_shared_library_pipeline(context, scope, options, result)
|
|
83
|
+
err, enddata = Pipeline.run_pipeline(pipeline, comp_src)
|
|
93
84
|
|
|
94
85
|
return err, enddata
|
|
@@ -149,6 +149,7 @@ class TestCyCache(CythonTest):
|
|
|
149
149
|
|
|
150
150
|
for output in expected:
|
|
151
151
|
self.assertTrue(os.path.exists(output), output)
|
|
152
|
+
self.assertTrue(os.path.isfile(output), output)
|
|
152
153
|
|
|
153
154
|
def test_multi_file_output_cythonize(self):
|
|
154
155
|
self._test_multi_file_output(self.fresh_cythonize)
|
Cython/Build/Tests/TestInline.py
CHANGED
|
@@ -125,7 +125,7 @@ class TestCymeit(unittest.TestCase):
|
|
|
125
125
|
self.assertGreaterEqual(max_time, 100_000)
|
|
126
126
|
else:
|
|
127
127
|
self.assertGreaterEqual(max_time, 0.0001)
|
|
128
|
-
self.assertGreater(number,
|
|
128
|
+
self.assertGreater(number, 4) # arbitrary lower bound for our very quick benchmarks
|
|
129
129
|
|
|
130
130
|
return timings
|
|
131
131
|
|
Cython/Compiler/Code.py
CHANGED
|
@@ -95,7 +95,7 @@ basicsize_builtins_map = {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
# Builtins as of Python version ...
|
|
98
|
-
KNOWN_PYTHON_BUILTINS_VERSION = (3,
|
|
98
|
+
KNOWN_PYTHON_BUILTINS_VERSION = (3, 15, 0, 'beta', 1)
|
|
99
99
|
KNOWN_PYTHON_BUILTINS = frozenset([
|
|
100
100
|
'ArithmeticError',
|
|
101
101
|
'AssertionError',
|
|
@@ -125,6 +125,7 @@ KNOWN_PYTHON_BUILTINS = frozenset([
|
|
|
125
125
|
'FutureWarning',
|
|
126
126
|
'GeneratorExit',
|
|
127
127
|
'IOError',
|
|
128
|
+
'ImportCycleError',
|
|
128
129
|
'ImportError',
|
|
129
130
|
'ImportWarning',
|
|
130
131
|
'IndentationError',
|
|
@@ -176,6 +177,7 @@ KNOWN_PYTHON_BUILTINS = frozenset([
|
|
|
176
177
|
'_IncompleteInputError',
|
|
177
178
|
'__build_class__',
|
|
178
179
|
'__debug__',
|
|
180
|
+
'__lazy_import__',
|
|
179
181
|
'__import__',
|
|
180
182
|
'abs',
|
|
181
183
|
'aiter',
|
|
@@ -206,6 +208,7 @@ KNOWN_PYTHON_BUILTINS = frozenset([
|
|
|
206
208
|
'filter',
|
|
207
209
|
'float',
|
|
208
210
|
'format',
|
|
211
|
+
'frozendict',
|
|
209
212
|
'frozenset',
|
|
210
213
|
'getattr',
|
|
211
214
|
'globals',
|
|
@@ -240,6 +243,7 @@ KNOWN_PYTHON_BUILTINS = frozenset([
|
|
|
240
243
|
'repr',
|
|
241
244
|
'reversed',
|
|
242
245
|
'round',
|
|
246
|
+
'sentinel',
|
|
243
247
|
'set',
|
|
244
248
|
'setattr',
|
|
245
249
|
'slice',
|
|
@@ -257,6 +261,11 @@ KNOWN_PYTHON_BUILTINS = frozenset([
|
|
|
257
261
|
uncachable_builtins = [
|
|
258
262
|
# Global/builtin names that cannot be cached because they may or may not
|
|
259
263
|
# be available at import time, for various reasons:
|
|
264
|
+
## Python 3.15+
|
|
265
|
+
'frozendict',
|
|
266
|
+
'sentinel',
|
|
267
|
+
'ImportCycleError',
|
|
268
|
+
'__lazy_import__',
|
|
260
269
|
## Python 3.13+
|
|
261
270
|
'_IncompleteInputError',
|
|
262
271
|
'PythonFinalizationError',
|
|
@@ -267,11 +276,10 @@ uncachable_builtins = [
|
|
|
267
276
|
'aiter',
|
|
268
277
|
'anext',
|
|
269
278
|
'EncodingWarning',
|
|
270
|
-
## - Py3.7+
|
|
271
|
-
'breakpoint', # might deserve an implementation in Cython
|
|
272
279
|
## - platform specific
|
|
273
280
|
'WindowsError',
|
|
274
281
|
## - others
|
|
282
|
+
'breakpoint', # Probably best left alone.
|
|
275
283
|
'_', # e.g. used by gettext
|
|
276
284
|
]
|
|
277
285
|
|
|
@@ -2421,19 +2429,26 @@ class GlobalState:
|
|
|
2421
2429
|
writer.putln("{")
|
|
2422
2430
|
writer.putln(f"PyObject **table = {array_cname};")
|
|
2423
2431
|
writer.putln(f"for (Py_ssize_t i=0; i<{constant_count}; ++i) {{")
|
|
2424
|
-
writer.putln("#if
|
|
2432
|
+
writer.putln("#if PY_VERSION_HEX >= 0x030F0000")
|
|
2433
|
+
writer.putln("PyUnstable_SetImmortal(table[i]);")
|
|
2434
|
+
writer.putln("#elif CYTHON_COMPILING_IN_CPYTHON_FREETHREADING")
|
|
2425
2435
|
# We don't want to set the refcount on shared constants (e.g. cached integers)
|
|
2426
2436
|
# because setting the refcount isn't thread-safe. The chances are that most of the constants
|
|
2427
2437
|
# that this applies to are already immortal though so that isn't a great loss.
|
|
2438
|
+
# Overflow, e.g. on 32 bit systems.
|
|
2439
|
+
writer.putln("if ((PY_SSIZE_T_MAX <= _Py_IMMORTAL_REFCNT_LOCAL)) break;")
|
|
2428
2440
|
writer.putln("#if PY_VERSION_HEX < 0x030E0000")
|
|
2429
2441
|
writer.putln("if (_Py_IsOwnedByCurrentThread(table[i]) && Py_REFCNT(table[i]) == 1)")
|
|
2430
2442
|
writer.putln("#else")
|
|
2431
2443
|
writer.putln("if (PyUnstable_Object_IsUniquelyReferenced(table[i]))")
|
|
2432
2444
|
writer.putln("#endif")
|
|
2433
2445
|
writer.putln("{")
|
|
2434
|
-
|
|
2446
|
+
# Go one higher than we think we need to because of a bug in SET_REFCNT check in CPython
|
|
2447
|
+
writer.putln("Py_SET_REFCNT(table[i], ((Py_ssize_t)_Py_IMMORTAL_REFCNT_LOCAL + 1));")
|
|
2435
2448
|
writer.putln("}")
|
|
2436
2449
|
writer.putln("#else")
|
|
2450
|
+
# Overflow, e.g. on 32 bit systems.
|
|
2451
|
+
writer.putln("if ((PY_SSIZE_T_MAX < _Py_IMMORTAL_INITIAL_REFCNT)) break;")
|
|
2437
2452
|
writer.putln("Py_SET_REFCNT(table[i], _Py_IMMORTAL_INITIAL_REFCNT);")
|
|
2438
2453
|
writer.putln("#endif")
|
|
2439
2454
|
writer.putln("}") # for()
|
Cython/Compiler/CythonScope.py
CHANGED
|
@@ -6,6 +6,7 @@ from .Scanning import StringSourceDescriptor
|
|
|
6
6
|
from . import MemoryView
|
|
7
7
|
from .StringEncoding import EncodedString
|
|
8
8
|
|
|
9
|
+
NON_TYPE_NAMES = {'pointer', 'const', 'volatile', 'restrict', 'struct', 'union', 'enum'}
|
|
9
10
|
|
|
10
11
|
class CythonScope(ModuleScope):
|
|
11
12
|
is_cython_builtin = 1
|
|
@@ -42,6 +43,8 @@ class CythonScope(ModuleScope):
|
|
|
42
43
|
|
|
43
44
|
def lookup_type(self, name):
|
|
44
45
|
# This function should go away when types are all first-level objects.
|
|
46
|
+
if name in NON_TYPE_NAMES:
|
|
47
|
+
return None
|
|
45
48
|
type = parse_basic_type(name)
|
|
46
49
|
if type:
|
|
47
50
|
return type
|
Cython/Compiler/ExprNodes.py
CHANGED
|
@@ -7551,7 +7551,7 @@ class MergedDictNode(ExprNode):
|
|
|
7551
7551
|
items = ((key.constant_result, value.constant_result)
|
|
7552
7552
|
for key, value in item.key_value_pairs)
|
|
7553
7553
|
else:
|
|
7554
|
-
items = item.constant_result.
|
|
7554
|
+
items = item.constant_result.items()
|
|
7555
7555
|
|
|
7556
7556
|
for key, value in items:
|
|
7557
7557
|
if reject_duplicates and key in result:
|
|
@@ -7569,7 +7569,7 @@ class MergedDictNode(ExprNode):
|
|
|
7569
7569
|
items = [(key.compile_time_value(denv), value.compile_time_value(denv))
|
|
7570
7570
|
for key, value in item.key_value_pairs]
|
|
7571
7571
|
else:
|
|
7572
|
-
items = item.compile_time_value(denv).
|
|
7572
|
+
items = item.compile_time_value(denv).items()
|
|
7573
7573
|
|
|
7574
7574
|
try:
|
|
7575
7575
|
for key, value in items:
|
Cython/Compiler/FlowControl.py
CHANGED
|
@@ -85,6 +85,18 @@ class ControlBlock:
|
|
|
85
85
|
self.children.add(block)
|
|
86
86
|
block.parents.add(self)
|
|
87
87
|
|
|
88
|
+
def print(self, level=0, seen=None):
|
|
89
|
+
if seen is None:
|
|
90
|
+
seen = set()
|
|
91
|
+
print(f"{' '*level}{self} {'*' if self in seen else ''}")
|
|
92
|
+
if self in seen:
|
|
93
|
+
return
|
|
94
|
+
for stat in self.stats:
|
|
95
|
+
print(f"{' '*(level+1)}-{stat}")
|
|
96
|
+
seen.add(self)
|
|
97
|
+
for child in self.children:
|
|
98
|
+
child.print(level+1, seen)
|
|
99
|
+
|
|
88
100
|
|
|
89
101
|
class ExitBlock(ControlBlock):
|
|
90
102
|
"""Non-empty exit point block."""
|
|
@@ -926,8 +938,9 @@ class ControlFlowAnalysis(CythonTransform):
|
|
|
926
938
|
parent = self.flow.block
|
|
927
939
|
# If clauses
|
|
928
940
|
for clause in node.if_clauses:
|
|
929
|
-
|
|
941
|
+
self.flow.nextblock(parent)
|
|
930
942
|
self._visit(clause.condition)
|
|
943
|
+
parent = self.flow.block
|
|
931
944
|
self.flow.nextblock()
|
|
932
945
|
self._visit(clause.body)
|
|
933
946
|
if self.flow.block:
|
|
@@ -974,6 +987,7 @@ class ControlFlowAnalysis(CythonTransform):
|
|
|
974
987
|
self.flow.loops.append(LoopDescr(next_block, condition_block))
|
|
975
988
|
if node.condition:
|
|
976
989
|
self._visit(node.condition)
|
|
990
|
+
condition_block_end = self.flow.block
|
|
977
991
|
# Body block
|
|
978
992
|
self.flow.nextblock()
|
|
979
993
|
self._visit(node.body)
|
|
@@ -984,12 +998,12 @@ class ControlFlowAnalysis(CythonTransform):
|
|
|
984
998
|
self.flow.block.add_child(next_block)
|
|
985
999
|
# Else clause
|
|
986
1000
|
if node.else_clause:
|
|
987
|
-
self.flow.nextblock(parent=
|
|
1001
|
+
self.flow.nextblock(parent=condition_block_end)
|
|
988
1002
|
self._visit(node.else_clause)
|
|
989
1003
|
if self.flow.block:
|
|
990
1004
|
self.flow.block.add_child(next_block)
|
|
991
1005
|
else:
|
|
992
|
-
|
|
1006
|
+
condition_block_end.add_child(next_block)
|
|
993
1007
|
|
|
994
1008
|
if next_block.parents:
|
|
995
1009
|
self.flow.block = next_block
|
|
@@ -1072,6 +1086,7 @@ class ControlFlowAnalysis(CythonTransform):
|
|
|
1072
1086
|
# Condition with iterator
|
|
1073
1087
|
self.flow.loops.append(LoopDescr(next_block, condition_block))
|
|
1074
1088
|
self._visit(node.iterator)
|
|
1089
|
+
condition_block_end = self.flow.block
|
|
1075
1090
|
# Target assignment
|
|
1076
1091
|
self.flow.nextblock()
|
|
1077
1092
|
|
|
@@ -1096,12 +1111,12 @@ class ControlFlowAnalysis(CythonTransform):
|
|
|
1096
1111
|
self.flow.block.add_child(condition_block)
|
|
1097
1112
|
# Else clause
|
|
1098
1113
|
if node.else_clause:
|
|
1099
|
-
self.flow.nextblock(parent=
|
|
1114
|
+
self.flow.nextblock(parent=condition_block_end)
|
|
1100
1115
|
self._visit(node.else_clause)
|
|
1101
1116
|
if self.flow.block:
|
|
1102
1117
|
self.flow.block.add_child(next_block)
|
|
1103
1118
|
else:
|
|
1104
|
-
|
|
1119
|
+
condition_block_end.add_child(next_block)
|
|
1105
1120
|
|
|
1106
1121
|
if next_block.parents:
|
|
1107
1122
|
self.flow.block = next_block
|
|
@@ -1152,6 +1167,7 @@ class ControlFlowAnalysis(CythonTransform):
|
|
|
1152
1167
|
self._visit(node.bound2)
|
|
1153
1168
|
if node.step is not None:
|
|
1154
1169
|
self._visit(node.step)
|
|
1170
|
+
condition_block_end = self.flow.block
|
|
1155
1171
|
# Target assignment
|
|
1156
1172
|
self.flow.nextblock()
|
|
1157
1173
|
self.mark_assignment(node.target, node.bound1)
|
|
@@ -1167,12 +1183,12 @@ class ControlFlowAnalysis(CythonTransform):
|
|
|
1167
1183
|
self.flow.block.add_child(condition_block)
|
|
1168
1184
|
# Else clause
|
|
1169
1185
|
if node.else_clause:
|
|
1170
|
-
self.flow.nextblock(parent=
|
|
1186
|
+
self.flow.nextblock(parent=condition_block_end)
|
|
1171
1187
|
self._visit(node.else_clause)
|
|
1172
1188
|
if self.flow.block:
|
|
1173
1189
|
self.flow.block.add_child(next_block)
|
|
1174
1190
|
else:
|
|
1175
|
-
|
|
1191
|
+
condition_block_end.add_child(next_block)
|
|
1176
1192
|
|
|
1177
1193
|
if next_block.parents:
|
|
1178
1194
|
self.flow.block = next_block
|
Cython/Compiler/MemoryView.py
CHANGED
|
@@ -301,6 +301,7 @@ class MemoryViewSliceBufferEntry(Buffer.BufferEntry):
|
|
|
301
301
|
util_name = "SimpleSlice"
|
|
302
302
|
else:
|
|
303
303
|
util_name = "ToughSlice"
|
|
304
|
+
code.globalstate.use_utility_code(slice_memviewslice_utility)
|
|
304
305
|
d['error_goto'] = code.error_goto(index.pos)
|
|
305
306
|
|
|
306
307
|
new_ndim += 1
|
|
@@ -847,6 +848,7 @@ refcount_utility = load_memview_c_utility("MemviewRefcount")
|
|
|
847
848
|
slice_init_utility = load_memview_c_utility("MemviewSliceInit")
|
|
848
849
|
memviewslice_declare_code = load_memview_c_utility("MemviewSliceStruct", context=template_context)
|
|
849
850
|
copy_contents_new_utility = load_memview_c_utility("MemviewSliceCopy")
|
|
851
|
+
slice_memviewslice_utility = load_memview_c_utility("SliceMemoryviewSlice")
|
|
850
852
|
|
|
851
853
|
|
|
852
854
|
@Utils.cached_function
|
|
@@ -863,6 +865,7 @@ def _get_memoryview_utility_code():
|
|
|
863
865
|
is_contig_utility,
|
|
864
866
|
overlapping_utility,
|
|
865
867
|
copy_contents_new_utility,
|
|
868
|
+
slice_memviewslice_utility,
|
|
866
869
|
],
|
|
867
870
|
)
|
|
868
871
|
|
Cython/Compiler/ModuleNode.py
CHANGED
|
@@ -1401,6 +1401,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
|
|
|
1401
1401
|
for method_entry in scope.cfunc_entries:
|
|
1402
1402
|
if not method_entry.is_inherited:
|
|
1403
1403
|
code.putln("%s;" % method_entry.type.declaration_code("(*%s)" % method_entry.cname))
|
|
1404
|
+
code.globalstate.use_entry_utility_code(method_entry)
|
|
1404
1405
|
code.putln("};")
|
|
1405
1406
|
|
|
1406
1407
|
def generate_exttype_vtabptr_declaration(self, entry, code):
|
Cython/Compiler/Nodes.py
CHANGED
|
@@ -646,11 +646,12 @@ class CArrayDeclaratorNode(CDeclaratorNode):
|
|
|
646
646
|
error(self.dimension.pos, "Array dimension cannot be const variable")
|
|
647
647
|
size = (self.dimension.constant_result if isinstance(self.dimension.constant_result, int)
|
|
648
648
|
else self.dimension.get_constant_c_result_code())
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
649
|
+
if size is not None:
|
|
650
|
+
try:
|
|
651
|
+
size = int(size)
|
|
652
|
+
except ValueError:
|
|
653
|
+
# runtime constant?
|
|
654
|
+
pass
|
|
654
655
|
|
|
655
656
|
if not base_type.is_complete():
|
|
656
657
|
error(self.pos, "Array element type '%s' is incomplete" % base_type)
|
|
@@ -4276,7 +4277,7 @@ class DefNodeWrapper(FuncDefNode):
|
|
|
4276
4277
|
f"{'' if accept_kwd_args else 'unlikely'}({Naming.kwds_cname}) ? "
|
|
4277
4278
|
f"__Pyx_NumKwargs_{self.signature.fastvar}({Naming.kwds_cname}) : 0;"
|
|
4278
4279
|
)
|
|
4279
|
-
code.putln(f"if (unlikely({Naming.kwds_len_cname}
|
|
4280
|
+
code.putln(f"if (unlikely({Naming.kwds_len_cname} < 0)) {goto_error}")
|
|
4280
4281
|
|
|
4281
4282
|
kw_unpacking_condition = f"{Naming.kwds_len_cname} > 0"
|
|
4282
4283
|
if self.num_required_kw_args > 0:
|
Cython/Compiler/Optimize.py
CHANGED
|
@@ -2882,7 +2882,11 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
|
|
|
2882
2882
|
# Map the separate type checks to check functions.
|
|
2883
2883
|
|
|
2884
2884
|
if types and (allowed_none_node or len(types) > 1):
|
|
2885
|
-
|
|
2885
|
+
# Only literals and simple (non-temp) name lookups are safe to use multiple times
|
|
2886
|
+
# without caching. Everything else — attributes, calls, walrus operators, temps,
|
|
2887
|
+
# etc. — must be evaluated exactly once and its result cached in a ResultRefNode
|
|
2888
|
+
# to avoid repeated evaluation across the short-circuit OR branches.
|
|
2889
|
+
if not (arg.is_literal or (arg.is_name and not arg.is_temp)):
|
|
2886
2890
|
arg = UtilNodes.ResultRefNode(arg)
|
|
2887
2891
|
temps.append(arg)
|
|
2888
2892
|
|
|
@@ -3531,7 +3535,8 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
|
|
|
3531
3535
|
PyUnicode_uchar_predicate_func_type = PyrexTypes.CFuncType(
|
|
3532
3536
|
PyrexTypes.c_bint_type, [
|
|
3533
3537
|
PyrexTypes.CFuncTypeArg("uchar", PyrexTypes.c_py_ucs4_type, None),
|
|
3534
|
-
]
|
|
3538
|
+
],
|
|
3539
|
+
exception_value=-1)
|
|
3535
3540
|
|
|
3536
3541
|
def _inject_unicode_predicate(self, node, function, args, is_unbound_method):
|
|
3537
3542
|
if is_unbound_method or len(args) != 1:
|
Cython/Compiler/PyrexTypes.py
CHANGED
|
@@ -4689,6 +4689,8 @@ class CTupleType(CType):
|
|
|
4689
4689
|
|
|
4690
4690
|
_convert_to_py_code = None
|
|
4691
4691
|
_convert_from_py_code = None
|
|
4692
|
+
to_py_function = None
|
|
4693
|
+
from_py_function = None
|
|
4692
4694
|
|
|
4693
4695
|
def __init__(self, cname, components):
|
|
4694
4696
|
from .Builtin import tuple_type
|
|
@@ -4696,8 +4698,6 @@ class CTupleType(CType):
|
|
|
4696
4698
|
self.components = components
|
|
4697
4699
|
self.equivalent_type = tuple_type
|
|
4698
4700
|
self.size = len(components)
|
|
4699
|
-
self.to_py_function = f"{Naming.convert_func_prefix}_to_py_{self.cname}"
|
|
4700
|
-
self.from_py_function = f"{Naming.convert_func_prefix}_from_py_{self.cname}"
|
|
4701
4701
|
|
|
4702
4702
|
def __str__(self):
|
|
4703
4703
|
return "(%s)" % ", ".join(str(c) for c in self.components)
|
|
@@ -4732,6 +4732,7 @@ class CTupleType(CType):
|
|
|
4732
4732
|
return False
|
|
4733
4733
|
|
|
4734
4734
|
if self._convert_to_py_code is None:
|
|
4735
|
+
self.to_py_function = f"{Naming.convert_func_prefix}_to_py_{self.cname}"
|
|
4735
4736
|
context = dict(
|
|
4736
4737
|
struct_type_decl=self.empty_declaration_code(),
|
|
4737
4738
|
components=self.components,
|
|
@@ -4755,6 +4756,7 @@ class CTupleType(CType):
|
|
|
4755
4756
|
return False
|
|
4756
4757
|
|
|
4757
4758
|
if self._convert_from_py_code is None:
|
|
4759
|
+
self.from_py_function = f"{Naming.convert_func_prefix}_from_py_{self.cname}"
|
|
4758
4760
|
context = dict(
|
|
4759
4761
|
struct_type_decl=self.empty_declaration_code(),
|
|
4760
4762
|
components=self.components,
|
|
@@ -5545,6 +5547,10 @@ def independent_spanning_type(type1, type2):
|
|
|
5545
5547
|
return resolved_type1
|
|
5546
5548
|
# e.g. PyInt + double => object
|
|
5547
5549
|
return py_object_type
|
|
5550
|
+
elif resolved_type1.is_builtin_type and resolved_type2.is_builtin_type:
|
|
5551
|
+
# Either numeric or incompatible. Do not try to find a widest Python type
|
|
5552
|
+
# (e.g. int+float => float) as it would change one of the result types.
|
|
5553
|
+
return py_object_type
|
|
5548
5554
|
|
|
5549
5555
|
span_type = _spanning_type(type1, type2)
|
|
5550
5556
|
if span_type is None:
|
Cython/Compiler/Scanning.py
CHANGED
|
@@ -281,6 +281,15 @@ class StringSourceDescriptor(SourceDescriptor):
|
|
|
281
281
|
return "<StringSourceDescriptor:%s>" % self.name
|
|
282
282
|
|
|
283
283
|
|
|
284
|
+
class SharedUtilitySourceDescriptor(FileSourceDescriptor):
|
|
285
|
+
"""
|
|
286
|
+
A specialized source descriptor for shared utility code only. Not part of public API.
|
|
287
|
+
"""
|
|
288
|
+
|
|
289
|
+
def get_file_object(self, encoding=None, error_handling=None):
|
|
290
|
+
from io import StringIO
|
|
291
|
+
return StringIO('')
|
|
292
|
+
|
|
284
293
|
#------------------------------------------------------------------
|
|
285
294
|
|
|
286
295
|
class PyrexScanner(Scanner):
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import builtins
|
|
2
|
+
import json
|
|
3
|
+
import subprocess
|
|
2
4
|
import sys
|
|
3
5
|
import unittest
|
|
4
6
|
|
|
@@ -41,9 +43,17 @@ class TestBuiltinCompatibility(unittest.TestCase):
|
|
|
41
43
|
expected_builtins = set(KNOWN_PYTHON_BUILTINS)
|
|
42
44
|
if sys.platform != 'win32':
|
|
43
45
|
expected_builtins.discard("WindowsError")
|
|
46
|
+
|
|
47
|
+
# Read builtins from fresh Python process to prevent modifications by test dependencies.
|
|
48
|
+
output = subprocess.run(
|
|
49
|
+
[sys.executable, '-c', 'import builtins, json, sys; sys.stdout.write(json.dumps(dir(builtins)))'],
|
|
50
|
+
capture_output=True,
|
|
51
|
+
encoding='utf8',
|
|
52
|
+
)
|
|
44
53
|
runtime_builtins = frozenset(
|
|
45
|
-
name for name in
|
|
54
|
+
name for name in json.loads(output.stdout)
|
|
46
55
|
if name not in ('__doc__', '__loader__', '__name__', '__package__', '__spec__'))
|
|
56
|
+
|
|
47
57
|
if sys.version_info < KNOWN_PYTHON_BUILTINS_VERSION:
|
|
48
58
|
missing_builtins = expected_builtins - runtime_builtins
|
|
49
59
|
if missing_builtins:
|
Cython/Compiler/TreeFragment.py
CHANGED
|
@@ -22,12 +22,12 @@ from . import UtilNodes
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
class StringParseContext(Main.Context):
|
|
25
|
-
def __init__(self, name, include_directories=None, compiler_directives=None, cpp=False):
|
|
25
|
+
def __init__(self, name, include_directories=None, compiler_directives=None, cpp=False, options=None):
|
|
26
26
|
if include_directories is None:
|
|
27
27
|
include_directories = []
|
|
28
28
|
if compiler_directives is None:
|
|
29
29
|
compiler_directives = {}
|
|
30
|
-
Main.Context.__init__(self, include_directories, compiler_directives, cpp=cpp, language_level='3')
|
|
30
|
+
Main.Context.__init__(self, include_directories, compiler_directives, cpp=cpp, language_level='3', options=options)
|
|
31
31
|
self.module_name = name
|
|
32
32
|
|
|
33
33
|
def find_module(self, module_name, from_module=None, pos=None, need_pxd=1, absolute_fallback=True, relative_import=False):
|
Cython/Compiler/UtilityCode.py
CHANGED
|
@@ -125,7 +125,8 @@ class CythonUtilityCode(Code.UtilityCodeBase):
|
|
|
125
125
|
from . import Pipeline, ParseTreeTransforms
|
|
126
126
|
context = CythonUtilityCodeContext(
|
|
127
127
|
self.name, compiler_directives=self.compiler_directives,
|
|
128
|
-
cpp=cython_scope.is_cpp() if cython_scope else False
|
|
128
|
+
cpp=cython_scope.is_cpp() if cython_scope else False,
|
|
129
|
+
options=cython_scope.context.options if cython_scope else None)
|
|
129
130
|
context.prefix = self.prefix
|
|
130
131
|
context.cython_scope = cython_scope
|
|
131
132
|
#context = StringParseContext(self.name)
|
|
@@ -327,6 +328,8 @@ class CythonSharedUtilityCode(Code.AbstractUtilityCode):
|
|
|
327
328
|
dep.declare_in_scope(scope, cython_scope=cython_scope)
|
|
328
329
|
for e in self._shared_library_scope.c_class_entries:
|
|
329
330
|
dest_scope.add_imported_entry(e.name, e, e.pos)
|
|
331
|
+
for e in self._shared_library_scope.var_entries:
|
|
332
|
+
dest_scope.add_imported_entry(e.name, e, e.pos)
|
|
330
333
|
return dest_scope
|
|
331
334
|
|
|
332
335
|
def get_shared_library_scope(self, cython_scope):
|
|
@@ -70,7 +70,9 @@ cdef extern from *: # Hard-coded utility code hack.
|
|
|
70
70
|
ctypedef object GETF(array a, Py_ssize_t ix)
|
|
71
71
|
ctypedef object SETF(array a, Py_ssize_t ix, object o)
|
|
72
72
|
ctypedef struct arraydescr: # [object arraydescr]:
|
|
73
|
-
char typecode
|
|
73
|
+
char typecode "typecode_char" # backwards compatibility only
|
|
74
|
+
char typecode_char # Python <= 3.14
|
|
75
|
+
char typecode_array[3] # Python 3.15+
|
|
74
76
|
int itemsize
|
|
75
77
|
GETF getitem # PyObject * (*getitem)(struct arrayobject *, Py_ssize_t);
|
|
76
78
|
SETF setitem # int (*setitem)(struct arrayobject *, Py_ssize_t, PyObject *);
|
|
@@ -104,34 +106,6 @@ cdef extern from *: # Hard-coded utility code hack.
|
|
|
104
106
|
cdef inline __data_union data(self) noexcept nogil:
|
|
105
107
|
return __Pyx_PyArray_Data(self)
|
|
106
108
|
|
|
107
|
-
def __getbuffer__(self, Py_buffer* info, int flags):
|
|
108
|
-
# This implementation of getbuffer is geared towards Cython
|
|
109
|
-
# requirements, and does not yet fulfill the PEP.
|
|
110
|
-
# In particular strided access is always provided regardless
|
|
111
|
-
# of flags
|
|
112
|
-
item_count = Py_SIZE(self)
|
|
113
|
-
|
|
114
|
-
info.suboffsets = NULL
|
|
115
|
-
info.buf = self.data.as_chars
|
|
116
|
-
info.readonly = 0
|
|
117
|
-
info.ndim = 1
|
|
118
|
-
info.itemsize = self.ob_descr.itemsize # e.g. sizeof(float)
|
|
119
|
-
info.len = info.itemsize * item_count
|
|
120
|
-
|
|
121
|
-
info.shape = <Py_ssize_t*> PyObject_Malloc(sizeof(Py_ssize_t) + 2)
|
|
122
|
-
if not info.shape:
|
|
123
|
-
raise MemoryError()
|
|
124
|
-
info.shape[0] = item_count # constant regardless of resizing
|
|
125
|
-
info.strides = &info.itemsize
|
|
126
|
-
|
|
127
|
-
info.format = <char*> (info.shape + 1)
|
|
128
|
-
info.format[0] = self.ob_descr.typecode
|
|
129
|
-
info.format[1] = 0
|
|
130
|
-
info.obj = self
|
|
131
|
-
|
|
132
|
-
def __releasebuffer__(self, Py_buffer* info):
|
|
133
|
-
PyObject_Free(info.shape)
|
|
134
|
-
|
|
135
109
|
array newarrayobject(PyTypeObject* type, Py_ssize_t size, arraydescr *descr)
|
|
136
110
|
|
|
137
111
|
__data_union __Pyx_PyArray_Data(array self) noexcept nogil
|
Cython/Includes/libcpp/mutex.pxd
CHANGED
|
@@ -158,7 +158,7 @@ cdef extern from *:
|
|
|
158
158
|
|
|
159
159
|
namespace {
|
|
160
160
|
|
|
161
|
-
|
|
161
|
+
CYTHON_UNUSED PyGILState_STATE __pyx_libcpp_mutex_limited_api_ensure_gil() {
|
|
162
162
|
#if CYTHON_COMPILING_IN_LIMITED_API
|
|
163
163
|
if ((__PYX_LIMITED_VERSION_HEX < 0x030d0000) && __Pyx_get_runtime_version() < 0x030d0000) {
|
|
164
164
|
return PyGILState_Ensure();
|
|
@@ -168,7 +168,7 @@ cdef extern from *:
|
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
#if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030d0000
|
|
171
|
-
|
|
171
|
+
CYTHON_UNUSED void __pyx_libcpp_mutex_limited_api_release_gil(PyGILState_STATE gil_state) {
|
|
172
172
|
if (__Pyx_get_runtime_version() < 0x030d0000)
|
|
173
173
|
PyGILState_Release(gil_state);
|
|
174
174
|
}
|
|
@@ -176,7 +176,7 @@ cdef extern from *:
|
|
|
176
176
|
#define __pyx_libcpp_mutex_limited_api_release_gil(ignore) (void)ignore
|
|
177
177
|
#endif
|
|
178
178
|
|
|
179
|
-
|
|
179
|
+
CYTHON_UNUSED int __pyx_libcpp_mutex_has_gil() {
|
|
180
180
|
#if CYTHON_COMPILING_IN_LIMITED_API
|
|
181
181
|
if ((__PYX_LIMITED_VERSION_HEX >= 0x030d0000) || __Pyx_get_runtime_version() >= 0x030d0000) {
|
|
182
182
|
// In 3.13+ we can temporarily give up the GIL to find out what the thread state was
|
|
@@ -232,7 +232,7 @@ cdef extern from *:
|
|
|
232
232
|
}
|
|
233
233
|
|
|
234
234
|
template <typename Callable, typename ... Args>
|
|
235
|
-
void __pyx_cpp_py_safe_call_once(std::once_flag& flag, Callable
|
|
235
|
+
void __pyx_cpp_py_safe_call_once(std::once_flag& flag, Callable&& callable, Args&&... args) {
|
|
236
236
|
class PyException : public std::exception {
|
|
237
237
|
public:
|
|
238
238
|
using std::exception::exception;
|
|
@@ -246,7 +246,7 @@ cdef extern from *:
|
|
|
246
246
|
|
|
247
247
|
try {
|
|
248
248
|
std::call_once(flag,
|
|
249
|
-
[&](Args
|
|
249
|
+
[&](Args&& ...args) {
|
|
250
250
|
// Make sure we have the GIL
|
|
251
251
|
PyGILState_STATE gil_state;
|
|
252
252
|
int had_gil_on_call = __Pyx_UnknownThreadStateDefinitelyHadGil(thread_state);
|
|
@@ -296,7 +296,7 @@ cdef extern from *:
|
|
|
296
296
|
std::lock(arg0, arg1, args...);
|
|
297
297
|
}
|
|
298
298
|
|
|
299
|
-
inline void __pyx_libcpp_mutex_unlock() {} // no-op
|
|
299
|
+
CYTHON_UNUSED inline void __pyx_libcpp_mutex_unlock() {} // no-op
|
|
300
300
|
|
|
301
301
|
template <typename Lockable0T, typename ... Lockables>
|
|
302
302
|
void __pyx_libcpp_mutex_unlock(Lockable0T& arg0, Lockables&... locks) {
|
|
@@ -79,8 +79,8 @@ cdef extern from "<vector>" namespace "std" nogil:
|
|
|
79
79
|
reverse_iterator operator--(int)
|
|
80
80
|
reverse_iterator operator+(size_type)
|
|
81
81
|
reverse_iterator operator-(size_type)
|
|
82
|
-
difference_type operator-(
|
|
83
|
-
difference_type operator-(
|
|
82
|
+
difference_type operator-(reverse_iterator)
|
|
83
|
+
difference_type operator-(const_reverse_iterator)
|
|
84
84
|
bint operator==(reverse_iterator)
|
|
85
85
|
bint operator==(const_reverse_iterator)
|
|
86
86
|
bint operator!=(reverse_iterator)
|
|
@@ -104,8 +104,8 @@ cdef extern from "<vector>" namespace "std" nogil:
|
|
|
104
104
|
const_reverse_iterator operator--(int)
|
|
105
105
|
const_reverse_iterator operator+(size_type)
|
|
106
106
|
const_reverse_iterator operator-(size_type)
|
|
107
|
-
difference_type operator-(
|
|
108
|
-
difference_type operator-(
|
|
107
|
+
difference_type operator-(reverse_iterator)
|
|
108
|
+
difference_type operator-(const_reverse_iterator)
|
|
109
109
|
bint operator==(reverse_iterator)
|
|
110
110
|
bint operator==(const_reverse_iterator)
|
|
111
111
|
bint operator!=(reverse_iterator)
|