Metadata-Version: 2.4
Name: envist
Version: 0.1.0
Summary: A simple .env file parser with types for Python
Project-URL: Homepage, https://github.com/Almas-Ali/envist
Project-URL: Documentation, https://github.com/Almas-Ali/envist#readme
Project-URL: Repository, https://github.com/Almas-Ali/envist
Project-URL: Bug Tracker, https://github.com/Almas-Ali/envist/issues
Author-email: "Md. Almas Ali" <almaspr3@gmail.com>
License: MIT License
        
        Copyright (c) 2023 Almas-Ali
        
        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
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
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: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Utilities
Requires-Python: <4.0,>=3.10
Provides-Extra: dev
Requires-Dist: coverage>=7.0.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
Requires-Dist: pytest-mock>=3.10.0; extra == 'dev'
Requires-Dist: pytest>=7.0.0; extra == 'dev'
Description-Content-Type: text/markdown

# 🌟 Envist

<div align="center">

<a href="https://pypi.org/project/envist" title="Envist PyPI Project">
<img src="https://github.com/Almas-Ali/envist/blob/master/logo.png?raw=true" alt="Envist Logo" width="200"/>
</a>

**The most powerful environment variable manager for Python** 🚀

[![PyPI version](https://badge.fury.io/py/envist.svg)](https://pypi.org/project/envist)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/envist)](https://pypi.org/project/envist)
[![PyPI - License](https://img.shields.io/pypi/l/envist)](https://pypi.org/project/envist)
[![Hits](https://hits.sh/github.com/Almas-Ali/envist.svg?label=Total%20hits&logo=dotenv)](https://github.com/Almas-Ali/envist "Total hits")
[![Downloads](https://pepy.tech/badge/envist)](https://pepy.tech/project/envist)

*Environment variables have never been this smart!* 

Transform your `.env` files from simple key-value pairs into **type-safe, intelligent configuration management** with automatic typecasting, variable expansion, and zero-hassle setup.

Created with ❤️ by [**Md. Almas Ali**](https://github.com/Almas-Ali)

</div>

---

## 📋 Table of Contents

- [🎯 Why Envist?](#-why-envist)
- [✨ Key Features](#-key-features)
- [⚡ Quick Start](#-quick-start)
- [📦 Installation](#-installation)
- [🎓 Complete Guide](#-complete-guide)
  - [Basic Usage](#basic-usage)
  - [Type Casting Magic](#type-casting-magic)
  - [Variable Expansion](#variable-expansion)
  - [Advanced Operations](#advanced-operations)
- [📚 API Reference](#-api-reference)
- [🏷️ Supported Data Types](#️-supported-data-types)
- [🔧 Configuration](#-configuration)
- [🛠️ Exception Handling](#exception-handling)
- [📊 Logging](#-logging)
- [🎯 Examples](#-examples)
- [🤝 Contributing](#-contributing)
- [📄 License](#-license)

---

## 🎯 Why Envist?

**Stop wrestling with environment variables!** 

Traditional `.env` files are just strings. What if your environment variables could be **intelligent**? What if they could know their own types, expand references to other variables, and validate themselves?

**Envist makes this possible:**

```env
# Traditional .env (boring 😴)
PORT=8080
DEBUG=True
DATABASE_URL=postgresql://user:pass@localhost:5432/mydb

# Envist .env (intelligent 🧠)
PORT <int> = 8080
DEBUG <bool> = True
HOST <str> = localhost
DATABASE_URL <str> = postgresql://user:pass@${HOST}:5432/mydb
ALLOWED_HOSTS <list> = localhost, 127.0.0.1, 0.0.0.0
CONFIG <json> = {"timeout": 30, "retries": 3}
```

**The result?** Type-safe, self-documenting configuration that prevents bugs before they happen!

## ✨ Key Features

🎯 **In-File Type Casting** - Define variable types directly in your `.env` file  
🔗 **Variable Expansion** - Reference other variables with `${variable}` syntax  
🛡️ **Type Safety** - Automatic validation and conversion to Python types  
📊 **Rich Data Types** - Support for lists, dicts, JSON, CSV, and more  
🔄 **Backward Compatible** - Works with existing `.env` files  
⚡ **Zero Dependencies** - Lightweight and fast  
🔧 **Full CRUD Operations** - Get, set, unset, and save variables  
📝 **Built-in Logging** - Comprehensive debugging capabilities  

---

## ⚡ Quick Start

**1. Install Envist**
```bash
pip install envist
```

**2. Create your smart `.env` file**
```env
# .env
APP_NAME <str> = My Awesome App
PORT <int> = 8080
DEBUG <bool> = True
ALLOWED_HOSTS <list> = localhost, 127.0.0.1
DATABASE_CONFIG <json> = {"host": "localhost", "port": 5432}
BASE_URL <str> = http://localhost:${PORT}
```

**3. Use it in your Python code**
```python
from envist import Envist

env = Envist()

# ✨ Automatic type casting!
app_name = env.get('APP_NAME')      # Returns: 'My Awesome App' (str)
port = env.get('PORT')              # Returns: 8080 (int)
debug = env.get('DEBUG')            # Returns: True (bool)
hosts = env.get('ALLOWED_HOSTS')    # Returns: ['localhost', '127.0.0.1'] (list)
db_config = env.get('DATABASE_CONFIG')  # Returns: {'host': 'localhost', 'port': 5432} (dict)
base_url = env.get('BASE_URL')      # Returns: 'http://localhost:8080' (str)

print(f"🚀 Starting {app_name} on port {port}")
print(f"🐛 Debug mode: {debug}")
print(f"🔗 Base URL: {base_url}")
```

**That's it!** No more manual type conversion, no more configuration headaches! 🎉

---

## 📦 Installation

### Using pip (Recommended)
```bash
pip install envist
```

### Using conda
```bash
conda install -c conda-forge envist
```

### Using poetry
```bash
poetry add envist
```

### From source
```bash
git clone https://github.com/Almas-Ali/envist.git
cd envist
pip install -e .
```

**Requirements:** Python 3.7+ (No external dependencies!)

---

## 🎓 Complete Guide

### Basic Usage

#### Creating an Envist Instance

```python
from envist import Envist

# Use default .env file with auto-casting enabled
env = Envist()

# Use custom file path
env = Envist(path="config/.env")

# Disable auto-casting (values remain as strings unless explicitly cast)
env = Envist(auto_cast=False)

# Accept empty values (variables declared without values)
env = Envist(accept_empty=True)

# Full configuration
env = Envist(
    path="config/production.env",
    accept_empty=True,
    auto_cast=True
)
```

#### Getting Variables

```python
# Get with automatic type casting (from .env type annotations)
value = env.get('VARIABLE_NAME')

# Get with default value
value = env.get('VARIABLE_NAME', default='fallback_value')

# Get with explicit type casting (overrides .env annotations)
value = env.get('VARIABLE_NAME', cast=int)

# Get all variables
all_vars = env.get_all()
```

### Type Casting Magic

**🎯 The game-changer:** Define types directly in your `.env` file!

#### Traditional .env (Before Envist)
```env
DATABASE_PORT=5432
DEBUG=true
ALLOWED_IPS=192.168.1.1,192.168.1.2,localhost
```

```python
import os
# 😞 Everything is a string, manual conversion needed
port = int(os.getenv('DATABASE_PORT'))  # Manual casting
debug = os.getenv('DEBUG').lower() == 'true'  # Manual parsing
ips = os.getenv('ALLOWED_IPS').split(',')  # Manual splitting
```

#### Smart .env (With Envist)
```env
DATABASE_PORT <int> = 5432
DEBUG <bool> = true
ALLOWED_IPS <list> = 192.168.1.1, 192.168.1.2, localhost
```

```python
from envist import Envist
env = Envist()

# ✨ Automatic type casting!
port = env.get('DATABASE_PORT')    # Already an int!
debug = env.get('DEBUG')           # Already a bool!
ips = env.get('ALLOWED_IPS')       # Already a list!
```

#### Supported Type Annotations

| Syntax | Python Type | Example |
|--------|-------------|---------|
| `<str>` | `str` | `NAME <str> = John Doe` |
| `<int>` | `int` | `PORT <int> = 8080` |
| `<float>` | `float` | `PI <float> = 3.14159` |
| `<bool>` | `bool` | `DEBUG <bool> = True` |
| `<list>` | `list` | `HOSTS <list> = web1, web2, web3` |
| `<tuple>` | `tuple` | `COORDS <tuple> = 10, 20, 30` |
| `<set>` | `set` | `TAGS <set> = python, web, api` |
| `<dict>` | `dict` | `CONFIG <dict> = key1:value1, key2:value2` |
| `<json>` | `dict` | `SETTINGS <json> = {"timeout": 30}` |
| `<csv>` | `list` | `DATA <csv> = name,age,email` |

### Variable Expansion

**🔗 Reference other variables like a pro!**

```env
# .env - Smart variable references
HOST <str> = localhost
PORT <int> = 8080
PROTOCOL <str> = https

# Variable expansion in action
API_BASE <str> = ${PROTOCOL}://${HOST}:${PORT}/api
DATABASE_URL <str> = postgresql://user:pass@${HOST}:5432/mydb
REDIS_URL <str> = redis://${HOST}:6379

# Nested expansion
APP_URL <str> = ${API_BASE}/v1
HEALTH_CHECK <str> = ${APP_URL}/health
```

```python
from envist import Envist
env = Envist()

print(env.get('API_BASE'))      # https://localhost:8080/api
print(env.get('DATABASE_URL'))  # postgresql://user:pass@localhost:5432/mydb
print(env.get('HEALTH_CHECK'))  # https://localhost:8080/api/v1/health
```

### Advanced Operations

#### Setting Variables

```python
# Set single variable
env.set('NEW_VARIABLE', 'some_value')

# Set multiple variables
env.set_all({
    'DATABASE_HOST': 'localhost',
    'DATABASE_PORT': 5432,
    'DATABASE_NAME': 'myapp'
})

# Variables are immediately available
db_host = env.get('DATABASE_HOST')  # 'localhost'
```

#### Removing Variables

```python
# Remove single variable
env.unset('TEMPORARY_VAR')

# Remove multiple variables
env.unset_all(['VAR1', 'VAR2', 'VAR3'])

# Remove all variables (be careful!)
env.unset_all()
```

#### Saving Changes

```python
# Save to the same file
env.save()

# Save with formatting options
env.save(
    pretty=True,     # Add spacing for readability
    sort_keys=True,   # Sort variables alphabetically
    example_file=False  # Save an .env.example file with type annotations
)
```

**Example of saved output:**
```env
# Automatically formatted and sorted
DATABASE_HOST <str> = localhost
DATABASE_PORT <int> = 5432
DEBUG <bool> = True
```

---

## 📚 API Reference

### Class: `Envist`

#### Constructor

```python
Envist(path: str = ".env", accept_empty: bool = False, auto_cast: bool = True)
```

**Parameters:**
- `path` (str, optional): Path to the environment file. Defaults to ".env".
- `accept_empty` (bool, optional): Accept keys declared without values. Defaults to False.
- `auto_cast` (bool, optional): Automatically cast values when type annotations are present. If False, values remain as strings. Defaults to True.

#### Core Methods

| Method | Description | Parameters | Returns |
|--------|-------------|------------|---------|
| `get(key, *, default=None, cast=None)` | Get a variable with optional type casting | `key`: Variable name<br>`default`: Fallback value<br>`cast`: Type to cast to (overrides auto_cast) | `Any` |
| `get_all()` | Get all environment variables | None | `dict` |
| `set(key, value, cast=None)` | Set a single variable | `key`: Variable name<br>`value`: Variable value<br>`cast`: Optional type casting hint | `Any` |
| `set_all(data)` | Set multiple variables | `data`: Dictionary of key-value pairs | `None` |
| `unset(key)` | Remove a single variable | `key`: Variable name | `None` |
| `unset_all(data_list=None)` | Remove multiple or all variables | `data_list`: List of keys (if None, removes all) | `None` |
| `save(pretty=False, sort_keys=False, example_file=False)` | Save changes to file | `pretty`: Format with spaces<br>`sort_keys`: Sort alphabetically<br>`example_file`: Create .env.example file | `None` |
| `reload()` | Reload environment variables from file | None | `None` |

#### Dictionary-Style Access

Envist supports dictionary-style operations:

```python
env = Envist()

# Dictionary-style access
value = env['DATABASE_URL']        # Same as env.get('DATABASE_URL')
env['NEW_VAR'] = 'value'          # Same as env.set('NEW_VAR', 'value')
del env['OLD_VAR']                # Same as env.unset('OLD_VAR')

# Check if variable exists
if 'API_KEY' in env:
    print("API_KEY is configured")

# Get number of variables
print(f"Total variables: {len(env)}")

# Iterate over keys
for key in env:
    print(f"{key}: {env[key]}")
```

#### Properties

| Property | Description | Type |
|----------|-------------|------|
| `path` | Path to the environment file | `str` |

#### Special Methods

| Method | Description | Example |
|--------|-------------|---------|
| `__getitem__()` | Dictionary-style access | `env['KEY']` |
| `__setitem__()` | Dictionary-style assignment | `env['KEY'] = 'value'` |
| `__delitem__()` | Dictionary-style deletion | `del env['KEY']` |
| `__contains__()` | Check if key exists | `'KEY' in env` |
| `__len__()` | Get number of variables | `len(env)` |
| `__iter__()` | Iterate over keys | `for key in env:` |
| `__repr__()` | String representation | `<Envist path=".env">` |

---

## 🏷️ Supported Data Types

Envist supports a rich set of data types with intelligent parsing, including **nested type support**:

### Simple Types

| Type | Syntax | Description | Example | Python Output |
|------|--------|-------------|---------|---------------|
| **String** | `<str>` | Text values | `NAME <str> = John Doe` | `'John Doe'` |
| **Integer** | `<int>` | Whole numbers | `PORT <int> = 8080` | `8080` |
| **Float** | `<float>` | Decimal numbers | `PI <float> = 3.14159` | `3.14159` |
| **Boolean** | `<bool>` | True/False values | `DEBUG <bool> = True` | `True` |
| **List** | `<list>` or `<array>` | Comma-separated values | `HOSTS <list> = web1, web2, web3` | `['web1', 'web2', 'web3']` |
| **Tuple** | `<tuple>` | Immutable sequences | `COORDS <tuple> = 10, 20, 30` | `(10, 20, 30)` |
| **Set** | `<set>` | Unique values only | `TAGS <set> = python, web, python` | `{'python', 'web'}` |
| **Dictionary** | `<dict>` | Key-value pairs | `CONFIG <dict> = key1:value1, key2:value2` | `{'key1': 'value1', 'key2': 'value2'}` |
| **JSON** | `<json>` | JSON objects | `SETTINGS <json> = {"timeout": 30, "retries": 3}` | `{'timeout': 30, 'retries': 3}` |
| **CSV** | `<csv>` or `<comma_separated>` | CSV-style data | `DATA <csv> = name,age,email` | `['name', 'age', 'email']` |

### 🚀 **New: Nested Type Support**

Envist now supports nested type annotations for complex data structures:

#### Typed Collections

```env
# List of integers
PORTS <list<int>> = 8080, 9000, 3000

# Set of floats  
PRICES <set<float>> = 19.99, 29.95, 19.99

# Tuple of strings
SERVERS <tuple<str>> = web1.example.com, web2.example.com

# List of boolean values
FEATURES <list<bool>> = true, false, true
```

```python
from envist import Envist
env = Envist()

ports = env.get('PORTS')        # [8080, 9000, 3000] (list of ints)
prices = env.get('PRICES')      # {19.99, 29.95} (set of floats)  
servers = env.get('SERVERS')    # ('web1.example.com', 'web2.example.com') (tuple)
features = env.get('FEATURES')  # [True, False, True] (list of bools)
```

#### Typed Dictionaries

```env
# Dictionary with string keys and integer values
PORT_MAP <dict<str, int>> = web:8080, api:9000, db:5432

# Dictionary with string keys and float values
WEIGHTS <dict<str, float>> = cpu:0.7, memory:0.2, disk:0.1

# Dictionary with string keys and boolean values
FEATURES <dict<str, bool>> = auth:true, cache:false, debug:true
```

```python
port_map = env.get('PORT_MAP')   # {'web': 8080, 'api': 9000, 'db': 5432}
weights = env.get('WEIGHTS')     # {'cpu': 0.7, 'memory': 0.2, 'disk': 0.1}
features = env.get('FEATURES')   # {'auth': True, 'cache': False, 'debug': True}
```

#### Complex Nested Types

```env
# Dictionary with string keys and list of integers as values
GROUPS <dict<str, list<int>>> = admins:1,2,3, users:4,5,6, guests:7,8,9

# List of dictionaries (using JSON syntax for complex structures)
ENDPOINTS <json> = [
  {"name": "api", "port": 8080, "ssl": true},
  {"name": "web", "port": 3000, "ssl": false}
]
```

### 🎯 Smart Type Detection

**Boolean values** are parsed intelligently:
```env
# All of these become Python True
ENABLED <bool> = True
ENABLED <bool> = true  
ENABLED <bool> = TRUE
ENABLED <bool> = 1
ENABLED <bool> = yes
ENABLED <bool> = on

# All of these become Python False  
DISABLED <bool> = False
DISABLED <bool> = false
DISABLED <bool> = FALSE
DISABLED <bool> = 0
DISABLED <bool> = no
DISABLED <bool> = off
```

**Lists and tuples** handle whitespace gracefully:
```env
# These are equivalent
HOSTS <list> = web1, web2, web3
HOSTS <list> = web1,web2,web3  
HOSTS <list> = web1 , web2 , web3
```

**JSON values** support complex structures:
```env
# Simple object
CONFIG <json> = {"debug": true, "timeout": 30}

# Nested structures
DATABASE <json> = {
  "host": "localhost",
  "credentials": {"user": "admin", "pass": "secret"},
  "pools": [10, 20, 30]
}
```

### 🔄 Backward Compatibility

**No type annotations?** No problem! Envist works with traditional `.env` files:

```env
# Traditional .env file (no type annotations)
DATABASE_URL=postgresql://localhost:5432/mydb
DEBUG=true
PORT=8080
```

```python
from envist import Envist
env = Envist()

# Manual casting still works
url = env.get('DATABASE_URL', cast=str)
debug = env.get('DEBUG', cast=bool) 
port = env.get('PORT', cast=int)

# Or with nested types
items = env.get('ITEMS', cast='list<int>')
```

### ⚙️ Advanced Type Casting Options

You can control type casting behavior:

```python
# Auto-cast enabled (default) - types are cast automatically from annotations
env = Envist(auto_cast=True)

# Auto-cast disabled - all values remain as strings unless explicitly cast
env = Envist(auto_cast=False)
value = env.get('PORT', cast=int)  # Manual casting required

# Accept empty values
env = Envist(accept_empty=True)
empty_val = env.get('OPTIONAL_SETTING')  # Returns None if empty
```

> **💡 Pro Tip:** Mix and match! You can gradually migrate your `.env` files by adding type annotations to new variables while keeping existing ones unchanged.

---

## 🔧 Configuration

### Custom File Paths

```python
# Development environment
dev_env = Envist(path="environments/development.env")

# Production environment  
prod_env = Envist(path="environments/production.env")

# Testing environment
test_env = Envist(path="tests/fixtures/test.env")
```

### Environment-Specific Loading

```python
import os
from envist import Envist

# Load environment-specific configuration
environment = os.getenv('ENVIRONMENT', 'development')
env_file = f"config/{environment}.env"
env = Envist(path=env_file)

print(f"🌍 Loaded {environment} configuration from {env_file}")
```

### Multiple Environment Files

```python
from envist import Envist

# Base configuration
base_env = Envist(path="config/base.env")

# Environment-specific overrides
local_env = Envist(path="config/local.env")

# Merge configurations (local overrides base)
config = {**base_env.get_all(), **local_env.get_all()}
```

---

### Exception Handling

Envist provides specific exception types for different error scenarios:

```python
from envist import (
    Envist, 
    EnvistError,           # Base exception
    EnvistCastError,       # Type casting failures
    EnvistParseError,      # File parsing errors
    EnvistValueError,      # Value not found errors
    EnvistTypeError,       # Type validation errors
    FileNotFoundError      # File not found errors
)

try:
    env = Envist(path="nonexistent.env")
except FileNotFoundError as e:
    print(f"Environment file not found: {e}")

try:
    value = env.get('PORT', cast='invalid_type')
except EnvistCastError as e:
    print(f"Type casting failed: {e}")

try:
    env.unset('NONEXISTENT_VAR')
except EnvistValueError as e:
    print(f"Variable not found: {e}")
```

---

## 📊 Logging

Envist provides comprehensive logging capabilities with flexible configuration options to help you debug configuration issues and monitor environment variable usage.

### Basic Logging Setup

```python
import logging
from envist import Envist

# Enable basic logging to see Envist operations
logging.basicConfig(level=logging.INFO)

env = Envist()
# Now you'll see info-level logs about file loading and variable parsing
```

### Advanced Logging Configuration

Envist uses a sophisticated logging system with multiple handler types and customizable configurations:

```python
from envist.logger import EnvistLogger, configure_logger, create_stream_handler, create_file_handler

# Configure with custom handlers
logger = configure_logger(
    handlers=[
        create_stream_handler(level=logging.DEBUG),  # Console output
        create_file_handler("envist.log", level=logging.INFO)  # File output
    ],
    level="DEBUG"
)

# Now create Envist instance - it will use the configured logger
env = Envist()
```

### Log Levels and Information

| Level | Information Logged | Use Case |
|-------|-------------------|----------|
| `DEBUG` | Detailed parsing, type casting, variable resolution | Development & troubleshooting |
| `INFO` | File loading, variable counts, set/unset operations | General monitoring |
| `WARNING` | Missing variables, type casting issues | Production monitoring |
| `ERROR` | File read errors, parsing failures | Error tracking |
| `CRITICAL` | System-level failures | Critical error alerts |

### Built-in Logging Methods

The Envist logger provides specialized logging methods:

```python
from envist.logger import logger

# Environment parsing
logger.log_env_parse("/path/to/.env", 15)  # File path and variable count

# Type casting operations
logger.log_typecast("PORT", "8080", "int", True)  # Key, value, type, success

# Variable expansion
logger.log_variable_expansion("${HOST}:${PORT}", "localhost:8080")

# Variable access
logger.log_variable_access("DATABASE_URL", True, "str")  # Key, found, cast_type
```

### Handler Types

Envist supports multiple logging handler types for different use cases:

#### 1. Console/Stream Handler
```python
from envist.logger import create_stream_handler
import sys

# Console output (default to stdout)
console_handler = create_stream_handler(level=logging.INFO)

# Error output to stderr
error_handler = create_stream_handler(stream=sys.stderr, level=logging.ERROR)
```

#### 2. File Handler
```python
from envist.logger import create_file_handler

# Basic file logging
file_handler = create_file_handler("app.log", level=logging.DEBUG)

# Automatic directory creation
file_handler = create_file_handler("logs/envist/app.log", level=logging.INFO)
```

#### 3. JSON Handler (Structured Logging)
```python
from envist.logger import create_json_handler

# JSON formatted logs for log aggregation systems
json_handler = create_json_handler("app.json", level=logging.INFO)
```

JSON output format:
```json
{
  "timestamp": "2025-01-15T10:30:45.123456",
  "level": "INFO",
  "logger": "envist",
  "module": "parser",
  "function": "_load_env",
  "line": 127,
  "message": "Parsed .env: found 12 variables"
}
```

#### 4. Rotating File Handler
```python
from envist.logger import create_rotating_handler

# Rotate when file reaches 10MB, keep 5 backups
rotating_handler = create_rotating_handler(
    "app.log",
    max_bytes=10 * 1024 * 1024,  # 10MB
    backup_count=5,
    level=logging.INFO
)
```

#### 5. Syslog Handler
```python
from envist.logger import create_syslog_handler

# Send logs to system logger
syslog_handler = create_syslog_handler(
    address=("localhost", 514),
    level=logging.WARNING
)
```

### Example Log Output

**Console Output (INFO level):**
```
INFO: Initializing Envist with file: .env
INFO: Parsed .env: found 12 variables
INFO: Set environment variable 'NEW_VAR' = 'test_value'
WARNING: Variable 'OPTIONAL_VAR' not found
```

**File Output (DEBUG level):**
```
2025-01-15 10:30:45,123 - envist - DEBUG - _load_env:127 - Loading environment file: .env
2025-01-15 10:30:45,124 - envist - DEBUG - _apply_type_casting:234 - Successfully cast 'PORT' to int
2025-01-15 10:30:45,125 - envist - DEBUG - _resolve_variable:156 - Expanded '${HOST}:${PORT}' to 'localhost:8080'
2025-01-15 10:30:45,126 - envist - INFO - _load_env:145 - Parsed .env: found 12 variables
```

### Production Logging Setup

For production environments, use a comprehensive logging configuration:

```python
import logging
from pathlib import Path
from envist.logger import (
    EnvistLogger, 
    create_stream_handler, 
    create_rotating_handler,
    create_json_handler
)

# Production logging setup
def setup_production_logging():
    log_dir = Path("/var/log/myapp")
    log_dir.mkdir(exist_ok=True)
    
    handlers = [
        # Console: only warnings and errors
        create_stream_handler(level=logging.WARNING),
        
        # Rotating file: all info and above
        create_rotating_handler(
            log_dir / "app.log",
            max_bytes=50 * 1024 * 1024,  # 50MB
            backup_count=10,
            level=logging.INFO
        ),
        
        # JSON for log aggregation (ELK, Splunk, etc.)
        create_json_handler(
            log_dir / "app.json",
            level=logging.INFO
        )
    ]
    
    return EnvistLogger.configure(custom_handlers=handlers, reset=True)

# Use in production
logger = setup_production_logging()
logger.set_level("INFO")

# Your app code
env = Envist()
```

### Development Logging Setup

For development, you might want more verbose logging:

```python
from envist.logger import configure_logger, create_stream_handler, create_file_handler

# Development: verbose console + debug file
dev_logger = configure_logger(
    handlers=[
        create_stream_handler(level=logging.DEBUG),      # All to console
        create_file_handler("debug.log", level=logging.DEBUG)  # All to file
    ],
    level="DEBUG"
)

env = Envist()
```

### Custom Logger Integration

You can integrate Envist logging with your existing application logger:

```python
import logging
from envist.logger import EnvistLogger

# Get your existing application logger
app_logger = logging.getLogger("myapp")

# Create a custom handler that forwards to your app logger
class AppLoggerHandler(logging.Handler):
    def __init__(self, app_logger):
        super().__init__()
        self.app_logger = app_logger
    
    def emit(self, record):
        # Forward Envist logs to your app logger with prefix
        msg = f"[ENVIST] {self.format(record)}"
        self.app_logger.log(record.levelno, msg)

# Configure Envist to use your app logger
custom_handler = AppLoggerHandler(app_logger)
envist_logger = EnvistLogger.configure(custom_handlers=[custom_handler])

env = Envist()
```

### Dynamic Logging Control

You can change logging levels and handlers at runtime:

```python
from envist.logger import logger, create_file_handler

# Change log level
logger.set_level("DEBUG")

# Add a new handler
debug_handler = create_file_handler("debug.log", level=logging.DEBUG)
logger.add_handler(debug_handler)

# Remove a handler
logger.remove_handler(debug_handler)

# Replace all handlers
new_handlers = [create_stream_handler(level=logging.INFO)]
logger.replace_handlers(new_handlers)
```

> **🔍 Debugging Tips:**
> - Use `DEBUG` level when troubleshooting type casting issues
> - Use `INFO` level for monitoring environment loading in production
> - Use JSON handlers for centralized logging systems
> - Use rotating handlers to prevent log files from growing too large

---

## 🎯 Examples

### 🌐 Web Application Configuration

```env
# config/web.env
APP_NAME <str> = My Web App
APP_VERSION <str> = 1.0.0
HOST <str> = localhost
PORT <int> = 8080
DEBUG <bool> = True

# Database
DB_HOST <str> = localhost
DB_PORT <int> = 5432
DB_NAME <str> = webapp
DB_URL <str> = postgresql://user:pass@${DB_HOST}:${DB_PORT}/${DB_NAME}

# Security
SECRET_KEY <str> = your-secret-key-here
ALLOWED_HOSTS <list> = localhost, 127.0.0.1, 0.0.0.0
CORS_ORIGINS <list> = http://localhost:3000, http://localhost:8080

# External Services
REDIS_URL <str> = redis://${HOST}:6379
EMAIL_CONFIG <json> = {"smtp_server": "smtp.gmail.com", "port": 587, "use_tls": true}

# Feature Flags
ENABLE_ANALYTICS <bool> = True
ENABLE_CACHING <bool> = True
MAINTENANCE_MODE <bool> = False
```

```python
from envist import Envist

# Load configuration
env = Envist(path="config/web.env")

# Flask/FastAPI application setup
app_config = {
    'name': env.get('APP_NAME'),
    'version': env.get('APP_VERSION'),
    'host': env.get('HOST'),
    'port': env.get('PORT'),
    'debug': env.get('DEBUG'),
    'secret_key': env.get('SECRET_KEY'),
    'database_url': env.get('DB_URL'),
    'redis_url': env.get('REDIS_URL'),
    'allowed_hosts': env.get('ALLOWED_HOSTS'),
    'cors_origins': env.get('CORS_ORIGINS'),
    'email_config': env.get('EMAIL_CONFIG'),
}

print(f"🚀 Starting {app_config['name']} v{app_config['version']}")
print(f"🌐 Server: {app_config['host']}:{app_config['port']}")
print(f"🔗 Database: {app_config['database_url']}")
print(f"📧 Email: {app_config['email_config']['smtp_server']}")
```

### 🔬 Data Science Project

```env
# config/ml.env
PROJECT_NAME <str> = ML Pipeline
DATA_PATH <str> = ./data
MODEL_PATH <str> = ./models
OUTPUT_PATH <str> = ./outputs

# Data Processing
BATCH_SIZE <int> = 32
MAX_WORKERS <int> = 4
SAMPLE_RATE <float> = 0.1
RANDOM_SEED <int> = 42

# Model Configuration
MODEL_PARAMS <json> = {
  "learning_rate": 0.001,
  "epochs": 100,
  "dropout": 0.2,
  "hidden_layers": [128, 64, 32]
}

# Feature Engineering
SELECTED_FEATURES <list> = age, income, education, experience
CATEGORICAL_FEATURES <list> = gender, department, city
NUMERICAL_FEATURES <list> = age, income, experience, score

# Paths with expansion
TRAIN_DATA <str> = ${DATA_PATH}/train.csv
TEST_DATA <str> = ${DATA_PATH}/test.csv
MODEL_OUTPUT <str> = ${MODEL_PATH}/${PROJECT_NAME}_model.pkl
```

```python
from envist import Envist
import pandas as pd

# Load ML configuration
env = Envist(path="config/ml.env")

# Training pipeline setup
config = {
    'project_name': env.get('PROJECT_NAME'),
    'batch_size': env.get('BATCH_SIZE'),
    'max_workers': env.get('MAX_WORKERS'),
    'sample_rate': env.get('SAMPLE_RATE'),
    'random_seed': env.get('RANDOM_SEED'),
    'model_params': env.get('MODEL_PARAMS'),
    'selected_features': env.get('SELECTED_FEATURES'),
    'categorical_features': env.get('CATEGORICAL_FEATURES'),
    'numerical_features': env.get('NUMERICAL_FEATURES'),
    'train_data_path': env.get('TRAIN_DATA'),
    'test_data_path': env.get('TEST_DATA'),
    'model_output_path': env.get('MODEL_OUTPUT'),
}

print(f"🔬 {config['project_name']} Configuration:")
print(f"📊 Batch size: {config['batch_size']}")
print(f"🎯 Model params: {config['model_params']}")
print(f"📁 Training data: {config['train_data_path']}")
```

### 🐳 Docker & DevOps

```env
# config/docker.env
ENVIRONMENT <str> = production
SERVICE_NAME <str> = my-api
VERSION <str> = 1.2.3

# Container Configuration
CONTAINER_PORT <int> = 8080
HOST_PORT <int> = 80
MEMORY_LIMIT <str> = 512m
CPU_LIMIT <float> = 0.5

# Registry
REGISTRY_URL <str> = your-registry.com
IMAGE_NAME <str> = ${REGISTRY_URL}/${SERVICE_NAME}:${VERSION}

# Health Check
HEALTH_CHECK_INTERVAL <int> = 30
HEALTH_CHECK_TIMEOUT <int> = 10
HEALTH_CHECK_RETRIES <int> = 3
HEALTH_CHECK_URL <str> = http://localhost:${CONTAINER_PORT}/health

# Environment Variables for Container
CONTAINER_ENV <json> = {
  "NODE_ENV": "production",
  "LOG_LEVEL": "info",
  "DATABASE_URL": "postgresql://prod-db:5432/app"
}
```

```python
from envist import Envist

# Load Docker configuration
env = Envist(path="config/docker.env")

# Generate Docker run command
def generate_docker_command():
    image = env.get('IMAGE_NAME')
    host_port = env.get('HOST_PORT')
    container_port = env.get('CONTAINER_PORT')
    memory = env.get('MEMORY_LIMIT')
    cpu = env.get('CPU_LIMIT')
    container_env = env.get('CONTAINER_ENV')
    
    cmd_parts = [
        "docker run -d",
        f"--name {env.get('SERVICE_NAME')}",
        f"-p {host_port}:{container_port}",
        f"--memory={memory}",
        f"--cpus={cpu}"
    ]
    
    # Add environment variables
    for key, value in container_env.items():
        cmd_parts.append(f"-e {key}={value}")
    
    cmd_parts.append(image)
    
    return " ".join(cmd_parts)

print("🐳 Docker Command:")
print(generate_docker_command())
```

### 🧪 Testing Configuration

```env
# config/test.env
TEST_MODE <bool> = True
TEST_DATABASE <str> = sqlite:///:memory:
MOCK_EXTERNAL_APIS <bool> = True

# Test Data
TEST_DATA_PATH <str> = ./tests/data
FIXTURES_PATH <str> = ${TEST_DATA_PATH}/fixtures
EXPECTED_RESULTS_PATH <str> = ${TEST_DATA_PATH}/expected

# Performance Testing
LOAD_TEST_USERS <int> = 100
LOAD_TEST_DURATION <int> = 300
PERFORMANCE_THRESHOLDS <json> = {
  "response_time_ms": 200,
  "error_rate_percent": 1,
  "throughput_rps": 1000
}

# Test Categories
UNIT_TESTS <list> = user, auth, payment, notification
INTEGRATION_TESTS <list> = api, database, cache
E2E_TESTS <list> = login_flow, purchase_flow, admin_flow
```

---

## 🤝 Contributing

We love contributions! 🎉 Whether you're fixing bugs, adding features, or improving documentation, your help makes Envist better for everyone.

### 🚀 Quick Start for Contributors

1. **Fork the repository**
   ```bash
   git clone https://github.com/your-username/envist.git
   cd envist
   ```

2. **Set up development environment**
   ```bash
   python -m venv venv
   source venv/bin/activate  # On Windows: venv\Scripts\activate
   pip install -e ".[dev]"
   ```

3. **Create your feature branch**
   ```bash
   git checkout -b feature/amazing-new-feature
   ```

4. **Make your changes and test**
   ```bash
   # Run tests
   pytest

   # Check code style
   flake8 envist/

   # Type checking
   mypy envist/
   ```

5. **Commit and push**
   ```bash
   git commit -am "✨ Add amazing new feature"
   git push origin feature/amazing-new-feature
   ```

6. **Create a Pull Request**
   - Go to GitHub and create a PR
   - Describe your changes clearly
   - Link any related issues

### 🎯 Areas We Need Help With

| Area | Description | Difficulty |
|------|-------------|------------|
| 🐛 **Bug Fixes** | Fix reported issues | Beginner |
| 📚 **Documentation** | Improve examples and guides | Beginner |
| ✨ **New Data Types** | Add support for more types | Intermediate |
| 🔄 **Multi-line Support** | Enable multi-line values | Advanced |
| ⚡ **Performance** | Optimize parsing and loading | Advanced |
| 🧪 **Testing** | Increase test coverage | Intermediate |

### 📋 Development Guidelines

- **Code Style:** Follow PEP 8
- **Testing:** Write tests for new features
- **Documentation:** Update docs for changes
- **Commit Messages:** Use conventional commit format
- **Backwards Compatibility:** Don't break existing APIs

### 🏆 Contributors

Thanks to all our amazing contributors! 🙌

<a href="https://github.com/Almas-Ali/envist/graphs/contributors">
  <img src="https://contrib.rocks/image?repo=Almas-Ali/envist" />
</a>

---

## 📄 License

This project is licensed under the **MIT License** - see the [LICENSE](LICENSE) file for details.

### What does this mean?

✅ **You can:** Use, copy, modify, merge, publish, distribute, sublicense, and/or sell  
✅ **You must:** Include the original copyright notice and license  
❌ **We're not liable:** The software is provided "as is" without warranty  

**TL;DR:** Free to use for any purpose! 🎉

---

<div align="center">

**Made with ❤️ by [Md. Almas Ali](https://github.com/Almas-Ali)**

⭐ **Star this repo if Envist helped you!** ⭐

[Report Bug](https://github.com/Almas-Ali/envist/issues) • [Request Feature](https://github.com/Almas-Ali/envist/issues) • [Documentation](https://github.com/Almas-Ali/envist) • [Examples](https://github.com/Almas-Ali/envist/tree/master/examples)

</div>
