envparse


Nameenvparse JSON
Version 0.2.0 PyPI version JSON
download
home_pagehttps://github.com/rconradharris/envparse
SummarySimple environment variable parsing
upload_time2015-12-19 17:24:03
maintainerNone
docs_urlNone
authorRick Harris
requires_pythonNone
licenseMIT
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI
coveralls test coverage No coveralls.
            envparse
========
``envparse`` is a simple utility to parse environment variables.

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.

``envparse`` 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 envparse

Manually::

    $ pip install git+https://github.com/rconradharris/envparse.git
    OR
    $ git clone https://github.com/rconradharris/envparse && cd envparse
    $ python setup.py install


Usage
-----
In your settings or configuration module, first either import the standard
parser or one with a schema::

    # Standard
    from envparse import env

    # Schema
    from envparse import Env
    env = Env(BOOLEAN_VAR=bool, LIST_VAR=dict(type=list, subtype=int))


``env`` can then be called in two ways:

* Type explicit: ``env('ENV_VAR_NAME', type=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::

    # Environment variable: MAIL_ENABLED=1

    mail_enabled = env('MAIL_ENABLED', type=bool)
    # OR mail_enabled = env.bool('MAIL_ENABLED')
    assert mail_enabled is True

Casting nested types::

    # Environment variable: FOO=1,2,3
    foo = env('FOO'), subtype=int)
    # OR: foo = env('FOO', type=list, subtype=int)
    # Note that there is no way to implicitly call subtypes.
    assert foo == [1, 2, 3]

Specifying defaults::

    # 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::

    # 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::

    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 type, subtype, and defaults
once::

    # 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(type=str, default='foo'),
              LIST_INT=dict(type=list, subtype=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: ``type``, ``subtype``, ``default``.


Pre- and Postprocessors
~~~~~~~~~~~~~~~~~~~~~~~
Preprocessors are callables that are run on the environment variable string
before any type casting takes place::

    # 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::

    # 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)::

    # This recurses up the directory tree until a file called '.env' is found.
    env.read_env()

    # Manually specifying a path
    env.read_env('/config/.myenv')

    # Values can be read as normal
    env.int('FOO')


Tests
-----
.. image:: https://secure.travis-ci.org/rconradharris/envparse.png?branch=master

To run the tests install tox::

    pip install tox

Then run them with::

    make test
            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/rconradharris/envparse",
    "name": "envparse",
    "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/2f/8d/bee8a59732c169a455627ff1557d0db180f7c352b0274480267ad3e46875/envparse-0.2.0.tar.gz",
    "platform": "any",
    "description": "envparse\n========\n``envparse`` is a simple utility to parse environment variables.\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``envparse`` 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 envparse\n\nManually::\n\n    $ pip install git+https://github.com/rconradharris/envparse.git\n    OR\n    $ git clone https://github.com/rconradharris/envparse && cd envparse\n    $ python setup.py install\n\n\nUsage\n-----\nIn your settings or configuration module, first either import the standard\nparser or one with a schema::\n\n    # Standard\n    from envparse import env\n\n    # Schema\n    from envparse import Env\n    env = Env(BOOLEAN_VAR=bool, LIST_VAR=dict(type=list, subtype=int))\n\n\n``env`` can then be called in two ways:\n\n* Type explicit: ``env('ENV_VAR_NAME', type=TYPE, ...)``\n* Type implicit (for Python builtin types only): ``env.TYPE('ENV_VAR_NAME', ...)``\nIf type is not specified, explicitly or implicitly, then the default\ntype is ``str``.\n\n\nCasting to a specified type::\n\n    # Environment variable: MAIL_ENABLED=1\n\n    mail_enabled = env('MAIL_ENABLED', type=bool)\n    # OR mail_enabled = env.bool('MAIL_ENABLED')\n    assert mail_enabled is True\n\nCasting nested types::\n\n    # Environment variable: FOO=1,2,3\n    foo = env('FOO'), subtype=int)\n    # OR: foo = env('FOO', type=list, subtype=int)\n    # Note that there is no way to implicitly call subtypes.\n    assert foo == [1, 2, 3]\n\nSpecifying defaults::\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    # 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    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 type, subtype, and defaults\nonce::\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(type=str, default='foo'),\n              LIST_INT=dict(type=list, subtype=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: ``type``, ``subtype``, ``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    # 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    # 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    # This recurses up the directory tree until a file called '.env' is found.\n    env.read_env()\n\n    # Manually specifying a path\n    env.read_env('/config/.myenv')\n\n    # Values can be read as normal\n    env.int('FOO')\n\n\nTests\n-----\n.. image:: https://secure.travis-ci.org/rconradharris/envparse.png?branch=master\n\nTo run the tests install tox::\n\n    pip install tox\n\nThen run them with::\n\n    make test",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Simple environment variable parsing",
    "version": "0.2.0",
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "md5": "c236ef17971aea885d6d934d7ddeb144",
                "sha256": "4f3b9a27bb55d27f124eb4adf006fec05e4588891c9a054a183a112645056eb7"
            },
            "downloads": -1,
            "filename": "envparse-0.2.0.tar.gz",
            "has_sig": false,
            "md5_digest": "c236ef17971aea885d6d934d7ddeb144",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 7576,
            "upload_time": "2015-12-19T17:24:03",
            "upload_time_iso_8601": "2015-12-19T17:24:03.234167Z",
            "url": "https://files.pythonhosted.org/packages/2f/8d/bee8a59732c169a455627ff1557d0db180f7c352b0274480267ad3e46875/envparse-0.2.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2015-12-19 17:24:03",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "github_user": "rconradharris",
    "github_project": "envparse",
    "travis_ci": true,
    "coveralls": false,
    "github_actions": false,
    "tox": true,
    "lcname": "envparse"
}
        
Elapsed time: 0.01377s