{ "info": { "author": "Stephan Richter and the Zope Community", "author_email": "zope-dev@zope.org", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Environment :: Web Environment", "Framework :: Zope3", "Intended Audience :: Developers", "License :: OSI Approved :: Zope Public License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Internet :: WWW/HTTP" ], "description": ".. contents ::\n\n===========\nQuick Entry\n===========\n\nThe quick entry processor allows a user to efficiently specify multiple values\nin one larger text block. The processor uses plugins to dynamically define the\ncommands to handle.\n\nThis type of input is not aimed at the average user, but at power users and\nusers that can be trained. The syntax is purposefully minimized to maximize\nthe input speed. This method of entry has been verified in a real life\nsetting.\n\n\nProcessor Plugins\n-----------------\n\nLet's start by looking at the processor plugins, which can handle one piece of\nthe quick entry text. The first plugin type can handle strings of the form:\n\n =\n\nA base implementation of this plugin is provided by the package. Let's create\na plugin that can process a name:\n\n >>> from z3c.quickentry import plugin\n >>> class NamePlugin(plugin.ShortNamePlugin):\n ... shortName = 'nm'\n ... varName = 'name'\n\nAny plugin is instantiated using an initial text and optionally a position\nthat is used during error reporting:\n\n >>> name = NamePlugin('nm=Stephan')\n >>> name\n \n\n >>> NamePlugin('nm=Stephan', 35)\n \n\nYou can now ask the plugin, whether it can process this text:\n\n >>> name.canProcess()\n True\n\n >>> NamePlugin('n=Stephan').canProcess()\n False\n >>> NamePlugin('Stephan').canProcess()\n False\n\nSometimes the processor adds more text later:\n\n >>> name.text += ' Richter'\n\nOnce all pieces have been processed by the quick entry processor, each\ninstantiated plugin gets processed. The result of this action is a dictionary:\n\n >>> name.process(None)\n {'name': u'Stephan Richter'}\n\nThe second type of plugin matches a regular expression to determine whether a\npiece of text can be processed. Let's create a phone number plugin:\n\n >>> import re\n >>> class PhonePlugin(plugin.RegexPlugin):\n ... regex = re.compile('^[0-9]{3}-[0-9]{3}-[0-9]{4}$')\n ... varName = 'phone'\n\nThis plugin is also instantiated using an initial text:\n\n >>> phone = PhonePlugin('978-555-5300')\n >>> phone\n \n\nYou can now ask the plugin, whether it can process this text:\n\n >>> name.canProcess()\n True\n\n >>> PhonePlugin('(978) 555-5300').canProcess()\n False\n >>> PhonePlugin('+1-978-555-5300').canProcess()\n False\n\nLet's now process the plugin:\n\n >>> phone.process(None)\n {'phone': u'978-555-5300'}\n\nIf the text changes, so that the plugin cannot parse the text anymore, a\nprocess error is raised:\n\n >>> phone.text += ' (ext. 2134)'\n >>> phone.process(None)\n Traceback (most recent call last):\n ...\n ProcessError: The regex did match anymore. Probably some text was added\n later that disrupted the pattern. (Position 0)\n\n\nFinally let's have a look at a more advanced example. We would like to be able\nto handle the string \"\" and parse it into 2 variables:\n\n >>> from z3c.quickentry import interfaces\n\n >>> class AgeGenderPlugin(plugin.BasePlugin):\n ... regex = re.compile('([0-9]{1,3})([FM])')\n ...\n ... def canProcess(self):\n ... return self.regex.match(self.text) is not None\n ...\n ... def process(self, context):\n ... match = self.regex.match(self.text)\n ... if match is None:\n ... raise interfaces.ProcessError(self.position, u'Error here.')\n ... return {'age': int(match.groups()[0]),\n ... 'gender': unicode(match.groups()[1])}\n\nLet's now make sure that the plugin can handle several strings:\n\n >>> AgeGenderPlugin('27M').canProcess()\n True\n >>> AgeGenderPlugin('8F').canProcess()\n True\n >>> AgeGenderPlugin('101F').canProcess()\n True\n >>> AgeGenderPlugin('27N').canProcess()\n False\n >>> AgeGenderPlugin('M').canProcess()\n False\n >>> AgeGenderPlugin('18').canProcess()\n False\n\nLet's also make sure it is processed correctly:\n\n >>> from pprint import pprint\n >>> pprint(AgeGenderPlugin('27M').process(None))\n {'age': 27, 'gender': u'M'}\n >>> pprint(AgeGenderPlugin('8F').process(None))\n {'age': 8, 'gender': u'F'}\n >>> pprint(AgeGenderPlugin('101F').process(None))\n {'age': 101, 'gender': u'F'}\n\nWhen an error occurs at any point during the processing, a process error must\nbe raised:\n\n >>> pprint(AgeGenderPlugin('27N').process(None))\n Traceback (most recent call last):\n ...\n ProcessError: Error here. (Position 0)\n\nThe plugin above used the ``BasePlugin`` class to minimize the\nboilerplate. The base plugin requires you to implement the ``canProcess()``\nand ``process()``:\n\n >>> base = plugin.BasePlugin('some text')\n\n >>> base.canProcess()\n Traceback (most recent call last):\n ...\n NotImplementedError\n\n >>> base.process(None)\n Traceback (most recent call last):\n ...\n NotImplementedError\n\n\nExecuting Plugins\n-----------------\n\nAn optional feature of the package is the ability for the plugin to apply the\nparsed data directly to a specified context. The simplest such case is to\nsimply set the attribute on the context. For this use case we have a mix-in\nclass:\n\n >>> class ExecutingAgeGenderPlugin(AgeGenderPlugin, plugin.SetAttributeMixin):\n ... pass\n\nLet's now create a person on which the attributes can be stored:\n\n >>> class Person(object):\n ... name = None\n ... phone = None\n ... age = None\n ... gender = None\n >>> stephan = Person()\n\nLet's now apply the executing age/gender plugin onto the person:\n\n >>> stephan.age\n >>> stephan.gender\n\n >>> ExecutingAgeGenderPlugin('27M').apply(stephan)\n\n >>> stephan.age\n 27\n >>> stephan.gender\n u'M'\n\n\nProcessors\n----------\n\nThe processor collects several plugins and handles one large chunk of quick\nentry text. Let's create a processor for the plugins above, using the default\nwhitespace character as field separator:\n\n >>> from z3c.quickentry import processor\n >>> info = processor.BaseProcessor()\n >>> info.plugins = (NamePlugin, PhonePlugin, AgeGenderPlugin)\n\nThe lowest level step of the processor is the parsing of the text; the result\nis a sequence of plugin instances:\n\n >>> info.parse('nm=Stephan 27M')\n [, ]\n\nLet's now parse and process a simple texts that uses some or all plugins:\n\n >>> pprint(info.process('nm=Stephan 27M'))\n {'age': 27, 'gender': u'M', 'name': u'Stephan'}\n\n >>> pprint(info.process('978-555-5300 27M'))\n {'age': 27, 'gender': u'M', 'phone': u'978-555-5300'}\n\n >>> pprint(info.process('nm=Stephan 978-555-5300 27M'))\n {'age': 27, 'gender': u'M', 'name': u'Stephan', 'phone': u'978-555-5300'}\n\nNote that you can also have names that contain spaces, because the last name\ncannot be matched to another plugin:\n\n >>> pprint(info.process('nm=Stephan Richter 27M'))\n {'age': 27, 'gender': u'M', 'name': u'Stephan Richter'}\n\nOptionally, you can also provide a processing context that can be used to look\nup values (for example vocabularies):\n\n >>> pprint(info.process('nm=Stephan Richter 27M', context=object()))\n {'age': 27, 'gender': u'M', 'name': u'Stephan Richter'}\n\nLet's now change the separation character to a comma:\n\n >>> info.separationCharacter = ','\n >>> pprint(info.process('nm=Stephan Richter,27M', context=object()))\n {'age': 27, 'gender': u'M', 'name': u'Stephan Richter'}\n\nBut what happens, if no plugin can be found. Then a process error is raised:\n\n >>> info.process('err=Value', context=object())\n Traceback (most recent call last):\n ...\n ProcessError: No matching plugin found. (Position 0)\n\n\nExecuting Processors\n--------------------\n\nThese processors can apply all of the plugins on a context. Let's convert the\nremaining plugins to be executable:\n\n >>> class ExecutingNamePlugin(NamePlugin, plugin.SetAttributeMixin):\n ... pass\n\n >>> class ExecutingPhonePlugin(PhonePlugin, plugin.SetAttributeMixin):\n ... pass\n\nLet's now create a new user and create an executing processor:\n\n >>> stephan = Person()\n\n >>> proc = processor.ExecutingBaseProcessor()\n >>> proc.plugins = (\n ... ExecutingNamePlugin, ExecutingPhonePlugin, ExecutingAgeGenderPlugin)\n\n >>> proc.apply('nm=Stephan 978-555-5300 27M', stephan)\n\n >>> stephan.name\n u'Stephan'\n >>> stephan.phone\n u'978-555-5300'\n >>> stephan.age\n 27\n >>> stephan.gender\n u'M'\n\n\n=========\n Changes\n=========\n\n0.1 (2010-08-23)\n----------------\n\n- Initial public release.", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://pypi.python.org/pypi/z3c.quickentry", "keywords": "zope3 ui user date entry", "license": "ZPL 2.1", "maintainer": null, "maintainer_email": null, "name": "z3c.quickentry", "package_url": "https://pypi.org/project/z3c.quickentry/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/z3c.quickentry/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://pypi.python.org/pypi/z3c.quickentry" }, "release_url": "https://pypi.org/project/z3c.quickentry/0.1/", "requires_dist": null, "requires_python": null, "summary": "Allows a user to efficiently specify multiple values in one larger text block.", "version": "0.1" }, "last_serial": 802071, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "79d431a47255e1a96e6daa77c98cb7eb", "sha256": "65b5ce7596735ef2413a2448b55fcdfd913e2ab9581f30f6e34e0437d919d83f" }, "downloads": -1, "filename": "z3c.quickentry-0.1.tar.gz", "has_sig": false, "md5_digest": "79d431a47255e1a96e6daa77c98cb7eb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10041, "upload_time": "2010-08-23T08:53:40", "url": "https://files.pythonhosted.org/packages/31/3a/8d5f75304afde823840cbe07c33dace846a004eb57cb5386f77dc225d935/z3c.quickentry-0.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "79d431a47255e1a96e6daa77c98cb7eb", "sha256": "65b5ce7596735ef2413a2448b55fcdfd913e2ab9581f30f6e34e0437d919d83f" }, "downloads": -1, "filename": "z3c.quickentry-0.1.tar.gz", "has_sig": false, "md5_digest": "79d431a47255e1a96e6daa77c98cb7eb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10041, "upload_time": "2010-08-23T08:53:40", "url": "https://files.pythonhosted.org/packages/31/3a/8d5f75304afde823840cbe07c33dace846a004eb57cb5386f77dc225d935/z3c.quickentry-0.1.tar.gz" } ] }