Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.8.3] - 2026-04-14

### Changed
- **Immutable registry keys with Literal types** - Type-safe name fields for queries and quality rules
- Query names now use `Literal["exact-name"]` instead of `str` for all 5 built-in queries
- `find-dead-code`, `analyze-module-centrality`, `find-critical-functions`, `analyze-call-complexity`, `detect-circular-dependencies`
- Quality rule names now use `Literal["exact-name"]` instead of `str` for all 3 built-in rules
- `type-coverage`, `docstring-coverage`, `param-complexity`
- Benefits:
- **Type safety**: Typos in registry lookups caught at type-check time instead of runtime
- **IDE autocomplete**: IDEs can suggest valid query/rule names from Literal type
- **Immutability**: Frozen attrs classes with Literal types prevent runtime name modifications
- **Self-documenting**: Type signature shows exact valid values
- No behavior changes - purely a type safety improvement
- All 289 tests passing

## [0.8.2] - 2026-04-14

### Added
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -423,4 +423,4 @@ Review these documents to understand patterns and best practices:
---

**Last Updated**: 2026-04-14
**Current Version**: 0.8.2
**Current Version**: 0.8.3
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Mapper (Application Mapper)

![Version](https://img.shields.io/badge/version-0.8.2-blue.svg)
![Version](https://img.shields.io/badge/version-0.8.3-blue.svg)
![Tests](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/ydkadri/9501806ed5eac873dd324bc606c6dd79/raw/mapper-tests.json&cacheSeconds=300)
![Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/ydkadri/9501806ed5eac873dd324bc606c6dd79/raw/mapper-coverage.json&cacheSeconds=300)
![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg)
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "mapper"
version = "0.8.2"
version = "0.8.3"
description = "Mapper (Application Mapper) - AST-based Python code analyzer with Neo4j graph storage"
readme = "README.md"
requires-python = ">=3.10"
Expand Down Expand Up @@ -93,7 +93,7 @@ addopts = [
testpaths = ["tests"]

[tool.bumpversion]
current_version = "0.8.2"
current_version = "0.8.3"
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
serialize = ["{major}.{minor}.{patch}"]
search = "{current_version}"
Expand Down
2 changes: 1 addition & 1 deletion src/mapper/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Public modules for programmatic access
from mapper import analyser, graph, graph_loader

__version__ = "0.8.2"
__version__ = "0.8.3"

__all__ = [
# Version
Expand Down
3 changes: 2 additions & 1 deletion src/mapper/quality/rules/docstring_coverage.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Docstring coverage quality rule implementation."""

import fnmatch
from typing import Literal

import attrs

Expand All @@ -12,7 +13,7 @@
class DocstringCoverageRule(models.QualityRule):
"""Quality rule for enforcing docstring coverage on public functions."""

name: str = "docstring-coverage"
name: Literal["docstring-coverage"] = "docstring-coverage"
description: str = "Enforce docstring coverage on public functions"

def is_enabled(self, config: models.QualityConfig) -> bool:
Expand Down
3 changes: 2 additions & 1 deletion src/mapper/quality/rules/param_complexity.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Parameter complexity quality rule implementation."""

import fnmatch
from typing import Literal

import attrs

Expand All @@ -12,7 +13,7 @@
class ParamComplexityRule(models.QualityRule):
"""Quality rule for enforcing parameter count limits on functions."""

name: str = "param-complexity"
name: Literal["param-complexity"] = "param-complexity"
description: str = "Enforce parameter count limits on functions"

def is_enabled(self, config: models.QualityConfig) -> bool:
Expand Down
3 changes: 2 additions & 1 deletion src/mapper/quality/rules/type_coverage.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Type coverage quality rule implementation."""

import fnmatch
from typing import Literal

import attrs

Expand All @@ -12,7 +13,7 @@
class TypeCoverageRule(models.QualityRule):
"""Quality rule for enforcing type hint coverage on public functions."""

name: str = "type-coverage"
name: Literal["type-coverage"] = "type-coverage"
description: str = "Enforce type hint coverage on public functions"

def is_enabled(self, config: models.QualityConfig) -> bool:
Expand Down
4 changes: 2 additions & 2 deletions src/mapper/query_system/queries/call_complexity.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Call complexity query - functions with deep call chains."""

from typing import Any
from typing import Any, Literal

import attrs

Expand Down Expand Up @@ -32,7 +32,7 @@ class CallComplexityQuery(Query):
# Metadata
# -------------------------------------------------------------------------

name: str = "analyze-call-complexity"
name: Literal["analyze-call-complexity"] = "analyze-call-complexity"
description: str = "Find functions with deep call chains"
group: QueryGroup = QueryGroup.RISK
columns: list[str] = attrs.field(factory=lambda: ["Severity", "Function", "Max Depth"])
Expand Down
4 changes: 2 additions & 2 deletions src/mapper/query_system/queries/circular_dependencies.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Circular dependencies query - module import cycles."""

from typing import Any
from typing import Any, Literal

import attrs

Expand Down Expand Up @@ -31,7 +31,7 @@ class CircularDependenciesQuery(Query):
# Metadata
# -------------------------------------------------------------------------

name: str = "detect-circular-dependencies"
name: Literal["detect-circular-dependencies"] = "detect-circular-dependencies"
description: str = "Find circular dependencies in module imports"
group: QueryGroup = QueryGroup.RISK
columns: list[str] = attrs.field(factory=lambda: ["Severity", "Cycle", "Length"])
Expand Down
4 changes: 2 additions & 2 deletions src/mapper/query_system/queries/critical_functions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Critical functions query - find most-called functions."""

from typing import Any
from typing import Any, Literal

import attrs

Expand All @@ -26,7 +26,7 @@ class CriticalFunctionsQuery(Query):
# Metadata
# -------------------------------------------------------------------------

name: str = "find-critical-functions"
name: Literal["find-critical-functions"] = "find-critical-functions"
description: str = "Find most-called functions"
group: QueryGroup = QueryGroup.CRITICAL
columns: list[str] = attrs.field(factory=lambda: ["Severity", "Function", "Callers", "Risk"])
Expand Down
4 changes: 2 additions & 2 deletions src/mapper/query_system/queries/dead_code.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Find dead code query - unused functions and classes."""

from typing import Any
from typing import Any, Literal

import attrs

Expand All @@ -24,7 +24,7 @@ class DeadCodeQuery(Query):
# Metadata
# -------------------------------------------------------------------------

name: str = "find-dead-code"
name: Literal["find-dead-code"] = "find-dead-code"
description: str = "Find unused functions and classes"
group: QueryGroup = QueryGroup.RISK
columns: list[str] = attrs.field(factory=lambda: ["Severity", "FQN", "Type", "Public"])
Expand Down
4 changes: 2 additions & 2 deletions src/mapper/query_system/queries/module_centrality.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Module centrality query - find most depended-on modules."""

from typing import Any
from typing import Any, Literal

import attrs

Expand All @@ -25,7 +25,7 @@ class ModuleCentralityQuery(Query):
# Metadata
# -------------------------------------------------------------------------

name: str = "analyze-module-centrality"
name: Literal["analyze-module-centrality"] = "analyze-module-centrality"
description: str = "Find most depended-on modules"
group: QueryGroup = QueryGroup.CRITICAL
columns: list[str] = attrs.field(factory=lambda: ["Severity", "Module", "Dependents", "Risk"])
Expand Down
Loading