Metadata-Version: 2.4
Name: aignostics-foundry-core
Version: 0.7.0
Summary: 🏭 Foundational infrastructure for Foundry components.
Project-URL: Homepage, https://github.com/aignostics/foundry-python-core
Project-URL: Documentation, https://github.com/aignostics/foundry-python-core#readme
Project-URL: Source, https://github.com/aignostics/foundry-python-core
Project-URL: Changelog, https://github.com/aignostics/foundry-python-core/releases
Project-URL: Issues, https://github.com/aignostics/foundry-python-core/issues
Author-email: Oliver Meyer <oliver.meyer@aignostics.com>
License: MIT License
        
        Copyright (c) [2026] [Aignostics GmbH (support@aignostics.com)]
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: act,aignostics-foundry-core,codecov,copier,cyclonedx,detect-secrets,foundry,foundry-python,jupyter,nox,pip-audit,pip-licenses,pre-commit,pypi,pytest,python,ruff,sonarcloud,sonarqube,uv
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Framework :: Pytest
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Natural Language :: English
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Typing :: Typed
Requires-Python: <3.15,>=3.11
Requires-Dist: asyncpg<1,>=0.29
Requires-Dist: auth0-fastapi<2,>=1.0.0b5
Requires-Dist: certifi>=2024
Requires-Dist: fastapi<1,>=0.110
Requires-Dist: loguru<1,>=0.7
Requires-Dist: nicegui<4,>=3
Requires-Dist: platformdirs<5,>=4
Requires-Dist: psutil>=6
Requires-Dist: pydantic-settings<3,>=2
Requires-Dist: pydantic<3,>=2
Requires-Dist: python-dotenv<2,>=1
Requires-Dist: rich<15,>=14
Requires-Dist: sentry-sdk<3,>=2
Requires-Dist: sqlalchemy[asyncio]<3,>=2
Requires-Dist: truststore<1,>=0.9
Requires-Dist: typer<1,>=0.14
Description-Content-Type: text/markdown

# 🏭 Foundry Python Core

[![License](https://img.shields.io/badge/license-MIT-blue)](https://github.com/aignostics/foundry-python-core/blob/main/LICENSE)
[![CI](https://github.com/aignostics/foundry-python-core/actions/workflows/ci-cd.yml/badge.svg)](https://github.com/aignostics/foundry-python-core/actions/workflows/ci-cd.yml)
[![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=aignostics_foundry-python-core&metric=alert_status&token=a2fcb508f6d22af0c9d0a38728a7f5ee22d5b2ab)](https://sonarcloud.io/summary/new_code?id=aignostics_foundry-python-core)
[![Security](https://sonarcloud.io/api/project_badges/measure?project=aignostics_foundry-python-core&metric=security_rating&token=a2fcb508f6d22af0c9d0a38728a7f5ee22d5b2ab)](https://sonarcloud.io/summary/new_code?id=aignostics_foundry-python-core)
[![Maintainability](https://sonarcloud.io/api/project_badges/measure?project=aignostics_foundry-python-core&metric=sqale_rating&token=a2fcb508f6d22af0c9d0a38728a7f5ee22d5b2ab)](https://sonarcloud.io/summary/new_code?id=aignostics_foundry-python-core)
[![Technical Debt](https://sonarcloud.io/api/project_badges/measure?project=aignostics_foundry-python-core&metric=sqale_index&token=a2fcb508f6d22af0c9d0a38728a7f5ee22d5b2ab)](https://sonarcloud.io/summary/new_code?id=aignostics_foundry-python-core)
[![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=aignostics_foundry-python-core&metric=code_smells&token=a2fcb508f6d22af0c9d0a38728a7f5ee22d5b2ab)](https://sonarcloud.io/summary/new_code?id=aignostics_foundry-python-core)
[![Dependabot](https://img.shields.io/badge/dependabot-active-brightgreen?style=flat-square&logo=dependabot)](https://github.com/aignostics/foundry-python-core/security/dependabot)
[![Renovate enabled](https://img.shields.io/badge/renovate-enabled-brightgreen.svg)](https://github.com/aignostics/foundry-python-core/issues?q=is%3Aissue%20state%3Aopen%20Dependency%20Dashboard)
[![Coverage](https://codecov.io/gh/aignostics/foundry-python-core/graph/badge.svg?token=MXmzYbXguM)](https://codecov.io/gh/aignostics/foundry-python-core)
[![Ruff](https://img.shields.io/badge/style-Ruff-blue?color=D6FF65)](https://github.com/aignostics/foundry-python-core/blob/main/noxfile.py)
[![Pyright](https://microsoft.github.io/pyright/img/pyright_badge.svg)](https://microsoft.github.io/pyright/)
[![Copier](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/copier-org/copier/master/img/badge/badge-grayscale-inverted-border-orange.json)](https://github.com/aignostics/foundry-python)

Foundational infrastructure for Foundry components.

## Prerequisites

Install [mise](https://mise.jdx.dev/) (task runner and dev tool manager):

```shell
brew install mise
```

Or follow the [installation guide](https://mise.jdx.dev/getting-started.html) for other methods. Then [activate mise](https://mise.jdx.dev/getting-started.html#activate-mise) in your shell profile.

## Usage

### Initialise the context at application startup

Call `set_context()` once, before any library code runs, then call `boot()` to
initialise logging, the SSL trust chain, and optional Sentry integration:

```python
# main.py
from aignostics_foundry_core.foundry import FoundryContext, set_context
from aignostics_foundry_core.boot import boot

set_context(FoundryContext.from_package("myproject"))
boot()
```

`FoundryContext.from_package()` derives everything from package metadata and
environment variables:

- `name`, `version`, `version_full` — from `importlib.metadata`
- `environment` — from `MYPROJECT_ENVIRONMENT` → `ENV` → `VERCEL_ENV` →
  `RAILWAY_ENVIRONMENT` → `"local"`
- `is_container`, `is_cli`, `is_test`, `is_library` — detected automatically
- `env_prefix` (`"MYPROJECT_"`) — used by every settings class in the library

### Access the context from any module

```python
from aignostics_foundry_core.foundry import get_context

ctx = get_context()
print(f"Running {ctx.name} v{ctx.version_full} in {ctx.environment}")
# → Running myproject v1.2.3+main---run.12345 in staging
```

`get_context()` raises `RuntimeError` with a clear message if `set_context()`
was never called.

### Pass context explicitly in tests

Never call `set_context()` in tests. Pass a `FoundryContext` directly to each
function via its optional `context` parameter instead:

```python
from aignostics_foundry_core.foundry import FoundryContext
from aignostics_foundry_core.log import logging_initialize

ctx = FoundryContext(name="myproject", version="0.0.0", version_full="0.0.0", environment="test")
logging_initialize(context=ctx)
```

All public library functions (`logging_initialize`, `sentry_initialize`, `boot`,
`load_modules`, etc.) accept an optional `context` keyword argument and fall
back to `get_context()` when it is `None`.

### Database

Once a context is configured via `set_context()`, all database functions work
with no arguments — the URL and pool settings are read from the context:

```python
from aignostics_foundry_core.database import init_engine, cli_run_with_db, with_engine

# Zero-arg engine init — reads MYPROJECT_DB_URL, _DB_POOL_SIZE, etc. from env
init_engine()

# CLI helper — initialises engine, runs coroutine, disposes engine
cli_run_with_db(my_async_func)


# Background job decorator — engine initialised before each invocation
@with_engine
async def my_job(): ...


# Override for a secondary database
@with_engine(db_url="postgresql+asyncpg://user:pass@host/secondary")
async def my_other_job(): ...
```

`FoundryContext.from_package()` activates database configuration automatically
when the following environment variables are present:

| Variable | Required | Description |
|---|---|---|
| `{PREFIX}DB_URL` | yes (to activate) | Full database connection URL |
| `{PREFIX}DB_POOL_SIZE` | no | Connection pool size (default `10`) |
| `{PREFIX}DB_MAX_OVERFLOW` | no | Max pool overflow (default `10`) |
| `{PREFIX}DB_POOL_TIMEOUT` | no | Pool wait timeout in seconds (default `30.0`) |
| `{PREFIX}DB_NAME` | no | Override database name in the URL path |

In tests, construct `DatabaseSettings` directly instead of setting env vars:

```python
from aignostics_foundry_core.database import DatabaseSettings
from tests.conftest import make_context

ctx = make_context(database=DatabaseSettings(_env_prefix="TEST_DB_", url="sqlite+aiosqlite:///test.db"))
```

### Health API

```python
from aignostics_foundry_core.health import Health, HealthStatus

health = Health(status=HealthStatus.UP)
```

## Further Reading

- [Foundry Project Guide](FOUNDRY_README.md) - Complete toolchain, testing, CI/CD, and project setup guide
- [Security policy](SECURITY.md) - Documentation of security checks, tools, and principles
- [Release notes](https://github.com/aignostics/foundry-python-core/releases) - Complete log of improvements and changes
- [Attributions](ATTRIBUTIONS.md) - Open source projects this project builds upon
