rusackas opened a new pull request, #44817:
URL: https://github.com/apache/superset/pull/44817

   ### SUMMARY
   
   Follow-up to #44789 (and its predecessors #44394, #44424, #44648) — same 
defect class, four separate fixup PRs now, so this addresses the root cause 
instead of the fourth symptom.
   
   `UUIDMixin.uuid` (`superset/models/helpers.py`) is declared as a plain mixin 
class attribute: `uuid = sa.Column(UUIDType(binary=True), ...)`. Under mypy, 
that resolves to `Any` (or the bare `Column[Any]` descriptor) unless the whole 
class hierarchy happens to already be loaded together in the same run. 
Reproduced directly: `reveal_type(some_dashboard.uuid)` in an isolated one-file 
mypy check returns `Any`/`Column[Any]`, not `UUID | None` — even though the 
column is nullable and every one of the four prior PRs had to fix exactly this 
mismatch.
   
   That's why this keeps recurring as a fixup PR instead of getting caught when 
the offending code is written: the per-PR `pre-commit (current)` check only 
lints the files changed in that PR, and in that narrow scope mypy can't resolve 
`.uuid`'s real type, so an unnarrowed read passed into a callee requiring a 
non-Optional `UUID` sails through silently. Only the nightly full-repo sweep 
(`pre-commit.yml`'s `schedule: cron` job) has enough context to resolve the 
type correctly and catch the mismatch — by which point it's already on `master`.
   
   **Fix**: switch `UUIDMixin.uuid` to the `@declared_attr` + explicit 
`Mapped[Optional[uuid.UUID]]` return-annotation pattern that 
`created_by_fk`/`changed_by_fk` already use a few lines above it in the same 
file. This makes the type resolve deterministically regardless of what else 
mypy happens to be checking in that run.
   
   No runtime behavior change — `@declared_attr` returning a `Column` is the 
exact same mechanism SQLAlchemy already uses for those two FK columns.
   
   ### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
   
   N/A (typing-only change, no UI).
   
   ### TESTING INSTRUCTIONS
   
   Verified directly rather than just asserted:
   
   1. **Before** (checked out #44514's pre-fix head, mypy scoped to just its 
two new test files): 0 errors reported for either file, despite the exact 
`RestoreDatasetVersionCommand(dataset.uuid, target)` mismatch #44789 later had 
to fix. `reveal_type(dashboard.uuid)` in an isolated file: `Any` / 
`Column[Any]`.
   2. **After this change**, same isolated-file check: 
`reveal_type(dashboard.uuid)` → `Union[uuid.UUID, None]`. A synthetic repro of 
the #44789-class bug (`RestoreDashboardVersionCommand(d.uuid, d.uuid)` in a 
fresh one-file mypy run) is now correctly flagged:
      ```
      error: Argument 1 to "RestoreDashboardVersionCommand" has incompatible 
type "UUID | None"; expected "UUID"  [arg-type]
      error: Argument 2 to "RestoreDashboardVersionCommand" has incompatible 
type "UUID | None"; expected "UUID"  [arg-type]
      ```
   3. `pre-commit run --files superset/models/helpers.py` — clean (mypy, ruff, 
pylint all pass; the `# pylint: disable=arguments-renamed` on the new method 
mirrors the identical suppression already present on 
`created_by_fk`/`changed_by_fk`).
   4. `pytest tests/unit_tests/versioning/ 
tests/unit_tests/databases/commands/importers/v1/import_test.py 
tests/unit_tests/examples/generic_loader_test.py 
tests/unit_tests/themes/model_test.py tests/unit_tests/datasets/ 
tests/unit_tests/dashboards/` — 444 passed, no regressions across every test 
path that exercises `.uuid` (import/export UUID coercion, versioning restore, 
dataset/dashboard model construction).
   
   ### ADDITIONAL INFORMATION
   - [ ] Has associated issue:
   - [ ] Required feature flags:
   - [ ] Changes UI
   - [ ] Includes DB Migration (follow approval process in 
[SIP-59](https://github.com/apache/superset/issues/13351))
     - [ ] Migration is atomic, supports rollback & is backwards-compatible
     - [ ] Confirm DB migration upgrade and downgrade tested
     - [ ] Runtime estimates and downtime expectations provided
   - [ ] Introduces new feature or API
   - [ ] Removes existing feature or API
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to