{ "info": { "author": "Hugh T. Ranalli", "author_email": "hugh@whtc.ca", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Framework :: Buildout :: Recipe", "Intended Audience :: Developers", "Intended Audience :: System Administrators", "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", "Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: System :: Software Distribution" ], "description": "Introduction\n************\nA buildout recipe to manage auto-populating portions of shared configuration \nfiles that cannot simply be overwritten.\n\n.. contents::\n\nOverview\n========\nIn complex buildouts, it is often necessary to create configuration files \nfor various services, such as an Apache web server. Where a separate file \nis used for each instance, or where it is possible to add an independent \nfile to a directory where it will be read and included in the configuration, \nthis is quite straightforward.\n\nBut some services have only one file which may need to have entries for \nmultiple applications or require manual editing. In this case generating \na file automatically is simply asking for trouble. \n\nThis recipe reads a configuration file and inserts the desired configuration \nbetween \"marker\" lines, which are comments in the configuration file. It also \nadds an optional comment identifying where these lines came from (and telling\npeople not to edit them). Upon update, the section is replaced with the \nupdated configuration and any changes outside the markers are preserved. \nThe section will also be removed if the part is removed.\n\nExample::\n\n # A sample config file\n Existing_1 = One\n Existing_2 = Two\n # START: my-buildout-section\n # Text between these lines generated by buildout. Do not remove or edit\n custom_1 = ONE\n custom_2 = TWO\n # END: my-buildout-section\n # Manual comment\n Manual_3 = Three\n\nCaveats\n=======\nWhile the marker format can be customised to accommodate different comment \nrequirements, there are probably all sorts fo things that can trip it up.\n\nThe program should run under Python 2.4 and onwards. It has not been tested \nwith Python 3, nor on a Windows platform, although it was written to be \nportable and platform independent. Feedback, test results, use cases and \npatches welcomed!\n\nUsage\n*****\n\nSimply add this recipe as a part in your buildout, specifying the target \nconfguration file to be modified and the information to add. The marker \nlines can be customised to accommodate different commenting requirements. \nBy default, a backup of the original configuation file is created before \nany changes are made, \n\nSupported options\n=================\n\n``target``\n\n Path to the file to be merged (required). If the file does not exist, it\n will be created unless create is set to False.\n \n``section`` \n \n A block of configuration text to place between the markers. You must \n specify this or \"section-file,\" or \"section-template.\"\n \n``section-file`` \n\n A file to read, whose contents will be placed between the markers. This \n is useful for more complex configurations. The file will be deleted after \n use, unless delete-file is set to False. You must specify this or \n \"section,\" or \"section-template.\"\n\n``section-template`` \n\n Set to the name of a section containing definitions for a \n collective.recipe.template template. The template section need not be \n added to the list of parts, unless you also want to execute it \n separately. When invoked, the output file will be overridden and no file \n will be created. You must specify this or \"section,\" or \"section-file.\"\n \n There are a few things to watch out for when using a template:\n \n - If you are not going to run the part, leave out the ``recipe`` \n definition, or buildout will throw an error;\n - If you aren't going to run the part, you needn't specify an output file\n either. The recipe will supply a dummy one but no output file will be \n created. If the part will be run, the output file you specify will not \n be altered;\n - The section defining the ``configmanager`` options, **not** the \n ``template`` options, will be the *base* section for the template. \n That is, defining ``foo`` in the template section and using ``${foo}``\n in the template will fail. Simply use fully qualified placeholders \n (``${section:foo}``) in your templates and everything will work \n properly.\n\n``allow-empty-section``\n\n Allow a section, section file or the results of a section-template to be \n empty (after stripping leading and trailing whitespace). If this is the \n case, the file will be left unchanged (but uninstall will still run on\n update to remove any existing entries).\n\n **Default:** False\n \n``backup`` \n \n Install and Update will create a backup which is the complete file name\n plus the extension ``.BK0``. Uninstall will create a backup with the \n extension ``.BK1``. We do it this way because of the way buildout calls\n the install and uninstall routines (and the disconnect between them). \n This approach ensures that we always have a valid backup, and that the \n install backup won't overwrite a freshly created uninstall backup. \n \n **Default:** True\n \n``create``\n \n If the target file does not exist, create it and add the defined section \n as the only contents. \n \n **Default:** True\n\n``uninstall`` \n \n Remove section from file if part is uninstalled. If the file would be \n empty after this it is deleted. If backup was originally set to True, \n A backup will be created (see the note under ``start-marker`` for \n caveats).\n \n **Default:** True\n \n``insert-after``\n \n A regex pattern to look for in the target file. If found, the section \n contents and markers will be inserted directly after this line. The regex \n uses search, not match, so it will match the pattern anywhere in the \n line. If whitespace or the location of the pattern in the line is \n important, structure your regex accordingly. If the pattern is not found,\n the section will be appended to the end of the file, as usual.\n\n **Default:** None \n \n``replace``\n \n A regex pattern to look for in the target file. If found, this line will \n be replaced by the section contents and markers. The regex \n uses search, not match, so it will match the pattern anywhere in the \n line. If whitespace or the location of the pattern in the line is \n important, structure your regex accordingly. \n \n If the pattern is not found, and ``insert-after`` was defined, that will \n be will will be used to look for an insertion point. If ``insert-after`` \n fails or was not defined, the section will be appended to the end of the \n file, as usual.\n \n **Default:** None \n\n``start-marker``\n \n A line that marks the beginning of an auto-generated section. It should\n include a unique name (e.g. the section name) in case multiple sections \n are added to the same file. You can do this by referencing \n ``${:_buildout_section_name_}`` in your custom marker definition\n\n **Default:** # BEGIN - Generated by: ${:_buildout_section_name_} \n\n .. note:: If you specify ``uninstall = false`` and later change the start-marker, the file won't be updated properly, as we rely on the uninstall routine to remove the previous markers.\n \n``end-marker`` \n\n The text to use for the ending marker line. \n \n **Default:** # END - Generated by: ${:_buildout_section_name_}\n \n``comment`` \n\n A line that will be added directly after the start marker. If blank, it \n will be omitted. \n \n **Default:** # DO NOT EDIT: Text between these lines generated \n automatically by buildout\n \n``delete-file``\n If true, delete the file specified in ``section-file`` after processing. \n \n **Default:** False\n \n``strict``\n If true, treat all warnings, such as finding a start marker without a \n matching end marker as errors.\n \n **Default:** False\n \n\nExample usage\n=============\nWe'll start with an existing file and add a section to it.\n\n >>> import os\n >>> from shutil import copy\n >>> test_path = join(os.path.dirname(__file__), 'testdata')\n >>> target_file = join(test_path, 'TEST_FILE.INI')\n >>> copy (\n ... join(test_path, 'MASTER_TEST_FILE.INI'),\n ... target_file\n ... )\n \nFirst we'll check that our data isn't in the file:\n\n >>> target = open(target_file, 'r')\n >>> contents = target.read()\n >>> target.close()\n >>> '# BEGIN' in contents\n False\n \nAnd write out our configuration:\n\n >>> write(\n ... 'buildout.cfg',\n ... \"\"\"\n ... [buildout]\n ... newest = false\n ... parts = config\n ...\n ... [config]\n ... recipe = whtc.recipe.configmanager\n ... target = %s\n ... section =\n ... four = 4\n ... five = 5\n ... \"\"\" % (target_file)\n ... )\n >>> print system(buildout)\n Installing...\n\nWe should now have a start marker, a comment, our new entries and our existing\nones:\n\n >>> target = open(target_file, 'r')\n >>> contents = target.read()\n >>> target.close()\n >>> '# BEGIN' in contents\n True\n >>> 'Text between' in contents\n True\n >>> 'four = 4' in contents\n True\n >>> '# END' in contents\n True\n >>> 'one = 1' in contents\n True\n >>> 'two = 2' in contents\n True\n\nWe always create a backup before doing anything, unless you explicity set\n``backup = false.`` See the backup option documentation for details:\n\n >>> backup_file = join(test_path, 'TEST_FILE.INI.BK0') \n >>> backup = open(backup_file, 'r')\n >>> contents = backup.read()\n >>> backup.close()\n\nOur backup has only our original contents: \n\n >>> 'one' in contents\n True\n >>> 'four' in contents\n False\n\nEmpty sections aren't allowed:\n\n >>> write(\n ... 'buildout.cfg',\n ... \"\"\"\n ... [buildout]\n ... newest = false\n ... parts = config\n ...\n ... [config]\n ... recipe = whtc.recipe.configmanager\n ... target = %s\n ... section =\n ... \"\"\" % (target_file)\n ... )\n >>> print system(buildout)\n While:\n ...\n\n Error:...\n\nIf this happens an already modified file won't be changed:\n\n >>> target = open(target_file, 'r')\n >>> contents = target.read()\n >>> target.close()\n >>> '# BEGIN' in contents\n True\n >>> 'four' in contents\n True\n \nUnless we explicitly say so:\n\n >>> write(\n ... 'buildout.cfg',\n ... \"\"\"\n ... [buildout]\n ... newest = false\n ... parts = config\n ...\n ... [config]\n ... recipe = whtc.recipe.configmanager\n ... allow-empty-section = true\n ... target = %s\n ... section =\n ... \"\"\" % (target_file)\n ... )\n >>> print system(buildout)\n Uninstalling...\n\nAnd now we see we have the markers but no data: \n \n >>> target = open(target_file, 'r')\n >>> contents = target.read()\n >>> target.close()\n >>> '# BEGIN' in contents\n True\n >>> 'one = 1' in contents\n True\n >>> 'four = 4' in contents\n False\n \nNow let's change our section contents slightly and update our file\n\n >>> write(\n ... 'buildout.cfg',\n ... \"\"\"\n ... [buildout]\n ... newest = false\n ... parts = config\n ...\n ... [config]\n ... recipe = whtc.recipe.configmanager\n ... target = %s\n ... section =\n ... four = 4\n ... six = 6\n ... \"\"\" % (target_file)\n ... )\n >>> print system(buildout)\n Uninstalling...\n\nWe should now have everything we had before, but with 'five = 5' replaced by\n'six = 6':\n\n >>> target = open(target_file, 'r')\n >>> contents = target.read()\n >>> target.close()\n >>> '# BEGIN' in contents\n True\n >>> 'Text between' in contents\n True\n >>> 'four = 4' in contents\n True\n >>> 'five' in contents\n False\n >>> 'six = 6' in contents\n True\n >>> '# END' in contents\n True\n >>> 'one = 1' in contents\n True\n >>> 'two = 2' in contents\n True\n \nWe can also look for a specific point to insert our contents: \n\n >>> write(\n ... 'buildout.cfg',\n ... \"\"\"\n ... [buildout]\n ... newest = false\n ... parts = config\n ...\n ... [config]\n ... recipe = whtc.recipe.configmanager\n ... target = %s\n ... comment = \n ... insert-after = two.*=.*\n ... section =\n ... seven = 7\n ... eight = 8\n ... \"\"\" % (target_file)\n ... )\n >>> print system(buildout)\n Uninstalling...\n\nAnd we see that our section comes after ``two = 2`` and before `three = 3``:\n >>> target = open(target_file, 'r')\n >>> contents = target.read()\n >>> target.close()\n >>> two_index = contents.find('two =')\n >>> three_index = contents.find('three =')\n >>> seven_index = contents.find('seven =')\n >>> two_index < three_index \n True\n >>> two_index < seven_index \n True\n >>> three_index > seven_index\n True \n \nAnd we can use insert-after if replace doesn't find anything: \n >>> write(\n ... 'buildout.cfg',\n ... \"\"\"\n ... [buildout]\n ... newest = false\n ... parts = config\n ...\n ... [config]\n ... recipe = whtc.recipe.configmanager\n ... target = %s\n ... comment = \n ... replace = zero.*=.*\n ... insert-after = two.*=.*\n ... section =\n ... nine = 9\n ... ten = 10\n ... \"\"\" % (target_file)\n ... )\n >>> print system(buildout)\n Uninstalling... \n\nAnd our section still comes after ``two = 2`` and before `three = 3``:\n >>> target = open(target_file, 'r')\n >>> contents = target.read()\n >>> target.close()\n >>> two_index = contents.find('two =')\n >>> three_index = contents.find('three =')\n >>> nine_index = contents.find('nine =')\n >>> two_index < three_index \n True\n >>> two_index < nine_index \n True\n >>> three_index > nine_index\n True \n \nWe can replace an existing line in a file:\n\n >>> write(\n ... 'buildout.cfg',\n ... \"\"\"\n ... [buildout]\n ... newest = false\n ... parts = config\n ...\n ... [config]\n ... recipe = whtc.recipe.configmanager\n ... target = %s\n ... comment = \n ... replace = two.*=.*\n ... section =\n ... eleven = 11\n ... twelve = 12\n ... \"\"\" % (target_file)\n ... )\n >>> target = open(target_file, 'r')\n >>> contents = target.read()\n >>> target.close()\n >>> original_two_index = contents.find('two =')\n >>> print system(buildout)\n Uninstalling...\n \nAnd now our section replaces ``two = 2``\n >>> target = open(target_file, 'r')\n >>> contents = target.read()\n >>> target.close()\n >>> two_index = contents.find('two =')\n >>> three_index = contents.find('three =')\n >>> begin_index = contents.find('# BEGIN')\n >>> eleven_index = contents.find('eleven =')\n >>> two_index == -1\n True\n >>> begin_index == original_two_index\n True\n >>> eleven_index < three_index \n True \n \nWe can also supply custom section markers:\n\n >>> write(\n ... 'buildout.cfg',\n ... \"\"\"\n ... [buildout]\n ... newest = false\n ... parts = config\n ...\n ... [config]\n ... recipe = whtc.recipe.configmanager\n ... target = %s\n ... start-marker = /*START: ${:_buildout_section_name_}*/\n ... end-marker = /*FINISH: ${:_buildout_section_name_}*/\n ... comment = \n ... section =\n ... thirteen = 13\n ... \"\"\" % (target_file)\n ... )\n >>> print system(buildout)\n Uninstalling...\n\nAnd we see our markers have changed\n\n >>> target = open(target_file, 'r')\n >>> contents = target.read()\n >>> target.close()\n >>> '# BEGIN' in contents\n False\n >>> '# END' in contents\n False\n >>> '/*START: config*/' in contents\n True\n >>> '/*FINISH: config*/' in contents\n True\n \nOur section contents can come from a file:\n\n >>> section_file = join(test_path, 'SECTION_FILE.TXT')\n >>> copy (\n ... join(test_path, 'MASTER_SECTION_FILE.TXT'),\n ... section_file\n ... )\n >>> write(\n ... 'buildout.cfg',\n ... \"\"\"\n ... [buildout]\n ... newest = false\n ... parts = config\n ...\n ... [config]\n ... recipe = whtc.recipe.configmanager\n ... target = %s\n ... start-marker = /*BEGIN: ${:_buildout_section_name_}*/\n ... end-marker = /*FINISH: ${:_buildout_section_name_}*/\n ... comment = \n ... section-file = %s\n ... \"\"\" % (target_file, section_file)\n ... )\n >>> print system(buildout)\n Uninstalling...\n\nAnd our file now contains the settings from the input file:\n >>> target = open(target_file, 'r')\n >>> contents = target.read()\n >>> target.close()\n >>> '# six' in contents\n False\n >>> 'fourteen = 14' in contents\n True\n >>> '// This' in contents\n True\n\nOur input file can be deleted after use if we wish:\n\n >>> write(\n ... 'buildout.cfg',\n ... \"\"\"\n ... [buildout]\n ... newest = false\n ... parts = config\n ...\n ... [config]\n ... recipe = whtc.recipe.configmanager\n ... target = %s\n ... start-marker = /*BEGIN: ${:_buildout_section_name_}*/\n ... end-marker = /*FINISH: ${:_buildout_section_name_}*/\n ... comment = \n ... section-file = %s\n ... delete-file = true\n ... \"\"\" % (target_file, section_file)\n ... )\n >>> print system(buildout)\n Uninstalling... \n >>> os.stat(section_file)\n Traceback (most recent call last):\n ...\n OSError: ...\n\nWe can also use a template generated by collective.recipe.template. Note \nthat we don't add the ``template`` section to the parts, as we aren't \ninstalling it on its own. If you did also want to generate an output file \nwith the ``template`` part, you could certainly do so. You also don't need\nto specify ``output`` or ``recipe``; we do here simply to show that no \noutput file will be created:\n \n >>> output_file = join(test_path, 'OUTPUT.TXT')\n >>> template_file = join(test_path, 'TEMPLATE.IN')\n >>> write(\n ... 'buildout.cfg',\n ... \"\"\"\n ... [buildout]\n ... newest = false\n ... parts = config\n ...\n ... [template]\n ... input = %s\n ... output = %s\n ... sixteen-var = 16\n ... seventeen-var = 17\n ... \n ... [config]\n ... recipe = whtc.recipe.configmanager\n ... target = %s\n ... start-marker = /*BEGIN: ${:_buildout_section_name_}*/\n ... end-marker = /*FINISH: ${:_buildout_section_name_}*/\n ... comment = \n ... section-template = template\n ... \"\"\" % (template_file, output_file, target_file)\n ... )\n >>> print system(buildout)\n Uninstalling... \n\nAnd our file now contains the settings from the template with the variables\ninserted:\n\n >>> target = open(target_file, 'r')\n >>> contents = target.read()\n >>> target.close()\n >>> '# seven' in contents\n False\n >>> 'sixteen = 16' in contents\n True\n >>> '// Test template' in contents\n True\n\nAnd a template output file was not created:\n \n >>> os.stat(output_file)\n Traceback (most recent call last):\n ...\n OSError: ...\n\nBut if we want, we can run the template part as well, and a file will be\ncreated:\n \n >>> write(\n ... 'buildout.cfg',\n ... \"\"\"\n ... [buildout]\n ... newest = false\n ... parts = config template\n ...\n ... [template]\n ... recipe = collective.recipe.template\n ... input = %s\n ... output = %s\n ... sixteen-var = 16\n ... seventeen-var = 17\n ... \n ... [config]\n ... recipe = whtc.recipe.configmanager\n ... target = %s\n ... start-marker = /*BEGIN: ${:_buildout_section_name_}*/\n ... end-marker = /*FINISH: ${:_buildout_section_name_}*/\n ... comment = // This is new\n ... section-template = template\n ... \"\"\" % (template_file, output_file, target_file)\n ... )\n >>> print system(buildout)\n Uninstalling... \n\nThe output file exists:\n\n >>> test = os.stat(output_file)\n \nAnd our section was updated: \n\n >>> target = open(target_file, 'r')\n >>> contents = target.read()\n >>> target.close()\n >>> '// This is new' in contents\n True\n \nWe don't have to have an input file to read from. If the file doesn't exist, \nwe will create it (unless you specify ``create = false``):\n \n >>> os.remove(target_file)\n >>> write(\n ... 'buildout.cfg',\n ... \"\"\"\n ... [buildout]\n ... newest = false\n ... parts = config\n ...\n ... [config]\n ... recipe = whtc.recipe.configmanager\n ... target = %s\n ... start-marker = /*BEGIN: ${:_buildout_section_name_}*/\n ... end-marker = /*FINISH: ${:_buildout_section_name_}*/\n ... comment = \n ... section =\n ... eighteen = 18\n ... nineteen = 19\n ... \"\"\" % (target_file)\n ... )\n >>> print system(buildout)\n Uninstalling...\n\nOur file has our data, but nothing else:\n\n >>> target = open(target_file, 'r')\n >>> contents = target.read()\n >>> target.close()\n >>> 'one' in contents\n False\n >>> 'eighteen' in contents\n True\n \nFinally, our section will be removed if the part is uninstalled. If the\nresult would be an empty file, the file will be removed. Just for fun we'll\nchange the marker definitions, to show that uninstall will still work:\n\n >>> os.remove(target_file)\n >>> write(\n ... 'buildout.cfg',\n ... \"\"\"\n ... [buildout]\n ... newest = false\n ... parts = \n ...\n ... [config]\n ... recipe = whtc.recipe.configmanager\n ... target = %s\n ... start-marker = //BEGIN: ${:_buildout_section_name_}\n ... end-marker = //FINISH: ${:_buildout_section_name_}\n ... comment = \n ... section =\n ... ten = 10\n ... eleven = 11\n ... \"\"\" % (target_file)\n ... )\n >>> print system(buildout)\n Uninstalling...\n\nThe file is gone:\n\n >>> os.stat(target_file)\n Traceback (most recent call last):\n ...\n OSError: ...\n\nBut a backup (.BK1) was created, because ``backup = true`` by default:\n >>> backup_file = join(test_path, 'TEST_FILE.INI.BK1') \n >>> backup = open(backup_file, 'r')\n >>> contents = backup.read()\n >>> backup.close()\n >>> print contents\n # Test file...\n\nChange History\n**************\n\n1.1.3\n=====\n- Fixed bug when, on an update, an existing line was removed and then \ncouldn't be found to update it, and so the lines were added to the end.\nThis was particularly a problem when the lines must be processed in their\noriginal order, such as in a PHP include file.\n- Updated tests file to use standard library doctest module in place of the\n(now removed) zope.testing version\n\n1.1.2\n=====\n- Fixed exception when uninstall was called\n\n1.1.1\n=====\n- Fixed bug when attempting to remove a file when contents would be empty\n\n1.1\n======\n\n- Added \"replace\" option and updated tests\n- Moved development status to Production/Stable\n\n\n1.0rc1\n======\n\n- Initial public release.\n\nDownload\n********", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://pypi.python.org/pypi/whtc.recipe.configmanager", "keywords": "config configuration recipe buildout template", "license": "", "maintainer": "", "maintainer_email": "", "name": "whtc.recipe.configmanager", "package_url": "https://pypi.org/project/whtc.recipe.configmanager/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/whtc.recipe.configmanager/", "project_urls": { "Homepage": "http://pypi.python.org/pypi/whtc.recipe.configmanager" }, "release_url": "https://pypi.org/project/whtc.recipe.configmanager/1.1.3/", "requires_dist": null, "requires_python": "", "summary": "A buildout recipe to manage auto-populating portions of shared configuration files that cannot simply be overwritten.", "version": "1.1.3" }, "last_serial": 2464857, "releases": { "1.0rc1": [ { "comment_text": "", "digests": { "md5": "f17f21d5919b9e383c96047369030538", "sha256": "c4abda4b44e7b3b698bde2b15645630374595162bb8bc297c0c241a494573c60" }, "downloads": -1, "filename": "whtc.recipe.configmanager-1.0rc1.tar.gz", "has_sig": false, "md5_digest": "f17f21d5919b9e383c96047369030538", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 29768, "upload_time": "2014-11-21T03:49:27", "url": "https://files.pythonhosted.org/packages/6a/73/06574ee565ecb9c7ac46eac4b26999a01a00973b8a2a203e4d1497120b72/whtc.recipe.configmanager-1.0rc1.tar.gz" }, { "comment_text": "", "digests": { "md5": "f8a5ce67aa3e49d356fab71e96d24c53", "sha256": "1c79eb0bf36dee67ff040f26d040a98df780784eb14784e9bb70473537760624" }, "downloads": -1, "filename": "whtc.recipe.configmanager-1.1.tar.gz", "has_sig": false, "md5_digest": "f8a5ce67aa3e49d356fab71e96d24c53", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 31040, "upload_time": "2015-07-03T16:45:37", "url": "https://files.pythonhosted.org/packages/f6/d1/71425a2dfe3c13766bcc9206b3fcfcbf7042a54e3389aedec39d9b1f6686/whtc.recipe.configmanager-1.1.tar.gz" } ], "1.1": [], "1.1.1": [ { "comment_text": "", "digests": { "md5": "0b90136abf26af7778828824df4f6b97", "sha256": "530ccb2ce387f54986abc443bc5fb822d0051bde1c86ee3a8002479bbfd8ced2" }, "downloads": -1, "filename": "whtc.recipe.configmanager-1.1.1.tar.gz", "has_sig": false, "md5_digest": "0b90136abf26af7778828824df4f6b97", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 31158, "upload_time": "2015-07-13T18:41:54", "url": "https://files.pythonhosted.org/packages/5f/b2/393101fa2f49f8c2a0cb5b8463b258a912922f29bf2d80bbdc481d0ef8fb/whtc.recipe.configmanager-1.1.1.tar.gz" } ], "1.1.2": [ { "comment_text": "", "digests": { "md5": "1c9d873af2a49f6136b88af8699eee29", "sha256": "dcb04a13d521da71ad3f8a79bbf781e9d501528ad64e3bfa506f0305764b5e54" }, "downloads": -1, "filename": "whtc.recipe.configmanager-1.1.2.tar.gz", "has_sig": false, "md5_digest": "1c9d873af2a49f6136b88af8699eee29", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 31219, "upload_time": "2016-11-04T17:17:11", "url": "https://files.pythonhosted.org/packages/03/f3/ed466e202b398cf034c73f2403302a8e65e9c3afd7a0882e7422ba5a0a0f/whtc.recipe.configmanager-1.1.2.tar.gz" } ], "1.1.3": [ { "comment_text": "", "digests": { "md5": "04de42c2e840e94fe2067872cebd8e45", "sha256": "fe13909ff34715e6741b2b604c9a983547fb6521ac75d3e965fe6a7034cccb9a" }, "downloads": -1, "filename": "whtc.recipe.configmanager-1.1.3.tar.gz", "has_sig": false, "md5_digest": "04de42c2e840e94fe2067872cebd8e45", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 31613, "upload_time": "2016-11-16T19:38:15", "url": "https://files.pythonhosted.org/packages/69/f8/38a3cec4ba2cd905dc38b94a15d075c73b903962cd31155141dcb7c7fe46/whtc.recipe.configmanager-1.1.3.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "04de42c2e840e94fe2067872cebd8e45", "sha256": "fe13909ff34715e6741b2b604c9a983547fb6521ac75d3e965fe6a7034cccb9a" }, "downloads": -1, "filename": "whtc.recipe.configmanager-1.1.3.tar.gz", "has_sig": false, "md5_digest": "04de42c2e840e94fe2067872cebd8e45", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 31613, "upload_time": "2016-11-16T19:38:15", "url": "https://files.pythonhosted.org/packages/69/f8/38a3cec4ba2cd905dc38b94a15d075c73b903962cd31155141dcb7c7fe46/whtc.recipe.configmanager-1.1.3.tar.gz" } ] }