Skip to content

Commit

Permalink
Only calculate hash once for Marker objects (alecthomas#513)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdraco authored Jun 16, 2024
1 parent 9451b61 commit b1b1090
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 7 deletions.
20 changes: 13 additions & 7 deletions voluptuous/schema_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import typing
from collections.abc import Generator
from contextlib import contextmanager
from functools import wraps
from functools import cache, wraps

from voluptuous import error as er
from voluptuous.error import Error
Expand Down Expand Up @@ -1026,6 +1026,8 @@ class Marker(object):
introspected by any external tool, for example to generate schema documentation.
"""

__slots__ = ('schema', '_schema', 'msg', 'description', '__hash__')

def __init__(
self,
schema_: Schemable,
Expand All @@ -1036,6 +1038,7 @@ def __init__(
self._schema = Schema(schema_)
self.msg = msg
self.description = description
self.__hash__ = cache(lambda: hash(schema_)) # type: ignore[method-assign]

def __call__(self, v):
try:
Expand All @@ -1056,9 +1059,6 @@ def __lt__(self, other):
return self.schema < other.schema
return self.schema < other

def __hash__(self):
return hash(self.schema)

def __eq__(self, other):
return self.schema == other

Expand Down Expand Up @@ -1244,16 +1244,22 @@ class Remove(Marker):
[1, 2, 3, 5, '7']
"""

def __init__(
self,
schema_: Schemable,
msg: typing.Optional[str] = None,
description: typing.Optional[str] = None,
) -> None:
super().__init__(schema_, msg, description)
self.__hash__ = cache(lambda: object.__hash__(self)) # type: ignore[method-assign]

def __call__(self, schema: Schemable):
super(Remove, self).__call__(schema)
return self.__class__

def __repr__(self):
return "Remove(%r)" % (self.schema,)

def __hash__(self):
return object.__hash__(self)


def message(
default: typing.Optional[str] = None,
Expand Down
1 change: 1 addition & 0 deletions voluptuous/tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,7 @@ def test_marker_hashable():
assert definition.get('y') == float
assert Required('x') == Required('x')
assert Required('x') != Required('y')
assert hash(Required('x').schema) == hash(Required('x'))
# Remove markers are not hashable
assert definition.get('j') is None

Expand Down

0 comments on commit b1b1090

Please sign in to comment.