typenv
Version 0.2.0
Typed environment variable parsing for Python
Table of Contents generated with mdformat-toc
Background
Typenv does environment variable parsing with an API almost identical to the excellent environs. There are a few reasons why typenv might be preferred:
- Type annotated typecast functions: type checkers are able to understand types of parsed environment variables.
- More flexible prefix manipulation of environment variable names.
- Validation of environment variable names.
- Optional automatic uppercasing of environment variable names.
- Ability to generate a .env.example that shows expected types of environment variables.
- Less dependencies. No marshmallow required.
Installing
Installing from PyPI repository (https://pypi.org/project/typenv):
pip install typenv
Usage
Basics
Set environment variables:
export NAME='Harry Potter'
export AGE=14
export IS_WIZARD=true
export PATRONUM_SUCCESS_RATE=0.92
export BANK_BALANCE=134599.01
export LUCKY_NUMBERS=7,3,11
export EXTRA_DETAILS='{"friends": ["Hermione", "Ron"]}'
export FAVORITE_COLOR=0x7f0909
Parse the values in Python:
from typenv import Env
env = Env()
NAME = env.str("NAME") # => "Harry Potter"
AGE = env.int("AGE") # => 14
IS_WIZARD = env.bool("IS_WIZARD") # => True
PATRONUM_SUCCESS_RATE = env.float("PATRONUM_SUCCESS_RATE") # => 0.92
BANK_BALANCE = env.decimal("BANK_BALANCE") # => decimal.Decimal("134599.01")
LUCKY_NUMBERS = env.list("LUCKY_NUMBERS", subcast=int) # => [7, 3, 11]
EXTRA_DETAILS = env.json("EXTRA_DETAILS") # => {"friends": ["Hermione", "Ron"]}
FAVORITE_COLOR = env.bytes("FAVORITE_COLOR", encoding="hex") # => b"\x7f\t\t"
# Optional settings must have a default value
IS_DEATH_EATER = env.bool("IS_DEATH_EATER", default=False) # => False
Supported types
The types supported by typenv are:
env.strenv.intenv.boolenv.floatenv.decimalenv.list- Takes a
subcastkeyword argument for casting list items to one ofstr,int,bool,floatordecimal.Decimal
- Takes a
env.jsonenv.bytes- Takes an
encodingkeyword argument for indicating how the bytes are encoded. For now onlyhexis supported.
- Takes an
Default values
Normally, if an environment variable is not found, typenv raises an exception. If a default value is provided, however, that will be returned instead of raising.
from typenv import Env
env = Env()
BOOL = env.bool("NON_EXISTING_NAME", default=False) # => False
LIST = env.list("NON_EXISTING_NAME", default=["a", "b"]) # => ["a", "b"]
OPTIONAL_INT = env.int("NON_EXISTING_NAME", default=None) # => None
Name prefixes
export FLASK_HOST=127.0.0.1
export FLASK_PORT=44144
from typenv import Env
env = Env()
# Explicitly prefixing variable names works, but repeats itself
# (especially given more environment variables and nested prefixes).
HOST = env.str("FLASK_HOST") # => "127.0.0.1"
PORT = env.int("FLASK_PORT") # => 44144
# This reads the same variables as above, and can be a nice way of
# reducing repetition and expressing structure. Note that it is possible
# to have nested `with` statements.
with env.prefixed("FLASK_"):
HOST = env.str("HOST") # => "127.0.0.1"
PORT = env.int("PORT") # => 44144
# For more control, one can mutate `env.prefix` (of type list[str])
# directly. Note that if an exception occurs reading the environment
# variables, then `env.prefix` will not be reset to its initial value,
# which is something that the `with` statement would take care of.
env.prefix.append("FLASK_")
HOST = env.str("HOST") # => "127.0.0.1"
PORT = env.int("PORT") # => 44144
env.prefix.pop()
Name character set
Typenv validates environment variable names.
By default, the set of allowed characters includes upper case ASCII letters, digits and the underscore (_).
The set of allowed characters can be configured:
from typenv import Env
env = Env(allowed_chars="ABCDEFGHIJKLMNOPQRSTUVWXYZ")
Name uppercasing
export UPPER_CASE_NAME=true
from typenv import Env
# Environment variable names in type cast methods will automatically be upper
# cased when `upper=True` is set here.
env = Env(upper=True)
NAME = env.bool("upper_casE_Name")
Validation
export NAME='Harry Potter'
export AGE=14
from typenv import Env
env = Env()
# A single validator function
NAME = env.str("NAME", validate=lambda n: n.startswith("Harry"))
# A validator function can signal error by raising an exception
def is_positive(num):
if num <= 0:
raise Exception("Number is not positive")
# A validator function can alternatively return `False` to signal an error
def is_less_than_thousand(num):
if num >= 1000:
return False
return True
# Multiple validator functions can be passed as an iterable of callables
AGE = env.int("AGE", validate=(is_positive, is_less_than_thousand))
Reading from a .env file
While developing, it is often useful to read environment variables from a file.
Typenv supports this via the Env.read_end() method.
The method will look for a file (by default) named .env in current working directory
and import environment variables from it.
If a file is not found,
the method will walk up in the directory tree until a file is found or the root directory is reached.
The method returns a boolean that is True if a file is found.
Given a .env file in current working directory with the following content
SOME_VAR='some value'
The following code will be able to read and parse the value
from typenv import Env
env = Env()
env.read_env()
SOME_VAR = env.str("SOME_VAR") # => "some value"
Dumping parsed values
export SOME_STR=blaablaa
export SOME_INT=99
from typenv import Env, ParsedValue
env = Env()
SOME_STR = env.str("SOME_STR")
SOME_INT = env.int("SOME_INT")
assert env.dump() == {
"SOME_INT": ParsedValue(value=99, type="int", optional=False),
"SOME_STR": ParsedValue(value="blaablaa", type="str", optional=False),
}
Acknowledgments
The public API of this library is almost an exact copy of environs, which is based on envparse and django-environ. Credit for the interface goes to the authors of those libraries.
Metadata
Release files for typenv 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| typenv-0.2.0.tar.gz | 10.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| typenv-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 18.4 kB
Release files / typenv-0.2.0.tar.gz
| Download URL | typenv-0.2.0.tar.gz |
|---|---|
| Size | 10.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6fd1e6964fe5bb4a9aefcd28557ee520913b51208d1afff33598fc677bc855fb
|
|
BLAKE2b-256 checksum How to use checksums |
96623da6e385d6e400e72edbee43b1b11c0c446d84db175a4a9174fefb463c50
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.1.5 CPython/3.7.10 Linux/5.4.0-1047-azure
|
Release files / typenv-0.2.0-py3-none-any.whl
| Download URL | typenv-0.2.0-py3-none-any.whl |
|---|---|
| Size | 8.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6cd2a00a0ce4ff03f8645f1b6da1f64e60a1f260a732ba7a716c17e3b0946915
|
|
BLAKE2b-256 checksum How to use checksums |
15bb1ca83f95829c1e0a36a8a1e9845b8d240f77547c8802654149e59eb6ce1c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.1.5 CPython/3.7.10 Linux/5.4.0-1047-azure
|