Skip to content

fix(typing): Annotate group_status parameters as int#113424

Merged
JoshFerge merged 1 commit into
masterfrom
joshferge/fix/group-status-annotation
Apr 22, 2026
Merged

fix(typing): Annotate group_status parameters as int#113424
JoshFerge merged 1 commit into
masterfrom
joshferge/fix/group-status-annotation

Conversation

@JoshFerge

@JoshFerge JoshFerge commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

`sentry.models.group.GroupStatus` is a plain class whose members are ints (`RESOLVED = 1`, `IGNORED = 2`, etc.) — not an enum. Callers of the functions below all pass ints, and the in-function `==` comparisons (`group_status == GroupStatus.RESOLVED`) are int-vs-int. But the parameters were annotated as `GroupStatus`, i.e. "instance of GroupStatus", which is never what the callers pass.

Under `strict_equality = true` the comparisons become semantically unreachable (instance-of-class never equals int). Stricter mypy reports them as `[unreachable]`.

Change the annotations to `int` to match actual usage:

  • `fetch_alert_threshold`
  • `fetch_resolve_threshold`
  • `AlertContext.from_workflow_engine_models`
  • `MetricAlertNotificationMessageBuilder.build_alert_context`

No runtime behavior change. Prep for the mypy 1.20 upgrade (#113419). Safe under 1.19.1.

Agent transcript: https://claudescope.sentry.dev/share/wKKwnZeeYc-V3zQbolQDCON52n93vyqkCmPrIs_kbnI

`sentry.models.group.GroupStatus` is a plain class whose members are ints
(`RESOLVED = 1`, `IGNORED = 2`, etc.), not an enum. Callers of these
functions all pass ints, and the in-function `==` comparisons against
`GroupStatus.RESOLVED` are int-vs-int. But the parameters were annotated as
`GroupStatus`, i.e. 'instance of GroupStatus'.

Under `strict_equality = true` the comparison becomes semantically
unreachable (instance-of-class never equals int), which is surfaced as
`[unreachable]` errors by stricter mypy. Change the annotations to `int`
to match how the values are actually used:

- `fetch_alert_threshold`
- `fetch_resolve_threshold`
- `AlertContext.from_workflow_engine_models`
- `MetricAlertNotificationMessageBuilder.build_alert_context`

No runtime behavior change. Prep for the mypy 1.20 upgrade (#113419).

Agent transcript: https://claudescope.sentry.dev/share/zuptd8j6fTczb1hxTiv3VRqXHCYcX_7vZGRag0vi_DY
@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label Apr 20, 2026
@JoshFerge
JoshFerge marked this pull request as ready for review April 22, 2026 15:57
@JoshFerge
JoshFerge requested review from a team as code owners April 22, 2026 15:57
@JoshFerge
JoshFerge requested a review from a team April 22, 2026 16:00
@JoshFerge
JoshFerge enabled auto-merge (squash) April 22, 2026 16:00
@JoshFerge
JoshFerge merged commit 947c276 into master Apr 22, 2026
59 checks passed
@JoshFerge
JoshFerge deleted the joshferge/fix/group-status-annotation branch April 22, 2026 16:40
JoshFerge added a commit that referenced this pull request Apr 24, 2026
Bumps the mypy pin to 1.20.1. Prep PRs for the bulk
class-level-attribute fixes have already merged; what remains here is
the pin bump, the `GroupType` ClassVar + `__init_subclass__` migration,
a handful of small typing cleanups, and targeted `# type: ignore`
comments for cases that will get proper fixes in the follow-up PRs
below.

### Prep PRs (already merged)

- #113422 — `ref(typing)`: `RegressionDetector` + `AttributeHandler` →
`ClassVar`
- #113423 — `ref(issues)`: `GroupType` → `ClassVar` + move validation to
`__init_subclass__`
- #113424 — `fix(typing)`: `group_status` args are `int`, not
`GroupStatus`
- #113427 — `test(typing)`: refetch via queryset instead of
`refresh_from_db` after narrowing
- #113428 — `test(typing)`: misc test-side type hint fixes

### What's in this PR

- Bump `mypy>=1.19.1` → `mypy>=1.20.1` (+ `uv.lock`)
- Drop the now-stale `kombu.*` entry from `[[tool.mypy.overrides]]`
- `src/sentry/issues/grouptype.py` — convert `GroupType` fields to
`ClassVar` and move the category-validation check from the dead
`__post_init__` into `__init_subclass__`. Plus the corresponding test
updates in `tests/sentry/issues/test_grouptype.py` and
`tests/sentry/workflow_engine/endpoints/test_validators.py`.
- Small typing fixes that don't change runtime behavior:
- `digests/backends/base.py` — widen options map to `Mapping[str, Any]`
- `discover/compare_timeseries.py` — heterogeneous mismatches dict typed
as `dict[int, dict[str, Any]]`
- `explore/endpoints/explore_saved_queries.py` — drop unused `# type:
ignore`
- `tests/sentry/incidents/test_logic.py` — stringify both sides of the
`target_identifier` comparison so mypy stops flagging it as unreachable
- Targeted `# type: ignore` on six files where the proper fix is being
landed as a follow-up PR (see below)
- `.github/workflows/scripts/bootstrap-snuba.py` — `# type:
ignore[arg-type]` on `int(workers_str)` (single-file mypy can't see
through `sys.exit`; follow-up can replace with `NoReturn`)

### Follow-up PRs (drafts, based on this branch)

Each one removes one of the `# type: ignore` comments and applies the
proper fix. They'll merge after this lands.

- #113927 — `fix(typing)`: narrow `organization_id` in `from_auth`
- #113928 — `fix(typing)`: guard None options in `ReconnectingMemcache`
- #113929 — `docs(typing)`: annotate the `save_team_assignments` ignore
with a FIXME
- #113930 — `ref(typing)`: drop redundant cast in trace metric search
type
- #113932 — `ref(typing)`: drop redundant cast on
`TraceMetric.metric_type`
- #113933 — `ref(typing)`: drop redundant casts in
`resolve_measurement_value`

### Performance

| version | cold | warm |
|---|---|---|
| 1.19.1 | 49.22s | 17.82s |
| 1.20.1 | 39.04s | 5.73s |

### CI expectation

- `mypy` job: clean (0 errors)
- `uv` jobs: resolve against `pypi.devinfra.sentry.io` (1.20.1 has been
published there)
@github-actions github-actions Bot locked and limited conversation to collaborators May 22, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants