{ "info": { "author": "Souheil Chelfouh", "author_email": "trollfot@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Web Environment", "Framework :: Zope3", "Intended Audience :: Other Audience", "License :: OSI Approved :: GNU General Public License (GPL)", "Operating System :: OS Independent", "Programming Language :: Python" ], "description": "=================\ndolmen.forms.base\n=================\n\n`dolmen.forms.base` is a package in charge of providing basic\nfunctionalities to work with `zeam.form` Forms.\n\n\nFrom the form to the field\n==========================\n\n``dolmen.forms.base`` provides few functions dedicated to the task of\napplying dict datas to object fields and to trigger events in order to\ninform handlers of the updates\n\nApplying values\n---------------\n\nWe create our test model::\n\n >>> from zope.schema import TextLine, Choice\n >>> from zope.interface import Interface, implements\n\n >>> class ICaveman(Interface):\n ... name = TextLine(title=u'a name')\n ... weapon = Choice(title=u'a weapon',\n ... values=[u'none', u'a club', u'a spear'])\n\n >>> class Neanderthal(object):\n ... implements(ICaveman)\n ... def __init__(self):\n ... self.name = u\"no name\"\n ... self.weapon = u\"none\"\n\n >>> moshe = Neanderthal()\n >>> moshe.name\n u'no name'\n >>> moshe.weapon\n u'none'\n\nWe can now use the first function, `set_fields_data`. It takes the\nfields list, extracted thanks to the `Fields` collection, the content\nand the data dictionnary. The result of this call is a dictionnary,\nwith the interface in which the field is defined and the field\nidentifier as a value::\n\n >>> from dolmen.forms.base import Fields, set_fields_data\n\n >>> fields = Fields(ICaveman)\n >>> for field in fields: print field\n \n \n\n >>> data = {u'name': u'Grok', u'weapon': u'a club'}\n\n >>> changes = set_fields_data(fields, moshe, data)\n >>> print changes\n {: [u'weapon', u'name']}\n\n >>> moshe.name\n u'Grok'\n >>> moshe.weapon\n u'a club'\n\nValues of the data dict can contain markers, to warn of a possible\nspecial case : the value is missing or there are no changes. In these\ntwo cases, the value assignation is skipped::\n\n >>> from dolmen.forms.base import NO_VALUE, NO_CHANGE\n >>> data = {u'name': NO_VALUE, u'weapon': NO_CHANGE}\n\n >>> changes = set_fields_data(fields, moshe, data)\n >>> print changes\n {}\n\nGenerating changes Attributes for events\n----------------------------------------\n\nOne advantage of generating a dict of changes is that you can trigger\nevent that are aware of a certain format of changes. The\nIObjectModifiedEvent, for exemple, uses the changes log to trigger the\nreindexation of the modified fields. The function `notify_changes` is\ndedicated to notifying a given event of the applied changes. It takes\nthe content, the changes dict and an event as arguments. If the event\nargument is omitted, ObjectModifiedEvent is used by default.\n\nWe first generate a changes dict::\n\n >>> data = {u'name': u'Grok', u'weapon': u'a club'}\n >>> changes = set_fields_data(fields, moshe, data)\n >>> print changes\n {: [u'weapon', u'name']}\n\nWe can now set a logger for the IObjectModifiedEvent, in order to\ncheck if the changes are being broadcasted::\n\n >>> from zope.component import adapter, provideHandler\n >>> from zope.lifecycleevent import IObjectModifiedEvent\n >>> from zope.event import subscribers\n\n\n >>> logger = []\n\n >>> @adapter(ICaveman, IObjectModifiedEvent)\n ... def changes_broadcasted(content, event):\n ... logger.append(event.descriptions)\n\n >>> provideHandler(changes_broadcasted)\n\nWe can now feed it to the function::\n\n >>> from dolmen.forms.base import notify_changes\n >>> change_log = notify_changes(moshe, changes)\n\nThe logger must have been trigged. We can check its value::\n\n >>> logger\n [(,)]\n\n >>> for attrs in logger[0]:\n ... print attrs.interface, attrs.attributes\n (u'weapon', u'name')\n\n\nField update event\n==================\n\n`dolmen.forms.base` also proposes the definition of a new component that\ncan be used to atomize the updating process of an object: `IFieldUpdate`.\n\nTo demonstrate this `IFieldUpdate`, we are going to implement a simple\nusecase where we instanciate a content, change a value and notify the\n`IFieldUpdate` components. For that, we'll use a basic logger object::\n\n >>> logger = []\n\nOnce this is done, we can define two `IFieldUpdate` components. We\nimplement them as named adapters. We'll retrieve them thanks to a\n\"getAdapters\" call::\n\n >>> from zope.interface import implementer\n >>> from dolmen.forms.base import IFieldUpdate\n\n >>> @implementer(IFieldUpdate)\n ... @adapter(TextLine, ICaveman)\n ... def updated_title(field, context):\n ... if field.__name__ == u\"name\":\n ... logger.append('Name updated on %r with `%s`' %\n ... (context, getattr(context, field.__name__)))\n\n >>> @implementer(IFieldUpdate)\n ... @adapter(TextLine, Interface)\n ... def updated_textfield(field, context):\n ... logger.append('A text field has been updated')\n\n\nThe components need to be named since they are adapters: we don't want\nthem to override each other. For the example, we want them both. let's\nregister them::\n\n >>> from zope.component import provideAdapter\n >>> provideAdapter(updated_title, name=\"updatetitle\")\n >>> provideAdapter(updated_textfield, name=\"updatetext\")\n\nNow, we develop the small scenarii : we instanciate a Content,\nadd a value for the `name` attribute and call the adapters::\n\n >>> manfred = Neanderthal()\n >>> manfred.name = u\"Manfred the Mighty\"\n\n >>> from zope.component import getAdapters\n >>> adapters = getAdapters((ICaveman['name'], manfred), IFieldUpdate)\n >>> for adapter in adapters:\n ... # We run through the generator\n ... pass\n\n >>> for line in logger: print line\n Name updated on with `Manfred the Mighty`\n A text field has been updated\n\n\nThe form model\n==============\n\n``dolmen.forms.base`` provides a form baseclass defining several\nuseful methods and overriding some default behavior from\n``zeam.form``.\n\n >>> from zope.interface import implementedBy\n >>> from dolmen.forms.base import ApplicationForm\n\nThe provided component, `ApplicationForm`, inherits from the base\n``zeam.form`` components and implements some extra methods, allowing\nit to fit into your application, such as `flash`, to emit messages\nto given sources. It's also layout aware::\n\n >>> for interface in implementedBy(ApplicationForm):\n ... print interface\n \n \n \n \n \n \n \n \n\nAs ``zeam.form`` uses Chameleon as a template engine, it is import we\nare able to compute the current request locale, in order to get the\nright translation environment::\n\n >>> from zope.publisher.browser import TestRequest\n >>> request = TestRequest()\n\n >>> from zope import site\n >>> from zope.location import Location\n >>> from zope.location.interfaces import IRoot\n >>> from zope.interface import implements\n\n >>> class MyApp(Location, site.SiteManagerContainer):\n ... implements(IRoot)\n ... __name__ = ''\n\n >>> item = MyApp()\n >>> sm = site.LocalSiteManager(item)\n >>> item.setSiteManager(sm)\n\n >>> form = ApplicationForm(item, request)\n >>> print form.i18nLanguage\n None\n\n >>> request = TestRequest(environ={'HTTP_ACCEPT_LANGUAGE': \"en,fr\"})\n >>> form = ApplicationForm(item, request)\n >>> print form.i18nLanguage\n en\n\nFurther more, the `ApplicationForm` overrides the ``extractData``\nmethod from the ``zeam.form`` Form in order to compute the interfaces\ninvariants.\n\n >>> from grokcore.site.interfaces import IApplication\n >>> from zope.interface import alsoProvides\n >>> from zope.component.hooks import setSite\n\n >>> setSite(item)\n >>> alsoProvides(item, IApplication)\n >>> form.application_url()\n 'http://127.0.0.1'\n\n\nDeclaring the invariants\n------------------------\n\n >>> from zope.schema import Password\n >>> from zope.interface import invariant, Interface\n >>> from zope.interface.exceptions import Invalid\n\n >>> class IPasswords(Interface):\n ... passwd = Password(\n ... title=u\"Password\",\n ... description=u\"Type the password.\",\n ... required=True)\n ...\n ... verify = Password(\n ... title=u\"Password checking\",\n ... description=u\"Retype the password.\",\n ... required=True)\n ...\n ... @invariant\n ... def check_pass(data):\n ... if data.passwd != data.verify:\n ... raise Invalid(u\"Mismatching passwords!\")\n\n >>> from zeam.form.base import Fields\n >>> from grokcore.component import testing\n\n >>> class MyForm(ApplicationForm):\n ... ignoreContent = True\n ... ignoreRequest = False\n ... fields = Fields(IPasswords)\n\n\nDefault behavior\n----------------\n\n >>> form = MyForm(item, request)\n >>> form.update()\n >>> form.updateForm()\n >>> data, errors = form.extractData()\n\n >>> print data\n {'passwd': , 'verify': }\n\n >>> for error in errors:\n ... print error.title\n Missing required value.\n Missing required value.\n There were errors.\n\n >>> for error in form.formErrors:\n ... print error.title\n There were errors.\n\n\nErrors computing\n----------------\n\n >>> post = TestRequest(form = {'form.field.passwd': u'test',\n ... 'form.field.verify': u'fail'})\n >>> form = MyForm(item, post)\n >>> form.update()\n >>> form.updateForm()\n >>> data, errors = form.extractData()\n\n >>> print data\n {'passwd': u'test', 'verify': u'fail'}\n\nThe returned error is a collection of Error components. Using the form\nprefix as an identifier, it logically wraps all the errors created by\nthe invariants validation::\n\n >>> for error in form.formErrors:\n ... print error.title\n Mismatching passwords!\n\n >>> form.errors.get(form.prefix) == form.formErrors[0]\n True\n\n\nMixed Fields\n------------\n\nThere are two types of fields, one from ``zeam.form.base``, the other\nfrom ``zope.schema``. They are both useable in a form, separately or\nmixed::\n\n >>> from zeam.form.base import Field\n >>> from dolmen.forms.base import Fields\n >>> class MixedForm(ApplicationForm):\n ... ignoreContent = True\n ... ignoreRequest = False\n ... fields = Fields(IPasswords) + Field(u'Name')\n\n >>> mixedform = MixedForm(item, post)\n >>> mixedform.update()\n >>> [x.title for x in mixedform.fields]\n [u'Password', u'Password checking', u'Name']\n\n >>> mixedform.updateForm()\n >>> data, errors = mixedform.extractData()\n\n >>> print form.formErrors\n []\n\n >>> for error in form.formErrors:\n ... print error.title\n Mismatching passwords!\n\n\nChangelog\n=========\n\n1.2.1 (2014-11-20)\n------------------\n\n* Updated the 'application_url' method to work with the latest changes in\n the ``grokcore`` stack. Also updated the versions in the standalone buildout.\n\n\n1.2 (2014-11-18)\n----------------\n\n* Added the `application_url` and `flash` methods to forms.\n This implied the use of ``grokcore.site``, now a dependency.\n\n\n1.1 (2014-06-18)\n----------------\n\n* `grokcore.layout` took the place of `megrok.layout`. All imports and \n tests were changed accordingly.\n\n\n1.0 (2012-10-24)\n----------------\n\n* Fixed the new dependencies and changes in the related packages.\n\n\n1.0b3 (2010-10-27)\n------------------\n\n* Util method ``set_fields_data`` now makes sure that, even if a data\n entry doesn't have a corresponding field, it doesn't raise an error,\n as it was supposed to do.\n\n\n1.0b2 (2010-10-20)\n------------------\n\n* Both ``zeam.form`` and ``zope.schema`` Fields are useable in a Form,\n now. The changes have been made in the inline validation, to take\n care of both types.\n\n* Now we are using formErrors from ``zeam.form.base`` Form instead of our\n own formError method.\n\n* The `InvariantsValidation` is now declared thanks to the\n ``dataValidators`` mechanism introduces by ``zeam.form.base`` 1.0.\n\n* The package is now tested under Grok 1.2.\n\n\n1.0b1 (2010-06-25)\n------------------\n\n* The package now uses the latest version of ``zeam.form.base``, that\n separates the `extractData` from the `validateData`. It allows to\n validate invariants in a cleaner way, without overriding generic\n code.\n\n* The DeprecationWarning in invariants validation is gone. It now uses\n the representation of the exception and no longer the `message`\n attribute.\n\n* The package now exposes the base ``zeam.form`` markers.\n\n\n1.0a2 (2010-06-25)\n------------------\n\n* `ApplicationForm` now validates interfaces invariants.\n\n* `ApplicationForm` is now localized, since it provides a contextual\n i18nLanguage attribute.\n\n* Added tests\n\n\n1.0a1 (2010-06-02)\n------------------\n\n* Added a base Form model : `ApplicationForm`\n\n* ``dolmen.forms.base`` no longer uses ``z3c.form`` but is now based\n on the ``zeam.form`` Form framework\n\n* Added several helpers functions, to extract changes Attributes and\n notify events\n\n* Added tests\n\n\n0.1 (2009-10-25)\n----------------\n\n* Initial release", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "UNKNOWN", "keywords": "Dolmen Forms", "license": "GPL", "maintainer": null, "maintainer_email": null, "name": "dolmen.forms.base", "package_url": "https://pypi.org/project/dolmen.forms.base/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/dolmen.forms.base/", "project_urls": { "Download": "UNKNOWN", "Homepage": "UNKNOWN" }, "release_url": "https://pypi.org/project/dolmen.forms.base/1.2.1/", "requires_dist": null, "requires_python": null, "summary": "Form utilities for Dolmen and zeam.form", "version": "1.2.1" }, "last_serial": 1314313, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "3483d66ff1c547f5a5859e3ca33eea0c", "sha256": "d3bf3c77a1f42671da94b67a05da57ce9150c6a19fc3c9ca844d03cb43491fe4" }, "downloads": -1, "filename": "dolmen.forms.base-0.1.tar.gz", "has_sig": false, "md5_digest": "3483d66ff1c547f5a5859e3ca33eea0c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3978, "upload_time": "2009-10-25T18:38:33", "url": "https://files.pythonhosted.org/packages/17/67/a4bb18a2479b823bcdc202faa6c08744a749198fa7ebfd62d496f6a89568/dolmen.forms.base-0.1.tar.gz" } ], "1.0": [ { "comment_text": "", "digests": { "md5": "29ea6512383baed075f14ed3a4f8727a", "sha256": "7cbe226b1c465639fd927375d81837c4014d8a97fbbfc6ae243260e3916cad03" }, "downloads": -1, "filename": "dolmen.forms.base-1.0.tar.gz", "has_sig": false, "md5_digest": "29ea6512383baed075f14ed3a4f8727a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10745, "upload_time": "2012-10-24T08:26:49", "url": "https://files.pythonhosted.org/packages/b4/e7/0562db919d180fcb9897abb5a8b671ac16079614f57e1c2ff16cb7b50879/dolmen.forms.base-1.0.tar.gz" } ], "1.0a1": [ { "comment_text": "", "digests": { "md5": "42c5e8be336ca0b26d2df0dbad7c114d", "sha256": "323b7e51af12d95e47f70f0c7a73ef6900b027edf737620ad5a2eb0ed3df6623" }, "downloads": -1, "filename": "dolmen.forms.base-1.0a1.tar.gz", "has_sig": false, "md5_digest": "42c5e8be336ca0b26d2df0dbad7c114d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6050, "upload_time": "2010-06-02T01:27:53", "url": "https://files.pythonhosted.org/packages/f0/67/0f2706528edfbadad8526625b55a828e59da0b3481c1e41240eeedc93ec9/dolmen.forms.base-1.0a1.tar.gz" } ], "1.0a2": [ { "comment_text": "", "digests": { "md5": "9c779f4fe871477de47bd24ab9762848", "sha256": "8f642263888f26c3eb6a4c3f46708a83ab40b26c6f8f69884058ac8d41cfae22" }, "downloads": -1, "filename": "dolmen.forms.base-1.0a2.tar.gz", "has_sig": false, "md5_digest": "9c779f4fe871477de47bd24ab9762848", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9494, "upload_time": "2010-06-25T14:45:34", "url": "https://files.pythonhosted.org/packages/92/34/77cf97a5011e6b45a127ad372063450c2210d43b99850bad867fbabc11a6/dolmen.forms.base-1.0a2.tar.gz" } ], "1.0b1": [ { "comment_text": "", "digests": { "md5": "1a3c0590b48aa19f6d3798269988b465", "sha256": "d890813e1f5fa4b2cf0909221833e675f31afb644f997d3b99e4ea3d9760e5e0" }, "downloads": -1, "filename": "dolmen.forms.base-1.0b1.tar.gz", "has_sig": false, "md5_digest": "1a3c0590b48aa19f6d3798269988b465", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9753, "upload_time": "2010-07-06T16:12:51", "url": "https://files.pythonhosted.org/packages/0c/04/03b67072fc18d91685cdba0af974c9de04932d1798f720f2a2d823805963/dolmen.forms.base-1.0b1.tar.gz" } ], "1.0b2": [ { "comment_text": "", "digests": { "md5": "cd8bdf86bad0b3f19db6738145b3561a", "sha256": "f6e15fcef82e0edf2f2d1cdcad4b80b2204a01886cb8e5e8f50c3135234f9d46" }, "downloads": -1, "filename": "dolmen.forms.base-1.0b2.tar.gz", "has_sig": false, "md5_digest": "cd8bdf86bad0b3f19db6738145b3561a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10366, "upload_time": "2010-10-20T11:04:07", "url": "https://files.pythonhosted.org/packages/46/2c/c3c77f1eb0b06e51251524aab6fe71facb28d7464da9e84a597000f73443/dolmen.forms.base-1.0b2.tar.gz" } ], "1.0b3": [ { "comment_text": "", "digests": { "md5": "a5bda4b86d7585189513ecdbf8972099", "sha256": "94d4caa678e49558b2792f8159129ecb430d84585ab40fe1b3cefc5c5661801a" }, "downloads": -1, "filename": "dolmen.forms.base-1.0b3.tar.gz", "has_sig": false, "md5_digest": "a5bda4b86d7585189513ecdbf8972099", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10587, "upload_time": "2010-10-27T18:22:27", "url": "https://files.pythonhosted.org/packages/f8/13/63ff1d3f9d22880a59890c09c2bad691bd64866bfbc469554e9f449dcae2/dolmen.forms.base-1.0b3.tar.gz" } ], "1.1": [ { "comment_text": "", "digests": { "md5": "9f9928d0bd8b275fb6fc9572218437a7", "sha256": "7968e52a2460acf7cbb7e67a14e242635c9fd24eae5adf8ee0119e29edf8df3a" }, "downloads": -1, "filename": "dolmen.forms.base-1.1.tar.gz", "has_sig": false, "md5_digest": "9f9928d0bd8b275fb6fc9572218437a7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10880, "upload_time": "2014-06-18T13:57:47", "url": "https://files.pythonhosted.org/packages/ce/54/61aacfcc293386abd3ad65180adf5f9b3d44283e8b1bf7030c66bf132358/dolmen.forms.base-1.1.tar.gz" } ], "1.2": [ { "comment_text": "", "digests": { "md5": "77e5ce9434e9879a60bd87d47c3c5ec1", "sha256": "a587004066bea879d2d53465dcf21d5b5b50e7ab1bff2c67f4c3232e612b3052" }, "downloads": -1, "filename": "dolmen.forms.base-1.2.tar.gz", "has_sig": false, "md5_digest": "77e5ce9434e9879a60bd87d47c3c5ec1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11195, "upload_time": "2014-11-18T18:24:29", "url": "https://files.pythonhosted.org/packages/84/3f/0e4b5fcf5e62e5862691780d7aac59116d1fdf1f3dffc849da5073a739db/dolmen.forms.base-1.2.tar.gz" } ], "1.2.1": [ { "comment_text": "", "digests": { "md5": "9bc1867cff22e0a334c1a3bcacb844be", "sha256": "6dd7c0dacc1c1522b43a7e30ed503611a182e52952b002881582d6cdf0908f59" }, "downloads": -1, "filename": "dolmen.forms.base-1.2.1.tar.gz", "has_sig": false, "md5_digest": "9bc1867cff22e0a334c1a3bcacb844be", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11618, "upload_time": "2014-11-20T12:15:12", "url": "https://files.pythonhosted.org/packages/06/da/95d1d194a223a4aa33c9366d29d44d931a01c56b7212ce48a781a8ad6324/dolmen.forms.base-1.2.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "9bc1867cff22e0a334c1a3bcacb844be", "sha256": "6dd7c0dacc1c1522b43a7e30ed503611a182e52952b002881582d6cdf0908f59" }, "downloads": -1, "filename": "dolmen.forms.base-1.2.1.tar.gz", "has_sig": false, "md5_digest": "9bc1867cff22e0a334c1a3bcacb844be", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11618, "upload_time": "2014-11-20T12:15:12", "url": "https://files.pythonhosted.org/packages/06/da/95d1d194a223a4aa33c9366d29d44d931a01c56b7212ce48a781a8ad6324/dolmen.forms.base-1.2.1.tar.gz" } ] }