mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
__doc__ handing in the right way (#6390)
This commit is contained in:
1
Lib/test/test_property.py
vendored
1
Lib/test/test_property.py
vendored
@@ -342,7 +342,6 @@ class PropertySubclassTests(unittest.TestCase):
|
||||
with self.assertRaises(AttributeError):
|
||||
p = slotted_prop(documented_getter)
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
@unittest.skipIf(sys.flags.optimize >= 2,
|
||||
"Docstrings are omitted with -O2 and above")
|
||||
def test_property_with_slots_and_doc_slot_docstring_present(self):
|
||||
|
||||
4
Lib/test/test_typing.py
vendored
4
Lib/test/test_typing.py
vendored
@@ -5269,7 +5269,7 @@ class GenericTests(BaseTestCase):
|
||||
for t in things:
|
||||
self.assertEqual(weakref.ref(t)(), t)
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON - __slots__ with Generic doesn't prevent new attributes
|
||||
def test_parameterized_slots(self):
|
||||
T = TypeVar('T')
|
||||
class C(Generic[T]):
|
||||
@@ -5289,7 +5289,7 @@ class GenericTests(BaseTestCase):
|
||||
self.assertEqual(get_type_hints(foo, globals(), locals())['x'], C[C])
|
||||
self.assertEqual(copy(C[int]), deepcopy(C[int]))
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON - __slots__ with Generic doesn't prevent new attributes
|
||||
def test_parameterized_slots_dict(self):
|
||||
T = TypeVar('T')
|
||||
class D(Generic[T]):
|
||||
|
||||
@@ -2679,10 +2679,12 @@ impl Compiler {
|
||||
let qualname_name = self.name("__qualname__");
|
||||
emit!(self, Instruction::StoreLocal(qualname_name));
|
||||
|
||||
// Store __doc__
|
||||
self.load_docstring(doc_str);
|
||||
let doc = self.name("__doc__");
|
||||
emit!(self, Instruction::StoreLocal(doc));
|
||||
// Store __doc__ only if there's an explicit docstring
|
||||
if let Some(doc) = doc_str {
|
||||
self.emit_load_const(ConstantData::Str { value: doc.into() });
|
||||
let doc_name = self.name("__doc__");
|
||||
emit!(self, Instruction::StoreLocal(doc_name));
|
||||
}
|
||||
|
||||
// Store __firstlineno__ (new in Python 3.12+)
|
||||
self.emit_load_const(ConstantData::Integer {
|
||||
@@ -2876,17 +2878,6 @@ impl Compiler {
|
||||
self.store_name(name)
|
||||
}
|
||||
|
||||
fn load_docstring(&mut self, doc_str: Option<String>) {
|
||||
// TODO: __doc__ must be default None and no bytecode unless it is Some
|
||||
// Duplicate top of stack (the function or class object)
|
||||
|
||||
// Doc string value:
|
||||
self.emit_load_const(match doc_str {
|
||||
Some(doc) => ConstantData::Str { value: doc.into() },
|
||||
None => ConstantData::None, // set docstring None if not declared
|
||||
});
|
||||
}
|
||||
|
||||
fn compile_while(&mut self, test: &Expr, body: &[Stmt], orelse: &[Stmt]) -> CompileResult<()> {
|
||||
let while_block = self.new_block();
|
||||
let else_block = self.new_block();
|
||||
|
||||
@@ -1198,11 +1198,10 @@ impl Constructor for PyType {
|
||||
member: member_def,
|
||||
});
|
||||
|
||||
let attr_name = vm.ctx.intern_str(member.to_string());
|
||||
if !typ.has_attr(attr_name) {
|
||||
typ.set_attr(attr_name, member_descriptor.into());
|
||||
}
|
||||
|
||||
let attr_name = vm.ctx.intern_str(member.as_str());
|
||||
// __slots__ attributes always get a member descriptor
|
||||
// (this overrides any inherited attribute from MRO)
|
||||
typ.set_attr(attr_name, member_descriptor.into());
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
@@ -1236,6 +1235,16 @@ impl Constructor for PyType {
|
||||
}
|
||||
}
|
||||
|
||||
// Set __doc__ to None if not already present in the type's dict
|
||||
// This matches CPython's behavior in type_dict_set_doc (typeobject.c)
|
||||
// which ensures every type has a __doc__ entry in its dict
|
||||
{
|
||||
let __doc__ = identifier!(vm, __doc__);
|
||||
if !typ.attributes.read().contains_key(&__doc__) {
|
||||
typ.attributes.write().insert(__doc__, vm.ctx.none());
|
||||
}
|
||||
}
|
||||
|
||||
// avoid deadlock
|
||||
let attributes = typ
|
||||
.attributes
|
||||
@@ -1377,8 +1386,9 @@ impl Py<PyType> {
|
||||
return Ok(vm.ctx.new_str(doc_str).into());
|
||||
}
|
||||
|
||||
// Check if there's a __doc__ in the type's dict
|
||||
if let Some(doc_attr) = self.get_attr(vm.ctx.intern_str("__doc__")) {
|
||||
// Check if there's a __doc__ in THIS type's dict only (not MRO)
|
||||
// CPython returns None if __doc__ is not in the type's own dict
|
||||
if let Some(doc_attr) = self.get_direct_attr(vm.ctx.intern_str("__doc__")) {
|
||||
// If it's a descriptor, call its __get__ method
|
||||
let descr_get = doc_attr
|
||||
.class()
|
||||
|
||||
@@ -186,7 +186,7 @@ A.b()
|
||||
class A:
|
||||
pass
|
||||
|
||||
assert A.__doc__ == None
|
||||
assert A.__doc__ is None, A.__doc__
|
||||
|
||||
class B:
|
||||
"Docstring"
|
||||
|
||||
Reference in New Issue
Block a user