Metadata-Version: 2.4
Name: environy
Version: 0.1.0
Summary: Typed environment variable loader with validation rules
Author: Environy contributors
License-Expression: MIT
License-File: LICENSE
Keywords: config,dotenv,environment,settings,validation
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
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.10
Provides-Extra: build
Requires-Dist: build>=1.2; extra == 'build'
Requires-Dist: twine>=5.1; extra == 'build'
Provides-Extra: test
Requires-Dist: pytest-cov>=5.0; extra == 'test'
Requires-Dist: pytest>=8.0; extra == 'test'
Description-Content-Type: text/markdown

# Environy

Typed environment variable loader with `.env` support and validation rules.

Environy loads values from `os.environ` first, then loads the configured env
file into the same value set. The default env file is `.env`, and file values
win when a key exists in both places.

## Installation

```bash
pip install environy
```

## Quick Start

```python
from environy import Environy

env = Environy()

app_name = env.string("ENVIRONY_APP_NAME")
port = env.port("ENVIRONY_PORT", default=8080)
timeout = env.float("ENVIRONY_TIMEOUT", default=2.5)
debug = env.boolean("ENVIRONY_DEBUG", default=False)
api_url = env.url("ENVIRONY_API_URL")
config_file = env.file_path("ENVIRONY_CONFIG_FILE")
data_dir = env.folder_path("ENVIRONY_DATA_DIR")
mode = env.enum("ENVIRONY_MODE", ["development", "staging", "production"])
```

## Optional Values

Values are required by default. Pass `required=False` to return `None` when a
key is absent and no default was provided.

```python
required_name = env.string("ENVIRONY_APP_NAME")
optional_note = env.string("ENVIRONY_OPTIONAL_NOTE", required=False)
```

## Value Validation

Validate a parsed value with a lambda or callable. The callable receives the
parsed value first, then any extra positional args passed after it.

```python
def is_between(value: int, minimum: int, maximum: int) -> bool:
    return minimum <= value <= maximum

port = env.integer("ENVIRONY_PORT", is_between, 1, 65535)
name = env.string(
    "ENVIRONY_APP_NAME",
    lambda value, prefix: value.startswith(prefix),
    "environy-",
)
timeout = env.float("ENVIRONY_TIMEOUT", lambda value, maximum: value <= maximum, 5.0)
```

Use `default` as a keyword when combining it with validation.

```python
port = env.integer("ENVIRONY_PORT", is_between, 1, 65535, default=8080)
```

## Dependency Rules

Validate relationships between multiple variables after loading them.

```python
env.require_distinct([
    "ENVIRONY_PRIMARY_REGION",
    "ENVIRONY_SECONDARY_REGION",
    "ENVIRONY_TERTIARY_REGION",
])

env.require_allowed_when(
    "ENVIRONY_MODE",
    "production",
    "ENVIRONY_LOG_LEVEL",
    ["warning", "error"],
)

env.require_present_when("ENVIRONY_AUTH_MODE", "oauth", "ENVIRONY_CLIENT_SECRET")
```

## Env Files

Use a custom env file:

```python
env = Environy(env_file=".env.local")
```

Disable env file loading:

```python
env = Environy(env_file=None)
```

Boolean values accept `true/false`, `yes/no`, `on/off`, and `1/0`.

## Development

```bash
python -m pip install -e ".[test,build]"
python -m pytest
python -m build
python -m twine check dist/*
```

Run the example:

```bash
python examples/basic.py
```
