Skip to main content
https://img.shields.io/badge/stdlib--only-yes-green.svg https://github.com/cjrh/biodome/workflows/Python%20application/badge.svg https://coveralls.io/repos/github/cjrh/biodome/badge.svg?branch=master https://img.shields.io/pypi/pyversions/biodome.svg https://img.shields.io/github/tag/cjrh/biodome.svg https://img.shields.io/badge/install-pip%20install%20biodome-ff69b4.svg https://img.shields.io/pypi/v/biodome.svg https://img.shields.io/badge/calver-YYYY.MM.MINOR-22bfda.svg

biodome

Controlled environments

Reading environment variables with os.environ is pretty easy, but after a while one gets pretty tired of having to cast variables to the right types and handling fallback to defaults.

This library provides a clean way read environment variables and fall back to defaults in a sane way.

How you were doing it:

import os

try:
    TIMEOUT = int(os.environ.get('TIMEOUT', 10))
except ValueError:
    TIMEOUT = 10

Wordy, boilerplate, DRY violation, etc.

How you will be doing it:

import biodome

TIMEOUT = biodome.environ.get('TIMEOUT', 10)

That’s right, it becomes a single line. But there’s a magic trick here: how does biodome know that TIMEOUT should be set to an int? It knows because it looks at the type of the default arguments. This works for a bunch of different things:

# Lists
os.environ['IGNORE_KEYS'] = '[1, 2, 3]'
biodome.environ.get('TIMEOUT', []) == [1, 2, 3]

# Dicts
os.environ['SETTINGS'] = '{"a": 1, "b": 2}'
biodome.environ.get('SETTINGS', {}) == dict(a=1, b=2)

If you look carefully at the above, you can see that we set the data via the stdlib os.environ dictionary; that’s right, biodome.environ is a drop-in replacement for os.environ. You don’t even have to switch out your entire codebase, you can do it piece by piece.

And while we’re on the subject of setting env vars, with biodome you don’t have to cast them first, it does string casting internally automatically, unlike os.environ:

# Dicts
biodome.environ['SETTINGS'] = dict(b=2, a=1)  # No cast required
biodome.environ.get('SETTINGS', {}) == dict(a=1, b=2)

Loading env files

biodome also provides a function to load a file which specifies the values of environment variables. An example of such an env file:

# myconfig.env
# This sets the log level for all the loggers in the program
LOGGER_LEVEL=info

# Hourly backups are stored at this path and named with a timestamp.
BACKUP_PATH=/data/backups/

# The number of times to retry outgoing HTTP requests if the status
# code is > 500
RETRY_TIME=5

The name of the environment variable must be on the left and the value on the right. Each variable must be on its own line. Lines starting with a # are considered comments and are ignored.

This env file can be loaded like this:

>>> import biodome
>>> biodome.load_env_file('myconfig.env')
>>> print(biodome.environ['RETRY_TIME'])
5

True and False

I don’t know about you, but I use bool settings a LOT in environment variables, so handling this properly is really important to me. When calling biodome.environ.get('SETTING', default=<value>), the default value can also be a bool, i.e., True or False. In this case, any of the following values, and their upper- or mixed-case equivalents will be recognized as True:

['1', 'y', 'yes', 'on', 'active', 'activated', 'enabled', 'true',
't', 'ok', 'yeah']

Anything not in this list will be considered as False. Do you have ideas for more things that should be considered as True? I take PRs!

Callables

For explictness it is often convenient to declare and load environment variables at the top of the module in which they’re used:

""" My new module """
import biodome

ENABLE_SETTING_XYZ = biodome.environ.get('ENABLE_SETTING_XYZ', True)

def blah():
    print(ENABLE_SETTING_XYZ)

You could call environ.get() inside the functions and methods where it is used, but then you would lose the convenience of documenting all the available environment variables at the top of the module. As a solution to this problem, biodome provides a way to produce a callable for a particular setting. An extra advantage of doing this is that it becomes quite easy to make use of changes in environment variables on the fly. Here’s the modified example:

""" My new module """
import biodome

ENABLE_SETTING_XYZ = biodome.environ.get_callable(
    # Same as before
    'ENABLE_SETTING_XYZ', True
    )

def blah():
    print(ENABLE_SETTING_XYZ())  # Now a callable!

How it works internally

The key theme here is that the type of the default value is used to determine how to cast the input value. This works for the following types:

  • int

  • float

  • str

  • list

  • dict

  • set (NOTE: only supported in Python 3+ due to ast.literal_eval())

  • tuple

For the containers, we use ast.literal_eval() which is much safer than using eval() because code is not evaluated. Safety first! (thanks to @nickdirienzo for the tip)

Metadata

Release files for biodome 2022.9.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for biodome 2022.9.1
File Size Uploaded Provenance
biodome-2022.9.1.tar.gz 12.0 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for biodome 2022.9.1
File Interpreter ABI Platform
biodome-2022.9.1-py2.py3-none-any.whl Python 3, Python 2 none any Details

Total release size: 21.8 kB

Release files / biodome-2022.9.1.tar.gz

Download URL biodome-2022.9.1.tar.gz
Size 12.0 kB
Tags Source
SHA-256 checksum
How to use checksums
eb2c44d53864eb5c942dceabb91a80facf234522dcc2d8a6ddef8ed2dcafdba1
BLAKE2b-256 checksum
How to use checksums
345704095a851879aadf857c9f52d737863521220eab8b43ac15bee5ce100ebd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-requests/2.26.0

Release files / biodome-2022.9.1-py2.py3-none-any.whl

Download URL biodome-2022.9.1-py2.py3-none-any.whl
Size 9.8 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
41e4e01b35162aadf62a5d0998cdadbe0d5e2fe485e499562379b49a1c2071c2
BLAKE2b-256 checksum
How to use checksums
e6da6f1f78fc487eecb865141968be2e7a2545ef2255d57e1f22b0e7782ed749
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-requests/2.26.0

Security for biodome 2022.9.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page