Skip to content

feat: adopt Python 3.14+ patterns — TypedDict, match/case, slots#98

Merged
lbliii merged 4 commits intomainfrom
lbliii/py314-audit
Apr 14, 2026
Merged

feat: adopt Python 3.14+ patterns — TypedDict, match/case, slots#98
lbliii merged 4 commits intomainfrom
lbliii/py314-audit

Conversation

@lbliii
Copy link
Copy Markdown
Owner

@lbliii lbliii commented Apr 14, 2026

Summary

  • Add 9 TypedDict definitions across 6 modules (JUnitReport, SARIFReport, CacheStats, ErrorDict, RenderSummary, ProjectContext, etc.), replacing dict[str, Any] return types for better type-checker and IDE coverage
  • Convert 30 isinstance dispatch branches in partial_eval.py (_transform_node + _transform_expr) to match/case class patterns, consistent with existing match usage in the same file
  • Add missing slots=True to TemplateWarning dataclass, making all 103 frozen dataclasses consistently slotted
  • Fix cli.py type annotations for TypedDict compatibility with ty

Test plan

  • Full test suite passes (3782 passed, 5 skipped)
  • ruff check . clean
  • ty check src/ clean (no new errors)
  • All changes are type-level or syntactic — zero runtime behavior change

🤖 Generated with Claude Code

lbliii and others added 4 commits April 14, 2026 09:52
…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>
Copilot AI review requested due to automatic review settings April 14, 2026 14:00
@lbliii lbliii merged commit 4faa27c into main Apr 14, 2026
12 checks passed
@lbliii lbliii deleted the lbliii/py314-audit branch April 14, 2026 14:04
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 TypedDict definitions (e.g., SARIF/JUnit reports, cache stats, render summaries, project context) and updates function return annotations accordingly.
  • Refactors partial_eval.py dispatch from isinstance chains to match/case class patterns.
  • Adds slots=True to TemplateWarning for 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.

Comment on lines 7 to +13
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:
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment thread src/kida/readme/detect.py


def detect_project(root: Path, *, depth: int = 2) -> dict[str, Any]:
def detect_project(root: Path, *, depth: int = 2) -> ProjectContext:
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment thread src/kida/readme/detect.py
dependencies = project.get("dependencies", [])

ctx: dict[str, Any] = {
base: dict[str, Any] = {
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment thread src/kida/readme/detect.py
Comment on lines +385 to +386
base["suggested_preset"] = detect_preset(base)
return base # type: ignore[return-value]
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants