Metadata-Version: 2.4
Name: envguard-sarve
Version: 0.1.0
Summary: Validate your .env files against a schema before your app blows up.
Author-email: Your Name <you@example.com>
License: MIT
Project-URL: Homepage, https://github.com/yourusername/envguard
Project-URL: Repository, https://github.com/yourusername/envguard
Project-URL: Bug Tracker, https://github.com/yourusername/envguard/issues
Keywords: env,dotenv,validation,configuration,schema
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
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 :: Utilities
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Dynamic: license-file

# envguard 🛡️

**Validate your `.env` files against a schema — before your app blows up in production.**

[![CI](https://github.com/yourusername/envguard/actions/workflows/ci.yml/badge.svg)](https://github.com/yourusername/envguard/actions)
[![PyPI](https://img.shields.io/pypi/v/envguard)](https://pypi.org/project/envguard/)
[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Zero dependencies](https://img.shields.io/badge/dependencies-zero-brightgreen)](pyproject.toml)

---

Ever deployed an app only to discover `SECRET_KEY` was missing, or `PORT` was set to `"eight-thousand"` by a copy-paste mistake? **envguard** catches those problems at startup, with clear human-readable error messages.

```
envguard validation failed:
  ✗ 'DATABASE_URL' is required but not set
  ✗ 'PORT' must be an integer, got: 'eight-thousand'
  ✗ 'LOG_LEVEL' must be one of 'DEBUG', 'INFO', 'WARNING', 'ERROR', got: 'VERBOSE'
```

## Features

- ✅ **Zero runtime dependencies** — stdlib only
- ✅ **Rich type support** — `str`, `int`, `float`, `bool`, `url`, `email`, `json`
- ✅ **Smart defaults** — optional fields with fallback values
- ✅ **Constraint checking** — min/max length, min/max value, allowed choices
- ✅ **Custom validators** — bring your own logic
- ✅ **`.env` file loading** — built-in parser, no `python-dotenv` required
- ✅ **CLI tool** — check your env from CI or the terminal
- ✅ **All errors at once** — see every problem in one shot, not one at a time

---

## Installation

```bash
pip install envguard
```

---

## Quickstart

### 1. Define your schema

```python
# envguard_schema.py
from envguard import EnvGuard, EnvSchema, EnvField

schema = EnvSchema({
    "DATABASE_URL": EnvField(type="url",   description="PostgreSQL DSN"),
    "SECRET_KEY":   EnvField(type="str",   min_length=32),
    "PORT":         EnvField(type="int",   default=8000, min_value=1, max_value=65535),
    "DEBUG":        EnvField(type="bool",  default=False),
    "LOG_LEVEL":    EnvField(type="str",   default="INFO",
                             choices=["DEBUG", "INFO", "WARNING", "ERROR"]),
})

guard = EnvGuard(schema, env_file=".env")
```

### 2. Validate at startup

```python
# main.py  /  settings.py  /  app.py — wherever your app boots
from envguard_schema import guard

config = guard.validate()   # raises ValidationError with ALL problems if anything is wrong

DB_URL  = config["DATABASE_URL"]
PORT    = config["PORT"]    # already cast to int ✓
DEBUG   = config["DEBUG"]   # already cast to bool ✓
```

That's it. If anything is wrong your app refuses to start with a clear error. If everything is fine you get a plain dict of correctly-typed values.

---

## Field reference

```python
EnvField(
    type        = "str",    # str | int | float | bool | url | email | json
    required    = True,     # False if you set a default
    default     = None,     # any value; makes field optional
    description = "",       # shown in CLI `envguard list`
    choices     = None,     # ["DEBUG", "INFO", "WARNING"]
    min_length  = None,     # string length (pre-cast)
    max_length  = None,
    min_value   = None,     # numeric range (post-cast)
    max_value   = None,
    validator   = None,     # callable(value) -> bool | raises ValueError
)
```

### Type details

| Type | Accepted values | Returns |
|------|----------------|---------|
| `str` | Any non-empty string | `str` |
| `int` | `"42"`, `"-1"` | `int` |
| `float` | `"3.14"` | `float` |
| `bool` | `true/false`, `1/0`, `yes/no`, `on/off` (case-insensitive) | `bool` |
| `url` | Must start with `http://`, `https://`, or `ftp://` | `str` |
| `email` | Basic `user@domain.tld` check | `str` |
| `json` | Any valid JSON string | parsed Python object |

---

## Custom validators

```python
import re

EnvField(
    type="str",
    validator=lambda v: bool(re.match(r"^[a-z0-9_-]+$", v)),
    description="Slug-safe identifier",
)

# Or raise ValueError for a custom message:
def must_be_https(url: str) -> bool:
    if not url.startswith("https://"):
        raise ValueError("must use HTTPS in production")
    return True

EnvField(type="url", validator=must_be_https)
```

---

## `.env` file loading

envguard has a built-in `.env` parser — no extra packages needed.

```python
guard = EnvGuard(schema, env_file=".env")          # os.environ takes precedence
guard = EnvGuard(schema, env_file=".env", override=True)  # .env wins
```

Supported syntax:
```dotenv
# Comments are ignored
DATABASE_URL=postgres://localhost/mydb
SECRET_KEY="my super secret key with spaces"
DEBUG=true
PORT=8000
```

---

## Non-raising mode

```python
ok, errors = guard.check()
if not ok:
    for error in errors:
        print(f"Config error: {error}")
```

---

## CLI

```bash
# Generate a starter schema
envguard init

# Validate your .env against the schema
envguard check
envguard check --schema my_schema.py --env-file .env.production

# List all variables defined in the schema
envguard list
envguard list --schema my_schema.py
```

Example output of `envguard list`:

```
Variable                       Type     Required   Default         Description
────────────────────────────────────────────────────────────────────────────────
  DATABASE_URL                 url      yes        —               PostgreSQL connection string
  SECRET_KEY                   str      yes        —               Secret key for session signing
  PORT                         int      no         8000            Port to listen on
  DEBUG                        bool     no         False           Enable debug mode
  LOG_LEVEL                    str      no         INFO            Logging verbosity
```

---

## Framework integration

### FastAPI / Starlette

```python
# settings.py
from envguard import EnvGuard, EnvSchema, EnvField

_guard = EnvGuard(EnvSchema({
    "DATABASE_URL": EnvField(type="url"),
    "SECRET_KEY":   EnvField(type="str", min_length=32),
    "DEBUG":        EnvField(type="bool", default=False),
}), env_file=".env")

config = _guard.validate()   # fails fast at import time
```

### Django

```python
# manage.py / wsgi.py — before django.setup()
from envguard import EnvGuard, EnvSchema, EnvField

EnvGuard(EnvSchema({
    "DJANGO_SECRET_KEY": EnvField(type="str", min_length=50),
    "DJANGO_DEBUG":      EnvField(type="bool", default=False),
    "DATABASE_URL":      EnvField(type="url"),
}), env_file=".env").validate()
```

---

## Contributing

Pull requests are welcome! Please open an issue first to discuss what you'd like to change.

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

---

## License

MIT © Your Name
