diff --git a/Lib/test/test_property.py b/Lib/test/test_property.py index 09123e08ae..5312925d93 100644 --- a/Lib/test/test_property.py +++ b/Lib/test/test_property.py @@ -226,6 +226,23 @@ def test_property_set_name_incorrect_args(self): ): p.__set_name__(*([0] * i)) + def test_property_setname_on_property_subclass(self): + # https://github.com/python/cpython/issues/100942 + # Copy was setting the name field without first + # verifying that the copy was an actual property + # instance. As a result, the code below was + # causing a segfault. + + class pro(property): + def __new__(typ, *args, **kwargs): + return "abcdef" + + class A: + pass + + p = property.__new__(pro) + p.__set_name__(A, 1) + np = p.getter(lambda self: 1) # Issue 5890: subclasses of property do not preserve method __doc__ strings class PropertySub(property): @@ -341,43 +358,35 @@ def _format_exc_msg(self, msg): def setUpClass(cls): cls.obj = cls.cls() + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_get_property(self): - with self.assertRaisesRegex(AttributeError, self._format_exc_msg("unreadable attribute")): + with self.assertRaisesRegex(AttributeError, self._format_exc_msg("has no getter")): self.obj.foo + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_set_property(self): - with self.assertRaisesRegex(AttributeError, self._format_exc_msg("can't set attribute")): + with self.assertRaisesRegex(AttributeError, self._format_exc_msg("has no setter")): self.obj.foo = None + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_del_property(self): - with self.assertRaisesRegex(AttributeError, self._format_exc_msg("can't delete attribute")): + with self.assertRaisesRegex(AttributeError, self._format_exc_msg("has no deleter")): del self.obj.foo class PropertyUnreachableAttributeWithName(_PropertyUnreachableAttribute, unittest.TestCase): - msg_format = "^{} 'foo'$" + msg_format = r"^property 'foo' of 'PropertyUnreachableAttributeWithName\.cls' object {}$" class cls: foo = property() - # TODO: RUSTPYTHON - @unittest.expectedFailure - def test_get_property(self): # TODO: RUSTPYTHON; remove this function when the test is fixed - super().test_get_property() - - # TODO: RUSTPYTHON - @unittest.expectedFailure - def test_set_property(self): # TODO: RUSTPYTHON; remove this function when the test is fixed - super().test_get_property() - - # TODO: RUSTPYTHON - @unittest.expectedFailure - def test_del_property(self): # TODO: RUSTPYTHON; remove this function when the test is fixed - super().test_get_property() class PropertyUnreachableAttributeNoName(_PropertyUnreachableAttribute, unittest.TestCase): - msg_format = "^{}$" + msg_format = r"^property of 'PropertyUnreachableAttributeNoName\.cls' object {}$" class cls: pass diff --git a/vm/src/builtins/property.rs b/vm/src/builtins/property.rs index 7322ba7d08..e572f081eb 100644 --- a/vm/src/builtins/property.rs +++ b/vm/src/builtins/property.rs @@ -51,7 +51,7 @@ impl GetDescriptor for PyProperty { } else if let Some(getter) = zelf.getter.read().as_ref() { getter.call((obj,), vm) } else { - Err(vm.new_attribute_error("unreadable attribute".to_string())) + Err(vm.new_attribute_error("property has no getter".to_string())) } } } @@ -73,14 +73,14 @@ impl PyProperty { if let Some(setter) = zelf.setter.read().as_ref() { setter.call((obj, value), vm).map(drop) } else { - Err(vm.new_attribute_error("can't set attribute".to_owned())) + Err(vm.new_attribute_error("property has no setter".to_owned())) } } PySetterValue::Delete => { if let Some(deleter) = zelf.deleter.read().as_ref() { deleter.call((obj,), vm).map(drop) } else { - Err(vm.new_attribute_error("can't delete attribute".to_owned())) + Err(vm.new_attribute_error("property has no deleter".to_owned())) } } }