1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
from . import mixins
class Test(mixins.TargetedNamespaceWalker, mixins.KlassWalker):
target_namespace = "snakeoil"
singleton = object()
def setup_method(self):
self._ignore_set = frozenset(self.iter_builtin_targets())
def _should_ignore(self, cls):
if cls in self._ignore_set:
return True
if getattr(cls, "__hash__intentionally_disabled__", False):
return True
namepath = f"{cls.__module__}.{cls.__name__}"
return not namepath.startswith(self.target_namespace)
def run_check(self, cls):
for parent in cls.__bases__:
if parent == object:
# object sets __hash__/__eq__, which isn't usually
# intended to be inherited/reused
continue
eq = getattr(parent, "__eq__", self.singleton)
h = getattr(parent, "__hash__", self.singleton)
if eq == object.__eq__ and h == object.__hash__:
continue
if eq and h:
break
else:
return
# pylint: disable=undefined-loop-variable
# 'parent' is guaranteed to be defined due to the 'else' clause above
assert getattr(cls, "__hash__") is not None, (
f"class '{cls.__module__}.{cls.__name__}' had its __hash__ reset, "
"while it would've inherited __hash__ from parent "
f"'{parent.__module__}.{parent.__name__}'; this occurs in py3k when "
"__eq__ is defined alone. If this is desired behaviour, set "
"__hash__intentionally_disabled__ to True to explicitly ignore this"
" class"
)
|