Make object by default hashable

This commit is contained in:
ben
2019-04-04 19:45:20 +13:00
parent 0bd08618af
commit ea872521d6
8 changed files with 75 additions and 4 deletions

View File

@@ -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()

View File

@@ -1 +0,0 @@
import abc

23
tests/snippets/hash.py Normal file
View File

@@ -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([])

View File

@@ -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)

View File

@@ -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),

View File

@@ -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),

View File

@@ -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(

View File

@@ -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),