Skip to content

Commit 4801956

Browse files
committed
Implemente type __qualname__ setter
1 parent 6da928e commit 4801956

6 files changed

Lines changed: 38 additions & 12 deletions

File tree

Lib/test/test_pickle.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,6 @@ def test_picklebuffer_error(self): # TODO: RUSTPYTHON, remove when this passes
146146
def test_py_methods(self): # TODO: RUSTPYTHON, remove when this passes
147147
super().test_py_methods() # TODO: RUSTPYTHON, remove when this passes
148148

149-
# TODO: RUSTPYTHON, AttributeError: attribute '__qualname__' of 'type' objects is not writable
150-
@unittest.expectedFailure
151149
def test_recursive_nested_names(self): # TODO: RUSTPYTHON, remove when this passes
152150
super().test_recursive_nested_names() # TODO: RUSTPYTHON, remove when this passes
153151

@@ -251,8 +249,6 @@ def test_picklebuffer_error(self): # TODO: RUSTPYTHON, remove when this passes
251249
def test_py_methods(self): # TODO: RUSTPYTHON, remove when this passes
252250
super().test_py_methods() # TODO: RUSTPYTHON, remove when this passes
253251

254-
# TODO: RUSTPYTHON, AttributeError: attribute '__qualname__' of 'type' objects is not writable
255-
@unittest.expectedFailure
256252
def test_recursive_nested_names(self): # TODO: RUSTPYTHON, remove when this passes
257253
super().test_recursive_nested_names() # TODO: RUSTPYTHON, remove when this passes
258254

Lib/test/test_pickletools.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,6 @@ def test_picklebuffer_error(self): # TODO: RUSTPYTHON, remove when this passes
6868
def test_py_methods(self): # TODO: RUSTPYTHON, remove when this passes
6969
super().test_py_methods()
7070

71-
# TODO: RUSTPYTHON, AttributeError: attribute '__qualname__' of 'type' objects is not writable
72-
@unittest.expectedFailure
7371
def test_recursive_nested_names(self): # TODO: RUSTPYTHON, remove when this passes
7472
super().test_recursive_nested_names()
7573

Lib/test/test_typing.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4283,8 +4283,6 @@ def test_namedtuple_errors(self):
42834283
with self.assertRaises(TypeError):
42844284
NamedTuple('Emp', fields=[('name', str), ('id', int)])
42854285

4286-
# TODO: RUSTPYTHON
4287-
@unittest.expectedFailure
42884286
def test_copy_and_pickle(self):
42894287
global Emp # pickle wants to reference the class by name
42904288
Emp = NamedTuple('Emp', [('name', str), ('cool', int)])

Lib/typing.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2283,10 +2283,6 @@ def __new__(cls, typename, bases, ns):
22832283
if key in _prohibited:
22842284
raise AttributeError("Cannot overwrite NamedTuple attribute " + key)
22852285
elif key not in _special and key not in nm_tpl._fields:
2286-
# TODO: RUSTPYTHON
2287-
# Special handling for __qualname__ not to trigger RustPython bug
2288-
if key == '__qualname__':
2289-
continue
22902286
setattr(nm_tpl, key, ns[key])
22912287
return nm_tpl
22922288

extra_tests/snippets/builtin_type.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,16 @@ class D:
9999
assert D.__module__ == 'd'
100100
assert D.__qualname__ == 'DD'
101101

102+
A.__qualname__ = 'AA'
103+
B.__qualname__ = 'b'
104+
assert A.__qualname__ == 'AA'
105+
assert B.__qualname__ == 'b'
106+
with assert_raises(TypeError):
107+
del D.__qualname__
108+
with assert_raises(TypeError):
109+
C.__qualname__ = 123
110+
with assert_raises(TypeError):
111+
del int.__qualname__
102112

103113
from testutils import assert_raises
104114

vm/src/builtins/type.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,34 @@ impl PyType {
405405
.unwrap_or_else(|| vm.ctx.new_str(self.name().deref()).into())
406406
}
407407

408+
#[pyproperty(magic, setter)]
409+
fn set_qualname(&self, value: PySetterValue, vm: &VirtualMachine) -> PyResult<()> {
410+
// TODO: we should replace heaptype flag check to immutable flag check
411+
if !self.slots.flags.has_feature(PyTypeFlags::HEAPTYPE) {
412+
return Err(vm.new_type_error(format!(
413+
"cannot set '__qualname__' attribute of immutable type '{}'",
414+
self.name()
415+
)));
416+
};
417+
let value = value.ok_or_else(|| {
418+
vm.new_type_error(format!(
419+
"cannot delete '__qualname__' attribute of immutable type '{}'",
420+
self.name()
421+
))
422+
})?;
423+
if !value.class().fast_issubclass(vm.ctx.types.str_type) {
424+
return Err(vm.new_type_error(format!(
425+
"can only assign string to {}.__qualname__, not '{}'",
426+
self.name(),
427+
value.class().name()
428+
)));
429+
}
430+
self.attributes
431+
.write()
432+
.insert(identifier!(vm, __qualname__), value);
433+
Ok(())
434+
}
435+
408436
#[pyproperty(magic)]
409437
pub fn module(&self, vm: &VirtualMachine) -> PyObjectRef {
410438
self.attributes

0 commit comments

Comments
 (0)