envparse2
=========
``envparse2`` is a simple utility to parse environment variables.
NOTE: `envparse2` is a fork of `envparse` which is no longer maintained, to check
original author and code visit <https://github.com/rconradharris/envparse.git>
If you use Heroku and/or subscribe to the tenets of the
`12 Factor App <http://www.12factor.net/>`_
you'll be using a lot of environment variable-based configuration in your app.
``os.environ`` is a great choice to start off with but over time you'll find
yourself duplicating quite a bit of code around handling raw environment
variables.
``envparse2`` aims to eliminate this duplicated, often inconsistent parsing
code and instead provide a single, easy-to-use wrapper.
Ideas, and code portions, have been taken from `django-environ
<https://github.com/joke2k/django-environ>`_ project but made framework
agnostic.
Installing
----------
Through PyPI::
$ pip install envparse2
Usage
-----
In your settings or configuration module, first either import the standard
parser or one with a schema:
.. code-block:: python
# Standard
from envparse2 import env
# Schema
from envparse2 import Env
env = Env(BOOLEAN_VAR=bool, LIST_VAR=dict(cast=list, subcast=int))
``env`` can then be called in two ways:
* Type explicit: ``env('ENV_VAR_NAME', cast=TYPE, ...)``
* Type implicit (for Python builtin types only): ``env.TYPE('ENV_VAR_NAME', ...)``
If type is not specified, explicitly or implicitly, then the default
type is ``str``.
Casting to a specified type:
.. code-block:: python
# Environment variable: MAIL_ENABLED=1
mail_enabled = env('MAIL_ENABLED', cast=bool)
# OR mail_enabled = env.bool('MAIL_ENABLED')
assert mail_enabled is True
Casting nested types:
.. code-block:: python
# Environment variable: FOO=1,2,3
foo = env('FOO'), subcast=int)
# OR: foo = env('FOO', cast=list, subcast=int)
# Note that there is no way to implicitly call subcast.
assert foo == [1, 2, 3]
Specifying defaults:
.. code-block:: python
# Environment variable MAX_ROWS has not been defined
max_rows = env.int('MAX_ROWS', default=100)
assert max_rows == 100
Proxying values, useful in Heroku for wiring up the environment variables they
provide to the ones that your app actually uses:
.. code-block:: python
# Environment variables: MAILGUN_SMTP_LOGIN=foo,
# SMTP_LOGIN='{{MAILGUN_SMTP_LOGIN}}'
smtp_login = env('SMTP_LOGIN')
assert smtp_login == 'foo'
Now if you switch to using Mandrill as an email provider, instead of having to
modify your app, you can simply make a configuration change:
.. code-block:: bash
SMTP_LOGIN='{{MANDRILL_UESRNAME}}'
There are also a few convenience methods:
* ``env.json``: parses JSON and returns a dict.
* ``env.url``: parses a url and returns a ``urlparse.ParseResult`` object.
Type specific notes:
* list: the expected environment variable format is ``FOO=1,2,3`` and may
contain spaces between the commas as well as preceding or trailing whitespace.
* dict: the expected environment variable format is ``FOO='key1=val1,
key2=val2``. Spaces are also allowed.
* json: a regular JSON string such as ``FOO='{"foo": "bar"}'`` is expected.
Schemas
~~~~~~~
Define a schema so you can only need to provide the cast, subcast, and defaults
once:
.. code-block:: python
# Environment variables: MAIL_ENABLED=0, LIST_INT='1,2,3'
# Bind schema to Env object to get schema-based lookups
env = Env(MAIL_ENABLED=bool, SMTP_LOGIN=dict(cast=str, default='foo'),
LIST_INT=dict(cast=list, subcast=int))
assert env('MAIL_ENABLED') is False
assert env('SMTP_LOGIN') == 'foo' # Not defined so uses default
assert env('LIST_INT') == [1, 2, 3]
The ``Env`` constructor takes values in the form of either: ``VAR_NAME=type``
or ``VAR_NAME=dict`` where ``dict`` is a dictionary with either one or more of
the following keys specified: ``cast``, ``subcast``, ``default``.
Pre- and Postprocessors
~~~~~~~~~~~~~~~~~~~~~~~
Preprocessors are callables that are run on the environment variable string
before any type casting takes place:
.. code-block:: python
# Environment variables: FOO=bar
# Preprocessor to change variable to uppercase
to_upper = lambda v: v.upper()
foo = env('FOO', preprocessor=to_upper)
assert foo == 'BAR'
Postprocessors are callables that are run after the type casting takes place.
An example of one might be returning a datastructure expected by a framework:
.. code-block:: python
# Environment variable: REDIS_URL='redis://:redispass@127.0.0.1:6379/0'
def django_redis(url):
return {'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': '{}:{}:{}'.format(url.hostname, url.port, url.path.strip('/')),
'OPTIONS': {'PASSWORD': url.password}}
redis_config = env('REDIS_URL', postprocessor=django_redis)
assert redis_config == {'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': '127.0.0.1:6379:0', 'OPTIONS': {'PASSWORD': 'redispass'}}
Environment File
~~~~~~~~~~~~~~~~
Read from a .env file (line delimited KEY=VALUE):
.. code-block:: python
# This recurses up the directory tree until a file called '.env' is found.
env.read_envfile()
# Manually specifying a path
env.read_envfile('/config/.myenv')
# Values can be read as normal
env.int('FOO')
Raw data
{
"_id": null,
"home_page": "https://github.com/beregond/envparse2",
"name": "envparse2",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": null,
"author": "Rick Harris",
"author_email": "rconradharris@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/40/37/6c8dbac240ddd65b6bb9c8519ba203afb51b67646b1630df710460cdd8d1/envparse2-0.3.0.tar.gz",
"platform": "any",
"description": "envparse2\n=========\n\n``envparse2`` is a simple utility to parse environment variables.\n\nNOTE: `envparse2` is a fork of `envparse` which is no longer maintained, to check\noriginal author and code visit <https://github.com/rconradharris/envparse.git>\n\nIf you use Heroku and/or subscribe to the tenets of the\n`12 Factor App <http://www.12factor.net/>`_\nyou'll be using a lot of environment variable-based configuration in your app.\n``os.environ`` is a great choice to start off with but over time you'll find\nyourself duplicating quite a bit of code around handling raw environment\nvariables.\n\n``envparse2`` aims to eliminate this duplicated, often inconsistent parsing\ncode and instead provide a single, easy-to-use wrapper.\n\nIdeas, and code portions, have been taken from `django-environ\n<https://github.com/joke2k/django-environ>`_ project but made framework\nagnostic.\n\n\nInstalling\n----------\nThrough PyPI::\n\n $ pip install envparse2\n\nUsage\n-----\nIn your settings or configuration module, first either import the standard\nparser or one with a schema:\n\n.. code-block:: python\n\n # Standard\n from envparse2 import env\n\n # Schema\n from envparse2 import Env\n env = Env(BOOLEAN_VAR=bool, LIST_VAR=dict(cast=list, subcast=int))\n\n\n``env`` can then be called in two ways:\n\n* Type explicit: ``env('ENV_VAR_NAME', cast=TYPE, ...)``\n* Type implicit (for Python builtin types only): ``env.TYPE('ENV_VAR_NAME', ...)``\n If type is not specified, explicitly or implicitly, then the default\n type is ``str``.\n\n\nCasting to a specified type:\n\n.. code-block:: python\n\n # Environment variable: MAIL_ENABLED=1\n\n mail_enabled = env('MAIL_ENABLED', cast=bool)\n # OR mail_enabled = env.bool('MAIL_ENABLED')\n assert mail_enabled is True\n\nCasting nested types:\n\n.. code-block:: python\n\n # Environment variable: FOO=1,2,3\n foo = env('FOO'), subcast=int)\n # OR: foo = env('FOO', cast=list, subcast=int)\n # Note that there is no way to implicitly call subcast.\n assert foo == [1, 2, 3]\n\nSpecifying defaults:\n\n.. code-block:: python\n\n # Environment variable MAX_ROWS has not been defined\n\n max_rows = env.int('MAX_ROWS', default=100)\n assert max_rows == 100\n\nProxying values, useful in Heroku for wiring up the environment variables they\nprovide to the ones that your app actually uses:\n\n.. code-block:: python\n\n # Environment variables: MAILGUN_SMTP_LOGIN=foo,\n # SMTP_LOGIN='{{MAILGUN_SMTP_LOGIN}}'\n\n smtp_login = env('SMTP_LOGIN')\n assert smtp_login == 'foo'\n\nNow if you switch to using Mandrill as an email provider, instead of having to\nmodify your app, you can simply make a configuration change:\n\n.. code-block:: bash\n\n SMTP_LOGIN='{{MANDRILL_UESRNAME}}'\n\nThere are also a few convenience methods:\n\n* ``env.json``: parses JSON and returns a dict.\n* ``env.url``: parses a url and returns a ``urlparse.ParseResult`` object.\n\n\nType specific notes:\n\n* list: the expected environment variable format is ``FOO=1,2,3`` and may\n contain spaces between the commas as well as preceding or trailing whitespace.\n* dict: the expected environment variable format is ``FOO='key1=val1,\n key2=val2``. Spaces are also allowed.\n* json: a regular JSON string such as ``FOO='{\"foo\": \"bar\"}'`` is expected.\n\n\nSchemas\n~~~~~~~\nDefine a schema so you can only need to provide the cast, subcast, and defaults\nonce:\n\n.. code-block:: python\n\n # Environment variables: MAIL_ENABLED=0, LIST_INT='1,2,3'\n\n # Bind schema to Env object to get schema-based lookups\n env = Env(MAIL_ENABLED=bool, SMTP_LOGIN=dict(cast=str, default='foo'),\n LIST_INT=dict(cast=list, subcast=int))\n assert env('MAIL_ENABLED') is False\n assert env('SMTP_LOGIN') == 'foo' # Not defined so uses default\n assert env('LIST_INT') == [1, 2, 3]\n\nThe ``Env`` constructor takes values in the form of either: ``VAR_NAME=type``\nor ``VAR_NAME=dict`` where ``dict`` is a dictionary with either one or more of\nthe following keys specified: ``cast``, ``subcast``, ``default``.\n\n\nPre- and Postprocessors\n~~~~~~~~~~~~~~~~~~~~~~~\nPreprocessors are callables that are run on the environment variable string\nbefore any type casting takes place:\n\n.. code-block:: python\n\n # Environment variables: FOO=bar\n\n # Preprocessor to change variable to uppercase\n to_upper = lambda v: v.upper()\n foo = env('FOO', preprocessor=to_upper)\n assert foo == 'BAR'\n\nPostprocessors are callables that are run after the type casting takes place.\nAn example of one might be returning a datastructure expected by a framework:\n\n.. code-block:: python\n\n # Environment variable: REDIS_URL='redis://:redispass@127.0.0.1:6379/0'\n def django_redis(url):\n return {'BACKEND': 'django_redis.cache.RedisCache',\n 'LOCATION': '{}:{}:{}'.format(url.hostname, url.port, url.path.strip('/')),\n 'OPTIONS': {'PASSWORD': url.password}}\n\n redis_config = env('REDIS_URL', postprocessor=django_redis)\n assert redis_config == {'BACKEND': 'django_redis.cache.RedisCache',\n 'LOCATION': '127.0.0.1:6379:0', 'OPTIONS': {'PASSWORD': 'redispass'}}\n\n\nEnvironment File\n~~~~~~~~~~~~~~~~\nRead from a .env file (line delimited KEY=VALUE):\n\n.. code-block:: python\n\n # This recurses up the directory tree until a file called '.env' is found.\n env.read_envfile()\n\n # Manually specifying a path\n env.read_envfile('/config/.myenv')\n\n # Values can be read as normal\n env.int('FOO')\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Simple environment variable parsing",
"version": "0.3.0",
"project_urls": {
"Homepage": "https://github.com/beregond/envparse2"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "09a7b084d7824a8ecc3d51cdf357dfe7263f75d1475c48fee6f0fa45e3f9881a",
"md5": "ee825dbbd6fd6855f47ebd21c4df51e9",
"sha256": "99a123f8ccaedf762d8f475ae802aeaa9f9699e0f4ecc3de2ec7dbe1aca1cc72"
},
"downloads": -1,
"filename": "envparse2-0.3.0-py2.py3-none-any.whl",
"has_sig": false,
"md5_digest": "ee825dbbd6fd6855f47ebd21c4df51e9",
"packagetype": "bdist_wheel",
"python_version": "py2.py3",
"requires_python": null,
"size": 6803,
"upload_time": "2024-07-29T13:54:06",
"upload_time_iso_8601": "2024-07-29T13:54:06.460224Z",
"url": "https://files.pythonhosted.org/packages/09/a7/b084d7824a8ecc3d51cdf357dfe7263f75d1475c48fee6f0fa45e3f9881a/envparse2-0.3.0-py2.py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "40376c8dbac240ddd65b6bb9c8519ba203afb51b67646b1630df710460cdd8d1",
"md5": "b2c7567c7d4bb4b773f9b0f84a33499e",
"sha256": "119ea05995f6a137a02ccf1deff5b34e6dacaba79b594c5837a7879cfa3c61ce"
},
"downloads": -1,
"filename": "envparse2-0.3.0.tar.gz",
"has_sig": false,
"md5_digest": "b2c7567c7d4bb4b773f9b0f84a33499e",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 8047,
"upload_time": "2024-07-29T13:54:07",
"upload_time_iso_8601": "2024-07-29T13:54:07.903569Z",
"url": "https://files.pythonhosted.org/packages/40/37/6c8dbac240ddd65b6bb9c8519ba203afb51b67646b1630df710460cdd8d1/envparse2-0.3.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-07-29 13:54:07",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "beregond",
"github_project": "envparse2",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "envparse2"
}