Metadata-Version: 2.1
Name: 12factor-configclasses
Version: 0.2.4
Summary: Like dataclasses but for config.
License: MIT
Author: Pablo Cabezas
Author-email: pabcabsal@gmail.com
Requires-Python: >=3.8,<4.0
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Provides-Extra: dotenv
Provides-Extra: full
Provides-Extra: toml
Provides-Extra: yaml
Requires-Dist: python-dotenv[dotenv] (>=0.10.3,<0.11.0); extra == "dotenv" or extra == "full"
Requires-Dist: pyyaml[yaml] (>=5.1,<6.0); extra == "yaml" or extra == "full"
Requires-Dist: starlette (>=0.12.12,<0.13.0)
Requires-Dist: tomlkit[toml] (>=0.5.8,<0.6.0); extra == "toml" or extra == "full"
Description-Content-Type: text/markdown

# configclasses

![PyPI](https://img.shields.io/pypi/v/12factor-configclasses)
[![codecov](https://codecov.io/gh/kingoodie/configclasses/branch/master/graph/badge.svg)](https://codecov.io/gh/kingoodie/configclasses)
<a href="https://codeclimate.com/github/kingoodie/configclasses/maintainability"><img src="https://api.codeclimate.com/v1/badges/9094f65f5caef64fb993/maintainability" /></a>


Like dataclases but for config.

Specify your config with a class and load it with your env vars or env files.


```python
>>> import httpx
... from configclasses import configclass
>>> class UserAPIClient(httpx.AsyncClient):
...     def __init__(self, config: ClientConfig, *args, **kwargs):
...         self.config = config
...         super().__init__(*args, **kwargs)
... 
...     async def get_users(self, headers: Optional[Headers] = None) -> Dict[str, Any]:
...         response = await self.get(f"{self.path}/users", auth=headers)
...         response.raise_for_status()
...         return response.json()
...     
>>> @configclass
... class ClientConfig:
...     host: str
...     port: int
...
>>> config = ClientConfig.from_path(".env")
... async with UserAPIClient(config) as client:
...     users = await client.get_users(auth_headers)
...   
```

## Features

- Fill your configclasses with existent env vars.
- Define default values in case these variables have no value at all.
- Load your config files in env vars following [12factor apps](https://12factor.net) recommendations.
- Support for _.env_, _yaml_, _toml_, _ini_ and _json_.
- Convert your env vars with specified type in configclass: `int`, `float`, `str` or `bool`.
- Use nested configclasses to more complex configurations.
- Specify a prefix with `@configclass(prefix="<PREFIX>")` to append this prefix to your configclass'  attribute names.
- Config groups (__TODO__): https://cli.dev/docs/tutorial/config_groups/

## Requirements

Python 3.8+


## Installation

    pip install 12factor-configclasses
    
## Supported formats

- .env ->   ```pip install 12factor-configclasses[dotenv]```
- .yaml ->   ```pip install 12factor-configclasses[yaml]```
- .toml ->   ```pip install 12factor-configclasses[toml]```
- .ini
- .json

Install all dependencies with:

    pip install 12factor-configclasses[full]
    
## Example

```.env
# .env
HOST=0.0.0.0
PORT=8000
DB_URL=sqlite://:memory:
GENERATE_SCHEMAS=True
DEBUG=True
HTTPS_ONLY=False
GZIP=True
SENTRY=False
```

```python
#config.py
from configclasses import configclass


@configclass
class DB:
    user: str
    password: str
    url: str


@configclass
class AppConfig:
    host: str
    port: int
    db: DB
    generate_schemas: bool
    debug: bool
    https_only: bool
    gzip: bool
    sentry: bool
```

```python
...
from api.config import AppConfig

app_config = AppConfig.from_path(".env")
app = Starlette(debug=app_config.debug)

if app_config.https_only:
    app.add_middleware(
        HTTPSRedirectMiddleware)
if app_config.gzip:
    app.add_middleware(GZipMiddleware)
if app_config.sentry:
    app.add_middleware(SentryAsgiMiddleware)

...

register_tortoise(
    app,
    db_url=app_config.db.url,
    modules={"models": ["api.models"]},
    generate_schemas=app_config.generate_schemas,
)

if __name__ == "__main__":
    uvicorn.run(app, host=app_config.host, port=app_config.port)
```

    
