### .env.override file example Source: https://fastenv.bws.bio/dotenv An example of an .env.override file used to provide local development overrides. ```text # .env.override APPLICATION_ENVIRONMENT=local CSV_VARIABLE=comma,separated,override URL_EXAMPLE=https://github.com ``` -------------------------------- ### Install fastenv in a virtual environment Source: https://fastenv.bws.bio/index.html Creates a Python virtual environment, activates it, and installs fastenv using pip. ```bash python3 -m venv .venv . .venv/bin/activate python -m pip install fastenv ``` -------------------------------- ### Example .env file Source: https://fastenv.bws.bio/dotenv A sample .env file demonstrating various variable formats including JSON, URIs, and comments. ```text # .env AWS_ACCESS_KEY_ID_EXAMPLE=AKIAIOSFODNN7EXAMPLE AWS_SECRET_ACCESS_KEY_EXAMPLE=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLE CSV_VARIABLE=comma,separated,value EMPTY_VARIABLE='' # comment INLINE_COMMENT=no_comment # inline comment JSON_EXAMPLE='{"array": [1, 2, 3], "exponent": 2.99e8, "number": 123}' PASSWORD='64w2Q$!&,,[EXAMPLE' QUOTES_AND_WHITESPACE='text and spaces' URI_TO_DIRECTORY='~/dev' URI_TO_S3_BUCKET=s3://mybucket/.env URI_TO_SQLITE_DB=sqlite:////path/to/db.sqlite URL_EXAMPLE=https://start.duckduckgo.com/ ``` -------------------------------- ### Example .env.testing file content Source: https://fastenv.bws.bio/contributing The .env.testing file should be uploaded to each bucket to provide necessary configuration variables for the integration tests. ```text # .env AWS_ACCESS_KEY_ID_EXAMPLE=AKIAIOSFODNN7EXAMPLE AWS_SECRET_ACCESS_KEY_EXAMPLE=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLE CSV_VARIABLE=comma,separated,value EMPTY_VARIABLE='' # comment INLINE_COMMENT=no_comment # inline comment JSON_EXAMPLE='{"array": [1, 2, 3], "exponent": 2.99e8, "number": 123}' PASSWORD='64w2Q$!&,,[EXAMPLE' QUOTES_AND_WHITESPACE='text and spaces' URI_TO_DIRECTORY='~/dev' URI_TO_S3_BUCKET=s3://mybucket/.env URI_TO_SQLITE_DB=sqlite:////path/to/db.sqlite URL_EXAMPLE=https://start.duckduckgo.com/ OBJECT_STORAGE_VARIABLE='DUDE!!! This variable came from object storage!' ``` -------------------------------- ### Start a Python REPL session Source: https://fastenv.bws.bio/index.html Starts an interactive Python REPL session after activating the virtual environment. ```bash .venv ❯ python ``` -------------------------------- ### Use os.environ-style API to manage environment variables Source: https://fastenv.bws.bio/environment Demonstrates setting, getting, and deleting environment variables using the DotEnv instance, mirroring os.environ behavior. The fastenv package must be installed in the environment. ```python import os import fastenv dotenv = fastenv.DotEnv() dotenv["EXAMPLE_VARIABLE"] = "example_value" dotenv["EXAMPLE_VARIABLE"] # 'example_value' os.environ["EXAMPLE_VARIABLE"] # 'example_value' del dotenv["EXAMPLE_VARIABLE"] dotenv.getenv("EXAMPLE_VARIABLE", "variable_was_deleted") # 'variable_was_deleted' os.getenv("EXAMPLE_VARIABLE", "variable_was_deleted") # 'variable_was_deleted' ``` -------------------------------- ### Import fastenv and instantiate DotEnv Source: https://fastenv.bws.bio/environment Import the fastenv module and create a DotEnv instance to start managing environment variables. ```python import fastenv dotenv = fastenv.DotEnv() ``` -------------------------------- ### Use fastenv in a FastAPI app with lifespan Source: https://fastenv.bws.bio/index.html Shows how to load a .env file asynchronously in a FastAPI lifespan and expose settings via a GET endpoint. ```python from contextlib import asynccontextmanager from typing import AsyncGenerator, TypedDict import fastenv from fastapi import FastAPI, Request class LifespanState(TypedDict): settings: fastenv.DotEnv @asynccontextmanager async def lifespan(_: FastAPI) -> AsyncGenerator[LifespanState]: """Configure app lifespan. https://fastapi.tiangolo.com/advanced/events/ https://www.starlette.io/lifespan/ """ settings = await fastenv.load_dotenv(".env") lifespan_state: LifespanState = {"settings": settings} yield lifespan_state app = FastAPI(lifespan=lifespan) @app.get("/settings") async def get_settings(request: Request) -> dict[str, str]: settings = request.state.settings return dict(settings) ``` -------------------------------- ### Finding and loading a .env file with python-dotenv Source: https://fastenv.bws.bio/comparisons This example demonstrates how to manually find and load a .env file using python-dotenv, including error handling, logging, and setting environment variables. ```python import logging from dotenv import find_dotenv from dotenv.main import DotEnv def find_and_load_my_dotenv(env_file: str = ".env") -> DotEnv: try: logger = logging.getLogger() source = find_dotenv(filename=env_file, raise_error_if_not_found=True) dotenv = DotEnv(source, verbose=True) dotenv.set_as_environment_variables() logger.info( f"Python-dotenv loaded {len(dotenv.dict())} variables from {env_file}" ) return dotenv except Exception as e: logger.error(f"Error loading {env_file}: {e.__class__.__qualname__} {e}") raise ``` -------------------------------- ### Get variables from a DotEnv instance Source: https://fastenv.bws.bio/environment Shows how calling a DotEnv instance with a key returns the value or None, and how multiple keys return a mapping. Also demonstrates the getenv method with a default. ```python import fastenv dotenv = fastenv.DotEnv("KEY1=value1") dotenv("KEY1") # 'value1' dotenv("NOT_SET") dotenv.getenv("NOT_SET", "default_value") # 'default_value' dotenv("KEY1", "NOT_SET NOT_SET_EITHER") # {'KEY1': 'value1', 'NOT_SET': None, 'NOT_SET_EITHER': None} ``` -------------------------------- ### Hatch key commands Source: https://fastenv.bws.bio/contributing Commands for managing the project's virtual environment and dependencies with Hatch. Use 'hatch env create' to set up the environment, 'hatch run' to execute commands inside it, and 'hatch shell' to activate it. Set HATCH_ENV_TYPE_VIRTUAL_PATH=.venv to install virtualenvs into .venv. ```bash # Basic usage: https://hatch.pypa.io/latest/cli/reference/ hatch env create # create virtual environment and install dependencies hatch env find # show path to virtual environment hatch env show # show info about available virtual environments hatch run COMMAND # run a command within the virtual environment hatch shell # activate the virtual environment, like source venv/bin/activate hatch version # list or update version of this package export HATCH_ENV_TYPE_VIRTUAL_PATH=.venv # install virtualenvs into .venv ``` -------------------------------- ### Use fastenv DotEnv in a REPL session Source: https://fastenv.bws.bio/index.html Demonstrates creating a DotEnv instance, adding and deleting variables, calling the instance, converting to a dict, and saving to a file asynchronously with anyio. ```python # instantiate a DotEnv with a variable import fastenv dotenv = fastenv.DotEnv("EXAMPLE_VARIABLE=example_value") # add a variable with dictionary syntax dotenv["ANOTHER_VARIABLE"] = "another_value" # delete a variable del dotenv["ANOTHER_VARIABLE"] # add a variable by calling the instance dotenv("I_THINK_FASTENV_IS=awesome") # {'I_THINK_FASTENV_IS': 'awesome'} # return a dict of the variables in the DotEnv instance dict(dotenv) # {'EXAMPLE_VARIABLE': 'example_value', 'I_THINK_FASTENV_IS': 'awesome'} # save the DotEnv instance to a file import anyio anyio.run(fastenv.dump_dotenv, dotenv) # Path('/path/to/this/dir/.env') ``` -------------------------------- ### Get and set variables in the same call to a DotEnv instance Source: https://fastenv.bws.bio/environment Shows how a single call can combine getting existing variables and setting new ones, returning the resulting mapping. ```python import fastenv dotenv = fastenv.DotEnv("KEY1=value1") dotenv("KEY1", "KEY2=value2 KEY3=value3", key4="value4") # {'KEY1': 'value1', 'KEY2': 'value2', 'KEY3': 'value3', 'KEY4': 'value4'} ``` -------------------------------- ### Setting credentials and running the script Source: https://fastenv.bws.bio/cloud-object-storage Use this shell command to provide AWS credentials via environment variables and execute the example.py script. ```bash AWS_ACCESS_KEY_ID="" \ AWS_SECRET_ACCESS_KEY="" \ python example.py ``` -------------------------------- ### Uploading a .env file to a bucket Source: https://fastenv.bws.bio/cloud-object-storage This script demonstrates how to instantiate a configuration and client to upload a local .env file to a specified bucket path. Save this code as example.py. ```python #!/usr/bin/env python3 # example.py from __future__ import annotations import anyio import fastenv import httpxyz async def upload_my_dotenv( bucket_host: str, bucket_region: str, bucket_path: str = "uploads/fastenv-docs/.env", source: anyio.Path | str = ".env", ) -> httpxyz.Response | None: config = fastenv.ObjectStorageConfig( # bucket_host=bucket_host, bucket_region=bucket_region, ) client = fastenv.ObjectStorageClient(config=config) # return await client.upload(bucket_path, source) # if __name__ == "__main__": bucket_host = ".s3..backblazeb2.com" bucket_region = "" anyio.run(upload_my_dotenv, bucket_host, bucket_region) ``` -------------------------------- ### Load .env file into DotEnv model with anyio.run Source: https://fastenv.bws.bio/dotenv Save as example.py in the same directory as the .env file and run from within the virtual environment. Uses anyio.run() to execute the async coroutine. The output shows the source path and a dictionary of environment variables with comments removed. ```python #!/usr/bin/env python3 # example.py import anyio import fastenv async def load_my_dotenv(filename: str = ".env") -> fastenv.DotEnv: dotenv = await fastenv.load_dotenv(filename) print(dotenv.source) print(dict(dotenv)) return dotenv if __name__ == "__main__": anyio.run(load_my_dotenv) ``` ```shell .venv ❯ python example.py # output formatted for clarity /Users/brendon/dev/fastenv-docs/.env { 'AWS_ACCESS_KEY_ID_EXAMPLE': 'AKIAIOSFODNN7EXAMPLE', 'AWS_SECRET_ACCESS_KEY_EXAMPLE': 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLE', 'CSV_VARIABLE': 'comma,separated,value', 'EMPTY_VARIABLE': '', 'INLINE_COMMENT': 'no_comment', 'JSON_EXAMPLE': '{"array": [1, 2, 3], "exponent": 2.99e8, "number": 123}', 'PASSWORD': '64w2Q$!&,,[EXAMPLE', 'QUOTES_AND_WHITESPACE': 'text and spaces', 'URI_TO_DIRECTORY': '~/dev', 'URI_TO_S3_BUCKET': 's3://mybucket/.env', 'URI_TO_SQLITE_DB': 'sqlite:////path/to/db.sqlite', 'URL_EXAMPLE': 'https://start.duckduckgo.com/' } ``` -------------------------------- ### Load and dump a DotEnv instance to .env.dump Source: https://fastenv.bws.bio/dotenv Updates example.py to load .env and .env.override, then dump the merged DotEnv instance to .env.dump using fastenv.dump_dotenv(). Run with 'python example.py' and inspect the generated .env.dump file. ```python #!/usr/bin/env python3 # example.py import anyio import fastenv async def load_my_dotenv(filename: str = ".env") -> fastenv.DotEnv: dotenv = await fastenv.load_dotenv(filename) print(dotenv.source) print(dict(dotenv)) return dotenv async def load_my_dotenvs(*filenames: str) -> fastenv.DotEnv: dotenv = await fastenv.load_dotenv(*filenames) print(dotenv.source) print(dict(dotenv)) return dotenv async def load_and_dump_my_dotenvs(*filenames: str) -> fastenv.DotEnv: dotenv = await fastenv.load_dotenv(*filenames) await fastenv.dump_dotenv(dotenv, ".env.dump") return dotenv if __name__ == "__main__": # anyio.run(load_my_dotenv) # anyio.run(load_my_dotenvs, ".env", ".env.override") anyio.run(load_and_dump_my_dotenvs, ".env", ".env.override") ``` -------------------------------- ### Loading multiple .env files in Python Source: https://fastenv.bws.bio/dotenv Updates the example.py module to load multiple files, where values in the second file override those in the first. ```python #!/usr/bin/env python3 # example.py import anyio import fastenv async def load_my_dotenv(filename: str = ".env") -> fastenv.DotEnv: dotenv = await fastenv.load_dotenv(filename) print(dotenv.source) print(dict(dotenv)) return dotenv async def load_my_dotenvs(*filenames: str) -> fastenv.DotEnv: dotenv = await fastenv.load_dotenv(*filenames) print(dotenv.source) print(dict(dotenv)) return dotenv if __name__ == "__main__": # anyio.run(load_my_dotenv) anyio.run(load_my_dotenvs, ".env", ".env.override") ``` -------------------------------- ### Error when using HTTPXYZ with Starlette TestClient Source: https://fastenv.bws.bio/changelog Shows the error raised when HTTPXYZ 0.28.2 is used with FastAPI/Starlette TestClient, which requires the httpx package. The error suggests installing httpx via pip. ```text ERROR tests/test_fastapi.py RuntimeError: The starlette.testclient module requires the httpx package to be installed. You can install this with: $ pip install httpx ``` -------------------------------- ### Instantiate DotEnv with variables Source: https://fastenv.bws.bio/environment Create a DotEnv instance using positional arguments, multi-variable strings, and keyword arguments. The resulting mapping is shown. ```python import fastenv dotenv = fastenv.DotEnv("KEY1=value1", "KEY2=value2 KEY3=value3", key4="value4") dict(dotenv) # {'KEY1': 'value1', 'KEY2': 'value2', 'KEY3': 'value3', 'KEY4': 'value4'} ``` -------------------------------- ### Download multiple .env files using fastenv Source: https://fastenv.bws.bio/cloud-object-storage Demonstrates how to download a common and a custom .env file from an S3-compatible bucket and merge them into a single DotEnv object. ```python #!/usr/bin/env python3 # example.py from __future__ import annotations import anyio import fastenv async def download_my_dotenvs( bucket_host: str, bucket_region: str, bucket_path_to_common_env: str = ".env.common", bucket_path_to_custom_env: str = ".env.custom", ) -> fastenv.DotEnv: config = fastenv.ObjectStorageConfig( bucket_host=bucket_host, bucket_region=bucket_region, ) client = fastenv.ObjectStorageClient(config=config) env_common = await client.download(bucket_path_to_common_env) env_custom = await client.download(bucket_path_to_custom_env) return fastenv.DotEnv(env_common, env_custom) if __name__ == "__main__": bucket_host = ".s3..backblazeb2.com" bucket_region = "" anyio.run(download_my_dotenvs, bucket_host, bucket_region) ``` -------------------------------- ### Simple Pydantic Settings Model Source: https://fastenv.bws.bio/comparisons Demonstrates defining a Pydantic BaseSettings model to automatically parse and validate environment variables. ```python import os from pydantic import BaseSettings os.environ["BOOLEAN_SETTING"] = "false" os.environ["INTEGER_SETTING"] = "123" os.environ["STRING_SETTING"] = "example_value" class SimpleSettings(BaseSettings): boolean_setting: bool = True integer_setting: int = 000 string_setting: str = "default_value" print(SimpleSettings().dict()) # {"boolean_setting": False, "integer_setting": 123, "string_setting": "example_value"} ``` -------------------------------- ### Download .env file with fastenv Source: https://fastenv.bws.bio/cloud-object-storage This Python script defines functions to upload and download .env files to and from an object storage bucket using fastenv.ObjectStorageClient. The main block demonstrates how to execute the download function using anyio. ```python #!/usr/bin/env python3 # example.py from __future__ import annotations import anyio import fastenv import httpxyz async def upload_my_dotenv( bucket_host: str, bucket_region: str, bucket_path: str = "uploads/fastenv-docs/.env", source: anyio.Path | str = ".env", ) -> httpxyz.Response | None: config = fastenv.ObjectStorageConfig( bucket_host=bucket_host, bucket_region=bucket_region, ) client = fastenv.ObjectStorageClient(config=config) return await client.upload(bucket_path, source) async def download_my_dotenv( bucket_host: str, bucket_region: str, bucket_path: str = "uploads/fastenv-docs/.env", destination: anyio.Path | str = ".env.download", ) -> anyio.Path: config = fastenv.ObjectStorageConfig( bucket_host=bucket_host, bucket_region=bucket_region, ) client = fastenv.ObjectStorageClient(config=config) return await client.download(bucket_path, destination) if __name__ == "__main__": bucket_host = ".s3..backblazeb2.com" bucket_region = "" # anyio.run(upload_my_dotenv, bucket_host, bucket_region) anyio.run(download_my_dotenv, bucket_host, bucket_region) ``` -------------------------------- ### Configure settings with starlette.config.Config Source: https://fastenv.bws.bio/comparisons Create a Config instance to read environment variables with optional type-casting and default values. ```python import starlette.config config = starlette.config.Config() FOO_CONSTANT = config("FOO_VARIABLE", cast=str, default="baz") ```