{ "info": { "author": "Zope Corporation and Contributors", "author_email": "zope-dev@zope.org", "bugtrack_url": null, "classifiers": [ "Environment :: Web Environment", "Framework :: Zope :: 3", "Intended Audience :: Developers", "License :: OSI Approved :: Zope Public License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Internet :: WWW/HTTP" ], "description": "The zc.form package is a possibly temporary appendage used to hold extra\nbrowser widgets and alternative approaches to code found in the\nzope.formlib package. Most or all of the code is created by Zope\nCorporation and is intended for eventual folding into the main Zope 3\nrelease.\n\n\n.. contents::\n\n=======\nChanges\n=======\n\n1.1 (2019-02-11)\n----------------\n\n- Fix ZCML configuration issue if the ``[mruwidget]`` extra was not installed.\n\n\n1.0 (2019-01-11)\n----------------\n\nFeatures\n++++++++\n\n- Claim support for Python 3.5, 3.6, 3.7, PyPy and PyPy3.\n\nBugfixes\n++++++++\n\n- Fix a ``NameError`` in ``BaseVocabularyDisplay.render()``.\n\n- Actually pass a ``missing_value`` set on the ``Combination`` field to the\n containing fields.\n\nCaveats\n+++++++\n\n- Installation of ``MruSourceInputWidget`` and ``TimeZoneWidget`` requires the\n ``[mruwidget]`` extra to break dependency on ``zc.resourcelibrary`` for\n projects which do not need it.\n\n\n0.5 (2016-08-02)\n----------------\n\n- Bind fields that are contained in a ``zc.form.field.Combination`` to fix the\n ``context`` of those fields.\n\n\n0.4 (2016-01-12)\n----------------\n\n- Get rid of the `zope.app.pagetemplate` dependency.\n\n\n0.3 (2014-04-23)\n----------------\n\n- Remove requirement, that ``zc.form.field.Combination`` needs at least\n two subfields.\n\n\n0.2 (2011-09-24)\n----------------\n\n- Got rid of ``zope.app.form`` dependency by requiring at least\n ``zope.formlib`` 4.0.\n\n- Got rid of ``zope.app.component`` dependency by requiring at least\n ``zope.component`` 3.8.\n\n- Depending on ``zope.catalog`` instead of ``zope.app.catalog``.\n\n- Depending on ``zope.security`` instead of ``zope.app.security``.\n\n- Depending on ``zope.app.wsgi`` >=3.7 instead of ``zope.app.testing`` for\n test setup.\n\n- Depending on ``zope.browserpage`` and ``zope.container`` instead of\n ``zope.app.publisher``.\n\n- Got rid of the following dependencies:\n\n - ``zope.app.basicskin``\n - ``zope.app.securitypolicy``\n - ``zope.app.zapi``\n - ``zope.app.zcmlfiles``\n\n- Fixed tests to run with ``zope.schema`` >= 3.6.\n\n- Made package fit to run on ZTK 1.1.\n\n- Moved test dependencies to `test` extra.\n\n- Using Python's ``doctest`` module instead of deprecated\n ``zope.testing.doctest``.\n\n\n0.1\n---\n\n- Exception views are now unicode aware. They used to break on translated\n content.\n\n- Added use_default_for_not_selected to Union field to use default\n value even if sub field is not selected.\n\n\n===================\n CombinationWidget\n===================\n\nThe combinationwidget collects two or more subfields to provide a convenient\nway to specify a sequence of values.\n\nRendering the widget returns a table with the subfields::\n\n >>> from zc.form.browser.combinationwidget import (\n ... CombinationWidget, CombinationDisplayWidget, default_template)\n >>> from zope import component, interface\n >>> component.provideAdapter(default_template, name='default')\n >>> from zc.form.field import Combination, OrderedCombinationConstraint\n >>> from zope.schema import Int\n >>> from zope.schema.interfaces import IInt\n >>> from zope.publisher.interfaces.browser import IBrowserRequest\n >>> from zope.formlib.interfaces import IInputWidget\n >>> from zope.formlib.textwidgets import IntWidget\n >>> component.provideAdapter(\n ... IntWidget, (IInt, IBrowserRequest), IInputWidget)\n >>> from zope import interface\n >>> class IDemo(interface.Interface):\n ... acceptable_count = Combination(\n ... (Int(title=u'Minimum', required=True, min=0),\n ... Int(title=u'Maximum', required=False)),\n ... title=u'Acceptable Count',\n ... required=False,\n ... constraints=(OrderedCombinationConstraint(),))\n ...\n >>> from zope.publisher.browser import TestRequest\n >>> request = TestRequest()\n >>> widget = CombinationWidget(IDemo['acceptable_count'], request)\n >>> widget.setPrefix('field')\n >>> widget.loadValueFromRequest() # None\n >>> print(widget())\n \n \n \n \n \n \n \n \n \n \n
\n \n \n
\n
\n
\n \n \n
\n
\n
\n\nSetting the appropriate values in the Request lets the widget correctly read\nthe specified value::\n\n >>> request.form['field.acceptable_count-marker'] = 'x'\n >>> request.form['field.acceptable_count.combination_00'] = '10'\n >>> request.form['field.acceptable_count.combination_01'] = ''\n >>> widget = CombinationWidget(IDemo['acceptable_count'], request)\n >>> widget.setPrefix('field')\n >>> widget.getInputValue()\n (10, None)\n >>> print(widget())\n <...\n ......\n ......\n\n\nThe field is fine with empty values, because it is not required::\n\n >>> request.form['field.acceptable_count-marker'] = 'x'\n >>> request.form['field.acceptable_count.combination_00'] = ''\n >>> request.form['field.acceptable_count.combination_01'] = ''\n >>> widget = CombinationWidget(IDemo['acceptable_count'], request)\n >>> widget.setPrefix('field')\n >>> widget.getInputValue() # None\n >>> print(widget())\n <...\n ......\n ......\n >>> bool(widget.error())\n False\n >>> bool(widget.widgets[0].error())\n False\n\nIf the optional value is filled in and the required one is not, though, there\nare errors::\n\n >>> request.form['field.acceptable_count-marker'] = 'x'\n >>> request.form['field.acceptable_count.combination_00'] = ''\n >>> request.form['field.acceptable_count.combination_01'] = '10'\n >>> widget = CombinationWidget(IDemo['acceptable_count'], request)\n >>> widget.setPrefix('field')\n >>> widget.getInputValue()\n Traceback (most recent call last):\n WidgetInputError: ('acceptable_count', u'Acceptable Count',\n WidgetInputError('combination_00', u'Minimum',\n RequiredMissing('combination_00')))\n >>> import zope.formlib.interfaces\n >>> import zope.publisher.interfaces.browser\n >>> @interface.implementer(zope.formlib.interfaces.IWidgetInputErrorView)\n ... @component.adapter(zope.formlib.interfaces.WidgetInputError,\n ... zope.publisher.interfaces.browser.IBrowserRequest)\n ... class SnippetView(object):\n ...\n ... def __init__(self, context, request):\n ... self.context = context\n ... self.request = request\n ... def snippet(self):\n ... return self.context.doc()\n ...\n >>> component.provideAdapter(SnippetView)\n >>> print(widget())\n <...\n ......\n ...Required input is missing...\n ......\n >>> print(widget.error())\n Required input is missing.\n >>> print(widget.widgets[0].error())\n Required input is missing.\n\nSimilarly, if the field's constraints are not met, the widget shows errors::\n\n >>> request.form['field.acceptable_count-marker'] = 'x'\n >>> request.form['field.acceptable_count.combination_00'] = '20'\n >>> request.form['field.acceptable_count.combination_01'] = '10'\n >>> widget = CombinationWidget(IDemo['acceptable_count'], request)\n >>> widget.setPrefix('field')\n >>> widget.getInputValue()\n Traceback (most recent call last):\n WidgetInputError: ('acceptable_count', u'Acceptable Count',\n MessageValidationError(u'${minimum} ...\n >>> print(widget())\n <...\n ...input class=\"textType\" id=\"field.acceptable_count.combination_00\"\n name=\"field.acceptable_count.combination_00\" size=\"10\"\n type=\"text\" value=\"20\" />...\n ......\n >>> print(widget.error())\n ${minimum} must be less than or equal to ${maximum}.\n\n\nThere's also a display version of the widget::\n\n >>> request = TestRequest()\n >>> from zope.formlib.widget import DisplayWidget\n >>> from zope.formlib.interfaces import IDisplayWidget\n >>> component.provideAdapter(\n ... DisplayWidget, (IInt, IBrowserRequest), IDisplayWidget)\n >>> widget = CombinationDisplayWidget(IDemo['acceptable_count'], request)\n >>> widget.setPrefix('field')\n >>> widget.setRenderedValue(('10', '2'))\n >>> print(widget())\n \n \n \n \n \n \n \n \n \n \n
\n \n \n
10\n
\n
\n \n \n
2\n
\n
\n\nIn case of a wrong amount of parameters, the missing_value is used::\n\n >>> field = IDemo['acceptable_count']\n >>> field.missing_value=('23', '42')\n >>> widget = CombinationDisplayWidget(field, request)\n >>> widget.setPrefix('field')\n >>> widget.setRenderedValue(('10', '2', '3'))\n >>> print(widget())\n \n \n \n \n \n \n \n \n \n \n
\n \n \n
23\n
\n
\n \n \n
42\n
\n
\n\nIn case the parameter is not a sequence, the missing_value is used::\n\n >>> widget = CombinationDisplayWidget(field, request)\n >>> widget.setPrefix('field')\n >>> widget.setRenderedValue(10)\n >>> print(widget())\n \n \n \n \n \n \n \n \n \n \n
\n \n \n
23\n
\n
\n \n \n
42\n
\n
\n\nThe order of label and field are inverted in case of boolean::\n\n >>> request = TestRequest()\n >>> from zope.schema import Bool\n >>> from zope.schema.interfaces import IBool\n >>> from zope.formlib.boolwidgets import CheckBoxWidget\n >>> from zope.formlib.widget import DisplayWidget\n >>> from zope.formlib.interfaces import IDisplayWidget\n >>> component.provideAdapter(\n ... CheckBoxWidget, (IBool, IBrowserRequest), IInputWidget)\n >>> class IBoolDemo(interface.Interface):\n ... choices = Combination(\n ... (Bool(title=u'first'),\n ... Bool(title=u'second')),\n ... title=u'Choices',\n ... required=False,)\n\n >>> widget = CombinationWidget(IBoolDemo['choices'], request)\n >>> widget.setPrefix('field')\n >>> print(widget())\n \n \n \n \n \n \n \n \n \n \n
\n
\n first\n
\n
\n
\n second\n
\n
\n\n\n\n========================================\n Most Recently Used (MRU) Source Widget\n========================================\n\nThe MRU widget keeps track of the last few values selected (on a per-principal\nbasis) and allows quickly selecting from that list instead of using a query\ninterface.\n\nWe can see the widget in action by using a custom form. Let's define a schema\nfor the form that uses a source::\n\n >>> import zope.interface\n >>> import zope.schema\n\n >>> class IDemo(zope.interface.Interface):\n ...\n ... color = zope.schema.Choice(\n ... title=u\"Color\",\n ... description=u\"My favorite color\",\n ... source=AvailableColors,\n ... )\n\nAnd then a class that implements the interface::\n\n >>> @zope.interface.implementer(IDemo)\n ... class Demo(object):\n ...\n ... color = None\n\nWe'll need a form that uses this schema::\n\n >>> import zope.formlib.form\n\n >>> class DemoInput(zope.formlib.form.EditForm):\n ... actions = ()\n ... form_fields = zope.formlib.form.fields(IDemo)\n\nBy rendering the form we can see that there are no MRU items to choose from\n(because this principal has never visited this form before) and the query\ninterface is displayed::\n\n >>> import zope.publisher.browser\n >>> import zope.security.interfaces\n >>> import zope.security.management\n >>> import zope.component.hooks\n\n >>> @zope.interface.implementer(zope.security.interfaces.IPrincipal)\n ... class DummyPrincipal(object):\n ...\n ... id = \"someuser\"\n ... title = \"Some User's Name\"\n ... description = \"A User\"\n\nNote that we need to use the special resourcelibrary request. We're\nhacking together the TestRequest and the resourcelibrary request here; when we\nswitch to TestBrowser we can remove this oddity.\n\n >>> import zc.resourcelibrary.publication\n >>> class TestRequest(zope.publisher.browser.TestRequest,\n ... zc.resourcelibrary.publication.Request):\n ... def _createResponse(self):\n ... return zc.resourcelibrary.publication.Request._createResponse(\n ... self)\n ...\n\n >>> request = TestRequest()\n >>> principal = DummyPrincipal()\n >>> request.setPrincipal(principal)\n >>> zope.security.management.newInteraction(request)\n\n >>> oldsite = zope.component.hooks.getSite()\n >>> zope.component.hooks.setSite(getRootFolder())\n\nNow we can use an instance of our demo object to see that the form\npulls the possible values from the vocabulary we've defined above::\n\n >>> form = DemoInput(Demo(), request)\n >>> print(form())\n <...\n
\n
\n
\n \n
\n
\n
\n ...\n\nNote that the select box of MRU values isn't in the output, because the user\nhas never selected a value before::\n\n >>> '\n \n \n ...\n\nAnd the query view is hidden because we have an MRU list::\n\n >>> print(form())\n <...\n \n ...\n\nIf we select another value...::\n\n >>> request = TestRequest()\n >>> request.form = {\n ... 'form.color.query.selection': 'green_token',\n ... 'form.color.query.apply': 'Apply',\n ... 'form.color.displayed': '',\n ... }\n >>> request.setPrincipal(principal)\n\n...and process the request, the list of MRU values includes the new one, at\nthe top, and it is selected::\n\n >>> form = DemoInput(Demo(), request)\n >>> print(form())\n <...\n \n ...\n\nIf we request a value not in the source everything stays the same, but nothing\nis selected::\n\n >>> request = TestRequest()\n >>> request.form = {\n ... 'form.color.query.selection': 'blue_token',\n ... 'form.color.query.apply': 'Apply',\n ... 'form.color.displayed': '',\n ... }\n >>> request.setPrincipal(principal)\n >>> form = DemoInput(Demo(), request)\n >>> print(form())\n <...\n \n ...\n\nWe can make the query visible::\n\n >>> request = TestRequest()\n >>> request.form = {\n ... 'form.color.query.selection': 'red_token',\n ... 'form.color.query.apply': 'Apply',\n ... 'form.color.queries.visible': 'yes',\n ... 'form.color.query.search': 'yes',\n ... 'form.color.query.searchstring': 'red',\n ... 'form.color.displayed': '',\n ... }\n >>> request.setPrincipal(principal)\n >>> form = DemoInput(Demo(), request)\n >>> print(form())\n <...\n \n ...\n \n \n ...\n\nIt is not shown if the query is not applied::\n\n >>> request = TestRequest()\n >>> request.form = {\n ... 'form.color.query.selection': 'red_token',\n ... 'form.color.queries.visible': 'yes',\n ... 'form.color.query.search': 'yes',\n ... 'form.color.query.searchstring': 'red',\n ... 'form.color.displayed': '',\n ... }\n >>> request.setPrincipal(principal)\n >>> form = DemoInput(Demo(), request)\n >>> print(form())\n <...\n \n ...\n \n \n ...\n\nTokens in the annotation of the principal are ignored if they are not in the\nsource::\n\n >>> from zope.annotation.interfaces import IAnnotations\n >>> annotations = IAnnotations(principal)\n >>> annotation = annotations.get('zc.form.browser.mruwidget')\n >>> tokens = annotation.get('form.color')\n >>> tokens.append('black_token')\n >>> tokens\n ['red_token', 'green_token', 'black_token']\n\n >>> print(form())\n <...\n \n ...\n \n \n ...\n\n\nClean up a bit::\n\n >>> zope.security.management.endInteraction()\n >>> zope.component.hooks.setSite(oldsite)\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/zopefoundation/zc.form", "keywords": "zope formlib form widget extra", "license": "ZPL 2.1", "maintainer": "", "maintainer_email": "", "name": "zc.form", "package_url": "https://pypi.org/project/zc.form/", "platform": "", "project_url": "https://pypi.org/project/zc.form/", "project_urls": { "Homepage": "https://github.com/zopefoundation/zc.form" }, "release_url": "https://pypi.org/project/zc.form/1.1/", "requires_dist": [ "pytz", "setuptools", "six", "zc.sourcefactory", "zope.browserpage", "zope.cachedescriptors", "zope.catalog", "zope.component (>=3.8)", "zope.exceptions", "zope.formlib (>=4.0)", "zope.index", "zope.interface", "zope.publisher", "zope.schema (>=3.6)", "zope.security", "BTrees; extra == 'mruwidget'", "persistent; extra == 'mruwidget'", "zc.resourcelibrary; extra == 'mruwidget'", "zope.annotation; extra == 'mruwidget'", "zope.app.appsetup; extra == 'slimtest'", "zope.app.principalannotation; extra == 'slimtest'", "zope.app.wsgi[testlayer] (>=3.7); extra == 'slimtest'", "zope.configuration; extra == 'slimtest'", "zope.container; extra == 'slimtest'", "zope.testing; extra == 'slimtest'", "zope.testrunner; extra == 'slimtest'", "zope.traversing; extra == 'slimtest'", "BTrees; extra == 'test'", "persistent; extra == 'test'", "zc.resourcelibrary; extra == 'test'", "zope.annotation; extra == 'test'", "zope.app.appsetup; extra == 'test'", "zope.app.principalannotation; extra == 'test'", "zope.app.wsgi[testlayer] (>=3.7); extra == 'test'", "zope.configuration; extra == 'test'", "zope.container; extra == 'test'", "zope.testing; extra == 'test'", "zope.testrunner; extra == 'test'", "zope.traversing; extra == 'test'" ], "requires_python": "", "summary": "Extra browser widgets and alternative approaches for zope.formlib.", "version": "1.1" }, "last_serial": 4804764, "releases": { "0.1.2": [ { "comment_text": "", "digests": { "md5": "b8006b2a0fc39d2d3e866fa0e8dab677", "sha256": "2934274cb9fc770f1997b63ce6bfdd9e030e014754d5b96bc3bf4a10b58da2e8" }, "downloads": -1, "filename": "zc.form-0.1.2.tar.gz", "has_sig": false, "md5_digest": "b8006b2a0fc39d2d3e866fa0e8dab677", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 28281, "upload_time": "2008-05-16T13:47:45", "url": "https://files.pythonhosted.org/packages/04/16/59d78da7627d8fe5f53fd85cef9a99929cc30d347bf8bb91c259864bc32a/zc.form-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "00cb97bf673e9c2b3a427bf13fad8cdc", "sha256": "8db2a4d303e22aa9ebcaef11a6ce4d076220dd54f6c21d1c14b4b0e62c2224ab" }, "downloads": -1, "filename": "zc.form-0.1.3.tar.gz", "has_sig": false, "md5_digest": "00cb97bf673e9c2b3a427bf13fad8cdc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 28333, "upload_time": "2009-01-05T20:36:17", "url": "https://files.pythonhosted.org/packages/3d/5b/3d91e26f10686d10f8e2dff3bf8fd5d7e82eb272b6b13db1f8d48a6c9185/zc.form-0.1.3.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "76c7b251199d256d74076d76e5f85320", "sha256": "9db2e641fe87fc224993cf23ae9cc58b667d99ff5df0f09cf9de9f8c10b85e05" }, "downloads": -1, "filename": "zc.form-0.2.tar.gz", "has_sig": false, "md5_digest": "76c7b251199d256d74076d76e5f85320", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 36829, "upload_time": "2011-09-24T07:07:07", "url": "https://files.pythonhosted.org/packages/bf/a9/57986d0443b877ff61034f134cd22260d2d01c18130098f50b193eb190b1/zc.form-0.2.tar.gz" } ], "0.3": [ { "comment_text": "", "digests": { "md5": "f15b08271df6251c869391460986fdd0", "sha256": "1db7345809382f98dbb1b68845c2e795efb5db8b60c37b17bc6e8abdea36339e" }, "downloads": -1, "filename": "zc.form-0.3.zip", "has_sig": false, "md5_digest": "f15b08271df6251c869391460986fdd0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 56105, "upload_time": "2014-04-23T12:43:14", "url": "https://files.pythonhosted.org/packages/bd/17/3ba070a5b5398622c7e47b0e1fa18c8cfcf9f5a8c3d6ac110bffc3805f39/zc.form-0.3.zip" } ], "0.4": [ { "comment_text": "", "digests": { "md5": "dad364416df12e31678db1a4738feeb4", "sha256": "4e843b59a771c9205422c12c50639bc910227a8f5fc7b8f3e8f0aba8d3102830" }, "downloads": -1, "filename": "zc.form-0.4.tar.gz", "has_sig": false, "md5_digest": "dad364416df12e31678db1a4738feeb4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 37070, "upload_time": "2016-01-12T09:48:45", "url": "https://files.pythonhosted.org/packages/3e/ce/a588590c505373de4a1e2df699a825d33dfda32c87838c9aae53f15bd1ce/zc.form-0.4.tar.gz" } ], "0.5": [ { "comment_text": "", "digests": { "md5": "0845583220393ecb258c34c998c3c3bc", "sha256": "7f4eb0b76b00a0dcdcbcde3d8dd099a66aeb36732c0e006b6750b59110226cc1" }, "downloads": -1, "filename": "zc.form-0.5.tar.gz", "has_sig": false, "md5_digest": "0845583220393ecb258c34c998c3c3bc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 37041, "upload_time": "2016-08-02T07:35:24", "url": "https://files.pythonhosted.org/packages/69/6b/56fe86868d0b0c14c844c8e2d4f20b85f39659090934fe6066789e9bc3f7/zc.form-0.5.tar.gz" } ], "1.0": [ { "comment_text": "", "digests": { "md5": "685e7937f3c9aa82aa35b0d98e6e4600", "sha256": "af63c8d6cc05f748e261aee83ac13671c84b5f3123e1996b64f522fe976fcfa0" }, "downloads": -1, "filename": "zc.form-1.0.tar.gz", "has_sig": false, "md5_digest": "685e7937f3c9aa82aa35b0d98e6e4600", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 41630, "upload_time": "2019-01-11T10:53:47", "url": "https://files.pythonhosted.org/packages/46/89/51b17f8176dfbbafd31047e4012f8b149484616eeaaeb62a44fdcba7867f/zc.form-1.0.tar.gz" } ], "1.1": [ { "comment_text": "", "digests": { "md5": "6f0d068933d5544a3625da15b8d76bb3", "sha256": "243c3818476d1317f118e2de43372270eb2e3ca33892066ddb164387af2c9d28" }, "downloads": -1, "filename": "zc.form-1.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "6f0d068933d5544a3625da15b8d76bb3", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 54090, "upload_time": "2019-02-11T08:22:54", "url": "https://files.pythonhosted.org/packages/00/73/78925ff2d0f3e274f01cf9813c03379cf38764220e017d50ccdb816c56aa/zc.form-1.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f3a66f421bbda6d72ed648b38b113015", "sha256": "cd554bd2d4981abe988f6ba157a7615c61518eb0c7143c1e4e00638c587b5022" }, "downloads": -1, "filename": "zc.form-1.1.tar.gz", "has_sig": false, "md5_digest": "f3a66f421bbda6d72ed648b38b113015", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 42047, "upload_time": "2019-02-11T08:23:01", "url": "https://files.pythonhosted.org/packages/cf/17/24b5ea865521b2429a5b05e4efe162ee9032a6ef57c4a197ffa03d3e09ce/zc.form-1.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "6f0d068933d5544a3625da15b8d76bb3", "sha256": "243c3818476d1317f118e2de43372270eb2e3ca33892066ddb164387af2c9d28" }, "downloads": -1, "filename": "zc.form-1.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "6f0d068933d5544a3625da15b8d76bb3", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 54090, "upload_time": "2019-02-11T08:22:54", "url": "https://files.pythonhosted.org/packages/00/73/78925ff2d0f3e274f01cf9813c03379cf38764220e017d50ccdb816c56aa/zc.form-1.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f3a66f421bbda6d72ed648b38b113015", "sha256": "cd554bd2d4981abe988f6ba157a7615c61518eb0c7143c1e4e00638c587b5022" }, "downloads": -1, "filename": "zc.form-1.1.tar.gz", "has_sig": false, "md5_digest": "f3a66f421bbda6d72ed648b38b113015", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 42047, "upload_time": "2019-02-11T08:23:01", "url": "https://files.pythonhosted.org/packages/cf/17/24b5ea865521b2429a5b05e4efe162ee9032a6ef57c4a197ffa03d3e09ce/zc.form-1.1.tar.gz" } ] }