z3c.layer.ready2go


Namez3c.layer.ready2go JSON
Version 2.0 PyPI version JSON
download
home_pagehttps://github.com/zopefoundation/z3c.layer.ready2go
SummaryA ready to go layer for Zope3
upload_time2023-02-08 15:10:51
maintainer
docs_urlNone
authorStephan Richter, Roger Ineichen and the Zope Community
requires_python>=3.7
licenseZPL 2.1
keywords zope3 z3c ready 2 go layer
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            This package provides a layer based on z3c.form and z3c.pagelet. This layer can 
be used in custom skins.


.. contents::


===========================
Ready-2-Go Layer for Zope 3
===========================

This package contains the `ready2go` layer. This layer supports a correct set of
component registration and can be used for inheritation in custom skins.

Important
---------

This layer supports the ``z3c.pagelet`` and the ``z3c.form`` pattern. This
means every page e.g. the error page is based on the ``z3c.pagelet``
concept. By default we use the ``<div>``-based layout for z3c forms.


``IReady2GoBrowserLayer`` Layer
-------------------------------

The `ready2go` layer is useful for build custom presentation skins without
access to ZMI menus like ``zmi_views`` etc. This means there is no menu item
registred if you use this layer.

For more information about what this layer offers, see ``z3c.layer.pagelet``.


Testing
-------

For testing the ``IReady2GoBrowserLayer`` layer we use the testing skin
defined in the tests package which uses the ``IReady2GoBrowserLayer`` layer as
the only base layer.  This means, that our testing skin provides only the
views defined in the minimal package and it's testing views defined in tests.

Login as manager first:

  >>> from webtest.app import TestApp
  >>> manager = TestApp(
  ...     make_wsgi_app(), extra_environ={
  ...         'wsgi.handleErrors': False,
  ...         'HTTP_AUTHORIZATION': 'Basic mgr:mgrpw'})
  >>> err_manager = TestApp(
  ...     make_wsgi_app(), extra_environ={
  ...         'HTTP_AUTHORIZATION': 'Basic mgr:mgrpw'})

Check if we can access the ``page.html`` view which is registred in the
``ftesting.zcml`` file with our skin:

  >>> skinURL = 'http://localhost/++skin++Ready2GoTestSkin'
  >>> res = manager.get(skinURL + '/page.html')
  >>> res.request.url
  'http://localhost/++skin++Ready2GoTestSkin/page.html'


Pagelet support
---------------

Check if we can access the test page given from the ``z3c.layer.pagelet``
``ftesting.zcml`` configuration.

  >>> print(res.html) #doctest: +PARSE_HTML
  <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
  <head>
  <title>PageletTestLayout</title>
  </head>
  <body>
    test page
  </body>
  </html>


Not Found
~~~~~~~~~

Now check the not found page which is a exception view on the exception
``zope.publisher.interfaces.INotFound``:

  >>> manager.get(skinURL + '/foobar.html')
  Traceback (most recent call last):
  ...
  NotFound: Object: <zope.site.folder.Folder ...>, name: 'foobar.html'

  >>> res = err_manager.get(skinURL + '/foobar.html', status=404)
  >>> print(res.html)
  <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
  <head>
  <title>PageletTestLayout</title>
  </head>
  <body>
    <div>
    <br />
    <br />
    <h3>
      The page you are trying to access is not available
    </h3>
    <br />
    <b>
      Please try the following:
    </b>
    <br />
    <ol>
      <li>
        Make sure that the Web site address is spelled correctly.
      </li>
      <li>
        <a href="javascript:history.back(1);">
          Go back and try another URL.
        </a>
      </li>
    </ol>
  </div>
  </body>
  </html>


User error
~~~~~~~~~~

And check the user error page which is a view registred for
``zope.exceptions.interfaces.IUserError`` exceptions:

  >>> res = err_manager.get(skinURL + '/@@usererror.html')
  >>> print(res.html)
  <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
  <head>
  <title>PageletTestLayout</title>
  </head>
  <body>
    <div>
    <div>simply user error</div>
  </div>
  </body>
  </html>


Common exception (system error)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

And check error view registred for
``zope.interface.common.interfaces.IException``:

  >>> res = err_manager.get(skinURL + '/@@systemerror.html', status=500)
  >>> print(res.html)
  <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
  <head>
  <title>PageletTestLayout</title>
  </head>
  <body>
    <div>
    <br />
    <br />
    <h3>A system error occurred</h3>
    <br />
    <b>Please contact the administrator.</b>
    <a href="javascript:history.back(1);">
      Go back and try another URL.
    </a>
  </div>
  </body>
  </html>


Forbidden 403
~~~~~~~~~~~~~

And check the ``zope.security.interfaces.IUnauthorized`` view, use a new
unregistred user (test browser) for this.

  >>> unauthorized = TestApp(make_wsgi_app())
  >>> unauthorized.get(skinURL + '/@@forbidden.html')
  Traceback (most recent call last):
  ...
  AppError: Bad response: 403 Forbidden

  >>> res = unauthorized.get(skinURL + '/@@forbidden.html', status=403)
  >>> print(res.html)
  <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
  <head>
  <title>PageletTestLayout</title>
  </head>
  <body>
    <div>
    <br />
    <br />
    <h3>Unauthorized</h3>
    <br />
    <b>You are not authorized.</b>
  </div>
  </body>
  </html>

As you can see, this test will return a 403 Forbidden error. But this is only
because we do not have an unauthenticated principal available. See the test
below what happens if we register an unauthenticated princiapl.


Unauthorized 401
~~~~~~~~~~~~~~~~

If we use an authenticated principal and access the forbitten page, we will get
a 401 Unauthorized instead of a 403 Forbidden error page.

  >>> from zope.configuration import xmlconfig
  >>> import zope.principalregistry
  >>> def zcml(s):
  ...     context = xmlconfig.file('meta.zcml', zope.principalregistry)
  ...     xmlconfig.string(s, context)

  >>> zcml("""
  ...    <configure
  ...        xmlns="http://namespaces.zope.org/zope"
  ...        >
  ...
  ...      <unauthenticatedPrincipal
  ...         id="zope.unknown"
  ...         title="Anonymous user"
  ...         description="A person we don't know"
  ...         />
  ...
  ...    </configure>
  ... """)

  >>> manager2 = TestApp(make_wsgi_app(), extra_environ={
  ...         'wsgi.handleErrors': True})
  >>> res = manager2.get(skinURL + '/@@forbidden.html')
  Traceback (most recent call last):
  ...
  AppError: Bad response: 401 Unauthorized

  >>> res = manager2.get(skinURL + '/@@forbidden.html', status=401)
  >>> print(res.html)
  <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
  <head>
  <title>PageletTestLayout</title>
  </head>
  <body>
    <div>
    <br />
    <br />
    <h3>Unauthorized</h3>
    <br />
    <b>You are not authorized.</b>
  </div>
  </body>
  </html>


Form and form layout support
----------------------------

This layer offers also form macros given from ``z3c.formui``. Let's create a
simple form:

  >>> from z3c.form import testing
  >>> testing.setupFormDefaults()

Before we can start writing forms, we must have the content to work with:

  >>> import zope.interface
  >>> import zope.schema
  >>> class IPerson(zope.interface.Interface):
  ...
  ...     name = zope.schema.TextLine(
  ...         title='Name',
  ...         required=True)
  ...
  ...     age = zope.schema.Int(
  ...         title='Age',
  ...         description=u"The person's age.",
  ...         min=0,
  ...         default=20,
  ...         required=False)

  >>> from zope.schema.fieldproperty import FieldProperty
  >>> @zope.interface.implementer(IPerson)
  ... class Person(object):
  ...     name = FieldProperty(IPerson['name'])
  ...     age = FieldProperty(IPerson['age'])
  ...
  ...     def __init__(self, name, age):
  ...         self.name = name
  ...         self.age = age
  ...
  ...     def __repr__(self):
  ...         return '<%s %r>' % (self.__class__.__name__, self.name)

Okay, that should suffice for now. Let's now create a working add form:

  >>> from z3c.form import field
  >>> from z3c.formui import form, layout
  >>> class PersonAddForm(form.AddForm):
  ...
  ...     fields = field.Fields(IPerson)
  ...
  ...     def create(self, data):
  ...         return Person(**data)
  ...
  ...     def add(self, object):
  ...         self.context[object.id] = object
  ...
  ...     def nextURL(self):
  ...         return 'index.html'

Let's create a request:

  >>> from z3c.form.testing import TestRequest
  >>> from zope.interface import alsoProvides
  >>> divRequest = TestRequest()

And support the div form layer for our request:

  >>> from z3c.formui.interfaces import IDivFormLayer
  >>> alsoProvides(divRequest, IDivFormLayer)

Now create the form:

  >>> root = getRootFolder()
  >>> addForm = PersonAddForm(root, divRequest)

Since we have not specified a template yet, we have to do this now. We use our
div based form template:

  >>> import os
  >>> import z3c.formui
  >>> divFormTemplate = os.path.join(os.path.dirname(z3c.formui.__file__),
  ...     'div-form.pt')

  >>> from z3c.template.template import TemplateFactory
  >>> divFormFactory = TemplateFactory(divFormTemplate, 'text/html')

Now register the form (content) template:

  >>> import zope.interface
  >>> import zope.component
  >>> from z3c.template.interfaces import IContentTemplate
  >>> zope.component.provideAdapter(divFormFactory,
  ...     (zope.interface.Interface, IDivFormLayer),
  ...     IContentTemplate)

And let's define a layout template which simply calls the render method. For a
more adavanced content/layout render concept see ``z3c.pagelet``.

  >>> import tempfile
  >>> temp_dir = tempfile.mkdtemp()

  >>> myLayout = os.path.join(temp_dir, 'myLayout.pt')
  >>> with open(myLayout, 'w') as file:
  ...     _ = file.write('''<html>
  ...   <body>
  ...     <tal:block content="structure view/render">
  ...       content
  ...     </tal:block>
  ...   </body>
  ... </html>''')
  >>> myLayoutFactory = TemplateFactory(myLayout, 'text/html')

  >>> from z3c.template.interfaces import ILayoutTemplate
  >>> zope.component.provideAdapter(myLayoutFactory,
  ...     (zope.interface.Interface, zope.interface.Interface), ILayoutTemplate)

Now we can get our layout template:

  >>> layout = zope.component.getMultiAdapter((addForm, divRequest),
  ...     ILayoutTemplate)

  >>> layout
  <zope.browserpage.viewpagetemplatefile.ViewPageTemplateFile object at ...>


DIV-based Layout
----------------

Let's now render the page. Note the output doesn't contain the layout template:

  >>> addForm.update()
  >>> print(addForm.render())
  <form action="http://127.0.0.1" method="post"
        enctype="multipart/form-data" class="edit-form"
        id="form" name="form">
    <div class="viewspace">
      <div class="required-info">
        <span class="required">*</span>&ndash; required
      </div>
      <div>
        <div id="form-widgets-name-row" class="row required">
          <div class="label">
            <label for="form-widgets-name">
              <span>Name</span>
              <span class="required">*</span>
            </label>
          </div>
          <div class="widget">
            <input id="form-widgets-name" name="form.widgets.name"
                   class="text-widget required textline-field"
                   value="" type="text" />
          </div>
        </div>
        <div id="form-widgets-age-row" class="row">
          <div class="label">
            <label for="form-widgets-age">
              <span>Age</span>
            </label>
          </div>
          <div class="widget">
            <input id="form-widgets-age" name="form.widgets.age"
                   class="text-widget int-field"
                   value="20" type="text" />
          </div>
        </div>
      </div>
    </div>
    <div>
      <div class="buttons">
        <input id="form-buttons-add" name="form.buttons.add"
               class="submit-widget button-field" value="Add" type="submit" />
      </div>
    </div>
  </form>


Form Macros
-----------

Try at least to load the confguration, which will make sure that all macros
get registered correctly.

  >>> from zope.configuration import xmlconfig
  >>> import zope.component
  >>> import zope.security
  >>> import zope.viewlet
  >>> import zope.browserpage
  >>> import zope.browserresource
  >>> import z3c.macro
  >>> import z3c.template
  >>> import z3c.formui
  >>> xmlconfig.XMLConfig('meta.zcml', zope.browserpage)()
  >>> xmlconfig.XMLConfig('meta.zcml', zope.browserresource)()
  >>> xmlconfig.XMLConfig('meta.zcml', zope.component)()
  >>> xmlconfig.XMLConfig('meta.zcml', zope.security)()
  >>> xmlconfig.XMLConfig('meta.zcml', zope.viewlet)()
  >>> xmlconfig.XMLConfig('meta.zcml', z3c.macro)()
  >>> xmlconfig.XMLConfig('meta.zcml', z3c.template)()
  >>> xmlconfig.XMLConfig('configure.zcml', z3c.formui)()


Div layout macros
-----------------

Now we can see that we have different form macros available:

  >>> from z3c.macro.interfaces import IMacroTemplate
  >>> objects = (None, addForm, divRequest)
  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form')
  [...div-form.pt'), ...metal:define-macro': 'form'...


  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'subform')
  [...div-form.pt'), ...define-macro': 'subform'...


  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-label')
  [...div-form.pt'), ...define-macro': 'label'...


  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-required-info')
  [...div-form.pt'), ...define-macro', 'required-info'...


  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-header')
  [...div-form.pt'), ...define-macro': 'header'...


  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-errors')
  [...div-form.pt'), ...define-macro': 'errors'...


  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'widget-rows')
  [...div-form.pt'), ...define-macro': 'widget-rows'...


  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'widget-row')
  [...div-form.pt'), ...define-macro': 'widget-row'...


  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-groups')
  [...div-form.pt'), ...define-macro': 'groups'...


  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-buttons')
  [...div-form.pt'), ...define-macro', 'buttons'...


Cleanup
-------

  >>> import shutil
  >>> shutil.rmtree(temp_dir)


=======
CHANGES
=======

2.0 (2023-02-08)
----------------

- Drop support for Python 2.7, 3.5, 3.6.

- Add support for Python 3.7, 3.8, 3.9, 3.10, 3.11.

- Drop deprecated support to run the tests via ``python setup.py test``.


1.0.0 (2017-04-17)
------------------

- Pin Python support to 2.7, 3.5, 3.6 and PyPy.


1.0.0a1 (2013-03-03)
--------------------

- Added support for Python 3.3.

- Changed ``zope.testbrowser`` tests to ``WebTest``, since ``zope.testbrowser``
  is not yet ported.

- Replaced deprecated ``zope.interface.implements`` usage with equivalent
  ``zope.interface.implementer`` decorator.

- Dropped support for Python 2.4 and 2.5.


- Fixed test setup and tests to run with current versions of the
  required packages.


0.6.0 (2009-12-01)
------------------

- Adjusted dependencies, skiped dependency on `zope.app.publisher` and
  `zope.app.http` and reflected changes in Zope packages.


0.5.3 (2009-07-24)
------------------

- Fix tests to work with latest packages.


0.5.2 (2009-02-19)
------------------

- No longer depends on deprecated ``z3c.viewlet``.

- Fixed tests to run with current ``z3c.form``.

- Fixed long_description to render properly on pypi.


0.5.1 (2008-01-24)
------------------

- Bug: Fix meta-data.


0.5.0 (2008-01-21)
------------------

- Initial Release

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/zopefoundation/z3c.layer.ready2go",
    "name": "z3c.layer.ready2go",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": "",
    "keywords": "zope3 z3c ready 2 go layer",
    "author": "Stephan Richter, Roger Ineichen and the Zope Community",
    "author_email": "zope-dev@zope.dev",
    "download_url": "https://files.pythonhosted.org/packages/a3/47/da767742011d03b8f56a92ac3437a9664762904b1bc868958e7039929cf1/z3c.layer.ready2go-2.0.tar.gz",
    "platform": null,
    "description": "This package provides a layer based on z3c.form and z3c.pagelet. This layer can \nbe used in custom skins.\n\n\n.. contents::\n\n\n===========================\nReady-2-Go Layer for Zope 3\n===========================\n\nThis package contains the `ready2go` layer. This layer supports a correct set of\ncomponent registration and can be used for inheritation in custom skins.\n\nImportant\n---------\n\nThis layer supports the ``z3c.pagelet`` and the ``z3c.form`` pattern. This\nmeans every page e.g. the error page is based on the ``z3c.pagelet``\nconcept. By default we use the ``<div>``-based layout for z3c forms.\n\n\n``IReady2GoBrowserLayer`` Layer\n-------------------------------\n\nThe `ready2go` layer is useful for build custom presentation skins without\naccess to ZMI menus like ``zmi_views`` etc. This means there is no menu item\nregistred if you use this layer.\n\nFor more information about what this layer offers, see ``z3c.layer.pagelet``.\n\n\nTesting\n-------\n\nFor testing the ``IReady2GoBrowserLayer`` layer we use the testing skin\ndefined in the tests package which uses the ``IReady2GoBrowserLayer`` layer as\nthe only base layer.  This means, that our testing skin provides only the\nviews defined in the minimal package and it's testing views defined in tests.\n\nLogin as manager first:\n\n  >>> from webtest.app import TestApp\n  >>> manager = TestApp(\n  ...     make_wsgi_app(), extra_environ={\n  ...         'wsgi.handleErrors': False,\n  ...         'HTTP_AUTHORIZATION': 'Basic mgr:mgrpw'})\n  >>> err_manager = TestApp(\n  ...     make_wsgi_app(), extra_environ={\n  ...         'HTTP_AUTHORIZATION': 'Basic mgr:mgrpw'})\n\nCheck if we can access the ``page.html`` view which is registred in the\n``ftesting.zcml`` file with our skin:\n\n  >>> skinURL = 'http://localhost/++skin++Ready2GoTestSkin'\n  >>> res = manager.get(skinURL + '/page.html')\n  >>> res.request.url\n  'http://localhost/++skin++Ready2GoTestSkin/page.html'\n\n\nPagelet support\n---------------\n\nCheck if we can access the test page given from the ``z3c.layer.pagelet``\n``ftesting.zcml`` configuration.\n\n  >>> print(res.html) #doctest: +PARSE_HTML\n  <html lang=\"en\" xml:lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\">\n  <head>\n  <title>PageletTestLayout</title>\n  </head>\n  <body>\n    test page\n  </body>\n  </html>\n\n\nNot Found\n~~~~~~~~~\n\nNow check the not found page which is a exception view on the exception\n``zope.publisher.interfaces.INotFound``:\n\n  >>> manager.get(skinURL + '/foobar.html')\n  Traceback (most recent call last):\n  ...\n  NotFound: Object: <zope.site.folder.Folder ...>, name: 'foobar.html'\n\n  >>> res = err_manager.get(skinURL + '/foobar.html', status=404)\n  >>> print(res.html)\n  <html lang=\"en\" xml:lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\">\n  <head>\n  <title>PageletTestLayout</title>\n  </head>\n  <body>\n    <div>\n    <br />\n    <br />\n    <h3>\n      The page you are trying to access is not available\n    </h3>\n    <br />\n    <b>\n      Please try the following:\n    </b>\n    <br />\n    <ol>\n      <li>\n        Make sure that the Web site address is spelled correctly.\n      </li>\n      <li>\n        <a href=\"javascript:history.back(1);\">\n          Go back and try another URL.\n        </a>\n      </li>\n    </ol>\n  </div>\n  </body>\n  </html>\n\n\nUser error\n~~~~~~~~~~\n\nAnd check the user error page which is a view registred for\n``zope.exceptions.interfaces.IUserError`` exceptions:\n\n  >>> res = err_manager.get(skinURL + '/@@usererror.html')\n  >>> print(res.html)\n  <html lang=\"en\" xml:lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\">\n  <head>\n  <title>PageletTestLayout</title>\n  </head>\n  <body>\n    <div>\n    <div>simply user error</div>\n  </div>\n  </body>\n  </html>\n\n\nCommon exception (system error)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nAnd check error view registred for\n``zope.interface.common.interfaces.IException``:\n\n  >>> res = err_manager.get(skinURL + '/@@systemerror.html', status=500)\n  >>> print(res.html)\n  <html lang=\"en\" xml:lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\">\n  <head>\n  <title>PageletTestLayout</title>\n  </head>\n  <body>\n    <div>\n    <br />\n    <br />\n    <h3>A system error occurred</h3>\n    <br />\n    <b>Please contact the administrator.</b>\n    <a href=\"javascript:history.back(1);\">\n      Go back and try another URL.\n    </a>\n  </div>\n  </body>\n  </html>\n\n\nForbidden 403\n~~~~~~~~~~~~~\n\nAnd check the ``zope.security.interfaces.IUnauthorized`` view, use a new\nunregistred user (test browser) for this.\n\n  >>> unauthorized = TestApp(make_wsgi_app())\n  >>> unauthorized.get(skinURL + '/@@forbidden.html')\n  Traceback (most recent call last):\n  ...\n  AppError: Bad response: 403 Forbidden\n\n  >>> res = unauthorized.get(skinURL + '/@@forbidden.html', status=403)\n  >>> print(res.html)\n  <html lang=\"en\" xml:lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\">\n  <head>\n  <title>PageletTestLayout</title>\n  </head>\n  <body>\n    <div>\n    <br />\n    <br />\n    <h3>Unauthorized</h3>\n    <br />\n    <b>You are not authorized.</b>\n  </div>\n  </body>\n  </html>\n\nAs you can see, this test will return a 403 Forbidden error. But this is only\nbecause we do not have an unauthenticated principal available. See the test\nbelow what happens if we register an unauthenticated princiapl.\n\n\nUnauthorized 401\n~~~~~~~~~~~~~~~~\n\nIf we use an authenticated principal and access the forbitten page, we will get\na 401 Unauthorized instead of a 403 Forbidden error page.\n\n  >>> from zope.configuration import xmlconfig\n  >>> import zope.principalregistry\n  >>> def zcml(s):\n  ...     context = xmlconfig.file('meta.zcml', zope.principalregistry)\n  ...     xmlconfig.string(s, context)\n\n  >>> zcml(\"\"\"\n  ...    <configure\n  ...        xmlns=\"http://namespaces.zope.org/zope\"\n  ...        >\n  ...\n  ...      <unauthenticatedPrincipal\n  ...         id=\"zope.unknown\"\n  ...         title=\"Anonymous user\"\n  ...         description=\"A person we don't know\"\n  ...         />\n  ...\n  ...    </configure>\n  ... \"\"\")\n\n  >>> manager2 = TestApp(make_wsgi_app(), extra_environ={\n  ...         'wsgi.handleErrors': True})\n  >>> res = manager2.get(skinURL + '/@@forbidden.html')\n  Traceback (most recent call last):\n  ...\n  AppError: Bad response: 401 Unauthorized\n\n  >>> res = manager2.get(skinURL + '/@@forbidden.html', status=401)\n  >>> print(res.html)\n  <html lang=\"en\" xml:lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\">\n  <head>\n  <title>PageletTestLayout</title>\n  </head>\n  <body>\n    <div>\n    <br />\n    <br />\n    <h3>Unauthorized</h3>\n    <br />\n    <b>You are not authorized.</b>\n  </div>\n  </body>\n  </html>\n\n\nForm and form layout support\n----------------------------\n\nThis layer offers also form macros given from ``z3c.formui``. Let's create a\nsimple form:\n\n  >>> from z3c.form import testing\n  >>> testing.setupFormDefaults()\n\nBefore we can start writing forms, we must have the content to work with:\n\n  >>> import zope.interface\n  >>> import zope.schema\n  >>> class IPerson(zope.interface.Interface):\n  ...\n  ...     name = zope.schema.TextLine(\n  ...         title='Name',\n  ...         required=True)\n  ...\n  ...     age = zope.schema.Int(\n  ...         title='Age',\n  ...         description=u\"The person's age.\",\n  ...         min=0,\n  ...         default=20,\n  ...         required=False)\n\n  >>> from zope.schema.fieldproperty import FieldProperty\n  >>> @zope.interface.implementer(IPerson)\n  ... class Person(object):\n  ...     name = FieldProperty(IPerson['name'])\n  ...     age = FieldProperty(IPerson['age'])\n  ...\n  ...     def __init__(self, name, age):\n  ...         self.name = name\n  ...         self.age = age\n  ...\n  ...     def __repr__(self):\n  ...         return '<%s %r>' % (self.__class__.__name__, self.name)\n\nOkay, that should suffice for now. Let's now create a working add form:\n\n  >>> from z3c.form import field\n  >>> from z3c.formui import form, layout\n  >>> class PersonAddForm(form.AddForm):\n  ...\n  ...     fields = field.Fields(IPerson)\n  ...\n  ...     def create(self, data):\n  ...         return Person(**data)\n  ...\n  ...     def add(self, object):\n  ...         self.context[object.id] = object\n  ...\n  ...     def nextURL(self):\n  ...         return 'index.html'\n\nLet's create a request:\n\n  >>> from z3c.form.testing import TestRequest\n  >>> from zope.interface import alsoProvides\n  >>> divRequest = TestRequest()\n\nAnd support the div form layer for our request:\n\n  >>> from z3c.formui.interfaces import IDivFormLayer\n  >>> alsoProvides(divRequest, IDivFormLayer)\n\nNow create the form:\n\n  >>> root = getRootFolder()\n  >>> addForm = PersonAddForm(root, divRequest)\n\nSince we have not specified a template yet, we have to do this now. We use our\ndiv based form template:\n\n  >>> import os\n  >>> import z3c.formui\n  >>> divFormTemplate = os.path.join(os.path.dirname(z3c.formui.__file__),\n  ...     'div-form.pt')\n\n  >>> from z3c.template.template import TemplateFactory\n  >>> divFormFactory = TemplateFactory(divFormTemplate, 'text/html')\n\nNow register the form (content) template:\n\n  >>> import zope.interface\n  >>> import zope.component\n  >>> from z3c.template.interfaces import IContentTemplate\n  >>> zope.component.provideAdapter(divFormFactory,\n  ...     (zope.interface.Interface, IDivFormLayer),\n  ...     IContentTemplate)\n\nAnd let's define a layout template which simply calls the render method. For a\nmore adavanced content/layout render concept see ``z3c.pagelet``.\n\n  >>> import tempfile\n  >>> temp_dir = tempfile.mkdtemp()\n\n  >>> myLayout = os.path.join(temp_dir, 'myLayout.pt')\n  >>> with open(myLayout, 'w') as file:\n  ...     _ = file.write('''<html>\n  ...   <body>\n  ...     <tal:block content=\"structure view/render\">\n  ...       content\n  ...     </tal:block>\n  ...   </body>\n  ... </html>''')\n  >>> myLayoutFactory = TemplateFactory(myLayout, 'text/html')\n\n  >>> from z3c.template.interfaces import ILayoutTemplate\n  >>> zope.component.provideAdapter(myLayoutFactory,\n  ...     (zope.interface.Interface, zope.interface.Interface), ILayoutTemplate)\n\nNow we can get our layout template:\n\n  >>> layout = zope.component.getMultiAdapter((addForm, divRequest),\n  ...     ILayoutTemplate)\n\n  >>> layout\n  <zope.browserpage.viewpagetemplatefile.ViewPageTemplateFile object at ...>\n\n\nDIV-based Layout\n----------------\n\nLet's now render the page. Note the output doesn't contain the layout template:\n\n  >>> addForm.update()\n  >>> print(addForm.render())\n  <form action=\"http://127.0.0.1\" method=\"post\"\n        enctype=\"multipart/form-data\" class=\"edit-form\"\n        id=\"form\" name=\"form\">\n    <div class=\"viewspace\">\n      <div class=\"required-info\">\n        <span class=\"required\">*</span>&ndash; required\n      </div>\n      <div>\n        <div id=\"form-widgets-name-row\" class=\"row required\">\n          <div class=\"label\">\n            <label for=\"form-widgets-name\">\n              <span>Name</span>\n              <span class=\"required\">*</span>\n            </label>\n          </div>\n          <div class=\"widget\">\n            <input id=\"form-widgets-name\" name=\"form.widgets.name\"\n                   class=\"text-widget required textline-field\"\n                   value=\"\" type=\"text\" />\n          </div>\n        </div>\n        <div id=\"form-widgets-age-row\" class=\"row\">\n          <div class=\"label\">\n            <label for=\"form-widgets-age\">\n              <span>Age</span>\n            </label>\n          </div>\n          <div class=\"widget\">\n            <input id=\"form-widgets-age\" name=\"form.widgets.age\"\n                   class=\"text-widget int-field\"\n                   value=\"20\" type=\"text\" />\n          </div>\n        </div>\n      </div>\n    </div>\n    <div>\n      <div class=\"buttons\">\n        <input id=\"form-buttons-add\" name=\"form.buttons.add\"\n               class=\"submit-widget button-field\" value=\"Add\" type=\"submit\" />\n      </div>\n    </div>\n  </form>\n\n\nForm Macros\n-----------\n\nTry at least to load the confguration, which will make sure that all macros\nget registered correctly.\n\n  >>> from zope.configuration import xmlconfig\n  >>> import zope.component\n  >>> import zope.security\n  >>> import zope.viewlet\n  >>> import zope.browserpage\n  >>> import zope.browserresource\n  >>> import z3c.macro\n  >>> import z3c.template\n  >>> import z3c.formui\n  >>> xmlconfig.XMLConfig('meta.zcml', zope.browserpage)()\n  >>> xmlconfig.XMLConfig('meta.zcml', zope.browserresource)()\n  >>> xmlconfig.XMLConfig('meta.zcml', zope.component)()\n  >>> xmlconfig.XMLConfig('meta.zcml', zope.security)()\n  >>> xmlconfig.XMLConfig('meta.zcml', zope.viewlet)()\n  >>> xmlconfig.XMLConfig('meta.zcml', z3c.macro)()\n  >>> xmlconfig.XMLConfig('meta.zcml', z3c.template)()\n  >>> xmlconfig.XMLConfig('configure.zcml', z3c.formui)()\n\n\nDiv layout macros\n-----------------\n\nNow we can see that we have different form macros available:\n\n  >>> from z3c.macro.interfaces import IMacroTemplate\n  >>> objects = (None, addForm, divRequest)\n  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form')\n  [...div-form.pt'), ...metal:define-macro': 'form'...\n\n\n  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'subform')\n  [...div-form.pt'), ...define-macro': 'subform'...\n\n\n  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-label')\n  [...div-form.pt'), ...define-macro': 'label'...\n\n\n  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-required-info')\n  [...div-form.pt'), ...define-macro', 'required-info'...\n\n\n  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-header')\n  [...div-form.pt'), ...define-macro': 'header'...\n\n\n  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-errors')\n  [...div-form.pt'), ...define-macro': 'errors'...\n\n\n  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'widget-rows')\n  [...div-form.pt'), ...define-macro': 'widget-rows'...\n\n\n  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'widget-row')\n  [...div-form.pt'), ...define-macro': 'widget-row'...\n\n\n  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-groups')\n  [...div-form.pt'), ...define-macro': 'groups'...\n\n\n  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-buttons')\n  [...div-form.pt'), ...define-macro', 'buttons'...\n\n\nCleanup\n-------\n\n  >>> import shutil\n  >>> shutil.rmtree(temp_dir)\n\n\n=======\nCHANGES\n=======\n\n2.0 (2023-02-08)\n----------------\n\n- Drop support for Python 2.7, 3.5, 3.6.\n\n- Add support for Python 3.7, 3.8, 3.9, 3.10, 3.11.\n\n- Drop deprecated support to run the tests via ``python setup.py test``.\n\n\n1.0.0 (2017-04-17)\n------------------\n\n- Pin Python support to 2.7, 3.5, 3.6 and PyPy.\n\n\n1.0.0a1 (2013-03-03)\n--------------------\n\n- Added support for Python 3.3.\n\n- Changed ``zope.testbrowser`` tests to ``WebTest``, since ``zope.testbrowser``\n  is not yet ported.\n\n- Replaced deprecated ``zope.interface.implements`` usage with equivalent\n  ``zope.interface.implementer`` decorator.\n\n- Dropped support for Python 2.4 and 2.5.\n\n\n- Fixed test setup and tests to run with current versions of the\n  required packages.\n\n\n0.6.0 (2009-12-01)\n------------------\n\n- Adjusted dependencies, skiped dependency on `zope.app.publisher` and\n  `zope.app.http` and reflected changes in Zope packages.\n\n\n0.5.3 (2009-07-24)\n------------------\n\n- Fix tests to work with latest packages.\n\n\n0.5.2 (2009-02-19)\n------------------\n\n- No longer depends on deprecated ``z3c.viewlet``.\n\n- Fixed tests to run with current ``z3c.form``.\n\n- Fixed long_description to render properly on pypi.\n\n\n0.5.1 (2008-01-24)\n------------------\n\n- Bug: Fix meta-data.\n\n\n0.5.0 (2008-01-21)\n------------------\n\n- Initial Release\n",
    "bugtrack_url": null,
    "license": "ZPL 2.1",
    "summary": "A ready to go layer for Zope3",
    "version": "2.0",
    "split_keywords": [
        "zope3",
        "z3c",
        "ready",
        "2",
        "go",
        "layer"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "0df982655d5f253475d6aed22968b551322f0e41442e6ee01b109a9058572452",
                "md5": "d4e4134070fea4e75e7955b0e9f81435",
                "sha256": "35696336a206c5f96c04b864d2453f11cd689bb24e735af6d9c033b870fa137b"
            },
            "downloads": -1,
            "filename": "z3c.layer.ready2go-2.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "d4e4134070fea4e75e7955b0e9f81435",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 16925,
            "upload_time": "2023-02-08T15:10:48",
            "upload_time_iso_8601": "2023-02-08T15:10:48.626879Z",
            "url": "https://files.pythonhosted.org/packages/0d/f9/82655d5f253475d6aed22968b551322f0e41442e6ee01b109a9058572452/z3c.layer.ready2go-2.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "a347da767742011d03b8f56a92ac3437a9664762904b1bc868958e7039929cf1",
                "md5": "a8229bb5204cc36ad675b4c22dcb1cda",
                "sha256": "1cada0d766595a1cdc55338ba7aa5575d17f22b0f34ad8fed05cd6524fe07b45"
            },
            "downloads": -1,
            "filename": "z3c.layer.ready2go-2.0.tar.gz",
            "has_sig": false,
            "md5_digest": "a8229bb5204cc36ad675b4c22dcb1cda",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 20030,
            "upload_time": "2023-02-08T15:10:51",
            "upload_time_iso_8601": "2023-02-08T15:10:51.015733Z",
            "url": "https://files.pythonhosted.org/packages/a3/47/da767742011d03b8f56a92ac3437a9664762904b1bc868958e7039929cf1/z3c.layer.ready2go-2.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-02-08 15:10:51",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "github_user": "zopefoundation",
    "github_project": "z3c.layer.ready2go",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "tox": true,
    "lcname": "z3c.layer.ready2go"
}
        
Elapsed time: 0.06315s