{ "info": { "author": "Tommy Yu", "author_email": "tommy.yu@auckland.ac.nz", "bugtrack_url": null, "classifiers": [ "Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "Introduction\n============\n\nThis package extends z3c.form and plone.z3cform for usage within PMR2\nand related libraries. Problems this package attempt to tackle are:\n\n - Ensure the correct root template is adapted when forms (and views/\n pages) are rendered, such that there will only be one class used for\n testing and production, without having to subclass for specific uses\n or make use of wrapper classes/methods. It may be possible to\n support other frameworks by registering the root view to the desired\n layer.\n - CSRF (Cross-Site Request Forgery) prevention via the use of\n appropriate form authenticators, e.g. plone.protect for Plone.\n - Offer the same adaptable browser class (pages) to standard non-form\n views.\n - Forms with traversal subpaths.\n\nInstallation and usage\n----------------------\n\nJust add or modified the ``install_requires`` option into the setup\nfunction in a typical ``setup.py``. Example::\n\n from setuptools import setup\n \n setup(\n ...\n install_requires=[\n ...\n 'pmr2.z3cform',\n ]\n )\n\nForms\n=====\n\nForms in PMR2 are built on top of z3c.forms. There are certain changes\nwe made to allow this library to better fit into our use cases. There\nare a couple modifications, the first being the enforcement of request\nmethod, and the other is CSRF (Cross-site Request Forgery) protection.\n\nFirst we import some base classes and create a test form class::\n\n >>> import zope.interface\n >>> import zope.schema\n >>> import z3c.form.field\n >>> from pmr2.z3cform.testing import BaseTestRequest as TestRequest\n >>> from pmr2.z3cform.tests import base\n >>> from pmr2.z3cform.form import AddForm\n >>>\n >>> class IDummy(zope.interface.Interface):\n ... id = zope.schema.DottedName(title=u'id')\n ...\n >>> class Dummy(object):\n ... zope.interface.implements(IDummy)\n ... def __init__(self, id_):\n ... self.id = id_\n ...\n >>> class TestAddForm(AddForm):\n ... fields = z3c.form.field.Fields(IDummy)\n ... def create(self, data):\n ... return Dummy(data['id'])\n ... def add_data(self, ctxobject):\n ... ctxobject.id = self._data['id']\n ... def add(self, obj):\n ... self.context.append(obj)\n ... def nextURL(self):\n ... return '' # unnecessary.\n\nFirst thing to demonstrate is is the request method verification. Forms\nthat manipulate data must not be activated by a simple GET request::\n\n >>> context = []\n >>> request = TestRequest(form={\n ... 'form.widgets.id': 'test',\n ... 'form.buttons.add': '1',\n ... })\n >>> request.method = 'GET'\n >>> form = TestAddForm(context, request)\n >>> result = form()\n Traceback (most recent call last):\n ...\n Unauthorized: Unauthorized()\n >>> context == []\n True\n\nOn the other hand, POST requests will not trigger the permission error::\n\n >>> request.method = 'POST'\n >>> form = TestAddForm(context, request)\n >>> form.disableAuthenticator = True\n >>> result = form()\n >>> print context[0].id\n test\n\nHowever, notice that the security authenticator is disabled. What this\nprovide is the check for a CSRF prevention token that must be part of a\nrequest. Now try the above with the check enabled, as it will be by\ndefault::\n\n >>> context = []\n >>> request.method = 'POST'\n >>> form = TestAddForm(context, request)\n >>> result = form()\n Traceback (most recent call last):\n ...\n Unauthorized: Unauthorized()\n >>> context == []\n True\n\nIf the token is provided, as part of a normal form submission process\nusing a form rendered by this site, the token will be included within\na hidden input field. In the case of Plone, this token is provided by\nan authenticator view. If we include the generated token the form\nwill be submitted properly::\n\n >>> context = []\n >>> authed_request = base.TestRequest(form=request.form)\n >>> authed_request.method = 'POST'\n >>> '_authenticator' in authed_request.form\n True\n >>> form = TestAddForm(context, authed_request)\n >>> result = form()\n >>> print context[0].id\n test\n\nPages\n=====\n\nThese were just simple rendering pages meant for wrapping by the layout\nclasses to be replaced by more standard Plone way of rendering \ntemplates.\n\nLet's subclass one::\n\n >>> from pmr2.z3cform.tests.base import TestRequest\n >>> from pmr2.z3cform.page import SimplePage\n >>>\n >>> class TestPage(SimplePage):\n ... template = lambda x: 'Hello'\n\nThen render it::\n\n >>> context = self.portal\n >>> request = TestRequest()\n >>> page = TestPage(context, request)\n >>> print page()\n

Plone site

\n
\n
Hello
\n
\n\nIf we register this view on the main site, we should be able to render\nthis using the testbrowser. This will then render the same page with\nall the templates associated with Plone::\n\n >>> import zope.component\n >>> from Testing.testbrowser import Browser\n >>> zope.component.provideAdapter(TestPage, (None, None),\n ... zope.publisher.interfaces.browser.IBrowserView,\n ... name='pmr2z3cform-testpage')\n ... \n >>> tb = Browser()\n >>> tb.open(context.absolute_url() + '/@@pmr2z3cform-testpage')\n >>> 'Plone - http://plone.org' in tb.contents\n True\n >>> '
Hello
' in tb.contents\n True\n\nWhile traversal views are generally implementation specific, a quick\ndemonstration is still possible. Try subclassing one::\n\n >>> from pmr2.z3cform.page import TraversePage\n >>>\n >>> class TestTraversePage(TraversePage):\n ... _template = 'Subpath is: %s'\n ... def template(self):\n ... subpath = '/'.join(self.traverse_subpath)\n ... return self._template % subpath\n\nManually simulate traversal and render the form::\n\n >>> context = self.portal\n >>> request = TestRequest()\n >>> page = TestTraversePage(context, request)\n >>> p = page.publishTraverse(request, 'a')\n >>> p = page.publishTraverse(request, 'b')\n >>> print page()\n

Plone site

\n
\n
Subpath is: a/b
\n
\n\nMuch like the SimplePage example, do the registration again::\n\n >>> zope.component.provideAdapter(TestTraversePage, (None, None),\n ... zope.publisher.interfaces.browser.IBrowserView,\n ... name='pmr2z3cform-testtraversepage')\n ... \n >>> tb = Browser()\n >>> tb.open(context.absolute_url() + '/@@pmr2z3cform-testtraversepage' +\n ... '/a/b/c/some_path')\n >>> 'Plone - http://plone.org' in tb.contents\n True\n >>> '
Subpath is: a/b/c/some_path
' in tb.contents\n True\n\nChangelog\n=========\n\n0.3.3 - 2017-01-11\n------------------\n\n* Using the view directly should work for both plone.protect 2 and 3\n within the unittesting environment.\n* Ensure the local test cases here work with fixes introduced by\n Products.PloneHotfix20160830.\n* Update the keyring support to deal with anonymous test users to permit\n following of the same logic.\n\n0.3 - 2017-01-05\n----------------\n\n* Support for the form specific keyring introduced by plone.protect>3\n and plone.keyring>3; fallback is also supported.\n\n0.2.1 - 2013-10-24\n------------------\n\n* Packaging fixes; this is done for wording and cleaner generic setup\n integration.\n\n0.2 - 2013-07-09\n----------------\n\n* Now provide the customized ploneform macros, migrated in from the\n pmr2.app module.\n* Making use of bootstrap classes\n* Removed deprecated zope.app.* imports.\n\n0.1 - 2013-01-17\n----------------\n\n* Initial release of various helper forms and view classes for the pmr2\n libraries.\n* Provide a wrapped BrowserView class that can adapt to multiple wrapper\n templates much like how plone.z3cform does, so that views don't invoke\n items that may not be available due to lack of a full portal.", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/PMR2/pmr2.z3cform", "keywords": "", "license": "GPL", "maintainer": null, "maintainer_email": null, "name": "pmr2.z3cform", "package_url": "https://pypi.org/project/pmr2.z3cform/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/pmr2.z3cform/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/PMR2/pmr2.z3cform" }, "release_url": "https://pypi.org/project/pmr2.z3cform/0.3.3/", "requires_dist": null, "requires_python": null, "summary": "Customized z3c.form and plone.z3cform library for PMR2", "version": "0.3.3" }, "last_serial": 2566855, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "e499aadd6b7e0633fc2b7299763692f8", "sha256": "caaa2141ad4ab95c45da0ce0f00df0caf177a4e0032507f7ff8576dda3552248" }, "downloads": -1, "filename": "pmr2.z3cform-0.1.tar.gz", "has_sig": false, "md5_digest": "e499aadd6b7e0633fc2b7299763692f8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11656, "upload_time": "2013-01-16T22:26:28", "url": "https://files.pythonhosted.org/packages/ab/76/7edfe0d77c5a471eb1e2f5fe2e8a1dd570f5853afd9fd35ceb2061ddbb20/pmr2.z3cform-0.1.tar.gz" } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "746f44dd94b2f856c2902e8ffe4bbb74", "sha256": "33475f439616a8e83ac06535e2dbf0b56ca7df81ba9253b8af811eba6e7dd76e" }, "downloads": -1, "filename": "pmr2.z3cform-0.2.1.tar.gz", "has_sig": false, "md5_digest": "746f44dd94b2f856c2902e8ffe4bbb74", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14400, "upload_time": "2013-10-24T10:18:16", "url": "https://files.pythonhosted.org/packages/11/c3/d99602b17c30aa46c7dc3775adfacbd3178e2ede6d1f0740c13bea6a9270/pmr2.z3cform-0.2.1.tar.gz" } ], "0.3.1": [ { "comment_text": "", "digests": { "md5": "be0b145b30d08b449ff7e228cd8aba71", "sha256": "5a1c1f621eb35004fa1cc0a84263c1a44e36825f758f92a7319f14b12f5c1581" }, "downloads": -1, "filename": "pmr2.z3cform-0.3.1.tar.gz", "has_sig": false, "md5_digest": "be0b145b30d08b449ff7e228cd8aba71", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 24435, "upload_time": "2017-01-11T06:30:22", "url": "https://files.pythonhosted.org/packages/c9/ea/2bf7cff2bf6b7db16c5e89f2915ff7ef9564d3b55ce294d9611b406ea072/pmr2.z3cform-0.3.1.tar.gz" } ], "0.3.2": [ { "comment_text": "", "digests": { "md5": "ff4fc5d550ab4e32ec7c1a35c237cc41", "sha256": "a82dd675358709aa22f3d114748751d390ff363ab7403a0a40955a306bdda23f" }, "downloads": -1, "filename": "pmr2.z3cform-0.3.2.tar.gz", "has_sig": false, "md5_digest": "ff4fc5d550ab4e32ec7c1a35c237cc41", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 24447, "upload_time": "2017-01-11T09:20:35", "url": "https://files.pythonhosted.org/packages/9d/05/1e1bddbdb9fa1307aa477460226dbd34fa2c2b5203f64f8ad45ae11a2d94/pmr2.z3cform-0.3.2.tar.gz" } ], "0.3.3": [ { "comment_text": "", "digests": { "md5": "19afca33547897fc9112d6b05f728cd9", "sha256": "b2803aa70591fe9ea603543f6283fd16ec527423bf6c9047573190c31770947c" }, "downloads": -1, "filename": "pmr2.z3cform-0.3.3.tar.gz", "has_sig": false, "md5_digest": "19afca33547897fc9112d6b05f728cd9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 24496, "upload_time": "2017-01-11T09:55:48", "url": "https://files.pythonhosted.org/packages/05/41/c1872ec3458d1a03f2466617fff3acf7599216415b750c690829d1746cc7/pmr2.z3cform-0.3.3.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "19afca33547897fc9112d6b05f728cd9", "sha256": "b2803aa70591fe9ea603543f6283fd16ec527423bf6c9047573190c31770947c" }, "downloads": -1, "filename": "pmr2.z3cform-0.3.3.tar.gz", "has_sig": false, "md5_digest": "19afca33547897fc9112d6b05f728cd9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 24496, "upload_time": "2017-01-11T09:55:48", "url": "https://files.pythonhosted.org/packages/05/41/c1872ec3458d1a03f2466617fff3acf7599216415b750c690829d1746cc7/pmr2.z3cform-0.3.3.tar.gz" } ] }