Enhanced environment variable management with multi-format support (.env, JSON, YAML, INI, TOML)
Project description
🌟 envdot
Enhanced environment variable management for Python with multi-format support and automatic type detection.
📋 Features
- 🔧 Multiple Format Support:
.env,.json,.yaml,.yml, and.inifiles - 🎯 Automatic Type Detection: Automatically converts strings to
bool,int,float, or keeps asstring - 💾 Read and Write: Load from and save to configuration files
- 🔄 Method Chaining: Fluent API for cleaner code
- 🌍 OS Environment Integration: Seamlessly works with
os.environ(os.getenv, os.setenv) - 📦 Zero Dependencies: Core functionality works without external packages (YAML support requires PyYAML)
- ✅ Nested structure flattening: Deep hierarchies → flat env vars
- ✅ Format conversion: Convert between any supported formats
- ✅ Auto-typed
os.getenv(): Get typed values instead of strings - ✅ Attribute-style access:
config.DATABASE_HOST - ✅ Dictionary-style access:
config['DATABASE_HOST']
Installation
pip install envdot
# Full installation (all formats)
pip install envdot[full]
# Specific format support
pip install envdot[yaml] # YAML support
pip install envdot[toml] # TOML support
pip install envdot[json5] # JSON5 support
Documentation
🚀 Quick Start
Basic Usage
from envdot import load_env, get_env
# Load configuration (auto-detects format)
load_env() # Searches for .env, config.json, config.yaml, etc.
# Or load specific file
load_env('config.toml')
# Get values (automatically typed!)
db_host = get_env('DATABASE_HOST') # Returns: "localhost" (str)
db_port = get_env('DATABASE_PORT') # Returns: 5432 (int)
debug = get_env('DEBUG') # Returns: True (bool)
timeout = get_env('TIMEOUT') # Returns: 30.5 (float)
# With defaults
redis_host = get_env('REDIS_HOST', default='127.0.0.1')
# Explicit type casting
max_connections = get_env('MAX_CONNECTIONS', cast_type=int)
allowed_hosts = get_env('ALLOWED_HOSTS', cast_type=list)
$ cat .env
CELERY_BACKEND=redis://redis:6379/0
CELERY_BROKER=redis://redis:6379/0
DEBUG=true
DEBUGGER_SERVER=5.5
DEBUG_SERVER=false
DJANGO_ALLOWED_HOSTS="localhost 127.0.0.1 [::1] 192.168.100.2 192.168.100.2"
POSTGRES_DB=django_celery
POSTGRES_PASSWORD=password1234-8
POSTGRES_USER=celery_admin
PYTHONDONTWRITEBYTECODE=true
PYTHONUNBUFFERED=true
RABBITMQ_DEFAULT_PASS=hackmeplease
RABBITMQ_DEFAULT_USER=syslog
RABBITMQ_HOST_DJANGO=rabbitmq
RABBITMQ_MANAGEMENT=true
RABBITMQ_PASSWORD_DJANGO=123-8
RABBITMQ_USERNAME_DJANGO=syslog
SECRET_KEY=dbaa1_i7%*3r9-=z-+_mz4r-!qeed@(-a_r(g@k8jo8y3r27%m
In [1]: from envdot import load_env, show
In [2]: load_env()
Out[2]: DotEnv(filepath=.env, vars=18)
In [3]: show()
Out[3]:
{'CELERY_BACKEND': 'redis://redis:6379/0',
'CELERY_BROKER': 'redis://redis:6379/0',
'DEBUG': True,
'DEBUGGER_SERVER': 5.5,
'DEBUG_SERVER': False,
'DJANGO_ALLOWED_HOSTS': 'localhost 127.0.0.1 [::1] 192.168.100.2 192.168.100.2',
'POSTGRES_DB': 'django_celery',
'POSTGRES_PASSWORD': 'password1234-8',
'POSTGRES_USER': 'celery_admin',
'PYTHONDONTWRITEBYTECODE': True,
'PYTHONUNBUFFERED': True,
'RABBITMQ_DEFAULT_PASS': 'hackmeplease',
'RABBITMQ_DEFAULT_USER': 'syslog',
'RABBITMQ_HOST_DJANGO': 'rabbitmq',
'RABBITMQ_MANAGEMENT': True,
'RABBITMQ_PASSWORD_DJANGO': '123-8',
'RABBITMQ_USERNAME_DJANGO': 'syslog',
'SECRET_KEY': 'dbaa1_i7%*3r9-=z-+_mz4r-!qeed@(-a_r(g@k8jo8y3r27%m'}
In [4]: config = load_env()
In [5]: config.show()
Out[5]:
{'CELERY_BACKEND': 'redis://redis:6379/0',
'CELERY_BROKER': 'redis://redis:6379/0',
'DEBUG': True,
'DEBUGGER_SERVER': 5.5,
'DEBUG_SERVER': False,
'DJANGO_ALLOWED_HOSTS': 'localhost 127.0.0.1 [::1] 192.168.100.2 192.168.100.2',
'POSTGRES_DB': 'django_celery',
'POSTGRES_PASSWORD': 'password1234-8',
'POSTGRES_USER': 'celery_admin',
'PYTHONDONTWRITEBYTECODE': True,
'PYTHONUNBUFFERED': True,
'RABBITMQ_DEFAULT_PASS': 'hackmeplease',
'RABBITMQ_DEFAULT_USER': 'syslog',
'RABBITMQ_HOST_DJANGO': 'rabbitmq',
'RABBITMQ_MANAGEMENT': True,
'RABBITMQ_PASSWORD_DJANGO': '123-8',
'RABBITMQ_USERNAME_DJANGO': 'syslog',
'SECRET_KEY': 'dbaa1_i7%*3r9-=z-+_mz4r-!qeed@(-a_r(g@k8jo8y3r27%m'}
In [6]: config.DEBUG_SERVER
Out[6]: False
In [7]: config.DEBUG_SERVER = True
In [8]: show()
Out[8]:
{'CELERY_BACKEND': 'redis://redis:6379/0',
'CELERY_BROKER': 'redis://redis:6379/0',
'DEBUG': True,
'DEBUGGER_SERVER': 5.5,
'DEBUG_SERVER': True,
'DJANGO_ALLOWED_HOSTS': 'localhost 127.0.0.1 [::1] 192.168.100.2 192.168.100.2',
'POSTGRES_DB': 'django_celery',
'POSTGRES_PASSWORD': 'password1234-8',
'POSTGRES_USER': 'celery_admin',
'PYTHONDONTWRITEBYTECODE': True,
'PYTHONUNBUFFERED': True,
'RABBITMQ_DEFAULT_PASS': 'hackmeplease',
'RABBITMQ_DEFAULT_USER': 'syslog',
'RABBITMQ_HOST_DJANGO': 'rabbitmq',
'RABBITMQ_MANAGEMENT': True,
'RABBITMQ_PASSWORD_DJANGO': '123-8',
'RABBITMQ_USERNAME_DJANGO': 'syslog',
'SECRET_KEY': 'dbaa1_i7%*3r9-=z-+_mz4r-!qeed@(-a_r(g@k8jo8y3r27%m'}
In [9]: config.show()
Out[9]:
{'CELERY_BACKEND': 'redis://redis:6379/0',
'CELERY_BROKER': 'redis://redis:6379/0',
'DEBUG': True,
'DEBUGGER_SERVER': 5.5,
'DEBUG_SERVER': True,
'DJANGO_ALLOWED_HOSTS': 'localhost 127.0.0.1 [::1] 192.168.100.2 192.168.100.2',
'POSTGRES_DB': 'django_celery',
'POSTGRES_PASSWORD': 'password1234-8',
'POSTGRES_USER': 'celery_admin',
'PYTHONDONTWRITEBYTECODE': True,
'PYTHONUNBUFFERED': True,
'RABBITMQ_DEFAULT_PASS': 'hackmeplease',
'RABBITMQ_DEFAULT_USER': 'syslog',
'RABBITMQ_HOST_DJANGO': 'rabbitmq',
'RABBITMQ_MANAGEMENT': True,
'RABBITMQ_PASSWORD_DJANGO': '123-8',
'RABBITMQ_USERNAME_DJANGO': 'syslog',
'SECRET_KEY': 'dbaa1_i7%*3r9-=z-+_mz4r-!qeed@(-a_r(g@k8jo8y3r27%m'}
In [10]: os.getenv('DEBUG_SERVER')
Out[10]: True
In [11]: config.DEBUG_SERVER = False
In [12]: os.getenv('DEBUG_SERVER')
Out[12]: False
from envdot import DotEnv
# Auto-detect and load from common config files (.env, config.json, etc.)
env = DotEnv()
# Or specify a file
env = DotEnv('.env')
# Get values with automatic type detection
db_host = env.get('DB_HOST') # Returns string
# or
db_host = os.getenv('DB_HOST') # Returns string
db_port = env.get('DB_PORT') # Returns int (auto-detected)
# or
db_port = os.getenv('DB_PORT') # Returns int (auto-detected)
debug_mode = env.get('DEBUG') # Returns bool (auto-detected)
# or
debug_mode = os.getenv('DEBUG') # Returns bool (auto-detected)
api_timeout = env.get('API_TIMEOUT') # Returns float (auto-detected)
# or
api_timeout = os.getenv('API_TIMEOUT') # Returns float (auto-detected)
# Set values
env.set('NEW_KEY', 'value')
# or
env.setenv('NEW_KEY', 'value')
env.set('FEATURE_ENABLED', True)
# or
env.setenv('FEATURE_ENABLED', True)
# Save to file
env.save('.env')
# or
env.save()
# or
os.save_env()
Convenience Functions
from envdot import load_env, get_env, set_env, save_env
# Load configuration
load_env('.env')
# or just
load_env()
# Get values
database_url = get_env('DATABASE_URL')
max_connections = get_env('MAX_CONNECTIONS', default=100)
# Set values
set_env('NEW_FEATURE', True)
# Save changes
save_env('.env') # or just save_env()
Working with Different File Formats
.env File
env = DotEnv('.env')
env.load()
JSON File
env = DotEnv('config.json')
env.load()
YAML File
env = DotEnv('config.yaml')
env.load() # Requires PyYAML
INI File
env = DotEnv('config.ini')
env.load()
Type Detection Examples
The package automatically detects and converts types:
# Given this .env file:
# DEBUG=true
# PORT=8080
# TIMEOUT=30.5
# APP_NAME=MyApp
# EMPTY_VALUE=
env = DotEnv('.env') # or load_env() or load_env('.env')
env.get('DEBUG') # Returns: True (bool)
env.get('PORT') # Returns: 8080 (int)
env.get('TIMEOUT') # Returns: 30.5 (float)
env.get('APP_NAME') # Returns: 'MyApp' (str)
env.get('EMPTY_VALUE') # Returns: None
# env.get same as os.getenv
Explicit Type Casting
# Force a specific type
version = env.get('VERSION', cast_type=str)
port = env.get('PORT', cast_type=int)
enabled = env.get('ENABLED', cast_type=bool)
Method Chaining
env = DotEnv('.env') \
.load() \
.set('NEW_KEY', 'value') \
.set('ANOTHER_KEY', 123) \
.save()
Dictionary-Style Access
env = DotEnv('.env')
# Get values
value = env['KEY_NAME']
# Set values
env['NEW_KEY'] = 'new value'
# Check existence
if 'API_KEY' in env:
print("API key is configured")
# Get all variables
all_vars = env.all()
Advanced Features
Load Without Overriding
env.load(override=False) # Keep existing values
Load Without Applying to OS Environment
env.load(apply_to_os=False) # Don't set in os.environ
Save to Different Format
env = DotEnv('.env')
env.load()
env.save('config.json') # Convert .env to JSON
Clear Variables
env.clear() # Clear internal storage only
env.clear(clear_os=True) # Also clear from os.environ
Delete Specific Keys
env.delete('OLD_KEY')
env.delete('TEMP_KEY', remove_from_os=True)
Type Detection Rules
The package uses the following rules for automatic type detection:
- Boolean:
true,yes,on,1→True|false,no,off,0→False - None:
none,null, empty string →None - Integer: Numbers without decimal point →
int - Float: Numbers with decimal point →
float - String: Everything else →
str
📝 Supported Formats
1. .env File (Most Common)
DEBUG=true
PORT=8080
DATABASE_URL=postgresql://localhost/mydb
# .env
DATABASE_HOST=localhost
DATABASE_PORT=5432
DEBUG=true
TIMEOUT=30.5
APP_NAME="My Application"
from envdot import load_env, get_env
load_env('.env')
print(get_env('DATABASE_PORT')) # 5432 (int, not string!)
print(get_env('DEBUG')) # True (bool, not string!)
2. JSON File
{
"DEBUG": true,
"PORT": 8080,
"DATABASE_URL": "postgresql://localhost/mydb"
}
{
"database": {
"host": "localhost",
"port": 5432,
"credentials": {
"username": "admin",
"password": "secret"
}
},
"features": ["auth", "cache"]
}
load_env('config.json')
# Nested keys are flattened with underscores
print(get_env('DATABASE_HOST')) # localhost
print(get_env('DATABASE_CREDENTIALS_USERNAME')) # admin
print(get_env('FEATURES_0')) # auth
Flattening Rules:
database.host→DATABASE_HOSTdatabase.credentials.username→DATABASE_CREDENTIALS_USERNAMEfeatures[0]→FEATURES_0
3. YAML File
DEBUG: true
PORT: 8080
DATABASE_URL: postgresql://localhost/mydb
# config.yaml
database:
host: localhost
port: 5432
credentials:
username: admin
password: secret
server:
primary:
host: server1.example.com
port: 8080
secondary:
host: server2.example.com
port: 8081
load_env('config.yaml')
print(get_env('DATABASE_HOST')) # localhost
print(get_env('DATABASE_CREDENTIALS_USERNAME')) # admin
print(get_env('SERVER_PRIMARY_HOST')) # server1.example.com
Installation: pip install pyyaml
4. INI File
[DEFAULT]
DEBUG = true
PORT = 8080
DATABASE_URL = postgresql://localhost/mydb
# config.ini
[DEFAULT]
app_name = My Application
version = 1.0.0
[database]
host = localhost
port = 5432
username = admin
[server]
host = 0.0.0.0
port = 8080
load_env('config.ini')
# DEFAULT section items have no prefix
print(get_env('APP_NAME')) # My Application
# Other sections use section name as prefix
print(get_env('DATABASE_HOST')) # localhost
print(get_env('SERVER_PORT')) # 8080
5. TOML File (⭐ Recommended for Python Projects)
# config.toml
title = "My Application"
version = "1.0.0"
[database]
host = "localhost"
port = 5432
[database.credentials]
username = "admin"
password = "secret"
[[features]]
name = "authentication"
enabled = true
[[features]]
name = "caching"
enabled = false
load_env('config.toml')
print(get_env('TITLE')) # My Application
print(get_env('DATABASE_HOST')) # localhost
print(get_env('DATABASE_CREDENTIALS_USERNAME')) # admin
print(get_env('FEATURES_0_NAME')) # authentication
print(get_env('FEATURES_0_ENABLED')) # True
Installation:
- Python 3.11+: Built-in support for reading
- Python < 3.11:
pip install tomli - Writing TOML:
pip install tomli-w(all Python versions)
🔄 Format Conversion
Convert between any supported formats:
from envdot import load_env, save_env
# Load from JSON
load_env('config.json')
# Save as different formats
save_env('config.env', format='env') # Convert to .env
save_env('config.yaml', format='yaml') # Convert to YAML
save_env('config.toml', format='toml') # Convert to TOML
save_env('config.ini', format='ini') # Convert to INI
🎯 Advanced Usage
1. Auto-typed os.getenv()
Make os.getenv() return typed values automatically:
from envdot import load_env
import os
# Enable auto-typed os.getenv()
load_env(auto_replace_getenv=True) # Default is True
# Now os.getenv() returns typed values!
port = os.getenv('DATABASE_PORT') # Returns: 5432 (int), not "5432" (str)
debug = os.getenv('DEBUG') # Returns: True (bool), not "true" (str)
timeout = os.getenv('TIMEOUT') # Returns: 30.5 (float), not "30.5" (str)
2. OS Module Patching
Add helpful methods to os module:
from envdot import load_env
import os
# Enable os module patching
load_env(patch_os=True) # Default is True
# Now you can use:
os.getenv_typed('PORT') # Auto-typed getenv
os.getenv_int('PORT', default=8080)
os.getenv_bool('DEBUG', default=False)
os.getenv_float('RATIO', default=1.0)
os.setenv('KEY', 'value') # Set and save
os.save_env() # Save to file
3. Attribute-Style Access
from envdot import DotEnv
env = DotEnv('config.toml')
# Access like attributes
print(env.DATABASE_HOST)
print(env.DATABASE_PORT)
# Set like attributes (auto-saves!)
env.NEW_KEY = 'new_value'
env.MAX_WORKERS = 10
4. Dictionary-Style Access
from envdot import DotEnv
env = DotEnv('config.json')
# Dictionary-like access
print(env['DATABASE_HOST'])
env['NEW_KEY'] = 'value'
# Check existence
if 'DEBUG' in env:
print("Debug mode is set")
5. Explicit Type Casting
from envdot import get_env
# Force specific types
port = get_env('PORT', cast_type=int)
enabled = get_env('ENABLED', cast_type=bool)
ratio = get_env('RATIO', cast_type=float)
# Cast to list
hosts = get_env('ALLOWED_HOSTS', cast_type=list)
# "localhost, 127.0.0.1, example.com" → ['localhost', '127.0.0.1', 'example.com']
# Cast to tuple
coords = get_env('COORDINATES', cast_type=tuple)
6. Production Environment Setup
from envdot import load_env, get_env
import os
# Load base configuration
load_env('config.base.toml')
# Override with environment-specific settings
environment = os.getenv('ENVIRONMENT', 'development')
if environment == 'production':
load_env('config.prod.env', override=True)
elif environment == 'staging':
load_env('config.staging.env', override=True)
# Now get_env() returns environment-specific values
db_host = get_env('DATABASE_HOST')
7. Recursive File Search
from envdot import DotEnv
# Automatically search current directory and subdirectories
env = DotEnv()
env.load(recursive=True)
# Or specify search parameters
env.find_settings_recursive(
start_path='/path/to/project',
max_depth=5,
filename=['.env', 'config.toml'],
exceptions=['node_modules', 'venv']
)
🔧 API Reference
DotEnv Class
__init__(filepath=None, auto_load=True)
Initialize DotEnv instance.
load(filepath=None, override=True, apply_to_os=True)
Load environment variables from file.
get(key, default=None, cast_type=None)
Get environment variable with automatic type detection.
set(key, value, apply_to_os=True)
Set environment variable.
os.getenv(key, default=None, cast_type=None)
Get environment variable with automatic type detection.
os.setenv(key, value, apply_to_os=True)
Set environment variable.
save(filepath=None, format=None)
Save environment variables to file.
delete(key, remove_from_os=True)
Delete environment variable.
all()
Get all environment variables as dictionary.
keys()
Get all variable names.
clear(clear_os=False)
Clear all stored variables.
Main Functions
# Load configuration
load_env(
filepath=None, # Path to config file (auto-detects if None)
auto_replace_getenv=True, # Replace os.getenv() with typed version
patch_os=True, # Add helpers to os module
override=True, # Override existing values
apply_to_os=True, # Set values in os.environ
store_typed=True, # Store typed values internally
recursive=True, # Search recursively for config files
newone=False # Create new file if not found
)
# Get environment variable
get_env(
key, # Variable name
default=None, # Default value if not found
cast_type=None # Force type conversion
)
# Set environment variable
set_env(
key, # Variable name
value, # Variable value
apply_to_os=True # Also set in os.environ
)
# Save configuration
save_env(
filepath=None, # Path to save (uses loaded path if None)
format=None # Format: 'env', 'json', 'yaml', 'ini', 'toml'
)
DotEnv Class
from envdot import DotEnv
env = DotEnv(
filepath='config.toml', # Config file path
auto_load=True, # Auto-load on init
newone=False # Create new if not exists
)
# Methods
env.load(filepath=None, **kwargs)
env.get(key, default=None, cast_type=None)
env.set(key, value, apply_to_os=True)
env.save(filepath=None, format=None)
env.delete(key, remove_from_os=True)
env.all() # Get all as dict
env.keys() # Get all keys
env.clear(clear_os=False) # Clear all variables
# Access styles
value = env.KEY # Attribute
value = env['KEY'] # Dictionary
value = env.get('KEY') # Method
value = env('KEY') # Callable
Convenience Functions
load_env(filepath=None, **kwargs)- Load environment variablesget_env(key, default=None, cast_type=None)- Get environment variable same as os.getenvset_env(key, value, **kwargs)- Set environment variable same as os.setenvsave_env(filepath=None, **kwargs)- Save environment variables
📊 Format Comparison
| Feature | .env | JSON | YAML | INI | TOML |
|---|---|---|---|---|---|
| Simplicity | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| Nesting | ❌ | ✅ Deep | ✅ Deep | ⚠️ 1 level | ✅ Deep |
| Comments | ✅ | ❌* | ✅ | ✅ | ✅ |
| Type Safety | ⚠️ Auto | ✅ Native | ✅ Native | ⚠️ Auto | ✅ Strong |
| Arrays | ❌ | ✅ | ✅ | ❌ | ✅ |
| Portability | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| Python Std | ❌ | ✅ | ❌ | ✅ | ✅ (3.11+) |
| Best For | Secrets | Web apps | Complex config | Legacy | Python projects |
* JSON5 supports comments
🎓 Best Practices
1. Choose the Right Format
- Use .env for: Secrets, simple configs, CI/CD, maximum portability
- Use JSON for: API configs, web apps, cross-language projects
- Use YAML for: Complex configs, Kubernetes/Docker, human-readable
- Use INI for: Legacy systems, section-based configs
- Use TOML for: Python projects (recommended), strong typing needs
2. Type Safety
# ✅ Good: Use explicit types for critical values
db_port = get_env('DATABASE_PORT', cast_type=int)
max_retries = get_env('MAX_RETRIES', cast_type=int)
# ✅ Good: Use defaults
timeout = get_env('TIMEOUT', default=30, cast_type=int)
# ⚠️ Careful: Auto-detection might surprise you
value = get_env('SOME_VALUE') # Could be str, int, float, bool, or None
3. Environment-Specific Configs
# config.base.toml - shared settings
# config.dev.env - development overrides
# config.prod.env - production overrides
load_env('config.base.toml')
import os
env = os.getenv('ENVIRONMENT', 'development')
if env == 'production':
load_env('config.prod.env', override=True)
4. Secure Secrets
# ✅ Good: Keep secrets in .env, never in version control
# .env (in .gitignore)
DATABASE_PASSWORD=secret123
API_KEY=xyz789
# config.toml (in git)
[database]
host = "localhost"
port = 5432
# password loaded from .env
# Load both
load_env('config.toml')
load_env('.env', override=True) # Secrets override config
🧪 Testing
# Run tests
pytest
# With coverage
pytest --cov=envdot --cov-report=html
# Specific test file
pytest tests/test_all_formats.py -v
📦 Dependencies
Core (always installed)
version-get- Version management
Optional
pyyaml>=6.0.1- YAML supporttomli>=2.0.1- TOML reading (Python < 3.11)tomli-w>=1.0.0- TOML writingjson5>=0.9.14- JSON5 supportrichcolorlog>=0.1.0- Rich logging
🔒 Security
- Never commit
.envfiles to version control - Use environment variables for secrets
- Use config files for non-sensitive settings
- Consider using secret management services for production
Example .gitignore
# Environment files
.env
.env.local
.env.*.local
config.local.*
*.env.local
# But keep examples
!.env.example
!config.example.*
📖 Examples
See the examples/ directory for complete examples:
example_basic.py- Basic usageexample_all_formats.py- All format examplesexample_production.py- Production setupexample_conversion.py- Format conversion
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- Inspired by
python-dotenv - TOML support via
tomli/tomllib - YAML support via
PyYAML
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Author
📞 Support
- Issues: GitHub Issues
- Email: cumulus13@gmail.com
- Documentation: See this README and inline documentation
Made with ❤️ by Hadi Cahyadi
⭐ Star this repo if you find it helpful!
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file envdot-1.0.29.tar.gz.
File metadata
- Download URL: envdot-1.0.29.tar.gz
- Upload date:
- Size: 40.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1b4e0c025159f2f2214d7544b479b887e623bd2f08f91ff2e336052df550954c
|
|
| MD5 |
1c5d72557895c7d8040f9008f0bb419c
|
|
| BLAKE2b-256 |
be93880c648e1842f7ba9e46af0b1da566b080ada197704c2aa70d3bcc7ce820
|
File details
Details for the file envdot-1.0.29-py3-none-any.whl.
File metadata
- Download URL: envdot-1.0.29-py3-none-any.whl
- Upload date:
- Size: 27.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
18c73ae7883b4220205f50ed52f3ce35921742e9a16a6428c6e05c8c2207c2bd
|
|
| MD5 |
7d5053a6674592954d94e4ddf7537ddf
|
|
| BLAKE2b-256 |
d7d1e88f90ef0372367572dce6b7fd02c2cf3d51b7c4631164bf91e31866e535
|