Fix abc error message (#4987)

* Print correct error message for abc instantiation

* Update dataclasses abc test
This commit is contained in:
Patrick
2023-05-23 03:43:52 -04:00
committed by GitHub
parent e864e26592
commit 0e24cf48c6
4 changed files with 26 additions and 21 deletions

12
Lib/test/test_abc.py vendored
View File

@@ -149,8 +149,6 @@ def test_factory(abc_ABCMeta, abc_get_cache_token):
self.assertEqual(D.foo(), 4)
self.assertEqual(D().foo(), 4)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_object_new_with_one_abstractmethod(self):
class C(metaclass=abc_ABCMeta):
@abc.abstractmethod
@@ -159,8 +157,6 @@ def test_factory(abc_ABCMeta, abc_get_cache_token):
msg = r"class C with abstract method method_one"
self.assertRaisesRegex(TypeError, msg, C)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_object_new_with_many_abstractmethods(self):
class C(metaclass=abc_ABCMeta):
@abc.abstractmethod
@@ -525,8 +521,6 @@ def test_factory(abc_ABCMeta, abc_get_cache_token):
self.assertEqual(A.__abstractmethods__, set())
A()
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_update_new_abstractmethods(self):
class A(metaclass=abc_ABCMeta):
@abc.abstractmethod
@@ -543,8 +537,6 @@ def test_factory(abc_ABCMeta, abc_get_cache_token):
msg = "class A with abstract methods bar, foo"
self.assertRaisesRegex(TypeError, msg, A)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_update_implementation(self):
class A(metaclass=abc_ABCMeta):
@abc.abstractmethod
@@ -596,8 +588,6 @@ def test_factory(abc_ABCMeta, abc_get_cache_token):
A()
self.assertFalse(hasattr(A, '__abstractmethods__'))
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_update_del_implementation(self):
class A(metaclass=abc_ABCMeta):
@abc.abstractmethod
@@ -617,8 +607,6 @@ def test_factory(abc_ABCMeta, abc_get_cache_token):
msg = "class B with abstract method foo"
self.assertRaisesRegex(TypeError, msg, B)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_update_layered_implementation(self):
class A(metaclass=abc_ABCMeta):
@abc.abstractmethod

View File

@@ -3676,8 +3676,6 @@ class TestAbstract(unittest.TestCase):
self.assertFalse(inspect.isabstract(Date))
self.assertGreater(Date(2020,12,25), Date(2020,8,31))
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_maintain_abc(self):
class A(abc.ABC):
@abc.abstractmethod

View File

@@ -13,9 +13,8 @@ class CustomInterface(abc.ABC):
return NotImplemented
# TODO raise an error if there are in any abstract methods not fulfilled
# with assert_raises(TypeError):
# CustomInterface()
with assert_raises(TypeError):
CustomInterface()
class Concrete:

View File

@@ -6,6 +6,7 @@ use crate::{
types::{Constructor, PyComparisonOp},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyResult, VirtualMachine,
};
use itertools::Itertools;
/// object()
/// --
@@ -38,10 +39,29 @@ impl Constructor for PyBaseObject {
// Ensure that all abstract methods are implemented before instantiating instance.
if let Some(abs_methods) = cls.get_attr(identifier!(vm, __abstractmethods__)) {
if let Some(unimplemented_abstract_method_count) = abs_methods.length_opt(vm) {
if unimplemented_abstract_method_count? > 0 {
return Err(
vm.new_type_error("You must implement the abstract methods".to_owned())
);
let methods: Vec<PyStrRef> = abs_methods.try_to_value(vm)?;
let methods: String =
Itertools::intersperse(methods.iter().map(|name| name.as_str()), ", ")
.collect();
let unimplemented_abstract_method_count = unimplemented_abstract_method_count?;
let name = cls.name().to_string();
match unimplemented_abstract_method_count {
0 => {}
1 => {
return Err(vm.new_type_error(format!(
"Can't instantiate abstract class {} with abstract method {}",
name, methods
)));
}
2.. => {
return Err(vm.new_type_error(format!(
"Can't instantiate abstract class {} with abstract methods {}",
name, methods
)));
}
_ => unreachable!("unimplemented_abstract_method_count is always positive"),
}
}
}