{ "info": { "author": "Carl A. Bauer", "author_email": "carl.a.bauer@gmail.com", "bugtrack_url": null, "classifiers": [], "description": "Installation\n------------\n\n::\n\n pip install configable\n\nExample\n-------\n\n.. code:: python\n\n from configable import Configable, setting\n\n class Car(Configable):\n fuel_efficiency = setting(\n required=true,\n kind=float\n )\n\n units = setting(\n default='metric',\n choices=[\n 'metric',\n 'english'\n ]\n )\n\n def mpg(self):\n eff = self.fuel_efficiency\n return eff if self.units == 'english' else 2.35214583 * eff\n\n car = Car({\n 'fuel_efficiency': 30,\n 'units': 'metric'\n })\n\n print car.mpg()\n\nTutorial\n--------\n\nConfigable\n~~~~~~~~~~\n\nCreate configable classes by subclassing Configable and adding\n`settings `__.\nHere's a very simple example. For introductory purposes, the settings\nare specified without options; this means they are optional, and their\nvalues are taken as is from whatever configuration object instantiates\nthe class.\n\n.. code:: python\n\n class Animal(Configable):\n species = setting()\n sound = setting()\n def speak(self):\n print self.sound\n\nA Configable expects a single argument in its constructor: a\n*configuration object*. A *config object* is just a plain old python\ndictionary, probably loaded from a JSON/YAML/etc config file. It should\ncontain properties that correspond to the\n`settings `__\ndefined on the Configable it is instantiating.\n\n.. code:: python\n\n cheetah = Animal({\n 'species': 'acinonyx jubatus',\n 'sound': 'rawr'\n })\n\nInheritance\n~~~~~~~~~~~\n\nWhen we subclass a subclass of Configable, we are doing some sort of\nspecialization of the parent class. This usually means there is a value\nfor a setting (or settings) defined on the parent class that implies the\nspecialization. Such special values are specified using the ``SUBTYPE``\nproperty. For example,\n\n.. code:: python\n\n class Cheetah(Animal):\n SUBTYPE = {'species': 'acinonyx jubatus'}\n def speak(self):\n print 'rawr' # hard-coded sound\n\n``SUBTYPE`` should be a dictionary with keys/values that correspond to\nsettings defined on the parent class. The purpose of the ``SUBTYPE``\nproperty is to identify matching configuration objects (passed into the\nparent class constructor) as instances of a special subtype of the\nparent class. In other words, we're injecting an inheritance scheme into\nthe inheritanceless hash table data structure.\n\nIt's way simpler by example; specifying the ``SUBTYPE`` property allows\nthis craziness:\n\n.. code:: python\n\n cheetah = Animal({\n 'species': 'acinonyx jubatus'\n })\n\n print isinstance(cheetah, Cheetah) // True!\n cheetah.speak() // 'rawr'\n\nThe Animal constructor was used to make a Cheetah instance.\n\n``SUBTYPE`` can also be specified as a staticmethod to handle more\ngeneral conditions:\n\n.. code:: python\n\n class Cheetah(Animal):\n @staticmethod\n def SUBTYPE(config):\n return config.get('species') == 'acinonyx jubatus'\n\n def speak(self):\n print 'rawr' # hard-coded sound\n\nIn this case, the ``SUBTYPE`` function should return True if its class\nshould be instantiated instead of the parent class for this\nconfiguration object.\n\nNow you can have collections of animals in your config file:\n\n.. code:: json\n\n {\n \"cheetah\": {\n \"species\": \"acinonyx jubatus\"\n },\n \"grizzly\": {\n \"species\": \"ursus arctos\",\n \"sound\": \"roar!\"\n }\n }\n\nand the correct subclass will be instantiated for each. Speaking of\nwhich...\n\nConfigableMap\n~~~~~~~~~~~~~\n\nA ConfigableMap is simply a mapping between strings and Configables. The\nclass is dead simple; have a look at the source if you want to see\nwhat's goin down. Or, take it all in with this juicy example:\n\n.. code:: python\n\n from configable import Configable, ConfigableMap, setting\n\n class Dog(Configable):\n breed = setting()\n\n class Dogs(ConfigableMap):\n TYPE = Dog\n\n dogs = Dogs({\n 'gracie': {'breed': 'golden'},\n 'spot': {'breed': 'terrier'}\n })\n\n print isinstance(dogs.gracie, Dog) // True!\n\nMake sure you assign a ``Type`` property to a Configable class in the\nConfigableMap prototype! You get all the benefits of subclass\ninstantiation\n\nConfigableArray\n~~~~~~~~~~~~~~~\n\nGiven\n`ConfigableMap `__,\nyou should be satisfied with an example,\n\n.. code:: python\n\n from configable import Configable, ConfigableArray, setting\n\n class Dog(Configable):\n breed = setting()\n\n class Dogs(ConfigableArray):\n TYPE = Dog\n\n dogs = Dogs([\n {'breed': 'golden'},\n {'breed': 'terrier'}\n ])\n\n print isinstance(dogs[0], Dog) // True!\n\nsetting\n~~~~~~~\n\nCall this and assign the result to a property on your Configable\nsubclass (see numerous examples above). Generically (where shown option\nvalues are the defaults),\n\n.. code:: python\n\n class Type(Configable):\n setting_name = setting(\n required=False, # Boolean\n default=None, # Instance of expected type (see 'kind' below)\n choices=None, # List of type expected in config obj\n kind=None # Callable\n )\n\nAdditionally, you can use ``setting`` as a decorator.\n\n.. code:: python\n\n class Type(Configable):\n @setting(\n required=False, # Boolean\n default=None, # Instance of expected type (see 'kind' below)\n choices=None, # List of type expected in config obj\n kind=None # Callable\n )\n def setting_name(self, value):\n # Do something with value\n\nThe decorated function will be called immediately before the value is\nset on the instance (after\n`kind `__ is\ncalled). You should *not* try to access other settings from inside this\nfunction as they may not have been loaded yet. If you need to call the\nparent class decorated function, you must use the following syntax,\n\n.. code:: python\n\n class Parent(Configable):\n @setting()\n def name(self, value):\n self.capname = value.upper()\n\n class Child(Parent):\n @setting()\n def name(self, value):\n Parent.name(self, value) # MUST USE THIS SYNTAX\n print self.capname\n\nThe following are short explanations of the setting options.\n\n``required {bool}``\n^^^^^^^^^^^^^^^^^^^\n\nIf set to true, instantiation of the containing Configable subclass will\nfail horribly if the setting is undefined on the configuration object.\n\n``default {*}``\n^^^^^^^^^^^^^^^\n\nPretty self-explanatory. You probably want\n`required `__ to\nbe ``false`` if you are supplying a default setting value. The default\nvalue should be a *raw* value, i.e. of a type expected in the\nconfiguration object (fundamental, like int, str, dict, list, etc). The\ndefault, if taken, will be run through all the following setting checks\nand ops.\n\n``choices {iterable<*>}``\n^^^^^^^^^^^^^^^^^^^^^^^^^\n\nIf your settings values are restricted to a small set, list them here.\nConfigable instantiation will fail if the *raw* value is not in this\nset.\n\n``kind {callable}``\n^^^^^^^^^^^^^^^^^^^\n\nThe raw value from the configuration object is run through this\nfunction; therefore, it should accept a single value and return the\ntransformed value or throw an error. This is often set as a class,\nespecially when you want nested Configables.", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/bauerca/configable", "keywords": "configuration", "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "configable", "package_url": "https://pypi.org/project/configable/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/configable/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/bauerca/configable" }, "release_url": "https://pypi.org/project/configable/0.1.10/", "requires_dist": null, "requires_python": null, "summary": "Don't repeat yourself. Configure everything.", "version": "0.1.10" }, "last_serial": 1088449, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "e3e2ccf075ae5122a4643d4cbf11325a", "sha256": "0d4948c6a13cf8d1e55699ff75ba4f22738682ee708233f65e77f072ad7362b1" }, "downloads": -1, "filename": "configable-0.1.tar.gz", "has_sig": false, "md5_digest": "e3e2ccf075ae5122a4643d4cbf11325a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5533, "upload_time": "2014-04-13T23:09:50", "url": "https://files.pythonhosted.org/packages/f2/54/cb6f2a8251e7d19162664949328aa49ba279f6f2a44d49295a1689f521a0/configable-0.1.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "c434ee6913c1ab0b89f2d59107b0ad11", "sha256": "e102ce09d98b5fb8cc17bc1e14b977b3a71f223d3ef233e7d7d3eb64aa19ff5f" }, "downloads": -1, "filename": "configable-0.1.1.tar.gz", "has_sig": false, "md5_digest": "c434ee6913c1ab0b89f2d59107b0ad11", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5361, "upload_time": "2014-04-14T19:57:01", "url": "https://files.pythonhosted.org/packages/84/0a/c9b91d2510c9017faa6c27c7e5bfdd3a23c62bd7fb24cab907c661a418bc/configable-0.1.1.tar.gz" } ], "0.1.10": [ { "comment_text": "", "digests": { "md5": "b787360f788c75858b9f90ef978561e4", "sha256": "9ed045483379eb72b6e524fb332966cd8dfd21fe1df1a2fb6dc6f799e01ade02" }, "downloads": -1, "filename": "configable-0.1.10.tar.gz", "has_sig": false, "md5_digest": "b787360f788c75858b9f90ef978561e4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5621, "upload_time": "2014-05-11T09:43:08", "url": "https://files.pythonhosted.org/packages/bc/ef/41319c3bb7cec0e35eadff72bcff7b18eec2bc10d24575f0335928d79aeb/configable-0.1.10.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "3ed621626c96c84acd079a47603ffe58", "sha256": "383d67c30a324d2a226211c13b5d987b5f4f82f2e080c7a8f131dd96e9dea673" }, "downloads": -1, "filename": "configable-0.1.2.tar.gz", "has_sig": false, "md5_digest": "3ed621626c96c84acd079a47603ffe58", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2643, "upload_time": "2014-04-22T18:29:31", "url": "https://files.pythonhosted.org/packages/67/11/67018489799528420154564e0e7ac127d738f494bf0516a1eb53ae877d2d/configable-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "c8d8ac3d6c7b5609fc9076aa0a77f426", "sha256": "5eef596a6e8ef99b61cb8b77995a00babf3edbddc3905a7c714df71e76fda83b" }, "downloads": -1, "filename": "configable-0.1.3.tar.gz", "has_sig": false, "md5_digest": "c8d8ac3d6c7b5609fc9076aa0a77f426", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5201, "upload_time": "2014-04-23T02:10:39", "url": "https://files.pythonhosted.org/packages/88/4e/56a02b675596bb9fe63a507fd3dd651a230e8112d6ab32bce12491868441/configable-0.1.3.tar.gz" } ], "0.1.4": [ { "comment_text": "", "digests": { "md5": "017f3e86e65953a7f3159ee221d09763", "sha256": "f82578baaccd8c5bfa4f3a5b46d03bc690ad9be7bb2dc806928b0390bbd86b27" }, "downloads": -1, "filename": "configable-0.1.4.tar.gz", "has_sig": false, "md5_digest": "017f3e86e65953a7f3159ee221d09763", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5082, "upload_time": "2014-04-23T07:35:51", "url": "https://files.pythonhosted.org/packages/e3/6b/a022edd5978abdc51779fcd4e5a6e0332eb27d0616a5444cdb1becba8a77/configable-0.1.4.tar.gz" } ], "0.1.5": [ { "comment_text": "", "digests": { "md5": "405d3af5eea9252f25944ad17e4c1329", "sha256": "85a422b99071ee02c32432733e4d02f1a881c97fe6fade60c9686580f317882b" }, "downloads": -1, "filename": "configable-0.1.5.tar.gz", "has_sig": false, "md5_digest": "405d3af5eea9252f25944ad17e4c1329", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5267, "upload_time": "2014-04-23T08:03:57", "url": "https://files.pythonhosted.org/packages/85/93/c92089b5d6c3faea38d563d99f01073e112333401bd188253f3ca8396fda/configable-0.1.5.tar.gz" } ], "0.1.6": [ { "comment_text": "", "digests": { "md5": "d5f6130dac8ee35ee5e35a860c0a2edd", "sha256": "a2933834cd231654e5cb1ef837c3bf8e32f35e3175b481df2f656c77eabdca5d" }, "downloads": -1, "filename": "configable-0.1.6.tar.gz", "has_sig": false, "md5_digest": "d5f6130dac8ee35ee5e35a860c0a2edd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5408, "upload_time": "2014-04-23T18:56:09", "url": "https://files.pythonhosted.org/packages/39/22/fe35b9f5014addd9275b3bee71e1f741ade44c7256a394160052d35090d7/configable-0.1.6.tar.gz" } ], "0.1.7": [ { "comment_text": "", "digests": { "md5": "724cb08d7ccdd4481350db36690853fa", "sha256": "82869a5d0fbcca92b5076497ede077a37a776bc9bad446d62f5a426d519964ef" }, "downloads": -1, "filename": "configable-0.1.7.tar.gz", "has_sig": false, "md5_digest": "724cb08d7ccdd4481350db36690853fa", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5403, "upload_time": "2014-04-23T19:13:38", "url": "https://files.pythonhosted.org/packages/8d/9f/b589d198f274fb7eb226cef481d43277b59f0f9a89237ef8e3e2644cd4c5/configable-0.1.7.tar.gz" } ], "0.1.8": [ { "comment_text": "", "digests": { "md5": "950eec76ac012e883151a203a6b51685", "sha256": "2f823fa2c116bf203bc21c9542c8ac7544801ae6740a6c5019db9e897b8a7ae0" }, "downloads": -1, "filename": "configable-0.1.8.tar.gz", "has_sig": false, "md5_digest": "950eec76ac012e883151a203a6b51685", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5454, "upload_time": "2014-04-24T20:06:28", "url": "https://files.pythonhosted.org/packages/1d/af/890725974e43e54350df4071998292900017b3432330baef342490c0da51/configable-0.1.8.tar.gz" } ], "0.1.9": [ { "comment_text": "", "digests": { "md5": "a916147b48496b96d5a041ff9a87f975", "sha256": "5e82b209307da4d2a5e26ac585edd44ffc88698186f60fcf28060f973d9bdb5c" }, "downloads": -1, "filename": "configable-0.1.9.tar.gz", "has_sig": false, "md5_digest": "a916147b48496b96d5a041ff9a87f975", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5467, "upload_time": "2014-04-29T22:25:31", "url": "https://files.pythonhosted.org/packages/a3/51/e08e9c4aaf3b30cdbfca87668fbec4489b9a2918124ae495d33f6e2b3c27/configable-0.1.9.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "b787360f788c75858b9f90ef978561e4", "sha256": "9ed045483379eb72b6e524fb332966cd8dfd21fe1df1a2fb6dc6f799e01ade02" }, "downloads": -1, "filename": "configable-0.1.10.tar.gz", "has_sig": false, "md5_digest": "b787360f788c75858b9f90ef978561e4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5621, "upload_time": "2014-05-11T09:43:08", "url": "https://files.pythonhosted.org/packages/bc/ef/41319c3bb7cec0e35eadff72bcff7b18eec2bc10d24575f0335928d79aeb/configable-0.1.10.tar.gz" } ] }