Skip to content

Commit fb77b60

Browse files
authored
Merge branch 'main' into new
2 parents c0f50b9 + a0a98dd commit fb77b60

7 files changed

Lines changed: 101 additions & 23 deletions

File tree

Lib/test/test_buffer.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4749,6 +4749,19 @@ def __buffer__(self, flags):
47494749
c.clear()
47504750
self.assertIs(c.buffer, None)
47514751

4752+
def test_release_buffer_with_exception_set(self):
4753+
class A:
4754+
def __buffer__(self, flags):
4755+
return memoryview(bytes(8))
4756+
def __release_buffer__(self, view):
4757+
pass
4758+
4759+
b = bytearray(8)
4760+
with memoryview(b):
4761+
# now b.extend will raise an exception due to exports
4762+
with self.assertRaises(BufferError):
4763+
b.extend(A())
4764+
47524765

47534766
if __name__ == "__main__":
47544767
unittest.main()

Lib/test/test_listcomps.py

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,15 +117,15 @@ def get_output(moddict, name):
117117
newcode = code
118118
def get_output(moddict, name):
119119
return moddict[name]
120-
ns = ns or {}
120+
newns = ns.copy() if ns else {}
121121
try:
122-
exec(newcode, ns)
122+
exec(newcode, newns)
123123
except raises as e:
124124
# We care about e.g. NameError vs UnboundLocalError
125125
self.assertIs(type(e), raises)
126126
else:
127127
for k, v in (outputs or {}).items():
128-
self.assertEqual(get_output(ns, k), v)
128+
self.assertEqual(get_output(newns, k), v)
129129

130130
def test_lambdas_with_iteration_var_as_default(self):
131131
code = """
@@ -180,6 +180,26 @@ def test_closure_can_jump_over_comp_scope(self):
180180
z = [x() for x in items]
181181
"""
182182
outputs = {"z": [2, 2, 2, 2, 2]}
183+
self._check_in_scopes(code, outputs, scopes=["module", "function"])
184+
185+
def test_cell_inner_free_outer(self):
186+
code = """
187+
def f():
188+
return [lambda: x for x in (x, [1])[1]]
189+
x = ...
190+
y = [fn() for fn in f()]
191+
"""
192+
outputs = {"y": [1]}
193+
self._check_in_scopes(code, outputs, scopes=["module", "function"])
194+
195+
def test_free_inner_cell_outer(self):
196+
code = """
197+
g = 2
198+
def f():
199+
return g
200+
y = [g for x in [1]]
201+
"""
202+
outputs = {"y": [2]}
183203
self._check_in_scopes(code, outputs)
184204

185205
def test_inner_cell_shadows_outer_redefined(self):
@@ -203,6 +223,37 @@ def inner():
203223
outputs = {"x": -1}
204224
self._check_in_scopes(code, outputs, ns={"g": -1})
205225

226+
def test_explicit_global(self):
227+
code = """
228+
global g
229+
x = g
230+
g = 2
231+
items = [g for g in [1]]
232+
y = g
233+
"""
234+
outputs = {"x": 1, "y": 2, "items": [1]}
235+
self._check_in_scopes(code, outputs, ns={"g": 1})
236+
237+
def test_explicit_global_2(self):
238+
code = """
239+
global g
240+
x = g
241+
g = 2
242+
items = [g for x in [1]]
243+
y = g
244+
"""
245+
outputs = {"x": 1, "y": 2, "items": [2]}
246+
self._check_in_scopes(code, outputs, ns={"g": 1})
247+
248+
def test_explicit_global_3(self):
249+
code = """
250+
global g
251+
fns = [lambda: g for g in [2]]
252+
items = [fn() for fn in fns]
253+
"""
254+
outputs = {"items": [2]}
255+
self._check_in_scopes(code, outputs, ns={"g": 1})
256+
206257
def test_assignment_expression(self):
207258
code = """
208259
x = -1
@@ -250,7 +301,7 @@ def g():
250301
g()
251302
"""
252303
outputs = {"x": 1}
253-
self._check_in_scopes(code, outputs)
304+
self._check_in_scopes(code, outputs, scopes=["module", "function"])
254305

255306
def test_introspecting_frame_locals(self):
256307
code = """

Lib/typing.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -775,8 +775,7 @@ def Concatenate(self, parameters):
775775
"ParamSpec variable or ellipsis.")
776776
msg = "Concatenate[arg, ...]: each arg must be a type."
777777
parameters = (*(_type_check(p, msg) for p in parameters[:-1]), parameters[-1])
778-
return _ConcatenateGenericAlias(self, parameters,
779-
_paramspec_tvars=True)
778+
return _ConcatenateGenericAlias(self, parameters)
780779

781780

782781
@_SpecialForm
@@ -1307,8 +1306,7 @@ def __getattr__(self, attr):
13071306
raise AttributeError(attr)
13081307

13091308
def __setattr__(self, attr, val):
1310-
if _is_dunder(attr) or attr in {'_name', '_inst', '_nparams',
1311-
'_paramspec_tvars'}:
1309+
if _is_dunder(attr) or attr in {'_name', '_inst', '_nparams'}:
13121310
super().__setattr__(attr, val)
13131311
else:
13141312
setattr(self.__origin__, attr, val)
@@ -1362,15 +1360,13 @@ class _GenericAlias(_BaseGenericAlias, _root=True):
13621360
# ClassVar[float]
13631361
# TypeVar[bool]
13641362

1365-
def __init__(self, origin, args, *, inst=True, name=None,
1366-
_paramspec_tvars=False):
1363+
def __init__(self, origin, args, *, inst=True, name=None):
13671364
super().__init__(origin, inst=inst, name=name)
13681365
if not isinstance(args, tuple):
13691366
args = (args,)
13701367
self.__args__ = tuple(... if a is _TypingEllipsis else
13711368
a for a in args)
13721369
self.__parameters__ = _collect_parameters(args)
1373-
self._paramspec_tvars = _paramspec_tvars
13741370
if not name:
13751371
self.__module__ = origin.__module__
13761372

@@ -1513,8 +1509,7 @@ def _make_substitution(self, args, new_arg_by_param):
15131509
return new_args
15141510

15151511
def copy_with(self, args):
1516-
return self.__class__(self.__origin__, args, name=self._name, inst=self._inst,
1517-
_paramspec_tvars=self._paramspec_tvars)
1512+
return self.__class__(self.__origin__, args, name=self._name, inst=self._inst)
15181513

15191514
def __repr__(self):
15201515
if self._name:
@@ -1624,8 +1619,7 @@ def __reduce__(self):
16241619
class _CallableType(_SpecialGenericAlias, _root=True):
16251620
def copy_with(self, params):
16261621
return _CallableGenericAlias(self.__origin__, params,
1627-
name=self._name, inst=self._inst,
1628-
_paramspec_tvars=True)
1622+
name=self._name, inst=self._inst)
16291623

16301624
def __getitem__(self, params):
16311625
if not isinstance(params, tuple) or len(params) != 2:
@@ -1869,8 +1863,7 @@ def __class_getitem__(cls, params):
18691863
new_args.append(new_arg)
18701864
params = tuple(new_args)
18711865

1872-
return _GenericAlias(cls, params,
1873-
_paramspec_tvars=True)
1866+
return _GenericAlias(cls, params)
18741867

18751868
def __init_subclass__(cls, *args, **kwargs):
18761869
super().__init_subclass__(*args, **kwargs)

Lib/uuid.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
__author__ = 'Ka-Ping Yee <ping@zesty.ca>'
5454

5555
# The recognized platforms - known behaviors
56-
if sys.platform in ('win32', 'darwin'):
56+
if sys.platform in ('win32', 'darwin', 'emscripten', 'wasi'):
5757
_AIX = _LINUX = False
5858
else:
5959
import platform
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Remove undocumented and unused ``_paramspec_tvars`` attribute from some
2+
classes in :mod:`typing`.

Objects/typeobject.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9117,14 +9117,20 @@ releasebuffer_maybe_call_super(PyObject *self, Py_buffer *buffer)
91179117
static void
91189118
releasebuffer_call_python(PyObject *self, Py_buffer *buffer)
91199119
{
9120+
// bf_releasebuffer may be called while an exception is already active.
9121+
// We have no way to report additional errors up the stack, because
9122+
// this slot returns void, so we simply stash away the active exception
9123+
// and restore it after the call to Python returns.
9124+
PyObject *exc = PyErr_GetRaisedException();
9125+
91209126
PyObject *mv;
91219127
bool is_buffer_wrapper = Py_TYPE(buffer->obj) == &_PyBufferWrapper_Type;
91229128
if (is_buffer_wrapper) {
91239129
// Make sure we pass the same memoryview to
91249130
// __release_buffer__() that __buffer__() returned.
91259131
PyBufferWrapper *bw = (PyBufferWrapper *)buffer->obj;
91269132
if (bw->mv == NULL) {
9127-
return;
9133+
goto end;
91289134
}
91299135
mv = Py_NewRef(bw->mv);
91309136
}
@@ -9134,7 +9140,7 @@ releasebuffer_call_python(PyObject *self, Py_buffer *buffer)
91349140
mv = PyMemoryView_FromBuffer(buffer);
91359141
if (mv == NULL) {
91369142
PyErr_WriteUnraisable(self);
9137-
return;
9143+
goto end;
91389144
}
91399145
// Set the memoryview to restricted mode, which forbids
91409146
// users from saving any reference to the underlying buffer
@@ -9155,6 +9161,10 @@ releasebuffer_call_python(PyObject *self, Py_buffer *buffer)
91559161
PyObject_CallMethodNoArgs(mv, &_Py_ID(release));
91569162
}
91579163
Py_DECREF(mv);
9164+
end:
9165+
assert(!PyErr_Occurred());
9166+
9167+
PyErr_SetRaisedException(exc);
91589168
}
91599169

91609170
/*

Python/compile.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5028,14 +5028,19 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
50285028
long scope = (symbol >> SCOPE_OFFSET) & SCOPE_MASK;
50295029
PyObject *outv = PyDict_GetItemWithError(c->u->u_ste->ste_symbols, k);
50305030
if (outv == NULL) {
5031+
assert(PyErr_Occurred());
50315032
return ERROR;
50325033
}
50335034
assert(PyLong_Check(outv));
50345035
long outsc = (PyLong_AS_LONG(outv) >> SCOPE_OFFSET) & SCOPE_MASK;
5035-
if (scope != outsc) {
5036+
if (scope != outsc && !(scope == CELL && outsc == FREE)) {
50365037
// If a name has different scope inside than outside the
50375038
// comprehension, we need to temporarily handle it with the
5038-
// right scope while compiling the comprehension.
5039+
// right scope while compiling the comprehension. (If it's free
5040+
// in outer scope and cell in inner scope, we can't treat it as
5041+
// both cell and free in the same function, but treating it as
5042+
// free throughout is fine; it's *_DEREF either way.)
5043+
50395044
if (state->temp_symbols == NULL) {
50405045
state->temp_symbols = PyDict_New();
50415046
if (state->temp_symbols == NULL) {
@@ -5071,7 +5076,11 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
50715076
// comprehension and restore the original one after
50725077
ADDOP_NAME(c, loc, LOAD_FAST_AND_CLEAR, k, varnames);
50735078
if (scope == CELL) {
5074-
ADDOP_NAME(c, loc, MAKE_CELL, k, cellvars);
5079+
if (outsc == FREE) {
5080+
ADDOP_NAME(c, loc, MAKE_CELL, k, freevars);
5081+
} else {
5082+
ADDOP_NAME(c, loc, MAKE_CELL, k, cellvars);
5083+
}
50755084
}
50765085
if (PyList_Append(state->pushed_locals, k) < 0) {
50775086
return ERROR;

0 commit comments

Comments
 (0)