{ "info": { "author": "Amine Ben Asker", "author_email": "ben.asker.amine@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Topic :: Software Development :: Build Tools" ], "description": "[![Latest version on](https://badge.fury.io/py/config42.svg)](https://badge.fury.io/py/config42)\n[![Supported Python versions](https://img.shields.io/pypi/pyversions/config42.svg)](https://pypi.org/project/config42/)\n[![Travis Pipelines build status](https://img.shields.io/travis/com/yurilaaziz/config42.svg)](https://travis-ci.com/yurilaaziz/config42/)\n[![codecov](https://codecov.io/gh/yurilaaziz/config42/branch/master/graph/badge.svg)](https://codecov.io/gh/yurilaaziz/config42)\n# Config42\n\nConfig42 is a complete configuration reader and manager. It aims to read the configuration from different sources: a memory Dict object, an external file ( YAML, JSON, INI, PYTHON Object ), an SQL database (Postgres, MySQL, Oracle) \nalternatively, Key-value data store ( Etcd )\n\nIt is designed to be extensible. Different handlers could support another data store. \nAll PR are welcome. \n\n## Related blog posts\n\n* [Easy configuration management with config42 for Python applications](https://medium.com/@asker_amine/easy-configuration-management-with-config42-for-python-applications-8e90bf4c6450)\n\n## Install \n\n**From sources:** (Bleeding edge)\n\n`pip install git+https://github.com/yurilaaziz/config42`\n\n**From PyPi:** (Stable)\n\n`pip install config42`\n\n## Getting started\nConfig42 abstract loading configuration complexity. Let config42 manage your configuration for you.\n\n### Using environment variables \nMost of the containerised applications change behaviour from environment variables to change their behaviour. config42 handle it easily.\n\nHere a working sample [examples/docker](examples/docker)\n\n```python\nfrom config42 import ConfigManager\nenv_config = ConfigManager(prefix=\"MYAPP\")\n# Access to configuration via the ConfigManager getter\nprint(\"username : {}\".format(env_config.get('username')))\nprint(\"nested key : {}\".format(env_config.get('secret.one')))\n```\n\nExport variables to system environment \n```bash\nexport MYAPP_USERNAME=yuri\nexport MYAPP_SECRET_ONE=password\npython app.py\n```\n\nExport variables to process environment \n\n```bash\nMYAPP_USERNAME=yuri2 python app.py\n```\n\nOnce you build you docker image, you may run the application by export variables into the container environment\n```bash\ndocker run -e MYAPP_USERNAME=yuri -e MYAPP_SECRET_ONE=secret testconfig42:latest\n```\n\n\n### Using Etcd Handler \nTo load configuration from Etcd data store, you need to specify the *keyspace* where the configuration is located, Etcd host(s) and port(s).\n\n```python\nfrom config42 import ConfigManager\nfrom config42.handlers import Etcd\n\nconfig = ConfigManager(handler=Etcd, keyspace='/config')\n# config = ConfigManager(handler=Etcd, keyspace='/config', port=4001)\n# config = ConfigManager(handler=Etcd, keyspace='/config', host='127.0.0.1', port=4001)\n# config = ConfigManager(handler=Etcd, keyspace='/config', host=(('127.0.0.1', 4001), ('127.0.0.1', 4002), ('127.0.0.1', 4003)))\n\n```\nNote : Etcd handler use [python-etcd](https://github.com/jplana/python-etcd) client \nAll args after keyspace are passed to Etcd.Client class. \n\n\n### Using Filehandler, Load configuration from file \n```python\nfrom pprint import pprint\nfrom config42 import ConfigManager\nfrom config42.handlers import FileHandler\n\n# Yaml files\nconfig = ConfigManager(handler=FileHandler, path='files/config1.yml')\n#config = ConfigManager(handler=FileHandler, path='files/config1.yaml')\n\n# Json file \n#config = ConfigManager(handler=FileHandler, path='files/config1.json')\n\n#INI structure support only one level of nesting (Sections = { key: value }) \n#config = ConfigManager(handler=FileHandler, path='files/config.ini')\n\nCONFIG = config.as_dict()\n\nprint(\"Configuration has been loaded\")\npprint(CONFIG)\n\n# Access to configuration via the ConfigManager getter\nprint(\"application_name : {}\".format(config.get('application_name')))\nprint(\"nested key : {}\".format(config.get('nested.nestedkey.key2')))\n\n# Access to configuration via the as dict utility; it will dump configuration file to data store if updated\nprint(\"user : {}\".format(config.as_dict()['user']))\n\n# Access to configuration via the classic CONFIG global variable\nprint(\"application_name : {}\".format(CONFIG['application_name']))\nprint(\"nested key : {}\".format(CONFIG['nested']['nestedkey']['key2']))\n````\n\n### Using argparse, Load configuration from commandline parameters (sys.argv)\n\n```python\nfrom config42 import ConfigManager\nfrom config42.handlers.argparse import Argparse\n\nschema = [\n dict(key=\"user\", description=\"username\"),\n dict(key=\"verbosity\", description=\"verbosity level\", choices=[\"debug\", \"info\"]),\n\n]\nconfig = ConfigManager(handler=Argparse, schema=schema)\n```\nPlease take a look to the [example using Argparse's handler](examples/cmdline.py)\n\n## Real use case\nBelow is a real use from Instabot-Py project that uses this library as a configuration manager.\n\nconfig42 handles 4 sources of configuration data in order of priority:\n\n* Default configuration from Dict Object\n* Environment variables prefixed by INSTABOT\n* Local file where value located in config.file (INSTABOT_CONFIG_FILE)\n* Etcd data-store\n\nref : [https://github.com/instabot-py/instabot.py](https://github.com/instabot-py/instabot.py) \n\n```python\nimport logging.config\nimport os\n\nfrom config42 import ConfigManager\n\nfrom instabot_py.default_config import DEFAULT_CONFIG\n\nenv_config = ConfigManager(prefix=\"INSTABOT\")\nlogging.basicConfig(level=logging.DEBUG if env_config.get(\"debug\") else logging.INFO)\nLOGGER = logging.getLogger(__name__)\nconfig = ConfigManager()\nconfig.set_many(DEFAULT_CONFIG)\n\nconfig.set_many(env_config.as_dict())\nconfig_file = config.get(\"config.file\")\nconfig_etcd = config.get(\"config.etcd\")\n\nif config_file:\n if config_file.startswith(\"/\"):\n config_path = config_file\n else:\n cwd = os.getcwd()\n config_path = cwd + \"/\" + config_file\n config.set_many(ConfigManager(path=config_path.replace('//', '/')).as_dict())\n LOGGER.info(\"Setting configuration from {} : OK\".format(config_file))\n\nif config_etcd:\n if not config_etcd.get(\"keyspace\"):\n raise Exception(\"etcd Keyspace is mandatory\")\n try:\n config.set_many(ConfigManager(**config_etcd).as_dict())\n LOGGER.info(\n \"Setting external configuration from {} : OK\".format(config_file))\n except Exception as exc:\n LOGGER.error(\n \"Setting external configuration from ({}) : NOT OK\".format(\n \",\".join({key + \"=\" + value for key, value in config_etcd.items() or {}})\n ))\n\n LOGGER.exception(exc)\n raise exc\n\nlogging.config.dictConfig(config.get(\"logging\"))\n\n``` \n\n\n## Requirements\n### Yaml configuration files\n\n```bash\npip install Pyaml\n```\n\n### Etcd data store \n```bash\npip install python-etcd\n```\n\n### DEV \nThe following packages are needed to run tests and coverage\n\n```bash\npip install tox pytest-cov pytest flake8\n```\n\nor \n\n```bash\npip install -r requirements/ci.txt\npip install -r requirements/tests.txt\n```\n\n\n## Usage examples\n\n* [from-etcd.py](examples/from-etcd.py)\n* [from-yaml.py](examples/from-yaml.py)\n\n\n## TODO\n* readthedoc with sphinx\n\n## Releases\n\n#### 0.3.1\n* Add set default variables feature\n#### 0.3\n* Add Environment Handler\n\n#### 0.2\n\n* Add Etcd Handler\n* Add Ini Yaml, Json Handlers\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "https://github.com/yurilaaziz/config42/releases/tag/0.2", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/yurilaaziz/config42", "keywords": "Pretty configuration manager,Key value data store,cloud native configuration", "license": "GPLv3+", "maintainer": "", "maintainer_email": "", "name": "config42", "package_url": "https://pypi.org/project/config42/", "platform": "", "project_url": "https://pypi.org/project/config42/", "project_urls": { "Download": "https://github.com/yurilaaziz/config42/releases/tag/0.2", "Homepage": "https://github.com/yurilaaziz/config42" }, "release_url": "https://pypi.org/project/config42/0.4.3/", "requires_dist": [ "Pyyaml (>=5.1)", "Jinja2 (>=2.0)", "Cerberus (>=1.3.1)" ], "requires_python": "", "summary": "Configuration manager for cloud native application, support configuration stored in memory, in files, in databases", "version": "0.4.3" }, "last_serial": 5996776, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "3b601fc01642c06c1e16122d1a7c23a6", "sha256": "4e478cbdd6e67a1e32ae597414c1de3294b5380461e555ac41d06bbb94e0469a" }, "downloads": -1, "filename": "config42-0.1-py2-none-any.whl", "has_sig": false, "md5_digest": "3b601fc01642c06c1e16122d1a7c23a6", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 16366, "upload_time": "2019-01-28T02:03:44", "url": "https://files.pythonhosted.org/packages/ff/8b/c4dd87f7e1602f83b5eb26087f30b2285032f59a235d7ee9181b969f3539/config42-0.1-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "2102f7aacd594261dbe5745876c34911", "sha256": "4db19ad56ab7b9fe8177d784be256788e20b1efbde72d8ba9e016c5bb42cb0f1" }, "downloads": -1, "filename": "config42-0.1.tar.gz", "has_sig": false, "md5_digest": "2102f7aacd594261dbe5745876c34911", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3224, "upload_time": "2019-01-28T02:03:47", "url": "https://files.pythonhosted.org/packages/b1/c9/a4c903788fc6a4a727b40b204819ac21cd1afa0d43cfd08beaf0aeeea023/config42-0.1.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "48a6a9bfb9852b91062bd49e8e6604d4", "sha256": "7f461ad24dce72de5c74b8f1da137c94a1eb9c49448ab822ffd9d63c632102f0" }, "downloads": -1, "filename": "config42-0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "48a6a9bfb9852b91062bd49e8e6604d4", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 19789, "upload_time": "2019-02-15T14:07:15", "url": "https://files.pythonhosted.org/packages/a4/12/8f8ea4831b175bf0bbad262b8aa1e48e3c7239d9707b272b62fb8ea75e33/config42-0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "91654169b3853a13085ab9f18cef2955", "sha256": "29e70797cc5f2fb1e2420ee27090ffde206481a32f2d8a984981c6ba4bcb9c72" }, "downloads": -1, "filename": "config42-0.2.tar.gz", "has_sig": false, "md5_digest": "91654169b3853a13085ab9f18cef2955", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5600, "upload_time": "2019-02-15T14:07:17", "url": "https://files.pythonhosted.org/packages/67/d2/bc72494b29a23e0b10799e5f9429f19367b9cdab806e5aecc22e3522738e/config42-0.2.tar.gz" } ], "0.2.3": [ { "comment_text": "", "digests": { "md5": "d1961504970819d351949b64b76c45bb", "sha256": "5de39a65a5ba3c0a72fed5386a124ec56986447c958a7a0fd4c7c4b51cf3903b" }, "downloads": -1, "filename": "config42-0.2.3-py3-none-any.whl", "has_sig": false, "md5_digest": "d1961504970819d351949b64b76c45bb", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 21090, "upload_time": "2019-02-15T14:53:00", "url": "https://files.pythonhosted.org/packages/cd/4f/ca0784b04de2eb25a50d1d32c5a395c78e0fce8f1d0511fc6b2124ab8390/config42-0.2.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "305e96c1f9b4acc1f1364757901e9e11", "sha256": "f91523ac9377ca14a7d982694aa74de5e5140dd3042c6c43a5f1ccf80ed7a6ed" }, "downloads": -1, "filename": "config42-0.2.3.tar.gz", "has_sig": false, "md5_digest": "305e96c1f9b4acc1f1364757901e9e11", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6085, "upload_time": "2019-02-15T14:53:01", "url": "https://files.pythonhosted.org/packages/85/df/ebb69bd455a905b4a58b49c980c4856da38317cb351c9cbb6ded9facb68f/config42-0.2.3.tar.gz" } ], "0.2.4": [ { "comment_text": "", "digests": { "md5": "33b673d83fa2931f73c355b308b6ada1", "sha256": "b8dc91fb653221e6747757081a580d0e136c880d2fe6a4bef9bc3bdc8eb65c6e" }, "downloads": -1, "filename": "config42-0.2.4-py3-none-any.whl", "has_sig": false, "md5_digest": "33b673d83fa2931f73c355b308b6ada1", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 21551, "upload_time": "2019-03-17T17:11:10", "url": "https://files.pythonhosted.org/packages/00/49/af0531e90b610615b7e4848e102bfe8cd57677431f9784ce31d738c9bfd7/config42-0.2.4-py3-none-any.whl" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "d4f64c7a973930e814ca4e7c028ffc28", "sha256": "cafa0a40bfbeefaba62a2444d247780e0508f4dd632f1b84db7f262ba1d62520" }, "downloads": -1, "filename": "config42-0.3.0-py3-none-any.whl", "has_sig": false, "md5_digest": "d4f64c7a973930e814ca4e7c028ffc28", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 22086, "upload_time": "2019-03-24T16:57:14", "url": "https://files.pythonhosted.org/packages/fc/a6/b0e583c5896d891d87b1e3559ad35aa06ae09600b16e0426e3dd21d6bccb/config42-0.3.0-py3-none-any.whl" } ], "0.3.1": [ { "comment_text": "", "digests": { "md5": "aec1dc30aad694c5a4f9c816c1a66982", "sha256": "bf3bc83a3d21ab930e5e0607d83f1fa1600805929713217f3a94c61250face24" }, "downloads": -1, "filename": "config42-0.3.1.macosx-10.6-intel.tar.gz", "has_sig": false, "md5_digest": "aec1dc30aad694c5a4f9c816c1a66982", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12495, "upload_time": "2019-04-27T22:25:30", "url": "https://files.pythonhosted.org/packages/19/af/24c04759fea59a3cd301db8f26ce3851fb44a172981b697461a7ea5586bc/config42-0.3.1.macosx-10.6-intel.tar.gz" }, { "comment_text": "", "digests": { "md5": "08b48e68908355caf32165bbf5283471", "sha256": "5b551930d79c95e266d496f436dc0b4439c1c8290007c5c7c46d87f2f0f2928a" }, "downloads": -1, "filename": "config42-0.3.1-py3-none-any.whl", "has_sig": false, "md5_digest": "08b48e68908355caf32165bbf5283471", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 22173, "upload_time": "2019-04-27T22:26:02", "url": "https://files.pythonhosted.org/packages/b3/eb/42825e0bcc0611b0690a672072a9b76130c75977e766226667ef14c9e7f4/config42-0.3.1-py3-none-any.whl" } ], "0.3.2": [ { "comment_text": "", "digests": { "md5": "8cadda5755f9391d635d3b3054536281", "sha256": "503ea3ceea2eebee887a8685520557250b3f0f2938a9859725b140aa337f28ad" }, "downloads": -1, "filename": "config42-0.3.2-py3-none-any.whl", "has_sig": false, "md5_digest": "8cadda5755f9391d635d3b3054536281", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 23625, "upload_time": "2019-07-04T15:18:54", "url": "https://files.pythonhosted.org/packages/04/f0/4693a28cee283f0122c0d0b261ed685a22ae8695915becea412e123228e1/config42-0.3.2-py3-none-any.whl" } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "fcf477a02aa0fb9eafe68dbec92f2076", "sha256": "bd019cf94e69e206a6aa986b61a8c103b9208993f613095fd917dbf6dcdd3ccd" }, "downloads": -1, "filename": "config42-0.4.0-py3-none-any.whl", "has_sig": false, "md5_digest": "fcf477a02aa0fb9eafe68dbec92f2076", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 29474, "upload_time": "2019-07-23T19:04:34", "url": "https://files.pythonhosted.org/packages/97/2f/4c0718133d062b2275fe55c82b336dd9ded0dee690c2eebfe4e0f3acc727/config42-0.4.0-py3-none-any.whl" } ], "0.4.1": [ { "comment_text": "", "digests": { "md5": "fc24d70f06502092b28f3950db9d1f2d", "sha256": "7aa9223944333272bd5b3985c6449ee0c62e2b545c9286d2cd146fae57ce7df3" }, "downloads": -1, "filename": "config42-0.4.1-py3-none-any.whl", "has_sig": false, "md5_digest": "fc24d70f06502092b28f3950db9d1f2d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 29502, "upload_time": "2019-07-24T16:10:09", "url": "https://files.pythonhosted.org/packages/fd/64/09ae43e55298c26e69ee7341261b5578b904a247efe75f3cbfe2279b7d40/config42-0.4.1-py3-none-any.whl" } ], "0.4.2": [ { "comment_text": "", "digests": { "md5": "2b1997b968ce67d4c0d29ed4fd0ff3b8", "sha256": "f458f18523b0c209198444060d887c28c08acfd4add148edd780bd054efdf162" }, "downloads": -1, "filename": "config42-0.4.2-py3-none-any.whl", "has_sig": false, "md5_digest": "2b1997b968ce67d4c0d29ed4fd0ff3b8", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 29564, "upload_time": "2019-08-05T16:35:26", "url": "https://files.pythonhosted.org/packages/5f/43/5fc25e3966549bb60d47ab7c21e6647521f7d7e6cd1ca38ea43fb1c3f6a9/config42-0.4.2-py3-none-any.whl" } ], "0.4.3": [ { "comment_text": "", "digests": { "md5": "c525909ea6bfe44ffcb5680093be76d7", "sha256": "15d3c57a7a193f6c45ff20d14dbeb1273bd72c372e2f24e0a2737127204a4968" }, "downloads": -1, "filename": "config42-0.4.3-py3-none-any.whl", "has_sig": false, "md5_digest": "c525909ea6bfe44ffcb5680093be76d7", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 29739, "upload_time": "2019-10-18T17:37:14", "url": "https://files.pythonhosted.org/packages/f8/a6/73ebccb41a320f7a7d93bf7932d552e049179de8827222649d66a1084fbf/config42-0.4.3-py3-none-any.whl" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "c525909ea6bfe44ffcb5680093be76d7", "sha256": "15d3c57a7a193f6c45ff20d14dbeb1273bd72c372e2f24e0a2737127204a4968" }, "downloads": -1, "filename": "config42-0.4.3-py3-none-any.whl", "has_sig": false, "md5_digest": "c525909ea6bfe44ffcb5680093be76d7", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 29739, "upload_time": "2019-10-18T17:37:14", "url": "https://files.pythonhosted.org/packages/f8/a6/73ebccb41a320f7a7d93bf7932d552e049179de8827222649d66a1084fbf/config42-0.4.3-py3-none-any.whl" } ] }