Skip to content

Commit 92e31b8

Browse files
authored
chore(utils): allow duplicate values in registry by making reverse lookup optional (#82114)
1 parent 3273e16 commit 92e31b8

File tree

2 files changed

+35
-6
lines changed

2 files changed

+35
-6
lines changed

src/sentry/utils/registry.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,15 @@ class NoRegistrationExistsError(ValueError):
1515

1616

1717
class Registry(Generic[T]):
18-
def __init__(self):
18+
"""
19+
A simple generic registry that allows for registering and retrieving items by key. Reverse lookup by value is enabled by default.
20+
If you have duplicate values, you may want to disable reverse lookup.
21+
"""
22+
23+
def __init__(self, enable_reverse_lookup=True):
1924
self.registrations: dict[str, T] = {}
2025
self.reverse_lookup: dict[T, str] = {}
26+
self.enable_reverse_lookup = enable_reverse_lookup
2127

2228
def register(self, key: str):
2329
def inner(item: T) -> T:
@@ -26,13 +32,14 @@ def inner(item: T) -> T:
2632
f"A registration already exists for {key}: {self.registrations[key]}"
2733
)
2834

29-
if item in self.reverse_lookup:
30-
raise AlreadyRegisteredError(
31-
f"A registration already exists for {item}: {self.reverse_lookup[item]}"
32-
)
35+
if self.enable_reverse_lookup:
36+
if item in self.reverse_lookup:
37+
raise AlreadyRegisteredError(
38+
f"A registration already exists for {item}: {self.reverse_lookup[item]}"
39+
)
40+
self.reverse_lookup[item] = key
3341

3442
self.registrations[key] = item
35-
self.reverse_lookup[item] = key
3643

3744
return item
3845

@@ -44,6 +51,8 @@ def get(self, key: str) -> T:
4451
return self.registrations[key]
4552

4653
def get_key(self, item: T) -> str:
54+
if not self.enable_reverse_lookup:
55+
raise NotImplementedError("Reverse lookup is not enabled")
4756
if item not in self.reverse_lookup:
4857
raise NoRegistrationExistsError(f"No registration exists for {item}")
4958
return self.reverse_lookup[item]

tests/sentry/utils/test_registry.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,23 @@ def unregistered_func():
3333

3434
test_registry.register("something else")(unregistered_func)
3535
assert test_registry.get("something else") == unregistered_func
36+
37+
def test_allow_duplicate_values(self):
38+
test_registry = Registry[str](enable_reverse_lookup=False)
39+
40+
@test_registry.register("something")
41+
@test_registry.register("something 2")
42+
def registered_func():
43+
pass
44+
45+
assert test_registry.get("something") == registered_func
46+
assert test_registry.get("something 2") == registered_func
47+
48+
with pytest.raises(NoRegistrationExistsError):
49+
test_registry.get("something else")
50+
51+
with pytest.raises(NotImplementedError):
52+
test_registry.get_key(registered_func)
53+
54+
test_registry.register("something else")(registered_func)
55+
assert test_registry.get("something else") == registered_func

0 commit comments

Comments
 (0)