Metadata-Version: 2.3
Name: utils
Version: 0.1.1
Summary: This is a test version bump with only minor improvements
Author: Mathias Schneider
Author-email: Mathias Schneider <mathias.schneider@d-fine.com>
Requires-Dist: pydantic>=2.13.5
Requires-Dist: twine>=7.0.0
Requires-Dist: uvicorn>=0.54.0
Requires-Python: >=3.14
Description-Content-Type: text/markdown

# utils

Reusable Python utilities for application configuration and logging.

The package currently provides:

- a Pydantic-based settings base class with environment-variable support
- configurable application logging via `uvicorn`'s `DefaultFormatter`
- console logging and optional daily rotating file logs
- configurable log retention and log file naming

The project requires Python 3.14 or newer.

## Publish package

### Prerequisites

- Python 3.14 or newer
- [`uv`](https://docs.astral.sh/uv/)
- a Gitea repository with Package Registry support enabled
- a Gitea Personal Access Token with permission to write packages

The examples below use:

```text
Gitea host: https://gitea.schneiderserver.site
Owner:     mathias
Package:   utils
```

Create a token in Gitea under **User settings → Applications → Access Tokens**.
Keep it private and do not commit it to the repository.

### Publish

Run the tests and build the source distribution and wheel:

```bash
uv sync
uv run pytest
rm -rf dist
uv build
```

The build artifacts will be written to `dist/`:

```text
dist/utils-<version>.tar.gz
dist/utils-<version>-py3-none-any.whl
```

Configure the Gitea PyPI registry in `~/.pypirc`:

```ini
[distutils]
index-servers =
    gitea

[gitea]
repository = https://gitea.schneiderserver.site/api/packages/mathias/pypi
username = mathias
password = YOUR_PRIVATE_GITEA_TOKEN
```

Upload the package:

```bash
python -m twine upload --repository gitea dist/*
```

Gitea does not allow the same package version to be uploaded twice. To publish
an update, increment `version` in `pyproject.toml`, rebuild, and upload again:

```toml
version = "0.1.1"
```

It is useful to create a matching Git tag for each published version:

```bash
git tag v0.1.0
git push origin v0.1.0
```

## Consume package in other projects

### Public package

If the package is publicly readable, install it with:

```bash
pip install \
  --index-url https://gitea.schneiderserver.site/api/packages/mathias/pypi/simple \
  utils
```

The equivalent `uv` command is:

```bash
uv pip install \
  --index-url https://gitea.schneiderserver.site/api/packages/mathias/pypi/simple \
  utils
```

### Private package

For a private package, use a token with package-read permission. Avoid putting
the token directly into commands where possible because it can end up in shell
history or process listings.

```bash
pip install \
  --index-url https://<username>:<read-token>@gitea.schneiderserver.site/api/packages/mathias/pypi/simple \
  utils
```

For CI, provide the token through a secret rather than committing it to a
configuration file.

### Add as a project dependency with `uv add`

Yes. `uv add` adds the package to the consuming project's
`[project].dependencies` in `pyproject.toml` and updates `uv.lock`:

```bash
uv add --index gitea=https://gitea.schneiderserver.site/api/packages/mathias/pypi/simple utils
```

For a public package, this may be enough for the initial add. To keep the
package source explicit and avoid accidentally resolving `utils` from another
index, configure the index and source in the consuming project's
`pyproject.toml`:

```toml
[project]
dependencies = [
    "utils>=0.1.0",
]

[tool.uv.sources]
utils = { index = "gitea" }

[[tool.uv.index]]
name = "gitea"
url = "https://gitea.schneiderserver.site/api/packages/mathias/pypi/simple"
explicit = true
```

For a private package, keep the URL free of credentials and provide them at
install or lock time through environment variables. For the index name
`gitea`, `uv` expects:

```bash
export UV_INDEX_GITEA_USERNAME=mathias
export UV_INDEX_GITEA_PASSWORD=YOUR_PRIVATE_GITEA_TOKEN
uv lock
uv sync
```

The token is not written to `pyproject.toml` or `uv.lock`. In CI, set these
variables from protected secrets. The `utils` entry in `pyproject.toml` can
then be installed in any checkout with:

```bash
uv sync
```

## Usage

### Logging configuration

`LoggingSettings` configures the root logger when instantiated. By default it
writes to the console and to `logs/monitoring_backend.log`, rotating the file
at midnight and retaining 30 rotated files.

```python
from utils.logging_config import LoggingSettings

settings = LoggingSettings(
    LOG_LEVEL="INFO",
    LOG_TO_FILE=True,
    LOG_FILE_PATH="logs/application.log",
    LOG_BACKUP_COUNT=14,
)
```

The settings can also be overridden with environment variables:

```bash
export LOG_LEVEL=DEBUG
export LOG_TO_FILE=true
export LOG_FILE_PATH=logs/application.log
export LOG_BACKUP_COUNT=14
```

Invalid log levels fall back to `INFO`. `LOG_BACKUP_COUNT` must be zero or
greater.

### Base settings

`BaseSettingsConfig` is a small base class for Pydantic settings models. Extra
environment variables are ignored and environment variable names are matched
case-sensitively:

```python
from utils.settings import BaseSettingsConfig


class ApplicationSettings(BaseSettingsConfig):
    APP_NAME: str = "example"
```

## Development

Install the locked development environment and run the test suite with:

```bash
uv sync
uv run pytest
```

Build the package without publishing it:

```bash
uv build
```
