Skip to content

Commit c91f27c

Browse files
committed
Fix nonlocal type param check, __class_getitem__, __set_name__ note, sre module names
- Reject nonlocal binding for type parameters in symboltable - Enable __class_getitem__ on memoryview, Template, Interpolation - Fix __set_name__ error note to quote attribute name - Set re.Match and re.Pattern module to "re" instead of "_sre" - Migrate parking_lot::Mutex to PyMutex in typevar.rs - Collapse nested if-let chains in typing_type_repr (clippy) - Remove 5 expectedFailure markers from test files
1 parent d1e8122 commit c91f27c

11 files changed

Lines changed: 62 additions & 39 deletions

File tree

Lib/test/test_re.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2107,7 +2107,6 @@ def test_issue17998(self):
21072107
self.assertEqual(re.compile(pattern, re.S).findall(b'xyz'),
21082108
[b'xyz'], msg=pattern)
21092109

2110-
@unittest.expectedFailure # TODO: RUSTPYTHON
21112110
def test_match_repr(self):
21122111
for string in '[abracadabra]', S('[abracadabra]'):
21132112
m = re.search(r'(.+)(.*?)\1', string)

Lib/test/test_type_params.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,6 @@ def inner[X]():
165165
"""
166166
check_syntax_error(self, code)
167167

168-
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: SyntaxError not raised
169168
def test_nonlocal_disallowed_02(self):
170169
code = """
171170
def outer2[T]():
@@ -174,7 +173,6 @@ def inner1():
174173
"""
175174
check_syntax_error(self, textwrap.dedent(code))
176175

177-
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: SyntaxError not raised
178176
def test_nonlocal_disallowed_03(self):
179177
code = """
180178
class Cls[T]:

Lib/test/test_typing.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8437,7 +8437,6 @@ class Bar(NamedTuple):
84378437
self.assertIsInstance(bar.attr, Vanilla)
84388438
self.assertEqual(bar.attr.name, "attr")
84398439

8440-
@unittest.expectedFailure # TODO: RUSTPYTHON; + Error calling __set_name__ on 'Annoying' instance attr in 'NamedTupleClass'
84418440
def test_setname_raises_the_same_as_on_other_classes(self):
84428441
class CustomException(BaseException): pass
84438442

@@ -9433,7 +9432,6 @@ def test_repr(self):
94339432
self.assertEqual(repr(Match[str]), 'typing.Match[str]')
94349433
self.assertEqual(repr(Match[bytes]), 'typing.Match[bytes]')
94359434

9436-
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: "type 're\.Match' is not an acceptable base type" does not match "type '_sre.Match' is not an acceptable base type"
94379435
def test_cannot_subclass(self):
94389436
with self.assertRaisesRegex(
94399437
TypeError,

crates/codegen/src/symboltable.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,6 @@ impl SymbolTableAnalyzer {
528528
if !self.tables.as_ref().is_empty() {
529529
let scope_depth = self.tables.as_ref().len();
530530
// check if the name is already defined in any outer scope
531-
// therefore
532531
if scope_depth < 2
533532
|| self.found_in_outer_scope(&symbol.name, st_typ)
534533
!= Some(SymbolScope::Free)
@@ -539,6 +538,25 @@ impl SymbolTableAnalyzer {
539538
location: None,
540539
});
541540
}
541+
// Check if the nonlocal binding refers to a type parameter
542+
if symbol.flags.contains(SymbolFlags::NONLOCAL) {
543+
for (symbols, _typ) in self.tables.iter().rev() {
544+
if let Some(sym) = symbols.get(&symbol.name) {
545+
if sym.flags.contains(SymbolFlags::TYPE_PARAM) {
546+
return Err(SymbolTableError {
547+
error: format!(
548+
"nonlocal binding not allowed for type parameter '{}'",
549+
symbol.name
550+
),
551+
location: None,
552+
});
553+
}
554+
if sym.is_bound() {
555+
break;
556+
}
557+
}
558+
}
559+
}
542560
} else {
543561
return Err(SymbolTableError {
544562
error: format!(

crates/vm/src/builtins/interpolation.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use super::{PyStr, PyStrRef, PyTupleRef, PyType, tuple::IntoPyTuple};
1+
use super::{
2+
PyStr, PyStrRef, PyTupleRef, PyType, PyTypeRef, genericalias::PyGenericAlias,
3+
tuple::IntoPyTuple,
4+
};
25
use crate::{
36
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
47
class::PyClassImpl,
@@ -135,6 +138,11 @@ impl PyInterpolation {
135138
self.format_spec.clone()
136139
}
137140

141+
#[pyclassmethod]
142+
fn __class_getitem__(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
143+
PyGenericAlias::from_args(cls, args, vm)
144+
}
145+
138146
#[pymethod]
139147
fn __reduce__(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyTupleRef {
140148
let cls = zelf.class().to_owned();

crates/vm/src/builtins/memory.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -552,8 +552,7 @@ impl Py<PyMemoryView> {
552552
flags(SEQUENCE)
553553
)]
554554
impl PyMemoryView {
555-
// TODO: Uncomment when Python adds __class_getitem__ to memoryview
556-
// #[pyclassmethod]
555+
#[pyclassmethod]
557556
fn __class_getitem__(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
558557
PyGenericAlias::from_args(cls, args, vm)
559558
}

crates/vm/src/builtins/template.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
use super::{PyStr, PyTupleRef, PyType};
2-
use crate::common::lock::LazyLock;
1+
use super::{PyStr, PyTupleRef, PyType, PyTypeRef, genericalias::PyGenericAlias};
32
use crate::{
43
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
54
atomic_func,
65
class::PyClassImpl,
6+
common::lock::LazyLock,
77
function::{FuncArgs, PyComparisonValue},
88
protocol::{PyIterReturn, PySequenceMethods},
99
types::{
@@ -178,6 +178,11 @@ impl PyTemplate {
178178
self.concat(&other, vm)
179179
}
180180

181+
#[pyclassmethod]
182+
fn __class_getitem__(cls: PyTypeRef, args: PyObjectRef, vm: &VirtualMachine) -> PyGenericAlias {
183+
PyGenericAlias::from_args(cls, args, vm)
184+
}
185+
181186
#[pymethod]
182187
fn __reduce__(&self, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
183188
// Import string.templatelib._template_unpickle

crates/vm/src/builtins/type.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1629,7 +1629,7 @@ impl Constructor for PyType {
16291629
// PEP 678: Add a note to the original exception instead of wrapping it
16301630
// (Python 3.12+, gh-77757)
16311631
let note = format!(
1632-
"Error calling __set_name__ on '{}' instance {} in '{}'",
1632+
"Error calling __set_name__ on '{}' instance '{}' in '{}'",
16331633
obj.class().name(),
16341634
name,
16351635
typ.name()

crates/vm/src/stdlib/sre.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ mod _sre {
190190
}
191191

192192
#[pyattr]
193-
#[pyclass(name = "Pattern")]
193+
#[pyclass(module = "re", name = "Pattern")]
194194
#[derive(Debug, PyPayload)]
195195
pub(crate) struct Pattern {
196196
pub pattern: PyObjectRef,
@@ -597,7 +597,7 @@ mod _sre {
597597
}
598598

599599
#[pyattr]
600-
#[pyclass(name = "Match")]
600+
#[pyclass(module = "re", name = "Match")]
601601
#[derive(Debug, PyPayload)]
602602
pub(crate) struct Match {
603603
string: PyObjectRef,

crates/vm/src/stdlib/typevar.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,11 @@ pub(crate) mod typevar {
6969
#[allow(dead_code)]
7070
pub struct TypeVar {
7171
name: PyObjectRef, // TODO PyStrRef?
72-
bound: parking_lot::Mutex<PyObjectRef>,
72+
bound: PyMutex<PyObjectRef>,
7373
evaluate_bound: PyObjectRef,
74-
constraints: parking_lot::Mutex<PyObjectRef>,
74+
constraints: PyMutex<PyObjectRef>,
7575
evaluate_constraints: PyObjectRef,
76-
default_value: parking_lot::Mutex<PyObjectRef>,
76+
default_value: PyMutex<PyObjectRef>,
7777
evaluate_default: PyMutex<PyObjectRef>,
7878
covariant: bool,
7979
contravariant: bool,
@@ -396,11 +396,11 @@ pub(crate) mod typevar {
396396

397397
Ok(Self {
398398
name,
399-
bound: parking_lot::Mutex::new(bound_obj),
399+
bound: PyMutex::new(bound_obj),
400400
evaluate_bound,
401-
constraints: parking_lot::Mutex::new(constraints_obj),
401+
constraints: PyMutex::new(constraints_obj),
402402
evaluate_constraints,
403-
default_value: parking_lot::Mutex::new(default_value),
403+
default_value: PyMutex::new(default_value),
404404
evaluate_default: PyMutex::new(evaluate_default),
405405
covariant,
406406
contravariant,
@@ -418,11 +418,11 @@ pub(crate) mod typevar {
418418
) -> Self {
419419
Self {
420420
name,
421-
bound: parking_lot::Mutex::new(vm.ctx.none()),
421+
bound: PyMutex::new(vm.ctx.none()),
422422
evaluate_bound,
423-
constraints: parking_lot::Mutex::new(vm.ctx.none()),
423+
constraints: PyMutex::new(vm.ctx.none()),
424424
evaluate_constraints,
425-
default_value: parking_lot::Mutex::new(vm.ctx.typing_no_default.clone().into()),
425+
default_value: PyMutex::new(vm.ctx.typing_no_default.clone().into()),
426426
evaluate_default: PyMutex::new(vm.ctx.none()),
427427
covariant: false,
428428
contravariant: false,
@@ -438,7 +438,7 @@ pub(crate) mod typevar {
438438
pub struct ParamSpec {
439439
name: PyObjectRef,
440440
bound: Option<PyObjectRef>,
441-
default_value: parking_lot::Mutex<PyObjectRef>,
441+
default_value: PyMutex<PyObjectRef>,
442442
evaluate_default: PyMutex<PyObjectRef>,
443443
covariant: bool,
444444
contravariant: bool,
@@ -637,7 +637,7 @@ pub(crate) mod typevar {
637637
let paramspec = Self {
638638
name,
639639
bound,
640-
default_value: parking_lot::Mutex::new(default_value),
640+
default_value: PyMutex::new(default_value),
641641
evaluate_default: PyMutex::new(vm.ctx.none()),
642642
covariant,
643643
contravariant,
@@ -668,7 +668,7 @@ pub(crate) mod typevar {
668668
Self {
669669
name,
670670
bound: None,
671-
default_value: parking_lot::Mutex::new(vm.ctx.typing_no_default.clone().into()),
671+
default_value: PyMutex::new(vm.ctx.typing_no_default.clone().into()),
672672
evaluate_default: PyMutex::new(vm.ctx.none()),
673673
covariant: false,
674674
contravariant: false,
@@ -683,7 +683,7 @@ pub(crate) mod typevar {
683683
#[allow(dead_code)]
684684
pub struct TypeVarTuple {
685685
name: PyObjectRef,
686-
default_value: parking_lot::Mutex<PyObjectRef>,
686+
default_value: PyMutex<PyObjectRef>,
687687
evaluate_default: PyMutex<PyObjectRef>,
688688
}
689689
#[pyclass(flags(HAS_DICT), with(Constructor, Representable, Iterable))]
@@ -813,7 +813,7 @@ pub(crate) mod typevar {
813813

814814
let typevartuple = Self {
815815
name,
816-
default_value: parking_lot::Mutex::new(default_value),
816+
default_value: PyMutex::new(default_value),
817817
evaluate_default: PyMutex::new(evaluate_default),
818818
};
819819

@@ -840,7 +840,7 @@ pub(crate) mod typevar {
840840
pub fn new(name: PyObjectRef, vm: &VirtualMachine) -> Self {
841841
Self {
842842
name,
843-
default_value: parking_lot::Mutex::new(vm.ctx.typing_no_default.clone().into()),
843+
default_value: PyMutex::new(vm.ctx.typing_no_default.clone().into()),
844844
evaluate_default: PyMutex::new(vm.ctx.none()),
845845
}
846846
}

0 commit comments

Comments
 (0)