From c3dfcb257d34e2c49c6410522ebdcd9855816847 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 5 Oct 2026 08:47:33 +0100 Subject: [PATCH] Rename pylogkit to ctxlogkit (#44) The name pylogkit on PyPI belongs to an unrelated project. Rename both the distribution and the import package so the two can coexist and this one can be published. Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01Cs1BoS2rKycdxjt8tTMk9h --- .github/workflows/ci.yml | 4 ++-- .github/workflows/release.yml | 2 +- CHANGELOG.md | 6 ++++++ README.md | 23 +++++++++++---------- {pylogkit => ctxlogkit}/__init__.py | 10 ++++----- {pylogkit => ctxlogkit}/_version.py | 0 {pylogkit => ctxlogkit}/log_setup.py | 4 ++-- {pylogkit => ctxlogkit}/py.typed | 0 docs/architecture.md | 14 ++++++------- docs/releasing.md | 8 ++++---- pyproject.toml | 14 ++++++------- tests/conftest.py | 2 +- tests/test_child_loggers.py | 2 +- tests/test_console_colour.py | 2 +- tests/test_contextual_adapter.py | 4 ++-- tests/test_demo.py | 4 ++-- tests/test_dependencies.py | 8 ++++---- tests/test_docs.py | 4 ++-- tests/test_emoji.py | 2 +- tests/test_environment.py | 2 +- tests/test_formatters.py | 4 ++-- tests/test_gitignore.py | 10 ++++----- tests/test_json_import.py | 4 ++-- tests/test_json_output.py | 2 +- tests/test_log_context.py | 18 ++++++++--------- tests/test_log_duration.py | 4 ++-- tests/test_log_exception.py | 4 ++-- tests/test_optional_imports.py | 10 ++++----- tests/test_packaging.py | 28 +++++++++++++------------- tests/test_queue.py | 2 +- tests/test_readme.py | 2 +- tests/test_redaction.py | 2 +- tests/test_rotation.py | 2 +- tests/test_setup_logging_idempotent.py | 4 ++-- tests/test_setup_logging_options.py | 2 +- tests/test_syslog.py | 2 +- tests/test_tqdm_logging.py | 6 +++--- 37 files changed, 114 insertions(+), 107 deletions(-) rename {pylogkit => ctxlogkit}/__init__.py (71%) rename {pylogkit => ctxlogkit}/_version.py (100%) rename {pylogkit => ctxlogkit}/log_setup.py (99%) rename {pylogkit => ctxlogkit}/py.typed (100%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d4747db..488e495 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,13 +79,13 @@ jobs: - run: python -m build - run: twine check dist/* - name: Check the wheel ships the py.typed marker - run: unzip -l dist/*.whl | grep -q "pylogkit/py.typed" + run: unzip -l dist/*.whl | grep -q "ctxlogkit/py.typed" - name: Install the wheel into a clean environment and import it run: | python -m venv "$RUNNER_TEMP/wheel-venv" "$RUNNER_TEMP/wheel-venv/bin/pip" install dist/*.whl cd "$RUNNER_TEMP" - "$RUNNER_TEMP/wheel-venv/bin/python" -c "import pylogkit; print(pylogkit.__all__)" + "$RUNNER_TEMP/wheel-venv/bin/python" -c "import ctxlogkit; print(ctxlogkit.__all__)" - uses: actions/upload-artifact@v4 with: name: dist diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0a11c1b..05d9cf1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: python-version: "3.12" - name: Check that the tag matches the package version run: | - version=$(python -c "import re, pathlib; print(re.search(r'__version__ = \"(.+?)\"', pathlib.Path('pylogkit/_version.py').read_text()).group(1))") + version=$(python -c "import re, pathlib; print(re.search(r'__version__ = \"(.+?)\"', pathlib.Path('ctxlogkit/_version.py').read_text()).group(1))") if [ "v$version" != "$GITHUB_REF_NAME" ]; then echo "Tag $GITHUB_REF_NAME does not match version $version" >&2 exit 1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 842287c..c0dc69f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## Unreleased +### Changed + +- **Breaking:** the project is renamed from `pylogkit` to `ctxlogkit`, for both the distribution + and the import package. The old name on PyPI belongs to an unrelated project. Replace + `from pylogkit import ...` with `from ctxlogkit import ...` (#44). + ### Added - `setup_logging()` accepts `syslog_address` (a `(host, port)` tuple or a Unix diff --git a/README.md b/README.md index 13b7b78..5003580 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# pylogkit +# ctxlogkit [![CI](https://github.com/markbac/py-logkit/actions/workflows/ci.yml/badge.svg)](https://github.com/markbac/py-logkit/actions/workflows/ci.yml) @@ -9,7 +9,7 @@ carrying the same request context (user, session, request, host, environment and It builds on the standard `logging` module and [`colorlog`](https://pypi.org/project/colorlog/), so everything it returns is an ordinary `logging.Logger`. -## Why pylogkit +## Why ctxlogkit - **One call, sensible defaults.** Console, file, JSON and syslog handlers with their own levels, formats and rotation, configured by keyword arguments. @@ -24,12 +24,13 @@ so everything it returns is an ordinary `logging.Logger`. Requires Python 3.10 or later. The only mandatory dependency is `colorlog`. -> **Warning:** The name `pylogkit` on PyPI belongs to a different, unrelated project, so -> `pip install pylogkit` does **not** install this library. Install it from this repository -> instead (see the naming discussion in [#44](https://github.com/markbac/py-logkit/issues/44)). +> **Note:** This project was previously called `pylogkit`. That name on PyPI belongs to a +> different, unrelated project, so the distribution and the import package are now `ctxlogkit` +> (see [#44](https://github.com/markbac/py-logkit/issues/44)). It is not on PyPI yet, so install it +> from this repository: ```bash -pip install "pylogkit[all] @ git+https://github.com/markbac/py-logkit" +pip install "ctxlogkit[all] @ git+https://github.com/markbac/py-logkit" ``` or from a clone: @@ -44,7 +45,7 @@ pip install ".[all]" # everything optional ## Quick start ```python -from pylogkit import ContextualLoggerAdapter, set_log_context, setup_logging +from ctxlogkit import ContextualLoggerAdapter, set_log_context, setup_logging logger = setup_logging( name="shop.checkout", @@ -109,7 +110,7 @@ exit, even when the block raises. The context is held in a `contextvars.ContextV `asyncio` tasks and threads do not see each other's values: ```python -from pylogkit import log_context +from ctxlogkit import log_context with log_context(request_id="abc"): log.info("handled") # carries request_id=abc @@ -168,7 +169,7 @@ Pass `redact_keys` to mask the value of any field whose name contains one of the syslog, and are off unless you ask for them. ```python -from pylogkit import DEFAULT_REDACT_KEYS, setup_logging +from ctxlogkit import DEFAULT_REDACT_KEYS, setup_logging logger = setup_logging( "app", @@ -192,7 +193,7 @@ only puts the record on an in-memory queue, and a background thread owns the rea writes it. The context fields are captured on the calling thread, so they are still correct. ```python -from pylogkit import setup_logging, shutdown_logging +from ctxlogkit import setup_logging, shutdown_logging logger = setup_logging("app", to_file=True, use_queue=True) logger.info("returns without waiting for the file") @@ -234,7 +235,7 @@ Each JSON record starts with `timestamp` (ISO 8601 with UTC offset), `level`, `l ## Helpers ```python -from pylogkit import log_duration, log_exception, tqdm_logging +from ctxlogkit import log_duration, log_exception, tqdm_logging @log_duration(logger, level="debug") def import_orders(): diff --git a/pylogkit/__init__.py b/ctxlogkit/__init__.py similarity index 71% rename from pylogkit/__init__.py rename to ctxlogkit/__init__.py index 3393f7d..a0e3ade 100644 --- a/pylogkit/__init__.py +++ b/ctxlogkit/__init__.py @@ -1,16 +1,16 @@ -"""pylogkit: a structured and colourised logging toolkit for Python applications. +"""ctxlogkit: a structured and colourised logging toolkit for Python applications. -The public API lives in :mod:`pylogkit.log_setup` and is re-exported here, so +The public API lives in :mod:`ctxlogkit.log_setup` and is re-exported here, so applications can write:: - from pylogkit import setup_logging, ContextualLoggerAdapter + from ctxlogkit import setup_logging, ContextualLoggerAdapter logger = ContextualLoggerAdapter(setup_logging(name=__name__, level="DEBUG")) logger.info("Hello, logging!") """ -from pylogkit._version import __version__ -from pylogkit.log_setup import ( +from ctxlogkit._version import __version__ +from ctxlogkit.log_setup import ( DEFAULT_REDACT_KEYS, ContextualLoggerAdapter, RedactionFilter, diff --git a/pylogkit/_version.py b/ctxlogkit/_version.py similarity index 100% rename from pylogkit/_version.py rename to ctxlogkit/_version.py diff --git a/pylogkit/log_setup.py b/ctxlogkit/log_setup.py similarity index 99% rename from pylogkit/log_setup.py rename to ctxlogkit/log_setup.py index b44f4c0..99b9f65 100644 --- a/pylogkit/log_setup.py +++ b/ctxlogkit/log_setup.py @@ -14,7 +14,7 @@ Example:: - from pylogkit import ContextualLoggerAdapter, setup_logging + from ctxlogkit import ContextualLoggerAdapter, setup_logging logger = setup_logging(name=__name__, to_file=True, file_path="app.log", level="DEBUG") logger = ContextualLoggerAdapter(logger) @@ -123,7 +123,7 @@ except ImportError: tqdm = None -_log_context: ContextVar[dict[str, Any] | None] = ContextVar("pylogkit_log_context", default=None) +_log_context: ContextVar[dict[str, Any] | None] = ContextVar("ctxlogkit_log_context", default=None) def set_log_context(**kwargs: Any) -> None: diff --git a/pylogkit/py.typed b/ctxlogkit/py.typed similarity index 100% rename from pylogkit/py.typed rename to ctxlogkit/py.typed diff --git a/docs/architecture.md b/docs/architecture.md index dff05ef..a43048a 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,21 +1,21 @@ # Architecture -This document explains how `pylogkit` is put together and why. It is written for contributors and for +This document explains how `ctxlogkit` is put together and why. It is written for contributors and for users who want to know exactly what happens between a logging call and the bytes on disk. For usage, see the [README](../README.md). ## Overview -`pylogkit` is a thin layer over the standard library's `logging` package. It does not replace +`ctxlogkit` is a thin layer over the standard library's `logging` package. It does not replace loggers, levels or handlers. It configures them consistently and adds three things: context fields on every record, a stable set of output formats, and a few opt-in behaviours (queueing, redaction and environment configuration). -The whole implementation is one module, `pylogkit/log_setup.py`, re-exported from the package root. +The whole implementation is one module, `ctxlogkit/log_setup.py`, re-exported from the package root. ```mermaid flowchart TB - subgraph pkg["pylogkit package"] + subgraph pkg["ctxlogkit package"] init["__init__.py
public API"] ver["_version.py
single-sourced version"] core["log_setup.py
implementation"] @@ -32,7 +32,7 @@ flowchart TB ## Public API -Everything in `pylogkit.__all__` is public. The rest of `log_setup.py` is private, marked by a leading +Everything in `ctxlogkit.__all__` is public. The rest of `log_setup.py` is private, marked by a leading underscore. | Area | Names | @@ -171,7 +171,7 @@ handler. Standard `LogRecord` attributes are never masked. Tracebacks are not se ## Optional dependencies `colorlog` is required. `python-json-logger` and `tqdm` are optional extras, imported inside -`try`/`except ImportError` blocks so that importing `pylogkit` never fails because of them. Asking for +`try`/`except ImportError` blocks so that importing `ctxlogkit` never fails because of them. Asking for JSON output without the library raises an `ImportError` that names the install command. `python-json-logger` changed between versions, and `_build_json_formatter()` hides the differences. @@ -192,7 +192,7 @@ CI runs the tests against the latest release, against 2.0.7, and with neither ex - `from __future__ import annotations` keeps annotations lazy so the code runs on Python 3.10 and later. `LoggerAdapter` is only subscriptable at runtime from Python 3.11, so a type-checking-only alias is used as the adapter's base class. -- The version is defined once, in `pylogkit/_version.py`, and `pyproject.toml` reads it without +- The version is defined once, in `ctxlogkit/_version.py`, and `pyproject.toml` reads it without importing the package. See [releasing](releasing.md). ## Testing diff --git a/docs/releasing.md b/docs/releasing.md index 3450bf8..452c661 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -1,13 +1,13 @@ # Releasing Releases follow [Semantic Versioning](https://semver.org/). The version lives in one place, -`pylogkit/_version.py`, and the build reads it from there. +`ctxlogkit/_version.py`, and the build reads it from there. ## Cutting a release 1. Move the entries under `## Unreleased` in `CHANGELOG.md` into a new `## X.Y.Z - YYYY-MM-DD` heading, and leave an empty `## Unreleased` section above it. -1. Set `__version__` in `pylogkit/_version.py` to `X.Y.Z`. +1. Set `__version__` in `ctxlogkit/_version.py` to `X.Y.Z`. 1. Open a pull request with those two changes and merge it once CI is green. 1. Tag the merge commit and push the tag: @@ -22,8 +22,8 @@ whose notes are generated from the merged pull requests. ## Publishing to PyPI -The workflow does not publish to PyPI yet. The name `pylogkit` is already used there by an -unrelated project (see issue #44), so a distribution name has to be chosen first. Once it is, +The workflow does not publish to PyPI yet. The name `ctxlogkit` was checked and was free when the project +was renamed from `pylogkit` (issue #44). To publish, reserve it on PyPI and then add a publish job that uses [trusted publishing](https://docs.pypi.org/trusted-publishers/) with the `id-token: write` permission, so that no API token is stored in the repository. diff --git a/pyproject.toml b/pyproject.toml index 744622e..cdb1ca7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ requires = ["setuptools>=77"] build-backend = "setuptools.build_meta" [project] -name = "pylogkit" +name = "ctxlogkit" dynamic = ["version"] description = "A structured and colourised logging toolkit for Python applications" readme = "README.md" @@ -30,7 +30,7 @@ dependencies = ["colorlog>=6.0.0"] [project.optional-dependencies] json = ["python-json-logger>=2.0.7"] progress = ["tqdm"] -all = ["pylogkit[json,progress]"] +all = ["ctxlogkit[json,progress]"] dev = ["pytest>=7", "pytest-cov", "ruff", "mypy", "build"] [project.urls] @@ -39,13 +39,13 @@ Issues = "https://github.com/markbac/py-logkit/issues" Changelog = "https://github.com/markbac/py-logkit/blob/main/CHANGELOG.md" [tool.setuptools.dynamic] -version = { attr = "pylogkit._version.__version__" } +version = { attr = "ctxlogkit._version.__version__" } [tool.setuptools.package-data] -pylogkit = ["py.typed"] +ctxlogkit = ["py.typed"] [tool.setuptools.packages.find] -include = ["pylogkit*"] +include = ["ctxlogkit*"] [tool.pytest.ini_options] testpaths = ["tests"] @@ -55,7 +55,7 @@ markers = [ ] [tool.coverage.run] -source = ["pylogkit"] +source = ["ctxlogkit"] branch = true [tool.coverage.report] @@ -83,7 +83,7 @@ convention = "google" [tool.mypy] strict = true python_version = "3.10" -files = ["pylogkit"] +files = ["ctxlogkit"] warn_unused_ignores = true warn_redundant_casts = true diff --git a/tests/conftest.py b/tests/conftest.py index 2ed824f..4063a6f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,7 +4,7 @@ import pytest -from pylogkit import clear_log_context +from ctxlogkit import clear_log_context _HAS_JSON_LOGGER = find_spec("pythonjsonlogger") is not None _HAS_TQDM = find_spec("tqdm") is not None diff --git a/tests/test_child_loggers.py b/tests/test_child_loggers.py index 47e0203..7befdca 100644 --- a/tests/test_child_loggers.py +++ b/tests/test_child_loggers.py @@ -5,7 +5,7 @@ import pytest -from pylogkit import set_log_context, setup_logging +from ctxlogkit import set_log_context, setup_logging def test_child_logger_records_are_formatted(capsys): diff --git a/tests/test_console_colour.py b/tests/test_console_colour.py index fffb519..583dd73 100644 --- a/tests/test_console_colour.py +++ b/tests/test_console_colour.py @@ -5,7 +5,7 @@ import pytest -from pylogkit import setup_logging +from ctxlogkit import setup_logging class FakeTTY(io.StringIO): diff --git a/tests/test_contextual_adapter.py b/tests/test_contextual_adapter.py index 63df515..e354f62 100644 --- a/tests/test_contextual_adapter.py +++ b/tests/test_contextual_adapter.py @@ -1,6 +1,6 @@ -"""Tests for :class:`pylogkit.log_setup.ContextualLoggerAdapter`.""" +"""Tests for :class:`ctxlogkit.log_setup.ContextualLoggerAdapter`.""" -from pylogkit import ( +from ctxlogkit import ( ContextualLoggerAdapter, get_log_context, set_log_context, diff --git a/tests/test_demo.py b/tests/test_demo.py index 816d6ce..57f60ec 100644 --- a/tests/test_demo.py +++ b/tests/test_demo.py @@ -1,11 +1,11 @@ -"""Smoke test for the example in ``python -m pylogkit.log_setup``.""" +"""Smoke test for the example in ``python -m ctxlogkit.log_setup``.""" import runpy import time import pytest -from pylogkit import log_setup +from ctxlogkit import log_setup pytestmark = pytest.mark.json_logger diff --git a/tests/test_dependencies.py b/tests/test_dependencies.py index 667a913..1df051e 100644 --- a/tests/test_dependencies.py +++ b/tests/test_dependencies.py @@ -1,6 +1,6 @@ """Tests that declared dependencies are real, installable distributions. -These tests read the metadata of the installed ``pylogkit`` distribution, so +These tests read the metadata of the installed ``ctxlogkit`` distribution, so run them in an environment created with ``pip install -e ".[all,dev]"``. """ @@ -14,20 +14,20 @@ def _requirement_names(): """Return the distribution names of every declared requirement.""" - requires = importlib.metadata.requires("pylogkit") or [] + requires = importlib.metadata.requires("ctxlogkit") or [] return {NAME.match(requirement).group(0) for requirement in requires} def test_core_dependency_is_colorlog(): """The only mandatory dependency is ``colorlog`` (not the misspelt name).""" - core = [r for r in importlib.metadata.requires("pylogkit") if "extra ==" not in r] + core = [r for r in importlib.metadata.requires("ctxlogkit") if "extra ==" not in r] assert [NAME.match(r).group(0) for r in core] == ["colorlog"] def test_optional_features_are_extras(): """JSON output and progress bars are optional extras.""" - extras = set(importlib.metadata.metadata("pylogkit").get_all("Provides-Extra")) + extras = set(importlib.metadata.metadata("ctxlogkit").get_all("Provides-Extra")) assert {"json", "progress", "all", "dev"} <= extras diff --git a/tests/test_docs.py b/tests/test_docs.py index dbe070d..7c9d5cd 100644 --- a/tests/test_docs.py +++ b/tests/test_docs.py @@ -25,11 +25,11 @@ def test_mermaid_diagrams_are_present_and_avoid_semicolons(): def test_architecture_names_the_public_api(): """Every exported name is mentioned, so new exports force a documentation update.""" - import pylogkit + import ctxlogkit text = ARCHITECTURE.read_text(encoding="utf-8") - missing = [name for name in pylogkit.__all__ if name not in text] + missing = [name for name in ctxlogkit.__all__ if name not in text] assert not missing, missing diff --git a/tests/test_emoji.py b/tests/test_emoji.py index c7f63d3..9e18b51 100644 --- a/tests/test_emoji.py +++ b/tests/test_emoji.py @@ -2,7 +2,7 @@ import logging -from pylogkit import log_setup, setup_logging +from ctxlogkit import log_setup, setup_logging STANDARD_LEVELS = {"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"} diff --git a/tests/test_environment.py b/tests/test_environment.py index a6f63ad..4b6b8e9 100644 --- a/tests/test_environment.py +++ b/tests/test_environment.py @@ -6,7 +6,7 @@ import pytest -from pylogkit import setup_logging +from ctxlogkit import setup_logging @pytest.fixture(autouse=True) diff --git a/tests/test_formatters.py b/tests/test_formatters.py index d4b469d..7b455d2 100644 --- a/tests/test_formatters.py +++ b/tests/test_formatters.py @@ -2,8 +2,8 @@ import logging -from pylogkit import set_log_context, setup_logging -from pylogkit.log_setup import ( +from ctxlogkit import set_log_context, setup_logging +from ctxlogkit.log_setup import ( FILE_FORMAT, SmartFieldFormatter, _build_console_formatter, diff --git a/tests/test_gitignore.py b/tests/test_gitignore.py index 8615679..3fdf75b 100644 --- a/tests/test_gitignore.py +++ b/tests/test_gitignore.py @@ -17,10 +17,10 @@ @pytest.mark.parametrize( "path", [ - "pylogkit/__pycache__/log_setup.cpython-313.pyc", - "dist/pylogkit-0.1.0-py3-none-any.whl", - "build/lib/pylogkit/__init__.py", - "pylogkit.egg-info/PKG-INFO", + "ctxlogkit/__pycache__/log_setup.cpython-313.pyc", + "dist/ctxlogkit-0.1.0-py3-none-any.whl", + "build/lib/ctxlogkit/__init__.py", + "ctxlogkit.egg-info/PKG-INFO", ".venv/bin/python", ".pytest_cache/README.md", ".mypy_cache/CACHEDIR.TAG", @@ -37,7 +37,7 @@ def test_generated_files_are_ignored(path): assert result.returncode == 0, f"{path} is not ignored" -@pytest.mark.parametrize("path", ["pylogkit/log_setup.py", "tests/test_gitignore.py", "README.md"]) +@pytest.mark.parametrize("path", ["ctxlogkit/log_setup.py", "tests/test_gitignore.py", "README.md"]) def test_source_files_are_not_ignored(path): """The patterns must not hide real source files.""" result = subprocess.run(["git", "check-ignore", "-q", path], cwd=ROOT, check=False) diff --git a/tests/test_json_import.py b/tests/test_json_import.py index efcfa22..abb8540 100644 --- a/tests/test_json_import.py +++ b/tests/test_json_import.py @@ -5,13 +5,13 @@ import pytest -from pylogkit import log_setup +from ctxlogkit import log_setup def test_import_emits_no_deprecation_warning(): """The deprecated ``pythonjsonlogger.jsonlogger`` path must not be used.""" result = subprocess.run( - [sys.executable, "-W", "error::DeprecationWarning", "-c", "import pylogkit"], + [sys.executable, "-W", "error::DeprecationWarning", "-c", "import ctxlogkit"], capture_output=True, text=True, ) diff --git a/tests/test_json_output.py b/tests/test_json_output.py index 409212e..d83aff8 100644 --- a/tests/test_json_output.py +++ b/tests/test_json_output.py @@ -5,7 +5,7 @@ import pytest -from pylogkit import log_setup, set_log_context, setup_logging +from ctxlogkit import log_setup, set_log_context, setup_logging pytestmark = pytest.mark.json_logger diff --git a/tests/test_log_context.py b/tests/test_log_context.py index b891a7f..c8bc694 100644 --- a/tests/test_log_context.py +++ b/tests/test_log_context.py @@ -1,9 +1,9 @@ -"""Tests for :func:`pylogkit.log_setup.get_log_context`.""" +"""Tests for :func:`ctxlogkit.log_setup.get_log_context`.""" import socket -from pylogkit import get_log_context, set_log_context -from pylogkit.log_setup import _hostname +from ctxlogkit import get_log_context, set_log_context +from ctxlogkit.log_setup import _hostname def test_hostname_is_looked_up_once(monkeypatch): @@ -74,7 +74,7 @@ def worker(): def test_context_argument_of_setup_logging_sets_the_global_context(): """``setup_logging(context=...)`` seeds the context for later records.""" - from pylogkit import setup_logging + from ctxlogkit import setup_logging setup_logging("ctx-arg", to_console=False, context={"user_id": "seeded"}) @@ -83,7 +83,7 @@ def test_context_argument_of_setup_logging_sets_the_global_context(): def test_log_context_adds_fields_and_restores_them(): """Fields apply inside the block and the previous context returns afterwards.""" - from pylogkit import log_context + from ctxlogkit import log_context set_log_context(user_id="alice") @@ -101,7 +101,7 @@ def test_log_context_restores_on_exception(): """The previous context is restored when the block raises.""" import pytest - from pylogkit import log_context + from ctxlogkit import log_context set_log_context(user_id="alice") @@ -113,7 +113,7 @@ def test_log_context_restores_on_exception(): def test_log_context_nests(): """Inner blocks add to the outer one and leave it intact on exit.""" - from pylogkit import log_context + from ctxlogkit import log_context with log_context(request_id="outer"): with log_context(user_id="bob"): @@ -127,7 +127,7 @@ def test_log_context_reaches_log_records(capsys): """Records logged inside the block carry its fields.""" import logging - from pylogkit import log_context, setup_logging + from ctxlogkit import log_context, setup_logging setup_logging("ctx-manager") @@ -144,7 +144,7 @@ def test_context_is_isolated_between_asyncio_tasks(): """Concurrent tasks must each keep their own context (``threading.local`` could not).""" import asyncio - from pylogkit import log_context + from ctxlogkit import log_context async def handle(name: str) -> str: with log_context(request_id=name): diff --git a/tests/test_log_duration.py b/tests/test_log_duration.py index fb86032..f4d84ba 100644 --- a/tests/test_log_duration.py +++ b/tests/test_log_duration.py @@ -1,11 +1,11 @@ -"""Tests for :func:`pylogkit.log_setup.log_duration`.""" +"""Tests for :func:`ctxlogkit.log_setup.log_duration`.""" import itertools import logging import pytest -from pylogkit import log_duration, log_setup +from ctxlogkit import log_duration, log_setup LOGGER = logging.getLogger("duration-test") diff --git a/tests/test_log_exception.py b/tests/test_log_exception.py index 00f6b67..8e73f52 100644 --- a/tests/test_log_exception.py +++ b/tests/test_log_exception.py @@ -1,8 +1,8 @@ -"""Tests for :func:`pylogkit.log_setup.log_exception`.""" +"""Tests for :func:`ctxlogkit.log_setup.log_exception`.""" import logging -from pylogkit import log_exception +from ctxlogkit import log_exception def test_logs_an_error_with_the_traceback(caplog): diff --git a/tests/test_optional_imports.py b/tests/test_optional_imports.py index 1a4986e..abe0678 100644 --- a/tests/test_optional_imports.py +++ b/tests/test_optional_imports.py @@ -22,7 +22,7 @@ def test_tqdm_is_optional(): """Without tqdm the module still imports and ``tqdm`` is ``None``.""" result = _run( "import sys; sys.modules['tqdm'] = None\n" - "from pylogkit import log_setup\n" + "from ctxlogkit import log_setup\n" "assert log_setup.tqdm is None" ) @@ -34,7 +34,7 @@ def test_json_logger_is_optional(): result = _run( "import sys\n" "sys.modules['pythonjsonlogger'] = None\n" - "from pylogkit import log_setup\n" + "from ctxlogkit import log_setup\n" "assert log_setup.JsonFormatter is None" ) @@ -55,7 +55,7 @@ def test_old_json_logger_import_path_is_used_as_a_fallback(): "fake.JsonFormatter = JsonFormatter\n" "sys.modules['pythonjsonlogger.json'] = None\n" "sys.modules['pythonjsonlogger.jsonlogger'] = fake\n" - "from pylogkit import log_setup\n" + "from ctxlogkit import log_setup\n" "assert log_setup.JsonFormatter is JsonFormatter" ) @@ -64,13 +64,13 @@ def test_old_json_logger_import_path_is_used_as_a_fallback(): def test_colorlog_is_required_and_the_error_says_how_to_install_it(): """The one mandatory dependency fails with an actionable message.""" - result = _run("import sys; sys.modules['colorlog'] = None\nimport pylogkit") + result = _run("import sys; sys.modules['colorlog'] = None\nimport ctxlogkit") assert result.returncode != 0 assert "pip install colorlog" in result.stderr -@pytest.mark.parametrize("module", ["pylogkit", "pylogkit.log_setup"]) +@pytest.mark.parametrize("module", ["ctxlogkit", "ctxlogkit.log_setup"]) def test_modules_import_cleanly(module): """Plain imports must not print anything or emit warnings.""" result = subprocess.run( diff --git a/tests/test_packaging.py b/tests/test_packaging.py index 440e74f..80eea68 100644 --- a/tests/test_packaging.py +++ b/tests/test_packaging.py @@ -7,39 +7,39 @@ def test_package_directory_is_a_regular_package(): """Without ``__init__.py`` build tools discover no package and ship no code.""" - assert (ROOT / "pylogkit" / "__init__.py").is_file() + assert (ROOT / "ctxlogkit" / "__init__.py").is_file() def test_public_api_is_exported(): """Every name in ``__all__`` is importable from the package root.""" - import pylogkit + import ctxlogkit - assert pylogkit.__all__ - for name in pylogkit.__all__: - assert hasattr(pylogkit, name), name + assert ctxlogkit.__all__ + for name in ctxlogkit.__all__: + assert hasattr(ctxlogkit, name), name def test_py_typed_marker_is_present(): """PEP 561: the marker tells type checkers that the package ships inline types.""" - assert (ROOT / "pylogkit" / "py.typed").is_file() + assert (ROOT / "ctxlogkit" / "py.typed").is_file() def test_package_data_includes_py_typed(): """The marker must be listed as package data or the wheel omits it.""" text = (ROOT / "pyproject.toml").read_text(encoding="utf-8") - assert 'pylogkit = ["py.typed"]' in text + assert 'ctxlogkit = ["py.typed"]' in text def test_public_api_is_annotated(): """Every public function and method has annotations for all parameters and the return.""" import inspect - import pylogkit + import ctxlogkit missing = [] - for name in pylogkit.__all__: - obj = getattr(pylogkit, name) + for name in ctxlogkit.__all__: + obj = getattr(ctxlogkit, name) if not callable(obj): continue members = [obj] @@ -64,15 +64,15 @@ def test_version_is_single_sourced(): """``pyproject.toml`` reads the version from ``_version.py`` instead of repeating it.""" import re - import pylogkit - from pylogkit import _version + import ctxlogkit + from ctxlogkit import _version text = (ROOT / "pyproject.toml").read_text(encoding="utf-8") assert 'dynamic = ["version"]' in text - assert "pylogkit._version.__version__" in text + assert "ctxlogkit._version.__version__" in text assert not re.search(r'^version = "', text, re.M) - assert pylogkit.__version__ == _version.__version__ + assert ctxlogkit.__version__ == _version.__version__ assert re.fullmatch(r"\d+\.\d+\.\d+", _version.__version__) diff --git a/tests/test_queue.py b/tests/test_queue.py index 9ae4818..d6b1500 100644 --- a/tests/test_queue.py +++ b/tests/test_queue.py @@ -7,7 +7,7 @@ import pytest -from pylogkit import log_context, log_exception, log_setup, setup_logging, shutdown_logging +from ctxlogkit import log_context, log_exception, log_setup, setup_logging, shutdown_logging @pytest.fixture(autouse=True) diff --git a/tests/test_readme.py b/tests/test_readme.py index fa35e46..0be7219 100644 --- a/tests/test_readme.py +++ b/tests/test_readme.py @@ -6,7 +6,7 @@ import pytest -from pylogkit import setup_logging +from ctxlogkit import setup_logging README = (Path(__file__).resolve().parent.parent / "README.md").read_text() diff --git a/tests/test_redaction.py b/tests/test_redaction.py index 79daf55..51e4e6c 100644 --- a/tests/test_redaction.py +++ b/tests/test_redaction.py @@ -5,7 +5,7 @@ import pytest -from pylogkit import ( +from ctxlogkit import ( DEFAULT_REDACT_KEYS, ContextualLoggerAdapter, RedactionFilter, diff --git a/tests/test_rotation.py b/tests/test_rotation.py index cabd672..bd2c18f 100644 --- a/tests/test_rotation.py +++ b/tests/test_rotation.py @@ -2,7 +2,7 @@ from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler -from pylogkit import setup_logging +from ctxlogkit import setup_logging def test_size_rotation_keeps_the_configured_number_of_backups(tmp_path): diff --git a/tests/test_setup_logging_idempotent.py b/tests/test_setup_logging_idempotent.py index 67e31bf..682d33c 100644 --- a/tests/test_setup_logging_idempotent.py +++ b/tests/test_setup_logging_idempotent.py @@ -2,8 +2,8 @@ import logging -from pylogkit import setup_logging -from pylogkit.log_setup import ContextFilter +from ctxlogkit import setup_logging +from ctxlogkit.log_setup import ContextFilter def _context_filters(obj): diff --git a/tests/test_setup_logging_options.py b/tests/test_setup_logging_options.py index 69a12d4..a054ab5 100644 --- a/tests/test_setup_logging_options.py +++ b/tests/test_setup_logging_options.py @@ -4,7 +4,7 @@ import pytest -from pylogkit import log_setup, setup_logging +from ctxlogkit import log_setup, setup_logging def _flush(logger): diff --git a/tests/test_syslog.py b/tests/test_syslog.py index 7cfb4da..b896fc4 100644 --- a/tests/test_syslog.py +++ b/tests/test_syslog.py @@ -5,7 +5,7 @@ import pytest -from pylogkit import set_log_context, setup_logging, setup_syslog_logger +from ctxlogkit import set_log_context, setup_logging, setup_syslog_logger @pytest.fixture diff --git a/tests/test_tqdm_logging.py b/tests/test_tqdm_logging.py index 6f99d99..7de656d 100644 --- a/tests/test_tqdm_logging.py +++ b/tests/test_tqdm_logging.py @@ -1,11 +1,11 @@ -"""Tests for :func:`pylogkit.log_setup.tqdm_logging`.""" +"""Tests for :func:`ctxlogkit.log_setup.tqdm_logging`.""" import logging import pytest -from pylogkit import log_setup -from pylogkit.log_setup import tqdm_logging +from ctxlogkit import log_setup +from ctxlogkit.log_setup import tqdm_logging LOGGER = logging.getLogger("tqdm-test")