Skip to content

ref(api): Remove unreachable blank branch from empty number fields - #129702

Open
joshuarli wants to merge 1 commit into
masterfrom
josh/typing-contracts/c1-empty-number-fields
Open

joshuarli wants to merge 1 commit into
masterfrom
josh/typing-contracts/c1-empty-number-fields

Conversation

@joshuarli

@joshuarli joshuarli commented Nov 3, 2026 •

Copy link
Copy Markdown
Member

EmptyDecimalField and EmptyIntegerField no longer cast None to Decimal / int. Since #129614, their to_internal_value overrides claimed a non-null result while returning None for blank input.

That branch was unreachable through DRF. Both fields already map "" to None in run_validation, which DRF calls before to_internal_value, so the overrides are removed rather than re-typed. Blank input still validates to None through run_validation (typed Decimal | None / int | None), and to_internal_value now inherits DRF's accurate Decimal / int contract. MissedMarginField uses that contract instead of Any -> Any.

Behavior change: none through serializers. Calling field.to_internal_value("") directly now raises ValidationError like the base DRF field instead of returning None. Nothing in sentry or getsentry calls it directly. Blank input through serializers stays covered by test_resolve_age in tests/sentry/core/endpoints/test_project_details.py.

@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label Nov 3, 2026
@joshuarli
joshuarli force-pushed the josh/typing-contracts/c1-empty-number-fields branch from 144ae53 to 70a4a2d Compare November 3, 2026 16:50
EmptyDecimalField and EmptyIntegerField both convert a blank string to
None in run_validation, which DRF calls before to_internal_value. The
blank check in their to_internal_value overrides could not be reached
through DRF, but #129614 typed it by casting None to Decimal and int, so
both overrides claimed a non-null result while holding a None branch.

Dropping the overrides leaves run_validation (typed `Decimal | None` /
`int | None`) as the only blank path, and to_internal_value inherits
DRF's honest `Decimal` / `int` contract. MissedMarginField now uses that
contract instead of `Any -> Any`.
@joshuarli
joshuarli force-pushed the josh/typing-contracts/c1-empty-number-fields branch from 70a4a2d to f292a21 Compare November 3, 2026 17:03
@joshuarli
joshuarli requested a review from vjeranc November 3, 2026 17:05
@joshuarli
joshuarli marked this pull request as ready for review November 3, 2026 17:06
@joshuarli
joshuarli requested review from a team as code owners November 3, 2026 17:06
@vjeranc

vjeranc commented Nov 9, 2026 •

Copy link
Copy Markdown
Member

Nice, that was my conclusion as well (that in the end None cast was not dangerous at all, despite looking very off). Good to see there's redundant code you can just remove instead of struggle to type correctly.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants