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
11 changes: 5 additions & 6 deletions .github/workflows/lint_and_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,11 @@ jobs:
env:
UV_PYTHON: ${{ matrix.python-version }}

- name: Run linters
run: make lint
- name: Run all checks
run: make all
env:
UV_PYTHON: ${{ matrix.python-version }}

- name: Run tests
run: make test
env:
UV_PYTHON: ${{ matrix.python-version }}
- name: Check if code was reformatted
if: always()
run: git diff --exit-code
7 changes: 7 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,10 @@ repos:
language: system
entry: make test
pass_filenames: false

- id: make-dead-code
name: make dead-code (pre-push)
stages: [pre-push]
language: system
entry: make dead-code
pass_filenames: false
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
## [0.3.1-rc.1](https://github.com/disafronov/python-logging-objects-with-schema/compare/v0.3.0...v0.3.1-rc.1) (2025-12-10)

## [0.3.0](https://github.com/disafronov/python-logging-objects-with-schema/compare/v0.2.0...v0.3.0) (2025-12-09)

### Features
Expand Down
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ PYTEST_CMD = uv run python -m pytest -v
COVERAGE_OPTS = --cov --cov-report=term-missing --cov-report=html

# Phony targets
.PHONY: all clean format help install lint test test-coverage
.PHONY: all clean dead-code format help install lint test test-coverage

# Default target
help: ## Show this help message
Expand All @@ -28,6 +28,10 @@ lint: ## Run linting tools
@echo "Running linting tools..."
uv run black --check . && uv run isort --check-only . && uv run flake8 . && uv run mypy . && uv run bandit -r -c pyproject.toml .

dead-code: ## Check for dead code using vulture
@echo "Checking for dead code..."
uv run vulture

# Testing
test: ## Run tests
@echo "Running tests..."
Expand All @@ -38,7 +42,7 @@ test-coverage: ## Run tests with coverage
$(PYTEST_CMD) $(COVERAGE_OPTS)

# Combined operations
all: format lint test ## Run format, lint, and test
all: format lint test dead-code ## Run format, lint, test, and dead-code check
@echo "All checks completed successfully!"

# Maintenance
Expand Down
11 changes: 9 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "uv_build"

[project]
name = "logging-objects-with-schema"
version = "0.3.0"
version = "0.3.1rc1"
description = "Proxy logging wrapper that validates extra fields against a JSON schema."
readme = "README.md"
requires-python = ">=3.10"
Expand Down Expand Up @@ -45,7 +45,8 @@ classifiers = [
"flake8-pyproject>=1.2.3",
"mypy>=1.18.1",
"bandit>=1.8.6",
"pre-commit>=3.5.0"
"pre-commit>=3.5.0",
"vulture>=2.0.0"
]

[project.urls]
Expand Down Expand Up @@ -115,3 +116,9 @@ skip_covered = false

[tool.coverage.html]
directory = "htmlcov"

[tool.vulture]
min_confidence = 80
exclude = [ "__pycache__" ]
ignore_names = [ "cls" ]
paths = [ "src" ]
58 changes: 33 additions & 25 deletions src/logging_objects_with_schema/schema_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,51 +177,59 @@ def _check_cached_found_file_path() -> Path | None:
When a schema file was found, its absolute path is cached as CWD-independent.
This function checks if the cached path still exists on disk.

Note: This function must be called while holding _path_cache_lock.

Returns:
Cached path if file still exists, None if file was deleted (cache invalidated).
"""
global _resolved_schema_path

with _path_cache_lock:
if _resolved_schema_path is None:
return None

# Schema file was found, absolute path doesn't depend on CWD
# Return it if it still exists
if _resolved_schema_path.exists():
return _resolved_schema_path
if _resolved_schema_path is None:
return None

# Cached file no longer exists; invalidate cache so caller will re-search
_resolved_schema_path = None
# Check if this is actually a found file cache (not missing file cache)
# by checking _cached_cwd. We don't need 'global' here since we only read it.
if _cached_cwd is not None:
# This path was cached as missing file, not found file
return None

# Schema file was found, absolute path doesn't depend on CWD
# Return it if it still exists
if _resolved_schema_path.exists():
return _resolved_schema_path

# Cached file no longer exists; invalidate cache so caller will re-search
_resolved_schema_path = None
return None


def _check_cached_missing_file_path() -> Path | None:
"""Check if cached path for a missing file is still valid.

When a schema file was not found, a path based on CWD is cached.
This function checks if CWD has changed since caching.

Note: This function must be called while holding _path_cache_lock.

Returns:
Cached path if CWD unchanged, None if CWD changed (cache invalidated).
"""
global _resolved_schema_path, _cached_cwd

with _path_cache_lock:
if _resolved_schema_path is None or _cached_cwd is None:
return None
if _resolved_schema_path is None or _cached_cwd is None:
return None

# Cached path is based on CWD when file was not found,
# check if CWD changed
current_cwd = _get_current_working_directory()
if current_cwd != _cached_cwd:
# CWD changed, invalidate cache and re-search from new CWD
_resolved_schema_path = None
_cached_cwd = None
return None
# Cached path is based on CWD when file was not found,
# check if CWD changed
current_cwd = _get_current_working_directory()
if current_cwd != _cached_cwd:
# CWD changed, invalidate cache and re-search from new CWD
_resolved_schema_path = None
_cached_cwd = None
return None

# CWD unchanged, return cached path
return _resolved_schema_path
# CWD unchanged, return cached path
return _resolved_schema_path


def _cache_and_return_found_path(found_path: Path) -> Path:
Expand Down Expand Up @@ -800,8 +808,8 @@ def _compile_schema_internal(
given path and forbidden keys set has been observed (including the cases
when it is missing or invalid), subsequent calls always return the cached
result without re-reading or re-compiling the schema. To pick up on-disk
changes to the schema, the application must restart the process. See the
README section \"Schema caching and thread safety\" for more details.
changes to the schema, the application must restart the process. The schema
is cached process-wide and is thread-safe.

Args:
forbidden_keys: Additional forbidden root keys to check against.
Expand Down
33 changes: 32 additions & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading