{ "info": { "author": "Jonas Grimfelt", "author_email": "grimen@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: POSIX", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 3", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development :: Libraries" ], "description": "\n# `config2` [![PyPI version](https://badge.fury.io/py/config2.svg)](https://badge.fury.io/py/config2) [![Build Status](https://travis-ci.com/grimen/python-config2.svg?branch=master)](https://travis-ci.com/grimen/python-config2) [![Coverage Status](https://codecov.io/gh/grimen/python-config2/branch/master/graph/badge.svg)](https://codecov.io/gh/grimen/python-config2)\n\n*Python environment configuration simplified.*\n\n\n## Introduction\n\n**Config2** (for Python) - which is highly inspired by [`node-config`](https://github.com/lorenwest/node-config) - organizes hierarchical configurations for your app deployments.\n\nIt lets you define a set of default parameters, and extend them for different deployment environments (development, qa, staging, production, etc.).\n\nConfigurations are stored in **configuration files** within your application, and can be overridden and extended by **environment variables**, **command line parameters**, or **external sources**.\n\nThis gives your application a consistent configuration interface shared among a growing list of npm modules also using node-config.\n\n**NOTE:** This project is more or less in pair with [`node-config`](https://github.com/lorenwest/node-config) implementation, with exception for some fluff that could be considered too much magic such as deployment specific *multi-instance deployments* which I so far haven't found any good motivation for, and some other questionable advanced features mentioned in the wiki pages.\n\n\n## Project Guidelines\n\n...based on [`node-config`](https://github.com/lorenwest/node-config) project guidelines:\n\n- *Simple* - Get started fast\n- ~~*Powerful* - For multi-node enterprise deployment~~ - excluded because [with power comes responsability](https://en.wikipedia.org/wiki/Principle_of_least_astonishment)\n- *Flexible* - Supporting multiple config file formats\n- *Lightweight* - Small file and memory footprint\n- *Predictable* - Well tested foundation for module and app developers\n\n\n## Install\n\nInstall using **pip**:\n\n```sh\n$ pip install config2\n```\n\n\n## Use\n\n**1.** Assuming we have a **python application** project...\n\n```\nsome_project\n\u2514\u2500\u2500 app.py\n```\n\n`app.py` - some app making serious **$$$**\n\n```python\n# business logic\nprint('$$$')\n```\n\n\n**2.** Let's add some environment specific **config files**...\n\n```\nsome_project\n\u2514\u2500\u2500 config\n \u251c\u2500\u2500 default.yml\n \u251c\u2500\u2500 development.yml\n \u251c\u2500\u2500 foo.yml\n \u2514\u2500\u2500 production.yml\n\u2514\u2500\u2500 app.py\n```\n\n`default.yml` - with some bogus nested settings shared for all environments (defaults)\n\n```yaml\na1: DEFAULT 1\na2:\n b1: [1, 2, 3]\n b2:\n - foo\n - bar\n b3:\n c1: 1\n c2: \"DEFAULT 2\"\n```\n\n`development.yml` - with some bogus nested settings overriden for `development` environment (overriden)\n\n```yaml\na2:\n b2:\n - DEV 1\n b3:\n c2: \"DEV 2\"\nsome_key_only_for_dev: true\n```\n\n`foo.yml` - with some bogus nested settings overriden for `foo` environment (overriden)\n\n```yaml\na2:\n b2:\n - FOO 1\n b3:\n c2: \"FOO 2\"\nsome_key_only_for_foo: true\n```\n\n`production.yml` - with some bogus nested settings overriden for `production` environment (overriden)\n\n```yaml\na2:\n b2:\n - PROD 1\n b3:\n c2: \"PROD 2\"\nsome_key_only_for_prod: true\n```\n\n\n**3.** Let's now **run the app** using **various environments**...\n\n`$ python app.py`\n\n```python\nfrom config2.config import config\n\nconfig.get_env() # => None\nconfig.get() # => {'a1': 'DEFAULT 1', 'a2': {'b1': [1, 2, 3], 'b2': ['foo', 'bar'], 'b3': {'c1': 1, 'c2': 'DEFAULT 2'}}}\n\nconfig.a1 # => 'DEFAULT 1'\nconfig.a2 # => {'b1': [1, 2, 3], 'b2': ['foo', 'bar'], 'b3': {'c1': 1, 'c2': 'DEFAULT 2'}}\nconfig.a2.b3.c2 # => 'DEFAULT 2'\n\nprint('$$$')\n```\n\n`$ ENV=development python app.py`\n\n```python\nfrom config2.config import config\n\nconfig.get_env() # => 'development'\nconfig.get() # => {'a1': 'DEFAULT 1', 'a2': {'b1': [1, 2, 3], 'b2': ['DEV 1'], 'b3': {'c1': 1, 'c2': 'DEV 2'}}, 'some_key_only_for_dev': True}\n\nconfig.a1 # => 'DEFAULT 1'\nconfig.a2 # => {'b1': [1, 2, 3], 'b2': ['DEV 1'], 'b3': {'c1': 1, 'c2': 'DEV 2'}}\nconfig.a2.b3.c2 # => 'DEV was here 2'\n\nconfig.some_key_only_for_dev # => True\n\nconfig.some_key_only_for_foo # => AttributeError\nconfig.some_key_only_for_prod # => AttributeError\n\nprint('$$$')\n```\n\n`$ ENV=foo python app.py`\n\n```python\nfrom config2.config import config\n\nconfig.get_env() # => 'foo'\nconfig.get() # => {'a1': 'DEFAULT 1', 'a2': {'b1': [1, 2, 3], 'b2': ['FOO 1'], 'b3': {'c1': 1, 'c2': 'FOO 2'}}, 'some_key_only_for_foo': True}\n\nconfig.a1 # => 'DEFAULT 1'\nconfig.a2 # => {'b1': [1, 2, 3], 'b2': ['FOO 1'], 'b3': {'c1': 1, 'c2': 'FOO 2'}}\nconfig.a2.b3.c2 # => 'FOO was here 2'\n\nconfig.key_only_for_foo # => True\n\nconfig.some_key_only_for_dev # => AttributeError\nconfig.some_key_only_for_prod # => AttributeError\n\nprint('$$$')\n```\n\n`$ ENV=production python app.py`\n\n```python\nfrom config2.config import config\n\nconfig.get_env() # => 'production'\nconfig.get() # => {'a1': 'DEFAULT 1', 'a2': {'b1': [1, 2, 3], 'b2': ['PROD 1'], 'b3': {'c1': 1, 'c2': 'PROD 2'}}, 'some_key_only_for_foo': True}\n\nconfig.a1 # => 'DEFAULT 1'\nconfig.a2 # => {'b1': [1, 2, 3], 'b2': ['PROD 1'], 'b3': {'c1': 1, 'c2': 'PROD 2'}}\nconfig.a2.b3.c2 # => 'PROD was here 2'\n\nconfig.some_key_only_for_prod # => True\n\nconfig.some_key_only_for_dev # => AttributeError\nconfig.some_key_only_for_foo # => AttributeError\n\nprint('$$$')\n```\n\netc.\n\n\n**4.** Optionally, let's now introduce custom **config environment variables**...\n\n\n```\nsome_project\n\u2514\u2500\u2500 config\n \u251c\u2500\u2500 custom-environment-variables.yml\n \u251c\u2500\u2500 default.yml\n \u251c\u2500\u2500 development.yml\n \u251c\u2500\u2500 foo.yml\n \u2514\u2500\u2500 production.yml\n\u2514\u2500\u2500 app.py\n```\n\n`custom-environment-variables.yml` - with mappings of config keys to environment variables\n\n```yaml\na1: A1\na2:\n b3:\n c2: C2\n```\n\n**5.** Let's now **run the app** using **custom environment variables** to override config...\n\n`$ A1=x C2=y python app.py`\n\n```python\nfrom config2.config import config\n\nconfig.get_env() # => None\nconfig.get() # => {'a1': 'x', 'a2': {'b1': [1, 2, 3], 'b2': ['foo', 'bar'], 'b3': {'c1': 1, 'c2': 'y'}}}\n\nconfig.a1 # => 'x'\nconfig.a2 # => {'b1': [1, 2, 3], 'b2': ['foo', 'bar'], 'b3': {'c1': 1, 'c2': 'y'}}\nconfig.a2.b3.c2 # => 'y'\n\nprint('$$$')\n```\n\n\n## Test\n\nClone down source code:\n\n```sh\n$ make install\n```\n\nRun **colorful tests**, with only native environment (dependency sandboxing up to you):\n\n```sh\n$ make test\n```\n\nRun **less colorful tests**, with **multi-environment** (using **tox**):\n\n```sh\n$ make test-tox\n```\n\n\n## About\n\nThis project was mainly initiated - in lack of existing alternatives - to be used at our work at **[Markable.ai](https://markable.ai)** to have common code conventions between various programming environments where **Python** (research, CV, AI) and **Node.js** (I/O, APIs, UIs, scripts) currently are most used.\n\n\n## License\n\nReleased under the MIT license.\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "https://github.com/grimen/python-config2", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/grimen/python-config2", "keywords": "config,configuration,configurations,settings,env,environment,environments,application,node-config,python-config", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "config2", "package_url": "https://pypi.org/project/config2/", "platform": "", "project_url": "https://pypi.org/project/config2/", "project_urls": { "Download": "https://github.com/grimen/python-config2", "Homepage": "https://github.com/grimen/python-config2", "bugs": "https://github.com/grimen/python-config2/issues", "repository": "https://github.com/grimen/python-config2" }, "release_url": "https://pypi.org/project/config2/0.3.2/", "requires_dist": [ "setupextras (>=0.1.5)", "rootpath (>=0.1.1)", "attributedict (>=0.3.0)", "inspecta (>=0.1.3)", "mybad (>=0.1.4)", "deepmerge (>=0.0.5)", "pyyaml (>=5.1)", "six (>=1.12.0)", "colour-runner (>=0.0.5)", "deepdiff (>=3.3.0)", "tox (>=3.0.0)", "coverage (>=4.5.2)", "codecov (>=2.0.15)" ], "requires_python": "", "summary": "Python application configuration - highly inspired by `node-config`.", "version": "0.3.2" }, "last_serial": 5249818, "releases": { "0.1.3": [ { "comment_text": "", "digests": { "md5": "02448773082a419a859d378441001c28", "sha256": "3286a7af32eba6caf05a65944829f55858168912e8313d7860914eb69a57fb2a" }, "downloads": -1, "filename": "config2-0.1.3-py2-none-any.whl", "has_sig": false, "md5_digest": "02448773082a419a859d378441001c28", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 28043, "upload_time": "2018-06-29T01:04:54", "url": "https://files.pythonhosted.org/packages/1f/07/ce6805f5eb0a948bda9e700c165f5458f46a019b4491d0ec72ce58317e22/config2-0.1.3-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "a2a1e5c216d62be77c3895f156603ee1", "sha256": "9338bf2ec806b74459832880c8645e88e48892f30abeb29559f8dc9c56f5f323" }, "downloads": -1, "filename": "config2-0.1.3.tar.gz", "has_sig": false, "md5_digest": "a2a1e5c216d62be77c3895f156603ee1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20314, "upload_time": "2018-06-29T01:04:55", "url": "https://files.pythonhosted.org/packages/8f/d7/1c0d95313020001e9888e7a53aa42cc1d64b7c668ecdf1b295a0f2a65562/config2-0.1.3.tar.gz" } ], "0.1.4": [ { "comment_text": "", "digests": { "md5": "a367e4525e4cf04605a01fc44148cada", "sha256": "5da16ac0a7146b43c8c9d25fb80e5eff2a8a46f307be8fe13ea11a890c9ffeae" }, "downloads": -1, "filename": "config2-0.1.4-py2-none-any.whl", "has_sig": false, "md5_digest": "a367e4525e4cf04605a01fc44148cada", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 29822, "upload_time": "2018-08-03T02:44:15", "url": "https://files.pythonhosted.org/packages/03/ab/896a01a4b72115493c6e5b92c4bd82b6eefb9e00dbb4a5bf3db2baad0ef8/config2-0.1.4-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "99824d0d36e5607f88f3abaeb7e74e1d", "sha256": "3266f0bcc5ca3a29892bf3fa9afba73ff4736319da86e7800150a86733251846" }, "downloads": -1, "filename": "config2-0.1.4.tar.gz", "has_sig": false, "md5_digest": "99824d0d36e5607f88f3abaeb7e74e1d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20787, "upload_time": "2018-08-03T02:44:16", "url": "https://files.pythonhosted.org/packages/c8/92/de0e8824b4228e10c369892c602ed28961b5a31148ed6d67a622721405e3/config2-0.1.4.tar.gz" } ], "0.1.5": [ { "comment_text": "", "digests": { "md5": "cabb5a7c2b038f4b1d2bc486f53f43b2", "sha256": "a6a83a398c217204db7a3827baefe73445bbc2a053d0a023c31822eac2c5197f" }, "downloads": -1, "filename": "config2-0.1.5-py3-none-any.whl", "has_sig": false, "md5_digest": "cabb5a7c2b038f4b1d2bc486f53f43b2", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 24135, "upload_time": "2018-10-13T04:54:40", "url": "https://files.pythonhosted.org/packages/fb/10/918cd6228ad8191137508dc04b0e12aa080e793f7a0efaed26d7b6911722/config2-0.1.5-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "06c70ff1bf303cb1c48bda970f20679f", "sha256": "e8dd9eca09b89ce6d3f5d6dbdf92bd66920aa2d2da8ce87985819b49330642ca" }, "downloads": -1, "filename": "config2-0.1.5.tar.gz", "has_sig": false, "md5_digest": "06c70ff1bf303cb1c48bda970f20679f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20454, "upload_time": "2018-10-13T04:54:42", "url": "https://files.pythonhosted.org/packages/93/e0/101a980d2c53fcf929276e85598c5cef266f626064e5a0270366ef5a66c7/config2-0.1.5.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "12c0e63bae6db4a5afbbc71c53c63adc", "sha256": "aee98e589faa2715e2ed3e2cca0c8f828f39e98918d8f2040ee7063e74d9fcf5" }, "downloads": -1, "filename": "config2-0.2.0-py2-none-any.whl", "has_sig": false, "md5_digest": "12c0e63bae6db4a5afbbc71c53c63adc", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 29660, "upload_time": "2018-11-14T15:59:13", "url": "https://files.pythonhosted.org/packages/4f/2d/e556a7a4bb8d7095cb253dd83b5033327e23310771f5e78de7dffe882938/config2-0.2.0-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "05cb8fbc34a5f18c0b8daec8a794f123", "sha256": "8a28f1a7b18b355267f59df661162bf71966b6f7eda5651f6302cd9a945bd2a3" }, "downloads": -1, "filename": "config2-0.2.0.tar.gz", "has_sig": false, "md5_digest": "05cb8fbc34a5f18c0b8daec8a794f123", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21471, "upload_time": "2018-11-14T15:59:14", "url": "https://files.pythonhosted.org/packages/f1/a3/fefe51c16cb3d8e152aca1164ef6fb99c3a01c638cad01a83f6d101959a2/config2-0.2.0.tar.gz" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "73c48838883eb95b720f4e349a0cb89e", "sha256": "065606db46fc3cfe706c0c29a15e16040b0672ff28086b5765ddea4037c357f2" }, "downloads": -1, "filename": "config2-0.3.0-py3-none-any.whl", "has_sig": false, "md5_digest": "73c48838883eb95b720f4e349a0cb89e", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 28337, "upload_time": "2019-01-17T08:30:36", "url": "https://files.pythonhosted.org/packages/b4/88/1e77844527aaf4c141b2cea65bafaa5c91b95c7b4004494019a4920ecf90/config2-0.3.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "20f26150000442baed9800cf49940074", "sha256": "ebf53ca22ba7434a1d716a6a3cce73039c47589dcb7980a2edb004475ec71b60" }, "downloads": -1, "filename": "config2-0.3.0.tar.gz", "has_sig": false, "md5_digest": "20f26150000442baed9800cf49940074", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22654, "upload_time": "2019-01-17T08:30:37", "url": "https://files.pythonhosted.org/packages/a8/ff/3f891c4af4937fdc2479bd62c55e465bb3c125c31201bb5865315e0bfef2/config2-0.3.0.tar.gz" } ], "0.3.1": [ { "comment_text": "", "digests": { "md5": "0c339097b1e3f08eda22abd59372c3e1", "sha256": "e9db3aaa9c4f7ad11946cc9c5bea62d20204014b9d3c01020aeda74eff17ee89" }, "downloads": -1, "filename": "config2-0.3.1-py3-none-any.whl", "has_sig": false, "md5_digest": "0c339097b1e3f08eda22abd59372c3e1", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 32803, "upload_time": "2019-03-10T11:06:52", "url": "https://files.pythonhosted.org/packages/cf/7b/b21fa19de836e57ca4f37bec81411cc2241a9fb6680a41b6ef83085d96ca/config2-0.3.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ab63fc6481ad410547bbf07a1845c45e", "sha256": "a3843856656c0d1ef6b346fcefaf8a2c5332b46f6edde4475a8644ab136ba1eb" }, "downloads": -1, "filename": "config2-0.3.1.tar.gz", "has_sig": false, "md5_digest": "ab63fc6481ad410547bbf07a1845c45e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22789, "upload_time": "2019-03-10T11:06:54", "url": "https://files.pythonhosted.org/packages/9d/89/8a977726de81c3f1ee08dd1ba10a441458857c34a64bcc08be23cbc780fe/config2-0.3.1.tar.gz" } ], "0.3.2": [ { "comment_text": "", "digests": { "md5": "c4f064a9c3f01feb0258c9c99f691c68", "sha256": "52fa6f70f16df59087e0bdf210fb2fd251452f5701e4668b34528e20388cc840" }, "downloads": -1, "filename": "config2-0.3.2-py3-none-any.whl", "has_sig": false, "md5_digest": "c4f064a9c3f01feb0258c9c99f691c68", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 38511, "upload_time": "2019-05-09T22:49:45", "url": "https://files.pythonhosted.org/packages/f4/a3/92a2693d7def37f0785b91fa8a5fa80023419c23e927db80e1f36d82d439/config2-0.3.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8d30d283ad62c3b86c6ad4c9829dfd21", "sha256": "6b3406b45a8aa86f25225f880dfdff523b01203e867501ed6c772b736a9a74c7" }, "downloads": -1, "filename": "config2-0.3.2.tar.gz", "has_sig": false, "md5_digest": "8d30d283ad62c3b86c6ad4c9829dfd21", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22438, "upload_time": "2019-05-09T22:49:46", "url": "https://files.pythonhosted.org/packages/df/ee/c0548078db70217616ac355b938a1be0a9d8c5427844ad719eb407229237/config2-0.3.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "c4f064a9c3f01feb0258c9c99f691c68", "sha256": "52fa6f70f16df59087e0bdf210fb2fd251452f5701e4668b34528e20388cc840" }, "downloads": -1, "filename": "config2-0.3.2-py3-none-any.whl", "has_sig": false, "md5_digest": "c4f064a9c3f01feb0258c9c99f691c68", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 38511, "upload_time": "2019-05-09T22:49:45", "url": "https://files.pythonhosted.org/packages/f4/a3/92a2693d7def37f0785b91fa8a5fa80023419c23e927db80e1f36d82d439/config2-0.3.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8d30d283ad62c3b86c6ad4c9829dfd21", "sha256": "6b3406b45a8aa86f25225f880dfdff523b01203e867501ed6c772b736a9a74c7" }, "downloads": -1, "filename": "config2-0.3.2.tar.gz", "has_sig": false, "md5_digest": "8d30d283ad62c3b86c6ad4c9829dfd21", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22438, "upload_time": "2019-05-09T22:49:46", "url": "https://files.pythonhosted.org/packages/df/ee/c0548078db70217616ac355b938a1be0a9d8c5427844ad719eb407229237/config2-0.3.2.tar.gz" } ] }