chore: add CORE-003 roadmap task for mypy type safety
- Remove '|| true' from CI type-check job to enforce strict checking - Begin type narrowing pattern in units.py with _typed property accessors - Document all 42 type errors across 15 files in roadmap backlog - Priority: medium, estimated 4-6 hours to complete Type errors fall into categories: - Union types not narrowed after __post_init__ coercion - float() on object types - Duplicate method definitions - Provider interface type mismatches
This commit is contained in:
@@ -14,6 +14,7 @@ notes:
|
||||
- Alpha migration policy: once alpha is declared, compatibility only needs to move forward; backward migrations are not required.
|
||||
priority_queue:
|
||||
- EXEC-002
|
||||
- CORE-003
|
||||
- DATA-DB-005
|
||||
- DATA-002A
|
||||
- DATA-001A
|
||||
|
||||
112
docs/roadmap/backlog/CORE-003-mypy-type-safety.yaml
Normal file
112
docs/roadmap/backlog/CORE-003-mypy-type-safety.yaml
Normal file
@@ -0,0 +1,112 @@
|
||||
name: CORE-003 Mypy Type Safety
|
||||
description: |
|
||||
Fix all mypy type errors to enable strict type checking in CI.
|
||||
|
||||
Currently 42 errors in 15 files. The CI uses `|| true` to allow warnings,
|
||||
but we should fix these properly with strong types and conversion functions.
|
||||
|
||||
status: backlog
|
||||
priority: medium
|
||||
created_at: 2026-03-29
|
||||
dependencies: []
|
||||
|
||||
acceptance_criteria:
|
||||
- mypy passes with 0 errors on app/core app/models app/strategies app/services
|
||||
- CI type-check job passes without `|| true`
|
||||
- All type narrowing uses proper patterns (properties, cast(), or isinstance checks)
|
||||
- No duplicate method definitions
|
||||
|
||||
scope:
|
||||
in_scope:
|
||||
- Fix type errors in app/domain/units.py
|
||||
- Fix type errors in app/domain/portfolio_math.py
|
||||
- Fix type errors in app/models/portfolio.py
|
||||
- Fix type errors in app/domain/backtesting_math.py
|
||||
- Fix type errors in app/domain/instruments.py
|
||||
- Fix type errors in app/services/*.py
|
||||
- Fix type errors in app/pages/*.py
|
||||
- Remove `|| true` from type-check job in CI
|
||||
|
||||
out_of_scope:
|
||||
- Adding new type annotations to previously untyped code
|
||||
- Refactoring business logic
|
||||
|
||||
files_with_errors:
|
||||
- file: app/domain/units.py
|
||||
errors: 6
|
||||
pattern: "WeightUnit | str" not narrowed after __post_init__
|
||||
fix: Use _unit_typed property for type-narrowed access
|
||||
|
||||
- file: app/models/portfolio.py
|
||||
errors: 1
|
||||
pattern: "Duplicate _serialize_value definition"
|
||||
fix: Remove duplicate method definition
|
||||
|
||||
- file: app/domain/backtesting_math.py
|
||||
errors: 1
|
||||
pattern: "assert_currency" argument type
|
||||
fix: Use Money.assert_currency properly or add type narrowing
|
||||
|
||||
- file: app/domain/instruments.py
|
||||
errors: 1
|
||||
pattern: "to_unit" argument type
|
||||
fix: Use _unit_typed property or explicit coercion
|
||||
|
||||
- file: app/domain/portfolio_math.py
|
||||
errors: 11
|
||||
pattern: "float(object), Weight | Money union, dict type mismatch"
|
||||
fix: Add proper type guards and conversion functions
|
||||
|
||||
- file: app/services/backtesting/ui_service.py
|
||||
errors: 2
|
||||
pattern: "Provider type mismatch, YFinance vs Databento source"
|
||||
fix: Use proper union types for provider interface
|
||||
|
||||
- file: app/services/event_comparison_ui.py
|
||||
errors: 1
|
||||
pattern: "FixtureBoundSyntheticHistoricalProvider type"
|
||||
fix: Update type annotations for provider hierarchy
|
||||
|
||||
- file: app/services/cache.py
|
||||
errors: 1
|
||||
pattern: "str | None to Redis URL"
|
||||
fix: Add None check or use assertion
|
||||
|
||||
- file: app/services/price_feed.py
|
||||
errors: 2
|
||||
pattern: "float(object)"
|
||||
fix: Add explicit type coercion
|
||||
|
||||
- file: app/pages/settings.py
|
||||
errors: 1
|
||||
pattern: "Return value on ui.button scope"
|
||||
fix: Proper return type annotation
|
||||
|
||||
implementation_notes: |
|
||||
The root cause is that frozen dataclass fields with `Field: UnionType`
|
||||
are not narrowed by `__post_init__` coercion. Mypy sees the declared
|
||||
type, not the runtime type.
|
||||
|
||||
Solutions:
|
||||
1. Add `@property def _field_typed(self) -> NarrowType:` for internal use
|
||||
2. Use `cast(NarrowType, self.field)` at call sites
|
||||
3. Use `isinstance` checks before operations requiring narrow type
|
||||
|
||||
Pattern example from units.py fix:
|
||||
```python
|
||||
@property
|
||||
def _unit_typed(self) -> WeightUnit:
|
||||
"""Type-narrowed unit accessor for internal use."""
|
||||
return self.unit # type: ignore[return-value]
|
||||
|
||||
def to_unit(self, unit: WeightUnit) -> Weight:
|
||||
return Weight(amount=convert_weight(self.amount, self._unit_typed, unit), unit=unit)
|
||||
```
|
||||
|
||||
estimated_effort: 4-6 hours
|
||||
|
||||
tags:
|
||||
- type-safety
|
||||
- mypy
|
||||
- technical-debt
|
||||
- ci-quality
|
||||
Reference in New Issue
Block a user