fastenv


Namefastenv JSON
Version 0.6.0 PyPI version JSON
download
home_pageNone
SummaryUnified environment variable and settings management for FastAPI and beyond.
upload_time2024-10-05 19:04:49
maintainerNone
docs_urlNone
authorNone
requires_python<4,>=3.9
licenseNone
keywords asgi dotenv environment variables fastapi settings
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # ⚙️ fastenv 🚀

_Unified environment variable and settings management for FastAPI and beyond_

[![PyPI](https://img.shields.io/pypi/v/fastenv?color=success)](https://pypi.org/project/fastenv/)
[![coverage](https://img.shields.io/badge/coverage-100%25-brightgreen?logo=pytest&logoColor=white)](https://coverage.readthedocs.io/en/latest/)
[![ci](https://github.com/br3ndonland/fastenv/workflows/ci/badge.svg)](https://github.com/br3ndonland/fastenv/actions/workflows/ci.yml)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)

## Description

fastenv [\[fæst iː ən v\]](https://en.wikipedia.org/wiki/Help:IPA/English) is a Python package for managing environment variables and application settings.

[Environment variables](https://en.wikipedia.org/wiki/Environment_variable) are key-value pairs provided to the operating system with syntax like `VARIABLE_NAME=value`. Collections of environment variables are stored in files commonly named _.env_ and called "dotenv" files. The Python standard library `os` module provides tools for reading environment variables, such as `os.getenv("VARIABLE_NAME")`, but only handles strings, and doesn't include tools for file I/O. Additional logic is therefore needed to load environment variables from files before they can be read by Python, and to convert variables from strings to other Python types.

This project aims to:

- [x] **Replace the aging [python-dotenv](https://github.com/theskumar/python-dotenv) project** with a similar, but more intuitive API, and modern syntax and tooling.
- [x] **Implement asynchronous file I/O**. Reading and writing files can be done asynchronously with packages like [AnyIO](https://github.com/agronholm/anyio).
- [x] **Implement asynchronous object storage integration**. Dotenv files are commonly kept in cloud object storage, but environment variable management packages typically don't integrate with object storage clients. Additional logic is therefore required to download _.env_ files from object storage prior to loading environment variables. This project aims to integrate with S3-compatible object storage, with a focus on downloading and uploading file objects.
- [ ] **Read settings from TOML**. [It's all about _pyproject.toml_ now](https://snarky.ca/what-the-heck-is-pyproject-toml/). The Python community has pushed [PEP 517](https://www.python.org/dev/peps/pep-0517/) build tooling and [PEP 518](https://www.python.org/dev/peps/pep-0518/) build requirements forward, and [even `setuptools` has come around](https://setuptools.readthedocs.io/en/latest/build_meta.html). [PEP 621](https://www.python.org/dev/peps/pep-0621/) defined how to store package metadata and dependencies in _pyproject.toml_. Why don't we use the metadata from our _pyproject.toml_ files in our Python applications?
- [ ] **Unify settings management for FastAPI**. [Uvicorn](https://www.uvicorn.org/), [Starlette](https://www.starlette.io/config/), and _[pydantic](https://pydantic-docs.helpmanual.io/usage/settings/)_ each have their own ways of loading environment variables and configuring application settings. This means that, when [configuring a FastAPI application](https://fastapi.tiangolo.com/advanced/settings/), there are at least three different settings management tools available, each with their own pros and cons. It would be helpful to address the limitations of each of these options, potentially providing a similar, improved API for each one.

The source code is 100% type-annotated and unit-tested.

For additional background on the project, see [www.bws.bio/projects/fastenv](https://www.bws.bio/projects/fastenv).

## Quickstart

Install fastenv into a virtual environment:

```sh
python3 -m venv .venv
. .venv/bin/activate
python -m pip install fastenv
```

Then start a REPL session and try it out:

```sh
.venv ❯ python
```

```py
# 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')
```

Use fastenv in your FastAPI app:

```py
from contextlib import asynccontextmanager
from typing import AsyncIterator, TypedDict

import fastenv
from fastapi import FastAPI, Request


class LifespanState(TypedDict):
    settings: fastenv.DotEnv


@asynccontextmanager
async def lifespan(_: FastAPI) -> AsyncIterator[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)
```

## Documentation

Documentation is built with [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/), deployed on [Vercel](https://vercel.com/), and available at [fastenv.bws.bio](https://fastenv.bws.bio) and [fastenv.vercel.app](https://fastenv.vercel.app).

[Vercel build configuration](https://vercel.com/docs/build-step):

- Build command: `python3 -m pip install mkdocs-material && mkdocs build --site-dir public`
- Output directory: `public` (default)

[Vercel site configuration](https://vercel.com/docs/configuration) is specified in _vercel.json_.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "fastenv",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4,>=3.9",
    "maintainer_email": null,
    "keywords": "asgi, dotenv, environment variables, fastapi, settings",
    "author": null,
    "author_email": "Brendon Smith <bws@bws.bio>",
    "download_url": "https://files.pythonhosted.org/packages/0b/90/a8297daf2256fbfe8d93d6ce2bab7e53ae75362f2d1b21742c1e430ba8c5/fastenv-0.6.0.tar.gz",
    "platform": null,
    "description": "# \u2699\ufe0f fastenv \ud83d\ude80\n\n_Unified environment variable and settings management for FastAPI and beyond_\n\n[![PyPI](https://img.shields.io/pypi/v/fastenv?color=success)](https://pypi.org/project/fastenv/)\n[![coverage](https://img.shields.io/badge/coverage-100%25-brightgreen?logo=pytest&logoColor=white)](https://coverage.readthedocs.io/en/latest/)\n[![ci](https://github.com/br3ndonland/fastenv/workflows/ci/badge.svg)](https://github.com/br3ndonland/fastenv/actions/workflows/ci.yml)\n[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)\n\n## Description\n\nfastenv [\\[f\u00e6st i\u02d0 \u0259n v\\]](https://en.wikipedia.org/wiki/Help:IPA/English) is a Python package for managing environment variables and application settings.\n\n[Environment variables](https://en.wikipedia.org/wiki/Environment_variable) are key-value pairs provided to the operating system with syntax like `VARIABLE_NAME=value`. Collections of environment variables are stored in files commonly named _.env_ and called \"dotenv\" files. The Python standard library `os` module provides tools for reading environment variables, such as `os.getenv(\"VARIABLE_NAME\")`, but only handles strings, and doesn't include tools for file I/O. Additional logic is therefore needed to load environment variables from files before they can be read by Python, and to convert variables from strings to other Python types.\n\nThis project aims to:\n\n- [x] **Replace the aging [python-dotenv](https://github.com/theskumar/python-dotenv) project** with a similar, but more intuitive API, and modern syntax and tooling.\n- [x] **Implement asynchronous file I/O**. Reading and writing files can be done asynchronously with packages like [AnyIO](https://github.com/agronholm/anyio).\n- [x] **Implement asynchronous object storage integration**. Dotenv files are commonly kept in cloud object storage, but environment variable management packages typically don't integrate with object storage clients. Additional logic is therefore required to download _.env_ files from object storage prior to loading environment variables. This project aims to integrate with S3-compatible object storage, with a focus on downloading and uploading file objects.\n- [ ] **Read settings from TOML**. [It's all about _pyproject.toml_ now](https://snarky.ca/what-the-heck-is-pyproject-toml/). The Python community has pushed [PEP 517](https://www.python.org/dev/peps/pep-0517/) build tooling and [PEP 518](https://www.python.org/dev/peps/pep-0518/) build requirements forward, and [even `setuptools` has come around](https://setuptools.readthedocs.io/en/latest/build_meta.html). [PEP 621](https://www.python.org/dev/peps/pep-0621/) defined how to store package metadata and dependencies in _pyproject.toml_. Why don't we use the metadata from our _pyproject.toml_ files in our Python applications?\n- [ ] **Unify settings management for FastAPI**. [Uvicorn](https://www.uvicorn.org/), [Starlette](https://www.starlette.io/config/), and _[pydantic](https://pydantic-docs.helpmanual.io/usage/settings/)_ each have their own ways of loading environment variables and configuring application settings. This means that, when [configuring a FastAPI application](https://fastapi.tiangolo.com/advanced/settings/), there are at least three different settings management tools available, each with their own pros and cons. It would be helpful to address the limitations of each of these options, potentially providing a similar, improved API for each one.\n\nThe source code is 100% type-annotated and unit-tested.\n\nFor additional background on the project, see [www.bws.bio/projects/fastenv](https://www.bws.bio/projects/fastenv).\n\n## Quickstart\n\nInstall fastenv into a virtual environment:\n\n```sh\npython3 -m venv .venv\n. .venv/bin/activate\npython -m pip install fastenv\n```\n\nThen start a REPL session and try it out:\n\n```sh\n.venv \u276f python\n```\n\n```py\n# instantiate a DotEnv with a variable\nimport fastenv\ndotenv = fastenv.DotEnv(\"EXAMPLE_VARIABLE=example_value\")\n# add a variable with dictionary syntax\ndotenv[\"ANOTHER_VARIABLE\"] = \"another_value\"\n# delete a variable\ndel dotenv[\"ANOTHER_VARIABLE\"]\n# add a variable by calling the instance\ndotenv(\"I_THINK_FASTENV_IS=awesome\")\n# {'I_THINK_FASTENV_IS': 'awesome'}\n# return a dict of the variables in the DotEnv instance\ndict(dotenv)\n# {'EXAMPLE_VARIABLE': 'example_value', 'I_THINK_FASTENV_IS': 'awesome'}\n# save the DotEnv instance to a file\nimport anyio\nanyio.run(fastenv.dump_dotenv, dotenv)\n# Path('/path/to/this/dir/.env')\n```\n\nUse fastenv in your FastAPI app:\n\n```py\nfrom contextlib import asynccontextmanager\nfrom typing import AsyncIterator, TypedDict\n\nimport fastenv\nfrom fastapi import FastAPI, Request\n\n\nclass LifespanState(TypedDict):\n    settings: fastenv.DotEnv\n\n\n@asynccontextmanager\nasync def lifespan(_: FastAPI) -> AsyncIterator[LifespanState]:\n    \"\"\"Configure app lifespan.\n\n    https://fastapi.tiangolo.com/advanced/events/\n    https://www.starlette.io/lifespan/\n    \"\"\"\n    settings = await fastenv.load_dotenv(\".env\")\n    lifespan_state: LifespanState = {\"settings\": settings}\n    yield lifespan_state\n\n\napp = FastAPI(lifespan=lifespan)\n\n\n@app.get(\"/settings\")\nasync def get_settings(request: Request) -> dict[str, str]:\n    settings = request.state.settings\n    return dict(settings)\n```\n\n## Documentation\n\nDocumentation is built with [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/), deployed on [Vercel](https://vercel.com/), and available at [fastenv.bws.bio](https://fastenv.bws.bio) and [fastenv.vercel.app](https://fastenv.vercel.app).\n\n[Vercel build configuration](https://vercel.com/docs/build-step):\n\n- Build command: `python3 -m pip install mkdocs-material && mkdocs build --site-dir public`\n- Output directory: `public` (default)\n\n[Vercel site configuration](https://vercel.com/docs/configuration) is specified in _vercel.json_.\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Unified environment variable and settings management for FastAPI and beyond.",
    "version": "0.6.0",
    "project_urls": {
        "Documentation": "https://fastenv.bws.bio",
        "Homepage": "https://github.com/br3ndonland/fastenv",
        "Repository": "https://github.com/br3ndonland/fastenv"
    },
    "split_keywords": [
        "asgi",
        " dotenv",
        " environment variables",
        " fastapi",
        " settings"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "5715caf9c8fbaf3c072f0410af45c11b3d13b2c5a44fc4c86a16349583c8e176",
                "md5": "8fff8faf10669821660d7509d341f3bf",
                "sha256": "eab9b801ae45b531cadb6cf801a2157cba4f10b2e68fd7903a431f8bc3982766"
            },
            "downloads": -1,
            "filename": "fastenv-0.6.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "8fff8faf10669821660d7509d341f3bf",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4,>=3.9",
            "size": 17311,
            "upload_time": "2024-10-05T19:04:47",
            "upload_time_iso_8601": "2024-10-05T19:04:47.540545Z",
            "url": "https://files.pythonhosted.org/packages/57/15/caf9c8fbaf3c072f0410af45c11b3d13b2c5a44fc4c86a16349583c8e176/fastenv-0.6.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "0b90a8297daf2256fbfe8d93d6ce2bab7e53ae75362f2d1b21742c1e430ba8c5",
                "md5": "e9d8c4d97a81b07e0db446e13950d3fa",
                "sha256": "7c5e506fdf7f53273f6f614a072119aed3b2c2a0eab08e41d581e7c55741ff82"
            },
            "downloads": -1,
            "filename": "fastenv-0.6.0.tar.gz",
            "has_sig": false,
            "md5_digest": "e9d8c4d97a81b07e0db446e13950d3fa",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4,>=3.9",
            "size": 16972,
            "upload_time": "2024-10-05T19:04:49",
            "upload_time_iso_8601": "2024-10-05T19:04:49.152946Z",
            "url": "https://files.pythonhosted.org/packages/0b/90/a8297daf2256fbfe8d93d6ce2bab7e53ae75362f2d1b21742c1e430ba8c5/fastenv-0.6.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-10-05 19:04:49",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "br3ndonland",
    "github_project": "fastenv",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "fastenv"
}
        
Elapsed time: 0.50904s