diff --git a/Lib/_py_abc.py b/Lib/_py_abc.py index 60adace9b..07044f2f7 100644 --- a/Lib/_py_abc.py +++ b/Lib/_py_abc.py @@ -43,7 +43,7 @@ class ABCMeta(type): value = getattr(cls, name, None) if getattr(value, "__isabstractmethod__", False): abstracts.add(name) - cls.__abstractmethods__ = frozenset(abstracts) + cls.__abstractmethods__ = set(abstracts) # Set up inheritance registry cls._abc_registry = WeakSet() cls._abc_cache = WeakSet() diff --git a/tests/snippets/abc_test.py b/tests/snippets/abc_test.py deleted file mode 100644 index 494f967be..000000000 --- a/tests/snippets/abc_test.py +++ /dev/null @@ -1 +0,0 @@ -import abc diff --git a/tests/snippets/hash.py b/tests/snippets/hash.py new file mode 100644 index 000000000..b108db705 --- /dev/null +++ b/tests/snippets/hash.py @@ -0,0 +1,23 @@ + +from testutils import assertRaises + + +class A: + pass + + +assert type(hash(None)) is int +assert type(hash(object())) is int +assert type(hash(A())) is int +assert type(hash(1)) is int +assert type(hash(1.1)) is int +assert type(hash("")) is int + +with assertRaises(TypeError): + hash({}) + +with assertRaises(TypeError): + hash(set()) + +with assertRaises(TypeError): + hash([]) diff --git a/tests/snippets/test_abc.py b/tests/snippets/test_abc.py new file mode 100644 index 000000000..6f0243fcd --- /dev/null +++ b/tests/snippets/test_abc.py @@ -0,0 +1,34 @@ +import abc + +from testutils import assertRaises + + +class CustomInterface(abc.ABC): + @abc.abstractmethod + def a(self): + pass + + @classmethod + def __subclasshook__(cls, subclass): + return NotImplemented + + +# with assertRaises(TypeError): +# CustomInterface() + + +class Concrete: + def a(self): + pass + + +CustomInterface.register(Concrete) + + +class SubConcrete(Concrete): + pass + + +assert issubclass(Concrete, CustomInterface) +assert issubclass(SubConcrete, CustomInterface) + diff --git a/vm/src/obj/objdict.rs b/vm/src/obj/objdict.rs index 79c98c2dd..28b3f4210 100644 --- a/vm/src/obj/objdict.rs +++ b/vm/src/obj/objdict.rs @@ -295,6 +295,10 @@ impl PyDictRef { } } } + + fn hash(self, vm: &VirtualMachine) -> PyResult { + Err(vm.new_type_error("unhashable type".to_string())) + } } impl DictProtocol for PyDictRef { @@ -333,6 +337,7 @@ pub fn init(context: &PyContext) { "__new__" => context.new_rustfunc(PyDictRef::new), "__repr__" => context.new_rustfunc(PyDictRef::repr), "__setitem__" => context.new_rustfunc(PyDictRef::setitem), + "__hash__" => context.new_rustfunc(PyDictRef::hash), "clear" => context.new_rustfunc(PyDictRef::clear), "values" => context.new_rustfunc(PyDictRef::values), "items" => context.new_rustfunc(PyDictRef::items), diff --git a/vm/src/obj/objlist.rs b/vm/src/obj/objlist.rs index 865707201..6f059b592 100644 --- a/vm/src/obj/objlist.rs +++ b/vm/src/obj/objlist.rs @@ -162,6 +162,10 @@ impl PyListRef { Ok(s) } + fn hash(self, vm: &VirtualMachine) -> PyResult { + Err(vm.new_type_error("unhashable type".to_string())) + } + fn mul(self, counter: isize, vm: &VirtualMachine) -> PyObjectRef { let new_elements = seq_mul(&self.elements.borrow(), counter); vm.ctx.new_list(new_elements) @@ -466,6 +470,7 @@ pub fn init(context: &PyContext) { "__len__" => context.new_rustfunc(PyListRef::len), "__new__" => context.new_rustfunc(list_new), "__repr__" => context.new_rustfunc(PyListRef::repr), + "__hash__" => context.new_rustfunc(PyListRef::hash), "__doc__" => context.new_str(list_doc.to_string()), "append" => context.new_rustfunc(PyListRef::append), "clear" => context.new_rustfunc(PyListRef::clear), diff --git a/vm/src/obj/objobject.rs b/vm/src/obj/objobject.rs index c43e31a96..df164f49b 100644 --- a/vm/src/obj/objobject.rs +++ b/vm/src/obj/objobject.rs @@ -55,8 +55,8 @@ fn object_ge(_zelf: PyObjectRef, _other: PyObjectRef, vm: &VirtualMachine) -> Py vm.ctx.not_implemented() } -fn object_hash(_zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult { - Err(vm.new_type_error("unhashable type".to_string())) +fn object_hash(zelf: PyObjectRef, _vm: &VirtualMachine) -> u64 { + zelf.get_id() as u64 } fn object_setattr( diff --git a/vm/src/obj/objset.rs b/vm/src/obj/objset.rs index fb558c990..34d487fbb 100644 --- a/vm/src/obj/objset.rs +++ b/vm/src/obj/objset.rs @@ -588,6 +588,10 @@ fn frozenset_repr(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { Ok(vm.new_str(s)) } +fn set_hash(_zelf: PySetRef, vm: &VirtualMachine) -> PyResult { + Err(vm.new_type_error("unhashable type".to_string())) +} + pub fn init(context: &PyContext) { let set_type = &context.set_type; @@ -600,6 +604,7 @@ pub fn init(context: &PyContext) { "__len__" => context.new_rustfunc(set_len), "__new__" => context.new_rustfunc(set_new), "__repr__" => context.new_rustfunc(set_repr), + "__hash__" => context.new_rustfunc(set_hash), "__eq__" => context.new_rustfunc(set_eq), "__ge__" => context.new_rustfunc(set_ge), "__gt__" => context.new_rustfunc(set_gt),