Skip to content
Draft
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
18 changes: 9 additions & 9 deletions .github/PULL_REQUEST_TEMPLATE
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
<!-- What is this pull request for? Does it fix any issues? -->

## Checklist
- [ ] If code changes were made, then they have been tested.
- [ ] I have updated the documentation to reflect the changes.
- [ ] I have thought about how this code may affect other services.
- [ ] This PR fixes an issue.
- [ ] This PR add/remove/change unit tests.
- [ ] This PR adds something new (e.g. new method or parameters).
- [ ] This PR is a breaking change (e.g. methods or parameters removed/renamed)
- [ ] This PR is **not** a code change (e.g. documentation, README, ...)
- [ ] If code changes were made, then they have been tested
- [ ] I have updated the documentation to reflect any changes made
- [ ] I have thought about how this code may affect other services
- [ ] This PR fixes an issue
- [ ] This PR is a breaking change (e.g. method, parameters, env variables)
- [ ] This PR adds something new (e.g. method, parameters, env variables)
- [ ] This PR change unit and integration tests
- [ ] This PR is **NOT** a code change (e.g. documentation, packages)

## Reviewer
- [ ] I understand that approving this code, I am also responsible for it going into the codebase.
- [ ] I understand that approving this code, I am also responsible for it going into the codebase
53 changes: 35 additions & 18 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
name: CI/CD Pipeline

'on':
pull_request:
push:
branches: ['**']
tags: ['v*']

env:
LATEST_PYTHON_VERSION: '3.14'

jobs:
lint:
name: Lint (ruff)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: astral-sh/ruff-action@v3
with:
args: "check"

test:
name: Test Python ${{ matrix.python-version }} on ${{ matrix.os }}
runs-on: ${{ matrix.runs-on || matrix.os }}
runs-on: ${{ matrix.os }}
needs: lint
strategy:
fail-fast: false
matrix:
os: ['ubuntu-latest', 'macos-latest', 'macos-14-arm64', 'windows-latest']
python-version: ['3.12', '3.13', '3.14']
include:
- os: 'macos-14-arm64'
runs-on: 'macos-14'
os: ['ubuntu-latest', 'macos-latest', 'windows-latest']
python-version: ['3.11', '3.14']
defaults:
run:
working-directory: ${{ github.workspace }}
Expand All @@ -26,62 +35,70 @@ jobs:

- name: Install uv
uses: astral-sh/setup-uv@v7
with:
enable-cache: true

- name: Set up Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}

- name: Install dependencies
run: uv sync --all-extras
run: uv sync --locked --all-extras --dev
shell: bash

- name: Run tests with coverage
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: uv run pytest
command: uv run --no-sync pytest
shell: bash

- name: Upload coverage to Codecov
if: matrix.python-version == '3.14' && matrix.os == 'ubuntu-latest'
if: matrix.python-version == env.LATEST_PYTHON_VERSION && matrix.os == 'ubuntu-latest'
uses: codecov/codecov-action@v5

- name: Upload test results to Codecov
if: matrix.python-version == '3.14' && matrix.os == 'ubuntu-latest'
if: matrix.python-version == env.LATEST_PYTHON_VERSION && matrix.os == 'ubuntu-latest'
uses: codecov/codecov-action@v5
with:
report_type: test_results


build:
name: Build package
name: Build Package
runs-on: ubuntu-latest
needs: [test]
needs: test
if: startsWith(github.ref, 'refs/tags/v')
steps:
- uses: actions/checkout@v6

- name: Install uv
uses: astral-sh/setup-uv@v7
with:
enable-cache: true

- name: Set up Python 3.14
run: uv python install 3.14
- name: Set up Python ${{ env.LATEST_PYTHON_VERSION }}
run: uv python install ${{ env.LATEST_PYTHON_VERSION }}

- name: Build package
run: uv build

- name: Smoke test (wheel)
run: uv run --isolated --no-project --with dist/*.whl tests/smoke_test.py

- name: Smoke test (sdist)
run: uv run --isolated --no-project --with dist/*.tar.gz tests/smoke_test.py

- name: Upload artifacts
uses: actions/upload-artifact@v6
with:
name: python-packages
path: dist/
retention-days: 7


release:
name: Create Release
runs-on: ubuntu-latest
needs: [build]
needs: build
if: startsWith(github.ref, 'refs/tags/v')
permissions:
contents: write
Expand Down
5 changes: 5 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
repos:
- repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.10.0
hooks:
- id: uv-lock
32 changes: 24 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@
- [Settings Cache Management](#settings-cache-management)
- [Flexible Configuration Options](#flexible-configuration-options)
- [Development](#development)
- [Create DEV Environment, Running Tests and Building Wheel](#create-dev-environment-running-tests-and-building-wheel)
- [Create DEV Environment and Running Tests](#create-dev-environment-and-running-tests)
- [Update DEV Environment Packages](#update-dev-environment-packages)
- [Building Wheel](#building-wheel)
- [Optionals](#optionals)
- [License](#license)
- [Support](#support)
Expand Down Expand Up @@ -349,20 +351,34 @@ RotateWhen.MONDAY # "W0"

# Development

Must have [UV](https://uv.run/docs/getting-started/installation),
[Black](https://black.readthedocs.io/en/stable/getting_started.html),
[Ruff](https://docs.astral.sh/ruff/installation/), and
[Poe the Poet](https://poethepoet.naber.dev/installation) installed.
Must have [UV](https://uv.run/docs/getting-started/installation) installed.

## Create DEV Environment, Running Tests and Building Wheel
## Create DEV Environment and Running Tests

> **Note:** All poe tasks automatically run ruff linter along with Black formatting

```shell
uv sync --all-extras
poe linter
uv sync --all-extras --all-groups
poe test
```


## Update DEV Environment Packages
This will update all packages dependencies

```shell
poe updatedev
```


## Building Wheel
This will update all packages, run linter, both unit and integration tests and finally build the wheel

```shell
poe build
```


## Optionals

### Create a cprofile.prof file from unit tests
Expand Down
78 changes: 40 additions & 38 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,31 @@
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.metadata]
allow-direct-references = true

[tool.hatch.build]
include = ["pythonLogs/**/*"]

[tool.hatch.build.targets.wheel]
packages = ["pythonLogs"]

[project]
name = "pythonLogs"
version = "6.0.1"
version = "6.0.2"
description = "High-performance Python logging library with file rotation and optimized caching for better performance"
urls.Repository = "https://github.com/ddc/pythonLogs"
urls.Homepage = "https://pypi.org/project/pythonLogs"
license = {text = "MIT"}
readme = "README.md"
authors = [{name = "Daniel Costa", email = "danieldcsta@gmail.com"}]
maintainers = [{name = "Daniel Costa"}]
authors = [
{name = "Daniel Costa", email = "danieldcsta@gmail.com"},
]
maintainers = [
{name = "Daniel Costa"},
]
keywords = [
"python3", "python-3", "python",
"python", "python3", "python-3",
"log", "logging", "logger",
"logutils", "log-utils", "pythonLogs"
]
Expand All @@ -20,6 +35,7 @@ classifiers = [
"Development Status :: 5 - Production/Stable",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
Expand All @@ -28,52 +44,44 @@ classifiers = [
"Intended Audience :: Developers",
"Natural Language :: English",
]
requires-python = ">=3.12"
requires-python = ">=3.11"
dependencies = [
"pydantic-settings>=2.11.0",
]

[project.urls]
Homepage = "https://pypi.org/project/pythonLogs"
Repository = "https://github.com/ddc/pythonLogs"

[project.optional-dependencies]
test = [
"poethepoet>=0.40.0",
[dependency-groups]
dev = [
"psutil>=7.2.2",
"pytest>=9.0.2",
"pytest-cov>=7.0.0",
"black>=26.1.0",
"poethepoet>=0.40.0",
"ruff>=0.15.0",
]

[tool.hatch.build]
include = ["pythonLogs/**/*"]

[tool.hatch.build.targets.wheel]
packages = ["pythonLogs"]

[tool.poe.tasks]
build = "uv build --wheel"
updatedev.shell = "uv lock && uv sync --no-install-project --all-extras"
linter.shell = "uv run ruff check --fix . && uv run black ."
profile = "uv run python -m cProfile -o cprofile.prof -m pytest"
test = "uv run pytest"
profile.sequence = ["linter", {shell = "uv run python -m cProfile -o cprofile_unit.prof -m pytest --no-cov"}]
test.sequence = ["linter", {shell = "uv run pytest"}]
updatedev.sequence = ["linter", {shell = "uv lock --upgrade && uv sync --all-extras --group dev"}]
build.sequence = ["updatedev", "test", {shell = "uv build --wheel"}]

[tool.pytest.ini_options]
addopts = "-v --cov --cov-report=term --cov-report=xml --junitxml=junit.xml"
junit_family = "legacy"
testpaths = ["tests"]
markers = [
"slow: marks tests as slow (deselect with '-m \"not slow\"')"
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
]

[tool.coverage.run]
omit = [
"tests/*",
"*/__init__.py",
"*/_version.py",
]

[tool.coverage.report]
show_missing = true
skip_covered = false
exclude_lines = [
"pragma: no cover",
"def __repr__",
Expand All @@ -86,31 +94,25 @@ exclude_lines = [
"class .*\\bProtocol\\):",
"@(abc\\.)?abstractmethod",
]
show_missing = true
skip_covered = false

[tool.black]
line-length = 120
skip-string-normalization = true

[tool.ruff]
line-length = 120
target-version = "py311"

[tool.ruff.lint]
# I - Import sorting and organization
# F401 - Detect and remove unused imports
select = ["I", "F401"]
select = ["E", "W", "F", "I", "B", "C4", "UP"]
ignore = ["E501", "E402", "UP046", "UP047"]

[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]
"tests/**/*.py" = ["S101", "S105", "S106", "S311", "SLF001", "F841"]

[tool.ruff.lint.isort]
known-first-party = ["pythonLogs"]
force-sort-within-sections = false
from-first = false
no-sections = true

[tool.ruff.lint.per-file-ignores]
# S101 Use of `assert` detected
# S105 Possible hardcoded password assigned to variable
# S106 Possible hardcoded password assigned to argument
# S311 Standard pseudo-random generators are not suitable for cryptographic purposes
# SLF001 Private member accessed
"tests/**/*.py" = ["S101", "S105", "S106", "S311", "SLF001"]
1 change: 1 addition & 0 deletions pythonLogs/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ LOG_STREAM_HANDLER=True
LOG_SHOW_LOCATION=False
# Memory Management Settings
LOG_MAX_LOGGERS=50
LOG_MAX_FORMATTERS=50
LOG_LOGGER_TTL_SECONDS=1800

# SizeRotatingLog Settings (only needed when using SizeRotatingLog)
Expand Down
6 changes: 3 additions & 3 deletions pythonLogs/basic_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from pythonLogs.core.thread_safety import auto_thread_safe


@auto_thread_safe(['init'])
@auto_thread_safe(["init"])
class BasicLog:
"""Basic logger with context manager support for automatic resource cleanup."""

Expand Down Expand Up @@ -48,13 +48,13 @@ def init(self):

def __enter__(self):
"""Context manager entry."""
if not hasattr(self, 'logger') or self.logger is None:
if not hasattr(self, "logger") or self.logger is None:
self.init()
return self.logger

def __exit__(self, exc_type, exc_val, exc_tb):
"""Context manager exit with automatic cleanup."""
if hasattr(self, 'logger'):
if hasattr(self, "logger"):
cleanup_logger_handlers(self.logger)

@staticmethod
Expand Down
Loading