227 lines
5.0 KiB
Markdown
227 lines
5.0 KiB
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
|
|
```
|