Metadata-Version: 2.4
Name: dotpop
Version: 1.0.0
Summary: dotenv++ parser with types, validation, and conditions
Author: Dekel Cohen
License: MIT
Project-URL: Homepage, https://github.com/dekelcohen/dotpop
Project-URL: Repository, https://github.com/dekelcohen/dotpop
Project-URL: Issues, https://github.com/dekelcohen/dotpop/issues
Keywords: env,environment,dotenv,config,configuration,dotenv++
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Systems Administration
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
Dynamic: license-file

# dotpop

dotenv++ parser with types, validation, interpolation, and conditional logic.

## Installation

```bash
pip install dotpop
```

## Quick Start

### Basic .env file

```env
HOST=localhost
PORT=8080
DEBUG=true
```

```python
from dotpop import load

env = load(".env")
print(env["HOST"])
print(env["PORT"])
```

### .dpop with types and validation

```dpop
HOST=${HOST:-localhost}
PORT:int=${PORT:-8000} | required | min=1 | max=65535
ENV:str=development | one_of=development,staging,production

@if ENV == "production"
DEBUG:bool=false
@else
DEBUG:bool=true
@end

API_URL="http://${HOST}:${PORT}"
```

```python
from dotpop import load

env = load("config.dpop")
print(env["PORT"])
print(env["DEBUG"])
print(env["API_URL"])
```

## Syntax Guide

### Types

```dpop
PORT:int=8080
RATE:float=3.14
DEBUG:bool=true
TAGS:list=tag1,tag2,tag3
CONFIG:json={"key": "value"}
FILE:path=/tmp/file.txt
API:url=https://api.example.com
```

Supported types: `str`, `int`, `float`, `bool`, `json`, `list`, `path`, `url`

### Validation

```dpop
PORT:int=8000 | required | min=1 | max=65535
ENV:str=production | one_of=development,staging,production
EMAIL:str=user@example.com | regex=^[^@]+@[^@]+\.[^@]+$
PASSWORD:str= | required | non_empty
```

Available validators: `required`, `non_empty`, `one_of`, `regex`, `min`, `max`

### Interpolation

```dpop
HOST=localhost
PORT=8080
URL=http://${HOST}:${PORT}
FALLBACK=${UNDEFINED:-default}
```

### Conditionals

```dpop
ENV=production

@if ENV == "production"
DEBUG:bool=false
LOG_LEVEL=error
@elif ENV == "staging"
DEBUG:bool=true
LOG_LEVEL=warning
@else
DEBUG:bool=true
LOG_LEVEL=debug
@end
```

Supported conditions: `==`, `!=`, `defined()`, `not_defined()`

### Includes

```dpop
@include ".env.base"
@include "configs/${ENV}.dpop"
```

### Overrides

```dpop
KEY=original
!KEY=forced_override
```

## API Reference

### Loading

```python
from dotpop import load, loads

env = load("config.dpop", format="auto", strict=True, use_os_env=True)

env = loads("KEY=value", format="auto", strict=True, use_os_env=True)
```

Parameters:
- `format`: `"auto"`, `"env"`, or `"dpop"`
- `strict`: Raise errors on validation failures
- `use_os_env`: Merge with OS environment variables

### ResolvedEnv

```python
port = env["PORT"]
host = env.get("HOST", "localhost")
port_str = env.get_str("PORT")

if "KEY" in env:
    print("Key exists")

source = env.sources["PORT"]
print(f"{source.file}:{source.line}")

for warning in env.warnings:
    print(warning)
```

### Helpers

```python
from dotpop import apply, export

apply(env.values, overwrite=False)

dotenv = export(env.values, format="dotenv", redact_secrets=True)
json_str = export(env.values, format="json")
cmake = export(env.values, format="cmake")
cpp_header = export(env.values, format="cpp-header")
```

## CLI

### Validate configuration

```bash
dotpop check config.dpop
```

### Print resolved environment

```bash
dotpop print config.dpop
dotpop print config.dpop --no-redact
```

### Export to different formats

```bash
dotpop export config.dpop --format json
dotpop export config.dpop --format cmake
dotpop export config.dpop --format cpp-header
```

### Apply to environment

```bash
# Apply variables to current Python process
dotpop apply config.dpop

# Overwrite existing variables
dotpop apply config.dpop --overwrite

# For shell usage, use export with eval:
eval $(dotpop export config.dpop)
```

### Clear from environment

```bash
# Remove variables from current Python process
dotpop clear config.dpop

# For shell usage:
for var in $(dotpop print config.dpop | cut -d= -f1); do unset $var; done
```

### Set/update variables

```bash
# Set a simple variable
dotpop set config.dpop PORT 8080

# Set with type annotation
dotpop set config.dpop PORT 8080 --type int

# Set with type and validators
dotpop set config.dpop PORT 8080 --type int --validators "required | min=1 | max=65535"

# Create file if it doesn't exist
dotpop set config.dpop DEBUG true --type bool --create

# Create backup before modifying
dotpop set config.dpop API_KEY "secret-key" --backup
```

### Get variable values

```bash
# Get typed value
dotpop get config.dpop PORT

# Get raw string value (no type conversion)
dotpop get config.dpop PORT --raw

# Without OS environment merging
dotpop get config.dpop PORT --no-os-env
```

### Remove variables

```bash
# Remove a variable
dotpop unset config.dpop OLD_KEY

# With backup
dotpop unset config.dpop OLD_KEY --backup
```

### List variables

```bash
# List all variables with values
dotpop list config.dpop

# List only variable names
dotpop list config.dpop --keys-only

# Filter by pattern (regex)
dotpop list config.dpop --filter "^DB_"
dotpop list config.dpop --filter "PORT|HOST"

# Without OS environment
dotpop list config.dpop --no-os-env
```

## CLI Examples for DevOps

### CI/CD Configuration Management

```bash
# Update version in config
dotpop set .dpop.production VERSION "1.2.3"

# Set deployment timestamp
dotpop set .dpop.production DEPLOY_TIME "$(date -u +%Y-%m-%dT%H:%M:%SZ)"

# Toggle feature flags
dotpop set .dpop.production FEATURE_NEW_UI true --type bool

# Update database connection
dotpop set .dpop.production DB_HOST "prod-db.example.com"
dotpop set .dpop.production DB_PORT 5432 --type int
```

### Environment Promotion

```bash
# Copy staging config to production
cp .dpop.staging .dpop.production

# Update environment-specific values
dotpop set .dpop.production ENV production
dotpop set .dpop.production DEBUG false --type bool
dotpop set .dpop.production LOG_LEVEL error
```

### Configuration Inspection

```bash
# Check what's different between environments
dotpop list .dpop.staging --keys-only > /tmp/staging-keys
dotpop list .dpop.production --keys-only > /tmp/prod-keys
diff /tmp/staging-keys /tmp/prod-keys

# Find all database-related config
dotpop list .dpop --filter "^DB_"

# Get specific value for scripts
API_URL=$(dotpop get .dpop API_URL)
echo "Connecting to: $API_URL"
```

### Backup and Restore

```bash
# Create backup before bulk changes
cp .dpop .dpop.backup

# Make changes with automatic backup
dotpop set .dpop PORT 9000 --backup
dotpop set .dpop HOST "0.0.0.0" --backup

# Restore from backup if needed
mv .dpop.backup .dpop
```

### Validation in CI

```bash
# Validate config in CI pipeline
dotpop check .dpop.production || exit 1

# Ensure required variables exist
dotpop get .dpop.production API_KEY > /dev/null || {
    echo "ERROR: API_KEY not set"
    exit 1
}
```

### Docker Environment Generation

```bash
# Generate .env file for Docker
dotpop export .dpop.production > .env

# Generate docker-compose environment
dotpop export .dpop.production --format dotenv > docker.env
docker-compose --env-file docker.env up
```

## Examples

See the `examples/` directory for complete examples.

## Development

```bash
git clone https://github.com/dekelcohen/dotpop
cd dotpop
pip install -e ".[dev]"
pytest
```

## License

MIT License
