{ "info": { "author": "Jo\u00e3o Santos", "author_email": "jmcs@jsantos.eu", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7" ], "description": ".. image:: https://travis-ci.org/jmcs/ecological.svg?branch=master\n :target: https://travis-ci.org/jmcs/ecological\n\n.. image:: https://api.codacy.com/project/badge/Grade/1ff45d0e1a5a40b8ad0569e3edb0539d\n :alt: Codacy Badge\n :target: https://www.codacy.com/app/jmcs/ecological?utm_source=github.com&utm_medium=referral&utm_content=jmcs/ecological&utm_campaign=badger\n\n.. image:: https://api.codacy.com/project/badge/Coverage/1ff45d0e1a5a40b8ad0569e3edb0539d\n :target: https://www.codacy.com/app/jmcs/ecological?utm_source=github.com&utm_medium=referral&utm_content=jmcs/ecological&utm_campaign=Badge_Coverage\n\n==========\nEcological\n==========\n\n``Ecological`` combines PEP526_ and environment variables to make the configuration of\n`12 factor apps `_ easy.\n\nGetting Started\n===============\n``Ecological`` automatically gets and converts environment variables according to the configuration class definition.\n\nFor example, imagine your application has a configurable (integer) Port and (boolean) Debug flag and a (string) Log\nLevel, that is ``INFO`` by default, you could simply declare your configuration as:\n\n.. code-block:: python\n\n class Configuration(ecological.Config):\n port: int\n debug: bool\n log_level: str = \"INFO\"\n\nAnd then set the environment variables ``PORT``, ``DEBUG`` and ``LOG_LEVEL``. ``Ecological`` will automatically set the\nclass properties from the environment variables with the same (but upper cased) name.\n\nBy default the values are set at the class definition type and assigned to the class itself (i.e. the class doesn't need to be\ninstantiated). If needed this behavior can be changed (see the Autoloading section).\n\nTutorial\n--------\nThe `tutorial `_ can be used to get to know with the library's basic features interactively.\n\nTyping Support\n==============\n``Ecological`` also supports some of the types defined in PEP484_, for example:\n\n.. code-block:: python\n\n\n class Configuration(ecological.Config):\n list_of_values: List[str]\n\nWill automatically parse the environment variable value as a list.\n\n.. note:: Please note that while this will ensure ``Configuration.list_of_values`` is a list it will not check that it\n contains only strings.\n\nPrefixed Configuration\n======================\nYou can also decide to prefix your application configuration, for example, to avoid collisions:\n\n.. code-block:: python\n\n class Configuration(ecological.Config, prefix='myapp'):\n home: str\n\n\nIn this case the ``home`` property will be fetched from the ``MYAPP_HOME`` environment property.\n\nNested Configuration\n=====================\n``Ecological.Config`` also supports nested configurations, for example:\n\n.. code-block:: python\n\n\n class Configuration(ecological.Config):\n integer: int\n\n class Nested(ecological.Config, prefix='nested'):\n boolean: bool\n\nThis way you can group related configuration properties hierarchically.\n\nAdvanced\n========\n\nFine-grained Control\n---------------------\nYou can control some behavior of how the configuration properties are set.\n\nIt can be achieved by providing a ``ecological.Variable`` instance as the default\nvalue for an attribute or by specifying global options on the class level:\n\n.. code-block:: python\n\n my_source = {\"KEY1\": \"VALUE1\"}\n\n class Configuration(ecological.Config, transform=lambda v, wt: v, wanted_type=int, ...):\n my_var1: WantedType = ecological.Variable(transform=lambda v, wt: wt(v), source=my_source, ...)\n my_var2: str\n # ...\n\nAll possible options and their meaning can be found in the table below:\n\n+-------------------+---------------+-----------------+-------------------------------------------------+-------------------------------------------------------------------+\n| Option | Class level | Variable level | Default | Description |\n+===================+===============+=================+=================================================+===================================================================+\n| ``prefix`` | yes | no | ``None`` | A prefix that is uppercased and prepended when a variable name |\n| | | | | is derived from an attribute name. |\n+-------------------+---------------+-----------------+-------------------------------------------------+-------------------------------------------------------------------+\n| ``variable_name`` | yes | yes | Derived from attribute name and prefixed | When specified on the variable level it states |\n| | | | with ``prefix`` if specified; uppercased. | the exact name of the source variable that will be used. |\n| | | | | |\n| | | | | When specified on the class level it is treated as a function |\n| | | | | that returns a variable name from the attribute name with |\n| | | | | the following signature: |\n| | | | | |\n| | | | | ``def func(attribute_name: str, prefix: Optional[str] = None)`` |\n+-------------------+---------------+-----------------+-------------------------------------------------+-------------------------------------------------------------------+\n| ``default`` | no | yes | (no default) | Default value for the property if it isn't set. |\n+-------------------+---------------+-----------------+-------------------------------------------------+-------------------------------------------------------------------+\n| ``transform`` | yes | yes | A source value is casted to the ``wanted_type`` | A function that converts a value from the ``source`` to the value |\n| | | | In case of non-scalar types (+ scalar ``bool``) | and ``wanted_type`` you expect with the following signature: |\n| | | | the value is Python-parsed first. | |\n| | | | | ``def func(source_value: str, wanted_type: Union[Type, str])`` |\n+-------------------+---------------+-----------------+-------------------------------------------------+-------------------------------------------------------------------+\n| ``source`` | yes | yes | ``os.environ`` | Dictionary that the value will be loaded from. |\n+-------------------+---------------+-----------------+-------------------------------------------------+-------------------------------------------------------------------+\n| ``wanted_type`` | yes | yes | ``str`` | Desired Python type of the attribute's value. |\n| | | | | |\n| | | | | On the variable level it is specified via a type annotation on |\n| | | | | the attribute: ``my_var_1: my_wanted_type``. |\n| | | | | |\n| | | | | However it can be also specified on the class level, then it acts |\n| | | | | as a default when the annotation is not provided: |\n| | | | | |\n| | | | | ``class MyConfig(ecological.Config, wanted_type=int, ...)`` |\n+-------------------+---------------+-----------------+-------------------------------------------------+-------------------------------------------------------------------+\n\nThe following rules apply when options are resolved:\n\n- when options are specified on both levels (variable and class),\n the variable ones take precedence over class ones,\n- when some options are missing on the variable level, their default values\n are taken from the class level,\n- it is not necessary to assign an ``ecological.Variable`` instance to\n change the behavior; it can still be changed on the class level (globally).\n\nAutoloading\n------------\nIt is possible to defer/disable autoloading (setting) of variable values by specifying the ``autoload`` option on class definition.\n\nOn class creation (default)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~\nWhen no option is provided values are loaded immediately on class creation and assigned to class attributes:\n\n.. code-block:: python\n\n class Configuration(ecological.Config):\n port: int\n # Values already read and set at this point.\n # assert Configuration.port == \n\nNever\n~~~~~\nWhen this option is chosen, no autoloading happens. In order to set variable values, the ``Config.load`` method needs to be called explicitly:\n\n.. code-block:: python\n\n class Configuration(ecological.Config, autoload=ecological.Autoload.NEVER):\n port: int\n # Values not set at this point.\n # Accessing Configuration.port would throw AttributeError.\n\n Configuration.load()\n # Values read and set at this point.\n # assert Configuration.port == \n\nOn object instance initialization\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nIf it is preferred to load and store attribute values on the object instance instead of the class itself, the ``Autoload.OBJECT`` strategy can be used:\n\n.. code-block:: python\n\n class Configuration(ecological.Config, autoload=ecological.Autoload.OBJECT):\n port: int\n # Values not set at this point.\n\n config = Configuration()\n # Values read and set at this point on ``config``.\n # assert config.port == \n # Accessing ``Configuration.port`` would throw AttributeError.\n\nCaveats and Known Limitations\n=============================\n\n- ``Ecological`` doesn't support (public) methods in ``Config`` classes\n\n.. _PEP484: https://www.python.org/dev/peps/pep-0484/\n.. _PEP526: https://www.python.org/dev/peps/pep-0526/\n", "description_content_type": "text/x-rst", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/jmcs/ecological", "keywords": "", "license": "MIT", "maintainer": "Jo\u00e3o Santos", "maintainer_email": "jmcs@jsantos.eu", "name": "ecological", "package_url": "https://pypi.org/project/ecological/", "platform": "", "project_url": "https://pypi.org/project/ecological/", "project_urls": { "Homepage": "https://github.com/jmcs/ecological", "Repository": "https://github.com/jmcs/ecological" }, "release_url": "https://pypi.org/project/ecological/2.0.0/", "requires_dist": [ "dataclasses (>=0.6.0,<0.7.0)" ], "requires_python": ">=3.6,<4.0", "summary": "Map a Python configuration from environment variables", "version": "2.0.0" }, "last_serial": 5415076, "releases": { "1.0": [ { "comment_text": "", "digests": { "md5": "4722d18f2baa3b698b41aa1e7183993f", "sha256": "1c94c7c407317a967247e8ba91555dbffc5186b0015fbd100a8fbac67738602b" }, "downloads": -1, "filename": "ecological-1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "4722d18f2baa3b698b41aa1e7183993f", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 6456, "upload_time": "2017-06-11T14:18:02", "url": "https://files.pythonhosted.org/packages/9a/61/8c0618f8714ee9450b4131ef592938a45063631645277357a5dc7be01f63/ecological-1.0-py3-none-any.whl" } ], "1.1": [ { "comment_text": "", "digests": { "md5": "04034edcb89eb09d67d3cefa7fbc3924", "sha256": "52d546374c95455da12809f5254b21d32c1247b8c84594c81a324b7d0d447ccb" }, "downloads": -1, "filename": "ecological-1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "04034edcb89eb09d67d3cefa7fbc3924", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 6476, "upload_time": "2017-06-12T17:04:37", "url": "https://files.pythonhosted.org/packages/41/32/fb724631a39f690b2844f17e4d1baf4c250fd32766f751d39e4e8a49db68/ecological-1.1-py3-none-any.whl" } ], "1.2": [ { "comment_text": "", "digests": { "md5": "98a503ecb7c415ca8cf86aafd790b5d7", "sha256": "c599cf480b415763f75e2576dc2dc0c0ffc0203d69bf88258ebefaae04361a4c" }, "downloads": -1, "filename": "ecological-1.2-py3-none-any.whl", "has_sig": false, "md5_digest": "98a503ecb7c415ca8cf86aafd790b5d7", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 6505, "upload_time": "2017-06-13T16:03:16", "url": "https://files.pythonhosted.org/packages/01/5d/e4fcbab30eebecf3d70f1ef8b3f707e161dbceb8a87b866d228e53702db7/ecological-1.2-py3-none-any.whl" } ], "1.2.1": [ { "comment_text": "", "digests": { "md5": "73df548358f9f78cc2ee745f5e16c34c", "sha256": "0dfb9bd1fb720e0b681500f956f2e385f0ba4a5171117e9e56a24ef3d8b6f467" }, "downloads": -1, "filename": "ecological-1.2.1-py3-none-any.whl", "has_sig": false, "md5_digest": "73df548358f9f78cc2ee745f5e16c34c", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 7711, "upload_time": "2017-06-17T09:12:27", "url": "https://files.pythonhosted.org/packages/19/78/be65b4968bfc108fe033921fc01e2e91d26ee5e7e6deb4ad4e8feb2d9e39/ecological-1.2.1-py3-none-any.whl" } ], "1.3.0": [ { "comment_text": "", "digests": { "md5": "eac82be3d21ef039fb1986cdcd0209c7", "sha256": "fdb87216b722a325474e4f22c29803254285c2c6bbe67292da57cbba853dcb93" }, "downloads": -1, "filename": "ecological-1.3.0-py3-none-any.whl", "has_sig": false, "md5_digest": "eac82be3d21ef039fb1986cdcd0209c7", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 7824, "upload_time": "2017-06-17T14:36:56", "url": "https://files.pythonhosted.org/packages/4d/f5/fb7a00e26fa69b70df4c9a8cbac949b43991dad292c2f122e0784f795a5e/ecological-1.3.0-py3-none-any.whl" } ], "1.4.0": [ { "comment_text": "", "digests": { "md5": "4b33ca54fedd34a9e855ff7f7c3ec741", "sha256": "c0d7e37ed29f60eebcd02763d9c41cc2e2ced23e4181ca20331460b3ab040a6a" }, "downloads": -1, "filename": "ecological-1.4.0-py3-none-any.whl", "has_sig": false, "md5_digest": "4b33ca54fedd34a9e855ff7f7c3ec741", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 7941, "upload_time": "2017-10-21T07:43:19", "url": "https://files.pythonhosted.org/packages/20/27/7c14f48a897bf8ed891e45a56c2a6a5dbbf92c75b01797727375dcc34a93/ecological-1.4.0-py3-none-any.whl" } ], "1.5.0": [ { "comment_text": "", "digests": { "md5": "952688e1b6e838dfdc9373ddb000b0e3", "sha256": "28e98489718f88e7238a94cbcc8f737d3fc2a79cc04a8e0bccba8e79e34bce5a" }, "downloads": -1, "filename": "ecological-1.5.0-py3-none-any.whl", "has_sig": false, "md5_digest": "952688e1b6e838dfdc9373ddb000b0e3", "packagetype": "bdist_wheel", "python_version": "3.7", "requires_python": null, "size": 5765, "upload_time": "2018-08-07T09:54:19", "url": "https://files.pythonhosted.org/packages/66/d3/ae6184628d3bb7bb319190ca643953c8c2a396f7a45101c7406d11125c13/ecological-1.5.0-py3-none-any.whl" } ], "1.6.0": [ { "comment_text": "", "digests": { "md5": "09aef163b7b3bde646e4be6e1bbe1c8e", "sha256": "ed0f6e5a6ae5bd0db32591c0ed0cb62816ae5e0f0a0677ce1192ebf00b7d83eb" }, "downloads": -1, "filename": "ecological-1.6.0-py3-none-any.whl", "has_sig": false, "md5_digest": "09aef163b7b3bde646e4be6e1bbe1c8e", "packagetype": "bdist_wheel", "python_version": "3.7", "requires_python": null, "size": 5779, "upload_time": "2018-08-17T05:06:49", "url": "https://files.pythonhosted.org/packages/49/26/4b81ea6d4f6e0d6d0b32631fbad3a54159530eeec6f4e4a50f49c2626aaf/ecological-1.6.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "1998ef0c4f6ba922c03d5f079c4905dd", "sha256": "536cca0c6d6f0a85dcf3c825ddc31189a5c78428b6deed0eac00637d450d4f89" }, "downloads": -1, "filename": "ecological-1.6.0.tar.gz", "has_sig": false, "md5_digest": "1998ef0c4f6ba922c03d5f079c4905dd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5524, "upload_time": "2018-11-11T13:03:35", "url": "https://files.pythonhosted.org/packages/55/be/b337f585b413ebd9c8ed4ae58854b036fed42ccc717cc776d663d13a50de/ecological-1.6.0.tar.gz" } ], "2.0.0": [ { "comment_text": "", "digests": { "md5": "96e10302bd57bcca404b63c75b975a4c", "sha256": "6c90386d3606911410246aef4b04592bd961c99c2789f52e23fcc66152b5164b" }, "downloads": -1, "filename": "ecological-2.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "96e10302bd57bcca404b63c75b975a4c", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6,<4.0", "size": 9239, "upload_time": "2019-06-18T12:58:43", "url": "https://files.pythonhosted.org/packages/8e/42/3d83e880115dbe5daf42a1cc5326eb674cf627fc199910e069cd3d0c2a03/ecological-2.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d56054e54780c5a8f8d1cf00f097cd11", "sha256": "1b147a1e9f517cc3cd8b5d721fdcc562f371af3d4507711d19ab1d47b89d3c5a" }, "downloads": -1, "filename": "ecological-2.0.0.tar.gz", "has_sig": false, "md5_digest": "d56054e54780c5a8f8d1cf00f097cd11", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6,<4.0", "size": 11168, "upload_time": "2019-06-18T12:58:45", "url": "https://files.pythonhosted.org/packages/13/06/c6c60ba2b394942276d58fb1c8b20a8c77b06b60d7e9204e486a99298025/ecological-2.0.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "96e10302bd57bcca404b63c75b975a4c", "sha256": "6c90386d3606911410246aef4b04592bd961c99c2789f52e23fcc66152b5164b" }, "downloads": -1, "filename": "ecological-2.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "96e10302bd57bcca404b63c75b975a4c", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6,<4.0", "size": 9239, "upload_time": "2019-06-18T12:58:43", "url": "https://files.pythonhosted.org/packages/8e/42/3d83e880115dbe5daf42a1cc5326eb674cf627fc199910e069cd3d0c2a03/ecological-2.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d56054e54780c5a8f8d1cf00f097cd11", "sha256": "1b147a1e9f517cc3cd8b5d721fdcc562f371af3d4507711d19ab1d47b89d3c5a" }, "downloads": -1, "filename": "ecological-2.0.0.tar.gz", "has_sig": false, "md5_digest": "d56054e54780c5a8f8d1cf00f097cd11", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6,<4.0", "size": 11168, "upload_time": "2019-06-18T12:58:45", "url": "https://files.pythonhosted.org/packages/13/06/c6c60ba2b394942276d58fb1c8b20a8c77b06b60d7e9204e486a99298025/ecological-2.0.0.tar.gz" } ] }