diff --git a/CHANGELOG.md b/CHANGELOG.md index 9863707..b252ff5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [0.3.0-rc.1](https://github.com/disafronov/python-logging-objects-with-schema/compare/v0.2.0...v0.3.0-rc.1) (2025-12-09) + +### Features + +* add type annotations and mypy support ([d907b1e](https://github.com/disafronov/python-logging-objects-with-schema/commit/d907b1e71c42efc0e54843877d4233d7e88d5f56)) + ## [0.2.0](https://github.com/disafronov/python-logging-objects-with-schema/compare/v0.1.4...v0.2.0) (2025-12-09) ### Features diff --git a/pyproject.toml b/pyproject.toml index 485997c..4ab6a91 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "uv_build" [project] name = "logging-objects-with-schema" -version = "0.2.0" +version = "0.3.0rc1" description = "Proxy logging wrapper that validates extra fields against a JSON schema." readme = "README.md" requires-python = ">=3.10" @@ -27,7 +27,8 @@ classifiers = [ "Programming Language :: Python :: 3.14", "Programming Language :: Python :: 3 :: Only", "Intended Audience :: Developers", - "Topic :: System :: Logging" + "Topic :: System :: Logging", + "Typing :: Typed" ] [[project.authors]] @@ -93,8 +94,7 @@ warn_unreachable = true strict_equality = true [tool.bandit] -skips = [ "B101", "B601" ] -exclude_dirs = [ ".venv", "__pycache__", ".git", "htmlcov" ] +exclude_dirs = [ ".venv", "__pycache__", ".git", "htmlcov", "tests" ] [tool.coverage.run] source = [ "src" ] diff --git a/src/logging_objects_with_schema/py.typed b/src/logging_objects_with_schema/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/src/logging_objects_with_schema/schema_applier.py b/src/logging_objects_with_schema/schema_applier.py index 2f30e86..74ff80b 100644 --- a/src/logging_objects_with_schema/schema_applier.py +++ b/src/logging_objects_with_schema/schema_applier.py @@ -42,7 +42,7 @@ def _create_validation_error_json(field: str, error: str, value: Any) -> str: def _validate_list_value( - value: list, + value: list[Any], source: str, item_expected_type: type | None, ) -> _DataProblem | None: diff --git a/tests/test_mypy_support.py b/tests/test_mypy_support.py new file mode 100644 index 0000000..d342088 --- /dev/null +++ b/tests/test_mypy_support.py @@ -0,0 +1,107 @@ +"""Tests for mypy type checking support.""" + +from __future__ import annotations + +import subprocess +import sys +from pathlib import Path + +import pytest + +from logging_objects_with_schema import SchemaLogger +from tests.helpers import _write_schema + + +def test_py_typed_file_exists() -> None: + """Verify that py.typed marker file exists in the package.""" + package_dir = Path(__file__).parent.parent / "src" / "logging_objects_with_schema" + py_typed = package_dir / "py.typed" + + assert py_typed.exists(), "py.typed marker file must exist for mypy support" + + +def test_mypy_type_checking() -> None: + """Verify that mypy can type-check the package without errors.""" + package_dir = Path(__file__).parent.parent / "src" / "logging_objects_with_schema" + + # Run mypy on the package directory + result = subprocess.run( + [ + sys.executable, + "-m", + "mypy", + str(package_dir), + "--no-error-summary", + ], + capture_output=True, + text=True, + cwd=Path(__file__).parent.parent, + ) + + assert ( + result.returncode == 0 + ), f"mypy found type errors:\n{result.stdout}\n{result.stderr}" + + +def test_mypy_strict_type_checking() -> None: + """Verify that mypy can type-check the package in strict mode without errors.""" + package_dir = Path(__file__).parent.parent / "src" / "logging_objects_with_schema" + + # Run mypy in strict mode on the package directory + result = subprocess.run( + [ + sys.executable, + "-m", + "mypy", + str(package_dir), + "--strict", + "--no-error-summary", + ], + capture_output=True, + text=True, + cwd=Path(__file__).parent.parent, + ) + + assert ( + result.returncode == 0 + ), f"mypy found type errors in strict mode:\n{result.stdout}\n{result.stderr}" + + +def test_schema_logger_type_annotations( + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, +) -> None: + """Verify that SchemaLogger has correct type annotations for mypy.""" + # This test verifies that type annotations are correct by using them + # If mypy is run on this file, it should not find any errors + + monkeypatch.chdir(tmp_path) + _write_schema(tmp_path, {"ServicePayload": {}}) + + # Test that SchemaLogger can be typed correctly + logger: SchemaLogger = SchemaLogger("test-logger", forbidden_keys=None) + + # Test that __init__ signature accepts correct types + logger2: SchemaLogger = SchemaLogger( + name="test-logger-2", + level=10, + forbidden_keys={"key1", "key2"}, + ) + + # Test that SchemaLogger is compatible with logging.Logger + import logging + + def accept_logger(logger: logging.Logger) -> logging.Logger: + return logger + + # This should work without type errors + result: logging.Logger = accept_logger(logger) + assert isinstance(result, SchemaLogger) + + # Test that logger methods are accessible and typed + logger.info("test message") + logger.debug("debug message", extra={"key": "value"}) + logger.warning("warning message") + + # Verify logger2 was created successfully (test __init__ signature) + assert logger2.name == "test-logger-2" diff --git a/uv.lock b/uv.lock index 316b18b..9d108cf 100644 --- a/uv.lock +++ b/uv.lock @@ -1394,7 +1394,7 @@ version = "0.6.3" [[package]] name = "logging-objects-with-schema" -version = "0.2.0" +version = "0.3.0rc1" [package.source] editable = "."