Skip to content

Commit 76d6d48

Browse files
lobsterkatiec298lee
authored andcommitted
chore(grouping): Add types to various grouping functions (#68568)
This adds types to a number of grouping-related functions, mostly because I was trying to figure out how they worked and knowing types makes that easier to reason about.
1 parent 00c1984 commit 76d6d48

File tree

5 files changed

+35
-15
lines changed

5 files changed

+35
-15
lines changed

src/sentry/eventstore/models.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from sentry import eventtypes
1919
from sentry.db.models import NodeData
2020
from sentry.grouping.result import CalculatedHashes
21+
from sentry.grouping.variants import BaseVariant, KeyedVariants
2122
from sentry.interfaces.base import Interface, get_interfaces
2223
from sentry.issues.grouptype import GroupCategory
2324
from sentry.issues.issue_occurrence import IssueOccurrence
@@ -374,15 +375,19 @@ def get_hashes(self, force_config: StrategyConfiguration | None = None) -> Calcu
374375
variants=[*flat_variants, *hierarchical_variants],
375376
)
376377

377-
def get_sorted_grouping_variants(self, force_config: StrategyConfiguration | None = None):
378+
def get_sorted_grouping_variants(
379+
self, force_config: StrategyConfiguration | None = None
380+
) -> tuple[KeyedVariants, KeyedVariants]:
378381
"""Get grouping variants sorted into flat and hierarchical variants"""
379382
from sentry.grouping.api import sort_grouping_variants
380383

381384
variants = self.get_grouping_variants(force_config)
382385
return sort_grouping_variants(variants)
383386

384387
@staticmethod
385-
def _hashes_from_sorted_grouping_variants(variants):
388+
def _hashes_from_sorted_grouping_variants(
389+
variants: KeyedVariants,
390+
) -> tuple[list[str], list[Any]]:
386391
"""Create hashes from variants and filter out duplicates and None values"""
387392

388393
from sentry.grouping.variants import ComponentVariant
@@ -421,7 +426,7 @@ def get_grouping_variants(
421426
self,
422427
force_config: StrategyConfiguration | GroupingConfig | str | None = None,
423428
normalize_stacktraces: bool = False,
424-
):
429+
) -> dict[str, BaseVariant]:
425430
"""
426431
This is similar to `get_hashes` but will instead return the
427432
grouping components for each variant in a dictionary.

src/sentry/grouping/api.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
ComponentVariant,
3030
CustomFingerprintVariant,
3131
FallbackVariant,
32+
KeyedVariants,
3233
SaltedComponentVariant,
3334
)
3435
from sentry.models.grouphash import GroupHash
@@ -279,10 +280,12 @@ def apply_server_fingerprinting(event, config, allow_custom_title=True):
279280
event["_fingerprint_info"]["is_builtin"] = True
280281

281282

282-
def _get_calculated_grouping_variants_for_event(event, context):
283+
def _get_calculated_grouping_variants_for_event(
284+
event: Event, context: GroupingContext
285+
) -> dict[str, GroupingComponent]:
283286
winning_strategy: str | None = None
284287
precedence_hint: str | None = None
285-
per_variant_components: dict[str, list[BaseVariant]] = {}
288+
per_variant_components: dict[str, list[GroupingComponent]] = {}
286289

287290
for strategy in context.config.iter_strategies():
288291
# Defined in src/sentry/grouping/strategies/base.py
@@ -392,7 +395,7 @@ def get_grouping_variants_for_event(
392395
return rv
393396

394397

395-
def sort_grouping_variants(variants):
398+
def sort_grouping_variants(variants: dict[str, BaseVariant]) -> tuple[KeyedVariants, KeyedVariants]:
396399
"""Sort a sequence of variants into flat and hierarchical variants"""
397400

398401
flat_variants = []

src/sentry/grouping/result.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from typing import Any, Optional, TypedDict
44

55
from sentry.db.models import NodeData
6-
from sentry.grouping.variants import BaseVariant
6+
from sentry.grouping.variants import KeyedVariants
77
from sentry.utils.safe import get_path, safe_execute, set_path
88

99
EventMetadata = dict[str, Any]
@@ -100,7 +100,7 @@ class CalculatedHashes:
100100
hashes: Sequence[str]
101101
hierarchical_hashes: Sequence[str]
102102
tree_labels: Sequence[TreeLabel | None]
103-
variants: list[tuple[str, BaseVariant]] | None = None
103+
variants: KeyedVariants | None = None
104104

105105
def write_to_event(self, event_data: NodeData) -> None:
106106
event_data["hashes"] = self.hashes

src/sentry/grouping/variants.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
from sentry.grouping.utils import hash_from_values, is_default_fingerprint_var
4+
from sentry.types.misc import KeyedList
45

56

67
class BaseVariant:
@@ -10,7 +11,7 @@ class BaseVariant:
1011
# This is true if `get_hash` does not return `None`.
1112
contributes = True
1213

13-
def get_hash(self):
14+
def get_hash(self) -> str | None:
1415
return None
1516

1617
@property
@@ -29,6 +30,9 @@ def __repr__(self):
2930
return f"<{self.__class__.__name__} {self.get_hash()!r} ({self.type})>"
3031

3132

33+
KeyedVariants = KeyedList[BaseVariant]
34+
35+
3236
class ChecksumVariant(BaseVariant):
3337
"""A checksum variant returns a single hardcoded hash."""
3438

@@ -44,15 +48,15 @@ def description(self):
4448
return "hashed legacy checksum"
4549
return "legacy checksum"
4650

47-
def get_hash(self):
51+
def get_hash(self) -> str | None:
4852
return self.hash
4953

5054

5155
class FallbackVariant(BaseVariant):
5256
id = "fallback"
5357
contributes = True
5458

55-
def get_hash(self):
59+
def get_hash(self) -> str | None:
5660
return hash_from_values([])
5761

5862

@@ -75,7 +79,7 @@ def __init__(self, event_performance_problem):
7579
self.event_performance_problem = event_performance_problem
7680
self.problem = event_performance_problem.problem
7781

78-
def get_hash(self):
82+
def get_hash(self) -> str | None:
7983
return self.problem.fingerprint
8084

8185
def _get_metadata_as_dict(self):
@@ -104,7 +108,7 @@ def description(self):
104108
def contributes(self):
105109
return self.component.contributes
106110

107-
def get_hash(self):
111+
def get_hash(self) -> str | None:
108112
return self.component.get_hash()
109113

110114
def _get_metadata_as_dict(self):
@@ -146,7 +150,7 @@ def __init__(self, values, fingerprint_info=None):
146150
def description(self):
147151
return "custom fingerprint"
148152

149-
def get_hash(self):
153+
def get_hash(self) -> str | None:
150154
return hash_from_values(self.values)
151155

152156
def _get_metadata_as_dict(self):
@@ -177,7 +181,7 @@ def __init__(self, values, component, config, fingerprint_info=None):
177181
def description(self):
178182
return "modified " + self.component.description
179183

180-
def get_hash(self):
184+
def get_hash(self) -> str | None:
181185
if not self.component.contributes:
182186
return None
183187
final_values = []

src/sentry/types/misc.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from typing import TypeVar
2+
3+
# This is meant to be a base type from which we can derive types useful when we have what is in
4+
# spirit a dictionary but is in practice a list of tuples. For example:
5+
# KeyedInts = KeyedList[int]
6+
# some_ints: KeyedInts = [("one", 1), ("two", 2)]
7+
T = TypeVar("T")
8+
KeyedList = list[tuple[str, T]]

0 commit comments

Comments
 (0)