Skip to content

feat(vm/slot): implement Py_TPFLAGS_MANAGED_DICT for class objects #5949

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions Lib/test/test_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -1285,8 +1285,6 @@ def check_overflow(self, lower, upper):
self.assertRaises(OverflowError, array.array, self.typecode, [upper+1])
self.assertRaises(OverflowError, a.__setitem__, 0, upper+1)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_subclassing(self):
typecode = self.typecode
class ExaggeratingArray(array.array):
Expand Down
17 changes: 14 additions & 3 deletions Lib/test/test_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -851,7 +851,11 @@ def __init__(self, obj):
except ImportError:
has_inline_values = None

Py_TPFLAGS_MANAGED_DICT = (1 << 2)

Py_TPFLAGS_MANAGED_DICT = (1 << 4)

class NoManagedDict:
__slots__ = ('a',)

class Plain:
pass
Expand All @@ -865,11 +869,18 @@ def __init__(self):
self.c = 3
self.d = 4


class TestInlineValues(unittest.TestCase):
class TestNoManagedValues(unittest.TestCase):
def test_flags(self):
self.assertEqual(NoManagedDict.__flags__ & Py_TPFLAGS_MANAGED_DICT, 0)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_no_inline_values_for_slots_class(self):
c = NoManagedDict()
self.assertFalse(has_inline_values(c))

class TestInlineValues(unittest.TestCase):

def test_flags(self):
self.assertEqual(Plain.__flags__ & Py_TPFLAGS_MANAGED_DICT, Py_TPFLAGS_MANAGED_DICT)
self.assertEqual(WithAttrs.__flags__ & Py_TPFLAGS_MANAGED_DICT, Py_TPFLAGS_MANAGED_DICT)
Expand Down
2 changes: 0 additions & 2 deletions Lib/test/test_importlib/test_metadata_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,6 @@ def test_entry_points_missing_name(self):
def test_entry_points_missing_group(self):
assert entry_points(group='missing') == ()

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_entry_points_allows_no_attributes(self):
ep = entry_points().select(group='entries', name='main')
with self.assertRaises(AttributeError):
Expand Down
2 changes: 0 additions & 2 deletions Lib/test/test_property.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,6 @@ class PropertySubSlots(property):

class PropertySubclassTests(unittest.TestCase):

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_slots_docstring_copy_exception(self):
try:
class Foo(object):
Expand Down
2 changes: 0 additions & 2 deletions Lib/test/test_weakref.py
Original file line number Diff line number Diff line change
Expand Up @@ -1068,8 +1068,6 @@ class MyRef(weakref.ref):
self.assertIn(r1, refs)
self.assertIn(r2, refs)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_subclass_refs_with_slots(self):
class MyRef(weakref.ref):
__slots__ = "slot1", "slot2"
Expand Down
10 changes: 6 additions & 4 deletions vm/src/builtins/type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1019,9 +1019,6 @@ impl Constructor for PyType {
.into()
});

// TODO: Flags is currently initialized with HAS_DICT. Should be
// updated when __slots__ are supported (toggling the flag off if
// a class has __slots__ defined).
let heaptype_slots: Option<PyTupleTyped<PyStrRef>> =
if let Some(x) = attributes.get(identifier!(vm, __slots__)) {
Some(if x.to_owned().class().is(vm.ctx.types.str_type) {
Expand Down Expand Up @@ -1053,7 +1050,12 @@ impl Constructor for PyType {
let heaptype_member_count = heaptype_slots.as_ref().map(|x| x.len()).unwrap_or(0);
let member_count: usize = base_member_count + heaptype_member_count;

let flags = PyTypeFlags::heap_type_flags() | PyTypeFlags::HAS_DICT;
let mut flags = PyTypeFlags::heap_type_flags();
// Only add HAS_DICT and MANAGED_DICT if __slots__ is not defined.
if heaptype_slots.is_none() {
flags |= PyTypeFlags::HAS_DICT | PyTypeFlags::MANAGED_DICT;
}

let (slots, heaptype_ext) = {
let slots = PyTypeSlots {
flags,
Expand Down
1 change: 1 addition & 0 deletions vm/src/types/slot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ bitflags! {
#[derive(Copy, Clone, Debug, PartialEq)]
#[non_exhaustive]
pub struct PyTypeFlags: u64 {
const MANAGED_DICT = 1 << 4;
const IMMUTABLETYPE = 1 << 8;
const HEAPTYPE = 1 << 9;
const BASETYPE = 1 << 10;
Expand Down
Loading