Skip to content

Commit 38b169e

Browse files
authored
Merge pull request RustPython#4217 from oow214/type_annotations
Add annotations for type
2 parents 268f3ae + ff057b2 commit 38b169e

File tree

3 files changed

+55
-2
lines changed

3 files changed

+55
-2
lines changed

Lib/test/test_opcodes.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ def test_setup_annotations_line(self):
3333
except OSError:
3434
pass
3535

36-
# TODO: RUSTPYTHON
37-
@unittest.expectedFailure
3836
def test_default_annotations_exist(self):
3937
class C: pass
4038
self.assertEqual(C.__annotations__, {})

vm/src/builtins/type.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,60 @@ impl PyType {
521521
Ok(())
522522
}
523523

524+
#[pygetset(magic)]
525+
fn annotations(&self, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
526+
if !self.slots.flags.has_feature(PyTypeFlags::HEAPTYPE) {
527+
return Err(vm.new_attribute_error(format!(
528+
"type object '{}' has no attribute '__annotations__'",
529+
self.name()
530+
)));
531+
}
532+
533+
let __annotations__ = identifier!(vm, __annotations__);
534+
let annotations = self.attributes.read().get(__annotations__).cloned();
535+
536+
let annotations = if let Some(annotations) = annotations {
537+
annotations
538+
} else {
539+
let annotations: PyObjectRef = vm.ctx.new_dict().into();
540+
let removed = self
541+
.attributes
542+
.write()
543+
.insert(__annotations__, annotations.clone());
544+
debug_assert!(removed.is_none());
545+
annotations
546+
};
547+
Ok(annotations)
548+
}
549+
550+
#[pygetset(magic, setter)]
551+
fn set_annotations(&self, value: Option<PyObjectRef>, vm: &VirtualMachine) -> PyResult<()> {
552+
if self.slots.flags.has_feature(PyTypeFlags::IMMUTABLETYPE) {
553+
return Err(vm.new_type_error(format!(
554+
"cannot set '__annotations__' attribute of immutable type '{}'",
555+
self.name()
556+
)));
557+
}
558+
559+
let __annotations__ = identifier!(vm, __annotations__);
560+
if let Some(value) = value {
561+
self.attributes.write().insert(__annotations__, value);
562+
} else {
563+
self.attributes
564+
.read()
565+
.get(__annotations__)
566+
.cloned()
567+
.ok_or_else(|| {
568+
vm.new_attribute_error(format!(
569+
"'{}' object has no attribute '__annotations__'",
570+
self.name()
571+
))
572+
})?;
573+
}
574+
575+
Ok(())
576+
}
577+
524578
#[pygetset(magic)]
525579
pub fn module(&self, vm: &VirtualMachine) -> PyObjectRef {
526580
self.attributes

vm/src/types/slot.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ impl std::fmt::Debug for PyTypeSlots {
105105
bitflags! {
106106
#[non_exhaustive]
107107
pub struct PyTypeFlags: u64 {
108+
const IMMUTABLETYPE = 1 << 8;
108109
const HEAPTYPE = 1 << 9;
109110
const BASETYPE = 1 << 10;
110111
const METHOD_DESCR = 1 << 17;

0 commit comments

Comments
 (0)