{ "info": { "author": "wil paredes", "author_email": "configgen@dystedium.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: Developers", "Intended Audience :: System Administrators", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.4", "Topic :: Software Development :: Code Generators", "Topic :: System :: Systems Administration", "Topic :: Text Processing :: Markup", "Topic :: Utilities" ], "description": "=========\nconfiggen\n=========\n\ndescription\n===========\n``configgen`` is a tool and library for generating JSON files given a script\nand set of options. [#]_ it's useful when you have multiple configurations\nthat share some information, but change in different ways in different\ncontexts. define your config info in one place and generate a version specific\nto your app, cron jobs, or developer utilities, in development, staging, or\nproduction, for your dev virtual machine or server environments,\nin any combination.\n\nthis is not intended to replace a full template language.\n\ninstall it with ``pip``::\n\n pip install configgen\n\nthe PyPI page is: https://pypi.python.org/pypi/configgen\n\nthe source code lives at bitbucket: https://bitbucket.org/dystedium/configgen\n\n.. [#] this totally wasn't written just to make the simpsons reference in the\n short description.\n\ncommand line usage\n==================\n::\n\n usage: configgen [-h] [--config CONFIG] [--module] [--option OPTION]\n [--printconfig] [--squishee] [--no-replace] [--verbose]\n [--version]\n input [output]\n\n generate a config file given a python module and set of options\n\n positional arguments:\n input where to get input class structure, by default this\n expects a path to a file, also see help text for the\n --module option\n output optional, file to which output is written, no output\n by default (see --printconfig)\n\n optional arguments:\n -h, --help show this help message and exit\n --config CONFIG, -c CONFIG\n if there are multiple Config instances in the class\n structure, the value of this parameter specifies which\n one to output\n --module, -m interpret the input parameter as a module import with\n dot notation, e.g. my.config.module, must be in python\n path\n --option OPTION, -o OPTION\n an option string that will be used to choose which\n value to output for a given field name (may be passed\n multiple times)\n --printconfig, -p print the converted config object to the console\n --squishee, -s make the converted config output less human-readable\n --no-replace, -n do not do internal string replacement in the output\n --verbose, -v increase console output\n --version show program's version number and exit\n\ncommand line examples\n=====================\n**disclaimer:** all of the below examples are for illustrative purposes only.\nthis is not a recommendation to do things like store production usernames and\npasswords in plaintext files.\n\nbasic usage\n-----------\nif ``hello.py`` contained the following::\n\n from configgen import Config\n\n cfg = Config(\n _object='world', # keys starting with \"_\" are not output\n _object__frog='ma baby', # options are separated from the key by \"__\"\n statement='hello, {_object}', # string replacement\n statement__frog__crowd='ribbit' # if multiple options are present, all must match\n )\n\n``configgen --printconfig hello.py`` would output::\n\n {\n \"statement\": \"hello, world\"\n }\n\n``configgen --printconfig --option frog hello.py`` would output::\n\n {\n \"statement\": \"hello, ma baby\"\n }\n\nput the frog in front of a crowd with ``configgen -p -o frog -o crowd hello.py``::\n\n {\n \"statement\": \"ribbit\"\n }\n\ninheritance and string replacement\n----------------------------------\ncontents of ``inherit.py``::\n\n from configgen import Config, KeyValue, make_multi_key as MK\n\n # option strings\n production = 'production'\n\n # define these field name strings in one place\n projectName = 'projectName'\n _db = '_db'\n dbType = 'dbType'\n user = 'user'\n password = 'password'\n host = 'host'\n\n # KeyValue objects have most of the same abilities as Config\n site1=KeyValue(\n projectName='site1',\n _db={ # KeyValue values aren't restricted to base types\n dbType:'mysql',\n user:'testuser',\n password:'testpass', # use your best judgment\n host:'localserver'\n },\n braces='{{}}' # actual { or } character escaping\n )\n\n # since this is a normal python script, the usual syntax rules and patterns\n # apply - parameters to KeyValue can be passed in a keyword argument dictionary\n # using the ** syntax. make_multi_key(), abbreviated here as MK(),\n # is a convenience function for combining keys and options - because it just\n # returns the concatenated string, it can't be used when using the\n # KeyValue(parameter=value) style declaration.\n site2 = KeyValue(**{\n projectName:'site2',\n _db:KeyValue(**{ # it is possible to nest KeyValue instances\n dbType:'postgresql',\n user:'testuser',\n password:'testpass',\n MK(user, production):'realuser',\n MK(password, production):'realpass', # use your best judgment\n host:'localserver',\n MK(host, production):'cloudserver'\n })\n })\n\n # note that the string replacement here references fields inherited by\n # the parent Config object. also note the use of attribute-style access\n # (via the \".\" operator) to reference fields in dictionaries/KeyValues\n siteCfg = KeyValue(\n rootPath='~/www/{projectName}',\n databaseUrl='{_db.dbType}://{_db.user}:{_db.password}@{_db.host}'\n )\n\n cfgSite1 = Config(inherits=site1, site=siteCfg)\n cfgSite2 = Config(inherits=site2, site=siteCfg)\n\nif multiple Config objects are defined in a file, the one to output must be\nspecified with the --config or -c option.\n\n``configgen --printconfig --config cfgSite1 inherit.py`` would output::\n\n {\n \"projectName\": \"site1\",\n \"site\": {\n \"databaseUrl\": \"mysql://testuser:testpass@localserver\",\n \"rootPath\": \"~/www/site1\"\n },\n \"braces\": \"{}\"\n }\n\n``configgen -p -c cfgSite2 inherit.py`` would output::\n\n {\n \"projectName\": \"site2\",\n \"site\": {\n \"databaseUrl\": \"postgresql://testuser:testpass@localserver\",\n \"rootPath\": \"~/www/site2\"\n }\n }\n\n``configgen -p -c cfgSite2 -o production inherit.py`` would output::\n\n {\n \"projectName\": \"site2\",\n \"site\": {\n \"databaseUrl\": \"postgresql://realuser:realpass@cloudserver\",\n \"rootPath\": \"~/www/site2\"\n }\n }\n\nnotes\n-----\nthere is currently no simple way to emit a key/value pair only for\na specific option set. there is a clunky way to do this::\n\n common = KeyValue(key1=value1, key2=value2)\n extraField = KeyValue(inherits=common, key3=value3)\n output = KeyValue(fields=common, fields__addkey3=extraField)\n\nthe JSON generated by output will include key3 only when the option string\n'addkey3' is present.\n\nlibrary examples\n================\nthe ``configgen`` package can also be used as a library in a larger program.\nthe source of ``configgen.main`` is an example of basic usage.\n\noperation\n=========\n``KeyValue`` string replacement\n-------------------------------\nwhen resolving named references to other parts of the KeyValue structure\nduring string replacement, the following steps are taken:\n\n1. define the ``KeyValue`` instance that contains the string being resolved\n as \"nearest\"\n2. start searching at the following ``KeyValue`` instances for the entire\n reference, continuing to the next one if the reference cannot be resolved:\n\n a. the nearest instance\n b. the nearest instance's inherited fields, if present\n c. the outermost ``KeyValue`` instance (usually the ``Config`` instance)\n d. the outermost instance's inherited fields, if present\n\n3. while searching, if a named field is found in a ``KeyValue`` instance,\n define that instance as \"nearest\" (overwriting any previous value)\n4. if not found, emit an error, otherwise, if the replaced value is a string,\n use the new nearest instance and begin a new string replacement operation\n (allowing replaced strings to contain string replacement directives\n themselves)\n\nTODO: create examples, for now, `the test.py script\n`_ has\nsome barely-commented examples\n\nbuilding ``MultiValue`` sets\n----------------------------\nwhen adding multiple keys with the same base name and options separated by\n\"__\", those keys are grouped and become a ``MultiValue``. only one value\nwill be emitted into the JSON, selected based on the set of options provided\nto the conversion function. for now, a ``MultiValue`` set must contain a\ndefault value, which is output when no options are provided or there is no\nmatching option set. any combination of the default value and keys for\nspecific option sets may be split across a ``KeyValue`` instance and the\ninstance it inherits from. some examples::\n\n from configgen import Config, KeyValue, make_multi_key as MK\n\n # keys\n multiValue0 = 'multiValue0'\n multiValue1 = 'multiValue1'\n multiValue2 = 'multiValue2'\n\n # options\n one = 'one'\n two = 'two'\n three = 'three'\n\n # the make_multi_key() convenience function (imported here as \"MK\") helps\n # define MultiValues in a KeyValue by joining all the string parameters with\n # the option separator.\n defaults = KeyValue(**{\n multiValue0:'multiValue0 inherited, default',\n MK(multiValue0, one):'multiValue0 inherited, options: one',\n })\n\n # MultiValue keys can come from the inherited object. when this happens,\n # all of the relevant keys are copied to the inheriting KeyValue instance\n # during construction and combined into a local MultiValue instance, so\n # overrides from one KeyValue instance will not affect another instance\n # that inherits from the same object. if a key is defined with the same\n # option set in both the inheriting and inherited KeyValue instances, the\n # one in the inheriting instance is used.\n # note that section0 does not define a default for multiValue0 - it's\n # inherited from the defaults object.\n section0 = KeyValue(inherits=defaults, **{\n MK(multiValue0, one):'multiValue0 section0, options: one',\n MK(multiValue0, two, three):'multiValue0 section0, options: two, three',\n multiValue1:'multiValue1 section0, default',\n MK(multiValue1, three):'multiValue1 section0, options: three',\n #MK(multiValue2, two):'defining this by itself is an error (no default value)'\n })\n\n # section1 overrides only the default value for multiValue0. section1.multiValue2\n # shows that the value type need not be the same across all of a MultiValue.\n # section1.multiValue2 also demonstrates a case where multiple values have an\n # option set of the same cardinality. as long as the options \"one\" and \"two\"\n # are mutually exclusive, this will not cause an error.\n section1 = KeyValue(inherits=defaults, **{\n multiValue0:'multiValue0 section1, default',\n multiValue1:'multiValue1 section1, simple value',\n multiValue2:None,\n MK(multiValue2, one):{'info':'options: one'},\n MK(multiValue2, two):{'info':'options: two'},\n })\n\n cfg = Config(section0=section0, section1=section1)\n\nselecting a specific value in a ``MultiValue``\n----------------------------------------------\nfrom the command line, specify the ``--option``/``-o`` option one or more times\nto build a set of options to use when generating JSON output (the *generation\nset*). when using the ``configgen`` library directly, a python ``frozenset``\nof options should be passed to the ``Config.convertToJson()`` function as the\ngeneration set. ``configgen`` uses the following criteria when selecting a\nvalue, in order:\n\n1. a value whose option set matches the generation set exactly\n2. the value whose option set is the largest common subset of the generation\n set (ignoring any option sets that are disjoint)\n3. the default value is used if no value's option set is a subset of the\n generation set\n\nnote that because the values are selected based on set intersections, neither\nthe order of the options specified in the MultiValue key nor the command line\naffect the selection process. if there is a tie for the largest common option\nsubset between values, a ``configgen.LookupError`` *may* be raised. this\nerror can be avoided in at least two ways:\n\n* the generation set matches one of the values' option sets exactly\n* one or more of the options in the tied values' option sets are\n mutually exclusive\n\nfor example, given a MultiValue containing values with these option sets\n(excluding the default value):\n\nA. (\"server\", \"logToFile\", \"production\")\nB. (\"server\", \"verbose\", \"staging\")\nC. (\"server\", \"logToFile\", \"staging\")\n\nhere are example cases:\n\n* (\"server\", \"logToFile\", \"production\"): exact match for value A, use that one\n* (\"server\", \"verbose\", \"logToFile\", \"staging\"): error, values B and C both\n match 3 items in the generation set\n* as long as \"production\" and \"staging\" never appear in the same generation\n set alongside \"server\" and \"logToFile\", values A and C will not conflict", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://bitbucket.org/dystedium/configgen", "keywords": null, "license": "UNKNOWN", "maintainer": null, "maintainer_email": null, "name": "configgen", "package_url": "https://pypi.org/project/configgen/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/configgen/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://bitbucket.org/dystedium/configgen" }, "release_url": "https://pypi.org/project/configgen/1.0.0/", "requires_dist": null, "requires_python": null, "summary": "a noble script configgens the smallest app", "version": "1.0.0" }, "last_serial": 1620675, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "c3a5fc7ba4502c8c8a20e4dfbc91901c", "sha256": "88f49ace3cb119d3f945ba7232ce6f607467eeb905e7c961dccc939ee520ca5f" }, "downloads": -1, "filename": "configgen-0.1.0.tar.gz", "has_sig": false, "md5_digest": "c3a5fc7ba4502c8c8a20e4dfbc91901c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13008, "upload_time": "2013-10-15T08:22:29", "url": "https://files.pythonhosted.org/packages/67/39/45c4a915f8a4b45dba0a9d1a1bc960a8253582c26f025acd7cdfc61267de/configgen-0.1.0.tar.gz" } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "1622c40ee4c83ca59485bc50f648f907", "sha256": "4129721ada6024e58a0069d981156a842040929e99e5b1063a8a9a7e2f907150" }, "downloads": -1, "filename": "configgen-0.2.1.tar.gz", "has_sig": false, "md5_digest": "1622c40ee4c83ca59485bc50f648f907", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13339, "upload_time": "2015-04-20T02:31:33", "url": "https://files.pythonhosted.org/packages/af/93/0929142f9d858875069093401c0429543e20d427720d3aa9e5aea724f783/configgen-0.2.1.tar.gz" } ], "1.0.0": [ { "comment_text": "", "digests": { "md5": "7ce08661c65a2688b2826194ba8803fa", "sha256": "81552dd651458f50ec8faa062df9c5acb330f335798582d952e18e089cee0b7a" }, "downloads": -1, "filename": "configgen-1.0.0.tar.gz", "has_sig": false, "md5_digest": "7ce08661c65a2688b2826194ba8803fa", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13390, "upload_time": "2015-07-06T06:16:53", "url": "https://files.pythonhosted.org/packages/dd/92/4432b77c0ef3361d1ed51c4c7d826fdd004ae71b5cce233b76a52360a653/configgen-1.0.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "7ce08661c65a2688b2826194ba8803fa", "sha256": "81552dd651458f50ec8faa062df9c5acb330f335798582d952e18e089cee0b7a" }, "downloads": -1, "filename": "configgen-1.0.0.tar.gz", "has_sig": false, "md5_digest": "7ce08661c65a2688b2826194ba8803fa", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13390, "upload_time": "2015-07-06T06:16:53", "url": "https://files.pythonhosted.org/packages/dd/92/4432b77c0ef3361d1ed51c4c7d826fdd004ae71b5cce233b76a52360a653/configgen-1.0.0.tar.gz" } ] }