feat: adopt Python 3.14+ patterns — TypedDict, match/case, slots#98
feat: adopt Python 3.14+ patterns — TypedDict, match/case, slots#98
Conversation
…ilities Replace dict[str, Any] return types with structured TypedDicts (JUnitReport, SARIFReport, CacheStats) for better type-checker coverage and IDE support. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…d readme detect Define ErrorDict, RenderSummary/BlockTimingSummary, and ProjectContext TypedDicts for structured return types in core modules. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace _transform_node (12 branches) and _transform_expr (18 branches) isinstance dispatch with match/case class patterns, consistent with the match statements already used elsewhere in the same file. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Consistent with the other 102 frozen+slotted dataclasses in the codebase. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR modernizes several Python modules by introducing TypedDict-based return types and updating dispatch logic to newer Python pattern-matching constructs, improving static typing/IDE support while keeping runtime behavior intended to remain unchanged.
Changes:
- Introduces multiple
TypedDictdefinitions (e.g., SARIF/JUnit reports, cache stats, render summaries, project context) and updates function return annotations accordingly. - Refactors
partial_eval.pydispatch fromisinstancechains tomatch/caseclass patterns. - Adds
slots=TruetoTemplateWarningfor frozen dataclass consistency.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/kida/utils/sarif.py | Adds SARIF TypedDicts and tightens sarif_to_dict / _empty_result return types. |
| src/kida/utils/lru_cache.py | Defines CacheStats TypedDict and updates LRUCache.stats() to return it. |
| src/kida/utils/junit_xml.py | Adds JUnit TypedDicts and tightens parse helper return types. |
| src/kida/template/core.py | Introduces ErrorDict TypedDict for template fallback error context. |
| src/kida/render_accumulator.py | Adds structured RenderSummary/BlockTimingSummary TypedDicts. |
| src/kida/readme/detect.py | Adds ProjectContext TypedDict and annotates detect_project accordingly. |
| src/kida/readme/init.py | Re-exports detect_project with ProjectContext typing and expands render_readme context union. |
| src/kida/exceptions.py | Adds slots=True to TemplateWarning dataclass. |
| src/kida/compiler/partial_eval.py | Converts node/expression transforms from isinstance branching to match/case. |
| src/kida/cli.py | Adjusts CLI context typing to interoperate with TypedDict returns. |
| if TYPE_CHECKING: | ||
| from pathlib import Path | ||
|
|
||
| from kida.readme.detect import ProjectContext | ||
|
|
||
| def detect_project(root: Path, *, depth: int = 2) -> dict[str, Any]: | ||
|
|
||
| def detect_project(root: Path, *, depth: int = 2) -> ProjectContext: |
There was a problem hiding this comment.
ProjectContext is imported only under TYPE_CHECKING but is referenced in a runtime function annotation. Unless this module uses postponed evaluation of annotations (e.g., from __future__ import annotations), importing the module will raise NameError: name 'ProjectContext' is not defined. Fix by either importing ProjectContext at runtime (not under TYPE_CHECKING), or by enabling postponed evaluation (from __future__ import annotations) / quoting the annotation.
|
|
||
|
|
||
| def detect_project(root: Path, *, depth: int = 2) -> dict[str, Any]: | ||
| def detect_project(root: Path, *, depth: int = 2) -> ProjectContext: |
There was a problem hiding this comment.
The function is annotated to return ProjectContext but returns a plain dict[str, Any] with a # type: ignore[return-value], which undermines the benefit of introducing the TypedDict and can hide real shape mismatches. Prefer constructing/typing the value as ProjectContext (e.g., declare the variable as ProjectContext and include all required keys in the returned object), or use an explicit cast to ProjectContext at the return site rather than ignoring the type checker.
| dependencies = project.get("dependencies", []) | ||
|
|
||
| ctx: dict[str, Any] = { | ||
| base: dict[str, Any] = { |
There was a problem hiding this comment.
The function is annotated to return ProjectContext but returns a plain dict[str, Any] with a # type: ignore[return-value], which undermines the benefit of introducing the TypedDict and can hide real shape mismatches. Prefer constructing/typing the value as ProjectContext (e.g., declare the variable as ProjectContext and include all required keys in the returned object), or use an explicit cast to ProjectContext at the return site rather than ignoring the type checker.
| base["suggested_preset"] = detect_preset(base) | ||
| return base # type: ignore[return-value] |
There was a problem hiding this comment.
The function is annotated to return ProjectContext but returns a plain dict[str, Any] with a # type: ignore[return-value], which undermines the benefit of introducing the TypedDict and can hide real shape mismatches. Prefer constructing/typing the value as ProjectContext (e.g., declare the variable as ProjectContext and include all required keys in the returned object), or use an explicit cast to ProjectContext at the return site rather than ignoring the type checker.
Summary
JUnitReport,SARIFReport,CacheStats,ErrorDict,RenderSummary,ProjectContext, etc.), replacingdict[str, Any]return types for better type-checker and IDE coverageisinstancedispatch branches inpartial_eval.py(_transform_node+_transform_expr) tomatch/caseclass patterns, consistent with existing match usage in the same fileslots=TruetoTemplateWarningdataclass, making all 103 frozen dataclasses consistently slottedcli.pytype annotations for TypedDict compatibility with tyTest plan
ruff check .cleanty check src/clean (no new errors)🤖 Generated with Claude Code