diff options
| author | Chris McDonough <chrism@agendaless.com> | 2009-05-01 10:26:57 +0000 |
|---|---|---|
| committer | Chris McDonough <chrism@agendaless.com> | 2009-05-01 10:26:57 +0000 |
| commit | ba9b0e647bff1bf0c437ab204ddf11783ed698f8 (patch) | |
| tree | 1952ebfdc40ae71a3bc54eb10a92a0fe1e8273ec | |
| parent | bc0698e1ac67106346d8c006bddcb38370f7c16b (diff) | |
| download | pyramid-ba9b0e647bff1bf0c437ab204ddf11783ed698f8.tar.gz pyramid-ba9b0e647bff1bf0c437ab204ddf11783ed698f8.tar.bz2 pyramid-ba9b0e647bff1bf0c437ab204ddf11783ed698f8.zip | |
Merge "c-free" branch to trunk.
53 files changed, 230 insertions, 2018 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 0ad703151..21e792fe2 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,5 +1,68 @@ -0.7.1 -===== +0.8dev +====== + +Features +-------- + +- This release of ``repoze.bfg`` is "C-free". This means it has no + hard dependencies on any software that must be compiled from C + source at installation time. In particular, ``repoze.bfg`` no + longer depends on the ``lxml`` package. XXX zope proxy. + + .. note:: this change has introduced some backwards + incompatibilities, described in the "Backwards + Incompatibilities" section below. + +Backwards Incompatibilities +--------------------------- + +Incompatibilities related to making ``repoze.bfg`` "C-free": + +- Removed the ``repoze.bfg.chameleon_genshi`` module, and thus support + for Genshi-style chameleon templates. Genshi-style Chameleon + templates depend upon ``lxml``, which is implemented in C (as + opposed to pure Python) and the ``repoze.bfg`` core is "C-free" as + of this release. You may get Genshi-style Chameleon support back by + installing the ``repoze.bfg.chameleon_genshi`` package availalable + from http://svn.repoze.org/repoze.bfg.chameleon_genshi/ (XXX index + path). All existing code that depended on the ``chameleon_genshi`` + module prior to this release of ``repoze.bfg`` should work without + change after this addon is installed. + +- Removed the ``repoze.bfg.xslt`` module and thus support for XSL + templates. The ``repoze.bfg.xslt`` module depended upon ``lxml``, + which is implemented in C, and the ``repoze.bfg`` core is "C-free" + as of this release. You bay get XSL templating back by installing + the ``repoze.bfg.xslt`` package available from + http://svn.repoze.org/repoze.bfg.xslt/ (XXX index path). All + existing code that depended upon the ``xslt`` module prior to this + release of ``repoze.bfg`` should work without modification after + this addon is installed. + +- Removed the ``repoze.bfg.interfaces.INodeTemplateRenderer`` + interface and the an old b/w compat aliases from that interface to + ``repoze.bfg.interfaces.INodeTemplate``. This interface must now be + imported from the ``repoze.bfg.xslt.interfaces`` package after + installation of the ``repoze.bfg.xslt`` addon package described + above as ``repoze.bfg.interfaces.INodeTemplateRenderer``. This + interface was never part of any public API. + +Other backwards incompatibilities: + +- The ``render_template`` function in ``repoze.bfg.chameleon_zpt`` + returns Unicode instead of a string. Likewise, the individual + values returned by the iterable created by the + ``render_template_to_iterable`` function are also each Unicode. + This is actually a backwards incompatibility inherited from our new + use of the combination of ``chameleon.core`` 1.0b32 (the + non-lxml-depending version) and ``chameleon.zpt`` 1.0b16+ ; the + ``chameleon.zpt`` PageTemplateFile implementation used to return a + string, but now returns Unicode. + +XXX get rid of zope.deferredimport (it relies on zope.proxy) + +0.7.1 (2009-05-01) +================== Index-Related ------------- diff --git a/docs/api/template.rst b/docs/api/template.rst index 8685073c3..026f1673a 100644 --- a/docs/api/template.rst +++ b/docs/api/template.rst @@ -3,16 +3,13 @@ :mod:`repoze.bfg` Built-in Templating Facilties =============================================== -Four templating facilities are provided by :mod:`repoze.bfg` "out of -the box": :term:`ZPT` -style, :term:`Genshi` -style, text templating, -and :term:`XSLT` templating. +Two templating facilities are provided by :mod:`repoze.bfg` "out of +the box": :term:`ZPT` -style and text templating. -ZPT-style, Genshi-style, and text templates are in :mod:`repoze.bfg` -are supported by the :term:`Chameleon` (nee :term:`z3c.pt`) templating -engine, which contains alternate implementations of both the ZPT and -Genshi language specifications. - -XSLT templating is supported by the use of :term:`lxml`. +ZPT-style and text templates are in :mod:`repoze.bfg` are supported by +the :term:`Chameleon` (nee :term:`z3c.pt`) templating engine, which +contains an alternate implementation of the ZPT language +specification. Below is API documentation for each of those facilities. Each facility is similar to the other, but to use a particular facility, @@ -20,8 +17,8 @@ you must import the API function from a specific module. For instance, to render a ZPT-style template to a response, you would import the ``render_template_to_response`` function from ``repoze.bfg.chameleon_zpt`` while you would import -``render_template_to_response`` from ``repoze.bfg.chameleon_genshi`` -in order to render a Genshi-style template to a response. While these +``render_template_to_response`` from ``repoze.bfg.chameleon_text`` in +order to render a text-style template to a response. While these functions have the same name, each will only operate on template files that match the style in which the template file itself is written. If you need to import API functions from two templating facilities within @@ -31,7 +28,6 @@ statement, e.g.: .. code-block:: python from repoze.chameleon_zpt import render_template as zpt_render - from repoze.chameleon_genshi import render_template as genshi_render from repoze.chameleon_text import render_template as text_render :mod:`repoze.bfg.chameleon_zpt` @@ -48,17 +44,6 @@ statement, e.g.: .. note:: For backwards compatibility purposes, these functions may also be imported from ``repoze.bfg.template``. -:mod:`repoze.bfg.chameleon_genshi` ----------------------------------- - -.. automodule:: repoze.bfg.chameleon_genshi - - .. autofunction:: get_template - - .. autofunction:: render_template - - .. autofunction:: render_template_to_response - :mod:`repoze.bfg.chameleon_text` ---------------------------------- @@ -70,17 +55,6 @@ statement, e.g.: .. autofunction:: render_template_to_response -:mod:`repoze.bfg.xslt` ----------------------- - -.. automodule:: repoze.bfg.xslt - - .. autofunction:: get_transform - - .. autofunction:: render_transform - - .. autofunction:: render_transform_to_response - .. note:: For backwards compatibility purposes, these functions may also be imported from ``repoze.bfg.template``. diff --git a/docs/glossary.rst b/docs/glossary.rst index 5427a7602..35b938345 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -202,12 +202,6 @@ Glossary :mod:`repoze.bfg` which makes it possible to configure :term:`WSGI` components together declaratively within an ``.ini`` file. It was developed by Ian Bicking as part of :term:`Paste`. - LXML - `lxml <http://codespeak.net/lxml/>`_ is a XML processing library - for Python by Martijn Faassen and others. - XSLT - `XSL Transformations <http://www.w3.org/TR/xslt>`_. A language - for transforming XML documents into other XML documents. Chameleon `chameleon <http://pypi.python.org/pypi/chameleon.core>`_ is an attribute language template compiler which supports both the @@ -217,23 +211,17 @@ Glossary ``${name}`` syntax, even within ZPT. It is also much faster than the reference implementations of both ZPT and Genshi. :mod:`repoze.bfg` offers Chameleon templating out of the box in - both ZPT and Genshi "flavors". + ZPT flavor and offers the Genshi flavor as an add on within the + :mod:`repoze.bfg.chameleon_genshi` package. chameleon.zpt ``chameleon.zpt`` is the package which provides :term:`ZPT` templating support under the :term:`Chameleon` templating engine. - chameleon.genshi - ``chameleon.genshi`` is the package which provides :term:`Genshi` - templating support under the :term:`Chameleon` templating engine. z3c.pt This was the previous name for :term:`Chameleon`, and is now a Zope 3 compatibility package for Chameleon. ZPT The `Zope Page Template <http://wiki.zope.org/ZPT/FrontPage>`_ templating language. - Genshi - `Genshi <http://genshi.edgewall.org/>`_ is an attribute-based XML - templating language similar to ZPT. Its syntax is supported - within :mod:`repoze.bfg` via :term:`Chameleon`. METAL `Macro Expansion for TAL <http://wiki.zope.org/ZPT/METAL>`_, a part of :term:`ZPT` which makes it possible to share common look @@ -333,12 +321,6 @@ Glossary `Barebones workflow for Python apps <http://static.repoze.org/workflowdocs>`_ . It can be used by :mod:`repoze.bfg` to form a workflow system. - repoze.bfg.convention - `An add-on for repoze.bfg - <http://static.repoze.org/conventiondocs>`_ which provides - alternative mechanisms for common :mod:`repoze.bfg` application - configuration tasks. The functionality of this package has been - merged into the :mod:`repoze.bfg` core as of version 0.6.3. Virtual root A model object representing the "virtual" root of a request; this is typically the physical root object (the object returned by the diff --git a/docs/index.rst b/docs/index.rst index 2fc022bc6..9384b1daa 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -70,13 +70,6 @@ Tutorials Step-by-step tutorials which demonstrate how you might use :mod:`repoze.bfg`. -``lxmlgraph`` Tutorial - -.. toctree:: - :maxdepth: 3 - - tutorials/lxmlgraph/index.rst - :mod:`repoze.bfg` for Zope CMF Developers .. toctree:: diff --git a/docs/narr/install.rst b/docs/narr/install.rst index 8eb0ae978..81294e896 100644 --- a/docs/narr/install.rst +++ b/docs/narr/install.rst @@ -13,31 +13,26 @@ done primarily under Python 2.4. :mod:`repoze.bfg` does *not* run under any version of Python before 2.4, and does *not* run under Python 3.X. -.. warning:: To succesfully install :mod:`repoze.bfg`, you will need - an environment capable of compiling C code (e.g. ``XCode Tools`` - will need to be installed if you're using MacOS X, and ``gcc`` and - other build tools will need to be installed if you're using other - UNIXlike systems). See the system's documentation about installing - this software. Additionally, the Python development libraries for - your Python version will need to be installed and the ``lixbml2`` - and ``libxslt`` development libraries will need to be installed. - These requirements are often satisfied by installing the - ``python-devel``, ``libxml2-devel`` and ``libxslt-devel`` packages - into your system. You will also need :term:`setuptools` installed +.. note:: You will need :term:`setuptools` installed on within your Python system in order to run the ``easy_install`` command. -At the time of this writing, ``repoze.bfg`` will not install on -Windows systems unless you have development tools (e.g. *Visual C++*) -installed. +.. note:: As of version 0.8.0, installation of :mod:`repoze.bfg` does + not require the compilation of any C code, so you do not need to + have development tools installed on the target machine. -.. note:: If you'd like to help produce and maintain a version of - :mod:`repoze.bfg` that works on Windows, we'd love to hear from - you. There's nothing intrinsic about :mod:`repoze.bfg` that would - prevent it from running on Windows, but none of the current - developers use the platform. Please contact us via the `repoze.dev - maillist <http://lists.repoze.org/listinfo/repoze-dev>`_ if you'd - like to try to tackle the job of compilation and maintenance. +Although BFG is known to run properly on all Unix-like systems, at the +time of this writing, ``repoze.bfg`` is not tested on Windows systems. +It might run; it might not. There's nothing intrinsic about +:mod:`repoze.bfg` that would prevent it from running on Windows, but +none of the current developers use the platform. Likewise for +platforms like Jython, and Google App Engine; it may run, it may not. + +.. note:: If you'd like to help make sure :mod:`repoze.bfg` keeps +.. running on your favorite alternate platform, we'd love to hear from + you. Please contact us via the `repoze.dev maillist + <http://lists.repoze.org/listinfo/repoze-dev>`_ if you'd like to + contribute. Installing :mod:`repoze.bfg` ---------------------------- @@ -70,7 +65,7 @@ can usually install a setuptools package using your system's package manager. If you cannot do this, or if you're using a self-installed version of Python, you will need to install setuptools "by hand". Installing setuptools "by hand" is always a reasonable thing to do, -even if your package manager already has a prechewed version of +even if your package manager already has a pre-chewed version of setuptools for installation. To install setuptools by hand, first download `ez_setup.py @@ -146,46 +141,18 @@ virtualenv (``bfgenv``) directory: :mod:`repoze.bfg` cannot be installed from PyPI. This command will take longer than the previous ones to complete, as it -compiles a number of dependencies. +downloads and installs a number of dependencies. What Gets Installed ~~~~~~~~~~~~~~~~~~~ When you ``easy_install`` :mod:`repoze.bfg`, various Zope libraries, -WebOb, Paste, PasteScript, and PasteDeploy libraries are installed. +various Chameleon libraries, WebOb, Paste, PasteScript, and +PasteDeploy libraries are installed. Additionally, as shown in the next section, PasteScript (aka *paster*) templates will be registered that make it easy to start a new :mod:`repoze.bfg` project. -Troubleshooting ---------------- - -If ``lxml`` Fails to Compile During ``easy_install`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If the installation of :mod:`repoze.bfg` fails due to problems -compiling ``lxml``, you should try installing ``lxml`` before -installing :mod:`repoze.bfg`. To do so, invoke ``easy_install``, -instructing ``lxml`` to download its own copy of ``libxml2``:: - - $ STATIC_DEPS=true bin/easy_install lxml - -Once that completes, you can start a subsequent ``easy_install`` of -:mod:`repoze.bfg` as per the instructions above; it should then work. - -If You Can't Install Via ``easy_install`` (Alternate Installation) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you can't get :mod:`repoze.bfg` installed using ``easy_install`` -because ``lxml`` fails to compile on your system, you can try the -`repoze.bfg buildout -<http://svn.repoze.org/buildouts/repoze.bfg/trunk/README.txt>`_. This -installation mechanism builds known-compatible ``libxml2`` and -``libxslt`` from source and causes ``lxml`` to link against these -instead of your system packages, as version incompatibilities between -system packages and ``lxml`` versions are typically to blame for -compilation problems. - diff --git a/docs/narr/introduction.rst b/docs/narr/introduction.rst index 83159dc45..072c6d8bf 100644 --- a/docs/narr/introduction.rst +++ b/docs/narr/introduction.rst @@ -147,90 +147,89 @@ It's Tested *If it ain't tested, it's broke.* We strive to test :mod:`repoze.bfg` completely. Below a run of the ``nosetests`` command configured to show code coverage information (run against the :mod:`repoze.bfg` -trunk just before the 0.6.8 release). +trunk sometime before the 0.8.0 release). .. code-block:: bash - [chrism@vitaminf trunk]$ python setup.py nosetests - running nosetests - running egg_info - writing requirements to repoze.bfg.egg-info/requires.txt - writing repoze.bfg.egg-info/PKG-INFO - writing namespace_packages to repoze.bfg.egg-info/namespace_packages.txt - writing top-level names to repoze.bfg.egg-info/top_level.txt - writing dependency_links to repoze.bfg.egg-info/dependency_links.txt - writing entry points to repoze.bfg.egg-info/entry_points.txt - writing manifest file 'repoze.bfg.egg-info/SOURCES.txt' - running build_ext - ............................................................................ - ............................................................................ - ............................................................................ - ............................................................................ - .......................................................................... - Name Stmts Exec Cover Missing - ---------------------------------------------------------------------- - repoze.bfg 1 1 100% - repoze.bfg.chameleon_genshi 44 44 100% - repoze.bfg.chameleon_text 48 48 100% - repoze.bfg.chameleon_zpt 44 44 100% - repoze.bfg.events 18 18 100% - repoze.bfg.functional 14 14 100% - repoze.bfg.includes 0 0 100% - repoze.bfg.interfaces 71 71 100% - repoze.bfg.location 42 42 100% - repoze.bfg.log 9 9 100% - repoze.bfg.lru 77 77 100% - repoze.bfg.path 12 12 100% - repoze.bfg.push 16 16 100% - repoze.bfg.registry 65 65 100% - repoze.bfg.request 16 16 100% - repoze.bfg.router 137 137 100% - repoze.bfg.security 150 150 100% - repoze.bfg.settings 24 24 100% - repoze.bfg.template 10 10 100% - repoze.bfg.templating 17 17 100% - repoze.bfg.testing 209 209 100% - repoze.bfg.tests 0 0 100% - repoze.bfg.tests.fixtureapp 0 0 100% - repoze.bfg.tests.fixtureapp.models 3 3 100% - repoze.bfg.tests.fixtureapp.views 4 4 100% - repoze.bfg.tests.grokkedapp 5 5 100% - repoze.bfg.tests.routesapp 0 0 100% - repoze.bfg.tests.routesapp.models 3 3 100% - repoze.bfg.tests.routesapp.views 4 4 100% - repoze.bfg.tests.test_chameleon_genshi 157 157 100% - repoze.bfg.tests.test_chameleon_text 172 172 100% - repoze.bfg.tests.test_chameleon_zpt 161 161 100% - repoze.bfg.tests.test_events 59 59 100% - repoze.bfg.tests.test_integration 127 127 100% - repoze.bfg.tests.test_location 83 83 100% - repoze.bfg.tests.test_log 11 11 100% - repoze.bfg.tests.test_lru 74 74 100% - repoze.bfg.tests.test_push 29 29 100% - repoze.bfg.tests.test_registry 112 112 100% - repoze.bfg.tests.test_router 668 668 100% - repoze.bfg.tests.test_security 464 464 100% - repoze.bfg.tests.test_settings 83 83 100% - repoze.bfg.tests.test_template 73 73 100% - repoze.bfg.tests.test_templating 45 45 100% - repoze.bfg.tests.test_testing 375 375 100% - repoze.bfg.tests.test_traversal 579 579 100% - repoze.bfg.tests.test_url 95 95 100% - repoze.bfg.tests.test_urldispatch 298 298 100% - repoze.bfg.tests.test_view 418 418 100% - repoze.bfg.tests.test_wsgi 75 75 100% - repoze.bfg.tests.test_xslt 191 191 100% - repoze.bfg.tests.test_zcml 608 608 100% - repoze.bfg.traversal 167 167 100% - repoze.bfg.url 35 35 100% - repoze.bfg.urldispatch 146 146 100% - repoze.bfg.view 76 76 100% - repoze.bfg.wsgi 23 23 100% - repoze.bfg.xslt 57 57 100% - repoze.bfg.zcml 246 244 99% 168-169 - ---------------------------------------------------------------------- - TOTAL 6750 6748 99% - ---------------------------------------------------------------------- - Ran 378 tests in 10.784s - - OK + [chrism@vitaminf c-less]$ env/bin/python setup.py nosetests + running nosetests + running egg_info + writing requirements to repoze.bfg.egg-info/requires.txt + writing repoze.bfg.egg-info/PKG-INFO + writing namespace_packages to repoze.bfg.egg-info/namespace_packages.txt + writing top-level names to repoze.bfg.egg-info/top_level.txt + writing dependency_links to repoze.bfg.egg-info/dependency_links.txt + writing entry points to repoze.bfg.egg-info/entry_points.txt + writing manifest file 'repoze.bfg.egg-info/SOURCES.txt' + running build_ext + ........................................................................... + ........................................................................... + ........................................................................... + ........................................................................... + ........................................................................... + ......... + Name Stmts Exec Cover Missing + -------------------------------------------------------------------- + repoze.bfg 0 0 100% + repoze.bfg.chameleon_text 48 48 100% + repoze.bfg.chameleon_zpt 44 44 100% + repoze.bfg.events 18 18 100% + repoze.bfg.functional 14 14 100% + repoze.bfg.includes 0 0 100% + repoze.bfg.interfaces 67 67 100% + repoze.bfg.location 42 42 100% + repoze.bfg.log 9 9 100% + repoze.bfg.lru 75 75 100% + repoze.bfg.path 12 12 100% + repoze.bfg.push 14 14 100% + repoze.bfg.registry 65 65 100% + repoze.bfg.request 25 25 100% + repoze.bfg.router 154 154 100% + repoze.bfg.security 150 150 100% + repoze.bfg.settings 24 24 100% + repoze.bfg.template 6 6 100% + repoze.bfg.templating 17 17 100% + repoze.bfg.testing 213 213 100% + repoze.bfg.tests 0 0 100% + repoze.bfg.tests.fixtureapp 0 0 100% + repoze.bfg.tests.fixtureapp.models 3 3 100% + repoze.bfg.tests.fixtureapp.views 4 4 100% + repoze.bfg.tests.grokkedapp 5 5 100% + repoze.bfg.tests.routesapp 0 0 100% + repoze.bfg.tests.routesapp.models 3 3 100% + repoze.bfg.tests.routesapp.views 4 4 100% + repoze.bfg.tests.test_chameleon_text 172 172 100% + repoze.bfg.tests.test_chameleon_zpt 161 161 100% + repoze.bfg.tests.test_events 59 59 100% + repoze.bfg.tests.test_integration 127 127 100% + repoze.bfg.tests.test_location 83 83 100% + repoze.bfg.tests.test_log 11 11 100% + repoze.bfg.tests.test_lru 74 74 100% + repoze.bfg.tests.test_push 29 29 100% + repoze.bfg.tests.test_registry 112 112 100% + repoze.bfg.tests.test_request 31 31 100% + repoze.bfg.tests.test_router 697 697 100% + repoze.bfg.tests.test_security 464 464 100% + repoze.bfg.tests.test_settings 83 83 100% + repoze.bfg.tests.test_template 73 73 100% + repoze.bfg.tests.test_templating 45 45 100% + repoze.bfg.tests.test_testing 379 379 100% + repoze.bfg.tests.test_traversal 616 616 100% + repoze.bfg.tests.test_url 126 126 100% + repoze.bfg.tests.test_urldispatch 338 338 100% + repoze.bfg.tests.test_view 418 418 100% + repoze.bfg.tests.test_wsgi 164 164 100% + repoze.bfg.tests.test_zcml 620 620 100% + repoze.bfg.traversal 215 215 100% + repoze.bfg.url 43 43 100% + repoze.bfg.urldispatch 157 157 100% + repoze.bfg.view 76 76 100% + repoze.bfg.wsgi 43 43 100% + repoze.bfg.zcml 246 246 100% + -------------------------------------------------------------------- + TOTAL 6678 6678 100% + ---------------------------------------------------------------------- + Ran 384 tests in 10.025s + + OK + diff --git a/docs/narr/project.rst b/docs/narr/project.rst index d18cfb7fd..66ce467f9 100644 --- a/docs/narr/project.rst +++ b/docs/narr/project.rst @@ -342,8 +342,8 @@ your application by requiring more settings in this section. The ``reload_templates`` setting in the ``[app:main]`` section is a :mod:`repoze.bfg`-specific setting which is passed into the framework. -If it exists, and is ``true``, :term:`Chameleon` and XSLT template -changes will not require an application restart to be detected. See +If it exists, and is ``true``, :term:`Chameleon` template changes will +not require an application restart to be detected. See :ref:`reload_templates_section` for more information. .. warning:: The ``reload_templates`` option should be turned off for diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst index f1839cfed..985e1e237 100644 --- a/docs/narr/templates.rst +++ b/docs/narr/templates.rst @@ -17,14 +17,21 @@ complies largely with the `Zope Page Template <http://wiki.zope.org/ZPT/FrontPage>`_ template specification and is significantly faster. -.. note:: :mod:`repoze.bfg` can also allow for the use of Genshi-style - templates via the ``chameleon.genshi`` package, support for which - is built-in to :mod:`repoze.bfg`. The :mod:`repoze.bfg` API - functions for getting and rendering Chameleon Genshi-style - templates mirrors the Chameleon ZPT-style API completely; only the - template files themselves must differ. See :ref:`template_module` - for more information about using Genshi-style templates within - :mod:`repoze.bfg`. +.. note:: The language definition documentation for Chameleon + ZPT-style templates is available from `the Chameleon website + <http://chameleon.repoze.org>`_. + +.. note:: As of version 0.8.0, :mod:`repoze.bfg` no longer supports + XSL templates "out of the box". The :mod:`repoze.bfg.xslt` package + is an add-on which provides XSL template bindings. + +.. note:: As of version 0.8.0, :mod:`repoze.bfg` no longer supports + Genshi-style Chameleon bindings "out of the box". The + :mod:`repoze.bfg.chameleon_genshi` package is an add-on which + provides Chameleon Genshi-style template support. + +.. note:: Jinja2 template bindings are available for :mod:`repoze.bfg` + in the :mod:`repoze.bfg.jinja2` package. Given that there is a :term:`chameleon.zpt` template named ``foo.pt`` in a directory in your application named ``templates``, @@ -118,50 +125,13 @@ And ``templates/mytemplate.pt`` might look like so: <html xmlns="http://www.w3.org/1999/xhtml" xmlns:tal="http://xml.zope.org/namespaces/tal" xmlns:metal="http://xml.zope.org/namespaces/metal"> - <span tal:use-macro="main['hello']"> + <span tal:use-macro="main.macros['hello']"> <span metal:use-macro="name"> <span metal:fill-slot="name">Chris</span> </span> </span> </html> - -Templating with XSLT ------------------------- - -:mod:`repoze.bfg` also supports XSLT as an optional templating -language. Like ZPT, an XSLT template is loaded once and re-used -between requests. - -Given a template ``foo.xsl`` in the templates directory, you can render -an XSLT as follows: - -.. code-block:: python - :linenos: - - from repoze.bfg.xslt import render_transform_to_response - from lxml import etree - node = etree.Element("root") - return render_transform_to_response('templates/foo.xsl', node) - -As shown, the second argument to ``render_transform_to_response`` is -the element (and children) that you want as the top of the data for -the XSLT. - -You can also pass XSLT parameters in as keyword arguments: - -.. code-block:: python - :linenos: - - from repoze.bfg.xslt import render_transform_to_response - from lxml import etree - node = etree.Element("root") - value1 = "'app1'" - return render_transform_to_response('templates/foo.xsl', node, param1=value1) - -This would then assign 'app1' as the value of an ``<xsl:param -name="param1"/>`` parameter in the XSLT template. - .. _reload_templates_section: Automatically Reloading Templates @@ -241,3 +211,21 @@ installed, here's an example of using Mako from within a Note that if you use third-party templating languages, the auto-template-reload strategy explained in :ref:`reload_templates_section` will not be available. + +Available Add-On Template System Bindings +----------------------------------------- + +:mod:`repoze.bfg.xslt` is an add-on which provides XSL template +bindings. It lives in the Repoze Subversion repository at +`http://svn.repoze.org/repoze.bfg.xslt +<http://svn.repoze.org/repoze.bfg.xslt>`_. + +:mod:`repoze.bfg.chameleon_genshi` package is an add-on which provides +Chameleon Genshi-style template support. It lives in the Repoze +Subversion repository at `http://svn.repoze.org/repoze.bfg.chameleon_genshi +<http://svn.repoze.org/repoze.bfg.chameleon_genshi>`_. + +Jinja2 template bindings are available for :mod:`repoze.bfg` in the +:mod:`repoze.bfg.jinja2` package. It lives in the Repoze Subversion +repository at `http://svn.repoze.org/repoze.bfg.jinja2 +<http://svn.repoze.org/repoze.bfg.jinja2>`_. diff --git a/docs/notes.txt b/docs/notes.txt index d303042de..aefbeb27d 100644 --- a/docs/notes.txt +++ b/docs/notes.txt @@ -1,9 +1,5 @@ -- Document z3c.pt - - WebOb Request basics -- "push" style templating - - Warn if permissions are defined but no security policy is in place. - Describe better that render_template_to_response is a shortcut. diff --git a/docs/tutorials/lxmlgraph/NOTES.txt b/docs/tutorials/lxmlgraph/NOTES.txt deleted file mode 100644 index 60b4b9f55..000000000 --- a/docs/tutorials/lxmlgraph/NOTES.txt +++ /dev/null @@ -1,6 +0,0 @@ - -To Do ------------- - -- Dream up a ZPT/XSLT theme engine - diff --git a/docs/tutorials/lxmlgraph/background.rst b/docs/tutorials/lxmlgraph/background.rst deleted file mode 100644 index aec4cda26..000000000 --- a/docs/tutorials/lxmlgraph/background.rst +++ /dev/null @@ -1,83 +0,0 @@ -Background -==================== - -In this demo application, we build up, bit-by-bit, the functionality -for a website based on a single XML document. You don't have to know -much about XML to follow along. In fact, the real purpose of this -demo app is to teach its author how to use the stack -(:mod:`repoze.bfg`, ``paster``, eggs, etc.) - -.. warning:: - - If you dislike XML and related technologies such as XPath and XSLT, - you'll thoroughly detest this sample application. Just to be - stupendously clear, :mod:`repoze.bfg` is in no way dependent on XML. - On the other hand, :mod:`repoze.bfg` happens to make XML publishing - kinda fun. - -In summary: - - - Represent a hierarchical website as an XML document - - - Inject :mod:`repoze.bfg` semantics into elements using - :term:`lxml` - - - Support rendering with :term:`XSLT` - -What It Does -------------------- - -Imagine you have a website that looks like this:: - - / - folder1/ - doc1 - doc2 - image1 - folder2/ - doc2 - -Meaning, a heterogenous, nested folder structure, just like your hard -drive. (Unless you're one of those folks that uses your Windows -Desktop as a flat filing system.) How might I get that information -into a website? - -Using :mod:`repoze.bfg`, of course. More specifically, with an XML file -that models that hierarchy: - -.. literalinclude:: step00/simplemodel.xml - :language: xml - -How It Works -------------------- - -To coerce :mod:`repoze.bfg` into publishing this model, I just need to -sprinkle in some Python behavior. For example, :mod:`repoze.bfg` uses -``__getitem__`` to traverse the model. I need my XML data to support -this method. Moreover, I want some specific behavior: run an XPath -express on the node to get the child with the ``@name`` attribute -matching the URL hop. - -Fortunately :term:`lxml` makes this easy. I can inject my nodes with a -class that I write, thus providing my own ``__getitem__`` behavior. - -That class can also assert that my XML nodes provide an interface. -The interface then lets me glue back into the standard :mod:`repoze.bfg` -machinery, such as associating views and permissions into the model. - -Next up, I need to provide views for the elements in the model. I -could, for example, use ZPT and manipulate the XML data using Python -expressions against the :term:`lxml` API. Or, I could use XSLT. - -For the latter, I could register a different XSLT for every "view" on -every interface. Or, I could write one big XSLT, and let its template -matching machinery decide who to render in a certain context. - -And finally, I could pass in just a single node and render it, or pass -in the entire tree with a parameter identifying the context node. - -In the course of this writeup, we'll build ``repoze.lxmlgraph`` -step-by-step, starting with no XML. Each of those decisions will be -analyzed an implemented. At the end, you'll see both the resulting -demo application, plus the thought process that went along with it. - diff --git a/docs/tutorials/lxmlgraph/index.rst b/docs/tutorials/lxmlgraph/index.rst deleted file mode 100644 index cc79f7e73..000000000 --- a/docs/tutorials/lxmlgraph/index.rst +++ /dev/null @@ -1,17 +0,0 @@ -``lxmlgraph``: Publishing An XML Tree with :mod:`repoze.bfg` -============================================================ - -Hierarchical websites are easy to develop with :mod:`repoze.bfg`. -That hierarchy doesn't need to be defined by any particular sort of -graph or databsase system. To demonstrate this, we present -``repoze.lxmlgraph``, a demo application for :mod:`repoze.bfg` that -describes publishing an XML document as a hierarchical website. - -.. toctree:: - :maxdepth: 2 - - background - step01 - step02 - step03 - step04 diff --git a/docs/tutorials/lxmlgraph/step00/simplemodel.xml b/docs/tutorials/lxmlgraph/step00/simplemodel.xml deleted file mode 100644 index 7dbc53951..000000000 --- a/docs/tutorials/lxmlgraph/step00/simplemodel.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0"?> -<site> - <title>My XMLGRAPH Website</title> - <folder xml:id="n1" name="folder1"> - <document xml:id="n11" name="doc1"> - <title>doc1 in folder1</title> - <body> - <div xmlns="http://www.w3.org/1999/xhtml"> - <p>Welcome to the site. We have lots to say.</p> - <p>Or, <em>maybe</em> not.</p> - </div> - </body> - </document> - <document xml:id="n12" name="doc2"> - <title>doc2 in folder1</title> - </document> - </folder> - <folder xml:id="n2" name="folder2"> - <document xml:id="n21" name="doc1"> - <title>doc1 in folder2</title> - </document> - <document xml:id="n22" name="doc2"> - <title>doc2 in folder2</title> - </document> - </folder> -</root> diff --git a/docs/tutorials/lxmlgraph/step01.rst b/docs/tutorials/lxmlgraph/step01.rst deleted file mode 100644 index 578f13608..000000000 --- a/docs/tutorials/lxmlgraph/step01.rst +++ /dev/null @@ -1,24 +0,0 @@ -======================= -Step 1: Getting Started -======================= - -To get started, using the ``paster`` command from a :term:`virtualenv` -you've created that has :mod:`repoze.bfg` installed, run ``paster -create -t bfg`` as described in :ref:`project_narr` to create your -``lxmlgraph`` project:: - - $ paster create -t bfg Selected and implied templates: repoze.bfg#bfg - repoze.bfg starter project - - Enter project name: lxmlgraph - ... - $ - -You now have a project named ``lxmlgraph`` in your current directory. -We'll add to this project in subsequent steps. - -To get your project ready for development and execution, use the -``setup.py develop`` command within the same virtualenv as bfg is -installed as documented in :ref:`project_narr` . You'll need to do -this in order to run the ``lxmlgraph`` application in subsequent -steps. diff --git a/docs/tutorials/lxmlgraph/step01/myapp/__init__.py b/docs/tutorials/lxmlgraph/step01/myapp/__init__.py deleted file mode 100644 index 792d60054..000000000 --- a/docs/tutorials/lxmlgraph/step01/myapp/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# diff --git a/docs/tutorials/lxmlgraph/step01/myapp/configure.zcml b/docs/tutorials/lxmlgraph/step01/myapp/configure.zcml deleted file mode 100644 index e06023c24..000000000 --- a/docs/tutorials/lxmlgraph/step01/myapp/configure.zcml +++ /dev/null @@ -1,12 +0,0 @@ -<configure xmlns="http://namespaces.repoze.org/bfg"> - - <!-- this must be included for the view declarations to work --> - <include package="repoze.bfg.includes" /> - - <!-- the default view for a MyModel --> - <view - for=".models.IMyModel" - view=".views.my_hello_view" - /> - -</configure> diff --git a/docs/tutorials/lxmlgraph/step01/myapp/models.py b/docs/tutorials/lxmlgraph/step01/myapp/models.py deleted file mode 100644 index 85d603d80..000000000 --- a/docs/tutorials/lxmlgraph/step01/myapp/models.py +++ /dev/null @@ -1,18 +0,0 @@ -from zope.interface import implements -from zope.interface import Attribute -from zope.interface import Interface - -class IMyModel(Interface): - __name__ = Attribute('Name of the model instance') - -class MyModel(dict): - implements(IMyModel) - def __init__(self, name): - self.__name__ = name - -root = MyModel('site') -root['a'] = MyModel('a') -root['b'] = MyModel('b') - -def get_root(environ): - return root diff --git a/docs/tutorials/lxmlgraph/step01/myapp/views.py b/docs/tutorials/lxmlgraph/step01/myapp/views.py deleted file mode 100644 index 13de3ae31..000000000 --- a/docs/tutorials/lxmlgraph/step01/myapp/views.py +++ /dev/null @@ -1,7 +0,0 @@ -from webob import Response - -def my_hello_view(context, request): - response = Response('Hello from %s @ %s' % ( - context.__name__, - request.environ['PATH_INFO'])) - return response diff --git a/docs/tutorials/lxmlgraph/step01/run.py b/docs/tutorials/lxmlgraph/step01/run.py deleted file mode 100644 index 1eac209dc..000000000 --- a/docs/tutorials/lxmlgraph/step01/run.py +++ /dev/null @@ -1,8 +0,0 @@ -from paste import httpserver - -from repoze.bfg import make_app -from myapp.models import get_root -import myapp - -app = make_app(get_root, myapp) -httpserver.serve(app, host='0.0.0.0', port='5432') diff --git a/docs/tutorials/lxmlgraph/step02.rst b/docs/tutorials/lxmlgraph/step02.rst deleted file mode 100644 index 1dc1ebcd3..000000000 --- a/docs/tutorials/lxmlgraph/step02.rst +++ /dev/null @@ -1,132 +0,0 @@ -================================================ -Step 2: Hello World as XML -================================================ - -We now have a project named ``lxmlgraph``. It contains a *package* -(also) named ``lxmlgraph``. - -In this step we will add an XML document to the *package* as our model -data. We will leverage the following :mod:`repoze.bfg` machinery: - - - Model data with interfaces that define "types" - - - ZCML configuration to provide type-specific views - -Our application will need to do these things: - - - Use :term:`lxml` Element classes to inject :mod:`repoze.bfg` - behavior into ``lxml`` nodes - - - That model class needs to implement the :mod:`repoze.bfg` - publishing contract - -All of the below filenames are relative to the ``lxmlgraph`` *package* -rather than the *project*. - -``samplemodel.xml`` ------------------------------------ - -We're going to add an XML document that will serve as a source for -model data named ``samplemodel.xml``. Put the content of this file in -your package: - -.. literalinclude:: step02/myapp/samplemodel.xml - :linenos: - :language: xml - -#. Line 2 provides the root of the model as an XML ``<site>`` node. - The element name doesn't have to be ``<site>``. It has a name of - ``site``. - -#. In lines 3-4, the ``<site>`` contains 2 top-level children: a and - b. These are provided as an element name ``<document>``. This, - also, is meaningless as far as :mod:`repoze.bfg` is concerned. - However, this is where you compose the information model you are - publishing. - -The only special constraint is that an XML node that wants to be -"found" by :mod:`repoze.bfg` in during traversal *must* have a -``name`` attribute. (The use of ``@name`` corresponds to ``__name__`` -in the :mod:`repoze.bfg` sense of :term:`location` ). Each hop in the -URL tries to grab a child with an attribute matching the next hop. -Also, the value of the ``@name`` should be unique in its containing -node. - -Module ``models.py`` ------------------------------- - -At a high level, we make write a class that "extends" ``lxml`` -``Element`` nodes, create an ``lxml`` parser, and register the custom -class with the parser. Replace the contents of the autogenerated -``models.py`` with the content we show below. - -.. literalinclude:: step02/myapp/models.py - :linenos: - -#. Line 4 imports :term:`lxml`. - -#. Line 9 creates the custom class we are going to use to extend - etree.ElementBase. The `<lxml website - <http://codespeak.net/lxml/>`_ has great documentation on the - various ways to inject custom Python behavior into XML. - -#. Just as before, line 12 says that instances of this class support a - certain content type (interface.) In our case, instances will be - XML nodes. - -#. :mod:`repoze.bfg` has a protocol where model data should have an - ``__name__`` attribute. Lines 14-16 implement this by grabbing the - ``@name`` attribute of the current node. - -#. URL traversal in :mod:`repoze.bfg` works via the ``__getitem__`` - protocol. Thus, we need a method that implements this. Lines - 18-26 use XPath to look for a direct child that has an ``@name`` - matching the item name that's being traversed to. If it finds it, - return it. If not, or if more than one is found, raise an error. - -#. As before, ``get_root`` is the function that is expected to return - the top of the model. In lines 30+ we do the :term:`lxml` magic to - get the custom Python class registered. We then load some XML and - return the top of the tree. - -Module ``views.py`` ------------------------------ - -Replace the autogenerated ``views.py`` code in the ``lxmlgraph`` -package with the following: - -.. literalinclude:: step02/myapp/views.py - :linenos: - -Here's what that file does: - -#. Line 5 grabs the element name (tag name) of the ``context``, which - is the current XML node that we're traversing through. - -#. Line 6 uses the special property we defined in our custom Python - class to get the ``__name__`` of the context. - -We don't need to change the ``configure.zcml`` because the -autogenerated one is still correct for this configuration. It -includes: - -.. literalinclude:: step02/myapp/configure.zcml - :linenos: - :language: xml - -Browsing the Model ------------------------- - -We're done changing code. Start the application by executing ``paster -serve lxmlgraph.ini`` (the ``.ini`` file is in the project directory). -It will listen on port 5432. We can use these URLs to browse the -model graph and see results:: - - http://localhost:5432/a (Hello to document from a @ /a) - - http://localhost:5432/b (Hello to document from b @ /b) - - http://localhost:5432/c (Not Found) - -In this case, each request grabs a node in the XML and uses it as the -data for the view. diff --git a/docs/tutorials/lxmlgraph/step02/myapp/__init__.py b/docs/tutorials/lxmlgraph/step02/myapp/__init__.py deleted file mode 100644 index 792d60054..000000000 --- a/docs/tutorials/lxmlgraph/step02/myapp/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# diff --git a/docs/tutorials/lxmlgraph/step02/myapp/configure.zcml b/docs/tutorials/lxmlgraph/step02/myapp/configure.zcml deleted file mode 100644 index 2414ae6b2..000000000 --- a/docs/tutorials/lxmlgraph/step02/myapp/configure.zcml +++ /dev/null @@ -1,10 +0,0 @@ -<configure xmlns="http://namespaces.repoze.org/bfg"> - - <include package="repoze.bfg.includes" /> - - <view - for=".models.IMyModel" - view=".views.my_view" - /> - -</configure> diff --git a/docs/tutorials/lxmlgraph/step02/myapp/models.py b/docs/tutorials/lxmlgraph/step02/myapp/models.py deleted file mode 100644 index 1d93ccdd0..000000000 --- a/docs/tutorials/lxmlgraph/step02/myapp/models.py +++ /dev/null @@ -1,42 +0,0 @@ -import os - -from zope.interface import implements -from zope.interface import Attribute -from zope.interface import Interface -from lxml import etree - -class IMyModel(Interface): - __name__ = Attribute('Name of the model instance') - -class BfgElement(etree.ElementBase): - """Handle access control and getitem behavior""" - - implements(IMyModel) - - @property - def __name__(self): - return self.xpath("@name")[0] - - def __getitem__(self, child_name): - xp = "*[@name='%s']" % child_name - matches = self.xpath(xp) - if len(matches) == 0: - raise KeyError('No child found for %s' % child_name) - elif len(matches) > 1: - raise KeyError('More than one child for %s' % child_name) - else: - return matches[0] - -def get_root(environ): - # Setup the custom parser with our BfgElement behavior - parser_lookup = etree.ElementDefaultClassLookup(element=BfgElement) - parser = etree.XMLParser() - parser.set_element_class_lookup(parser_lookup) - - # Now load the XML file - here = os.path.join(os.path.dirname(__file__)) - samplemodel = os.path.join(here, 'samplemodel.xml') - xmlstring = open(samplemodel).read() - root = etree.XML(xmlstring, parser) - - return root diff --git a/docs/tutorials/lxmlgraph/step02/myapp/samplemodel.xml b/docs/tutorials/lxmlgraph/step02/myapp/samplemodel.xml deleted file mode 100644 index bbe474c63..000000000 --- a/docs/tutorials/lxmlgraph/step02/myapp/samplemodel.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<site name="site"> - <document name="a"/> - <document name="b"/> -</site> diff --git a/docs/tutorials/lxmlgraph/step02/myapp/views.py b/docs/tutorials/lxmlgraph/step02/myapp/views.py deleted file mode 100644 index 75e390efb..000000000 --- a/docs/tutorials/lxmlgraph/step02/myapp/views.py +++ /dev/null @@ -1,8 +0,0 @@ -from webob import Response - -def my_view(context, request): - response = Response('Hello to %s from %s @ %s' % ( - context.tag, - context.__name__, - request.environ['PATH_INFO'])) - return response diff --git a/docs/tutorials/lxmlgraph/step02/run.py b/docs/tutorials/lxmlgraph/step02/run.py deleted file mode 100644 index 1eac209dc..000000000 --- a/docs/tutorials/lxmlgraph/step02/run.py +++ /dev/null @@ -1,8 +0,0 @@ -from paste import httpserver - -from repoze.bfg import make_app -from myapp.models import get_root -import myapp - -app = make_app(get_root, myapp) -httpserver.serve(app, host='0.0.0.0', port='5432') diff --git a/docs/tutorials/lxmlgraph/step03.rst b/docs/tutorials/lxmlgraph/step03.rst deleted file mode 100644 index ce88b78c8..000000000 --- a/docs/tutorials/lxmlgraph/step03.rst +++ /dev/null @@ -1,209 +0,0 @@ -================================================ -Step 3: Basic Rendering With ZPT and XSLT -================================================ - -Our XML-based model is now usable. However, we're using Python to -generate the HTML, instead of a template. In this step, we'll look at -wiring up some templates, using both ZPT and XSLT. - -In a nutshell, this means: - - - Slight changes to the ZCML - - - View functions that assemble information and call the template - -ZPT Templates -======================== - -Let's start with a ZPT-based default view for the nodes in the XML. -Change your project's ``configure.zcml`` so that it looks like this: - -.. code-block:: xml - - <configure xmlns="http://namespaces.repoze.org/bfg"> - - <!-- this must be included for the view declarations to work --> - <include package="repoze.bfg.includes" /> - - <view - for=".models.IMyModel" - view=".views.zpt_view" - /> - - </configure> - -In other words, replace the default view function with -``.views.zpt_view``. This view stanza indicates that the *default -view* for a model that implements ``lxmlgraph.models.IMyModel`` should -be the ``lxmlgraph.views.zpt_view`` function. It is the *default* -view because this stanza does not have a ``name`` attribute. - -Additonally, add a template to your project's ``templates`` directory -named ``default.pt`` with this content: - -.. literalinclude:: step03/myapp/templates/default.pt - :linenos: - :language: xml - -Also add a function in ``views.py`` that looks like the following: - -.. code-block:: python - :linenos: - - from repoze.bfg.chameleon_zpt import render_template_to_response - def zpt_view(context, request): - return render_template_to_response('templates/default.pt', - name=context.__name__, - node=context) - -This function is relatively simple: - -#. Line 1 imports a :mod:`repoze.bfg` function that renders ZPT - templates to a response. :mod:`repoze.bfg` uses the - :term:`chameleon.zpt` ZPT engine. - -#. Line 2, like our other view functions, gets passed a ``context`` - (the current hop in the URL) and WebOb ``request`` object. - -#. Line 3 calls the ``render_template_to_response`` function, passing - in the filename for the ZPT and two top-level variables that can be - used in the ZPT. The first is the name of the current URL hop - (context). The second is the XML node object for that hop - (context). - -In Step 02, we returned a :term:`WebOb` Response object that we -created. ``render_template_to_response`` makes a Response itself. -The response's status is always ``200 OK`` and the content-type is -always ``text/html`` if you use this shortcut function. - -Here's what the ZPT looks like again: - -.. literalinclude:: step03/myapp/templates/default.pt - :linenos: - :language: xml - -Life is better with templating: - -#. Lines 1-2 make an ``<html>`` node with a namespace for TAL. - -#. Line 5 inserts the value of the ``name`` that we passed into - ``render_template_to_response``. - -#. Line 6 looks interesting. It uses the ``node`` that we passed in - via ``render_template_to_response``. Since :term:`chameleon.zpt` - uses Python as its expession language, we can put anything - Python-legal between the braces. And since ``node`` is an ``lxml`` - ``Element`` object, we just ask for its ``.tag``, like regular - Python ``lxml`` code. - -Viewing the ZPT ------------------- - -With all of that in place, restarting the application and visiting -``http://localhost:5432/a`` now generates, via the ZPT, the -following:: - - My template is viewing item: a - - The node has a tag name of: document. - -If you visit ``http://localhost:5432/`` you will see:: - - My template is viewing item: site - - The node has a tag name of: site. - -We've successfully rendered a view that uses a template against a -model using the ZPT templating language. - - -XSLT Templates -============== - -So that's the ZPT way of rendering HTML for an XML document. We can -additonally use XSLT to do templating. How might XSLT look? - -``configure.zcml`` ----------------------------------- - -Make your ``configure.zcml`` look like so: - -.. literalinclude:: step03/myapp/configure.zcml - :linenos: - :language: xml - -#. Lines 10-14 wire up a new view, in addition to the default view. - -#. Line 13 provides the difference: ``name="xsltview.html"`` means - that URLs invoked against our model can have ``/xsltview.html`` - appended to them, which will invoke our XSLT view. - -In the ZCML, there is no distinction between a ZPT view and an XSLT -view. The difference is only in the function that is pointed to by -the ``view=`` attribute. The view itself controls which templating -language is in use. - -``views.py`` --------------------------------- - -The ZCML says that our XSLT view (``xsltview.html`` on the URL) comes -from the ``lxmlgraph.views.xslt_view`` function, which you should add -to your ``views.py`` file: - -.. literalinclude:: step03/myapp/views.py - :linenos: - -#. Line 9 starts the Python function which serves as the view for this - template. The function has the same signature as the - ``zpt_default_view`` function we defined for the ZPT template's - view. - -#. Line 10 implements the difference. We call - ``render_transform_to_response`` instead of - ``render_template_to_response``. This tells :mod:`repoze.bfg` to - make an XSLT processor for this template, instead of a ZPT. The - second argument passes in ``context`` to the XSLT transform. - ``context``` is an instance of an Element node. Namely, a node - from the XML document that corresponds to the current hop in the - URL. - - -``xsltview.xsl`` --------------------------------- - -Add a file named ``xsltview.xsl`` to your application's ``templates`` -directory and give it the following contents: - -.. literalinclude:: step03/myapp/templates/xsltview.xsl - :linenos: - :language: xml - -#. Lines 1 and 2 are typical XSLT setup. - -#. Line 3 defines a rule to match on the node that is passed in. In - our case, a ``<document>`` node. - -#. Line 7 inserts the value of the ``@id`` attribute from the - "current" node at that point in the rule. We're sitting on the - ``<document>`` node (thanks to line 3). Thus, ``<xsl:value of - select="@id"/>`` inserts ``a`` or ``b``, depending on which - document we are sitting on. - -#. Line 8 shows the element name of the current node. - -Viewing the XSLT --------------------- - -With those changes in place, restart the application. Visiting to the -``http://localhost:5432/a/xsltview.html`` URL should show:: - - My template is viewing item: a - - The node has a name of: document. - -We've successfully run an XSL template against our model object. - -We've now seen how to use ZPT and XSL templates against model objects -created via an XML tree. - - diff --git a/docs/tutorials/lxmlgraph/step03/myapp/__init__.py b/docs/tutorials/lxmlgraph/step03/myapp/__init__.py deleted file mode 100644 index 792d60054..000000000 --- a/docs/tutorials/lxmlgraph/step03/myapp/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# diff --git a/docs/tutorials/lxmlgraph/step03/myapp/configure.zcml b/docs/tutorials/lxmlgraph/step03/myapp/configure.zcml deleted file mode 100644 index 43b766cfb..000000000 --- a/docs/tutorials/lxmlgraph/step03/myapp/configure.zcml +++ /dev/null @@ -1,16 +0,0 @@ -<configure xmlns="http://namespaces.repoze.org/bfg"> - - <include package="repoze.bfg.includes" /> - - <view - for=".models.IMyModel" - view=".views.zpt_view" - /> - - <view - for=".models.IMyModel" - view=".views.xslt_view" - name="xsltview.html" - /> - -</configure> diff --git a/docs/tutorials/lxmlgraph/step03/myapp/models.py b/docs/tutorials/lxmlgraph/step03/myapp/models.py deleted file mode 100644 index 1d93ccdd0..000000000 --- a/docs/tutorials/lxmlgraph/step03/myapp/models.py +++ /dev/null @@ -1,42 +0,0 @@ -import os - -from zope.interface import implements -from zope.interface import Attribute -from zope.interface import Interface -from lxml import etree - -class IMyModel(Interface): - __name__ = Attribute('Name of the model instance') - -class BfgElement(etree.ElementBase): - """Handle access control and getitem behavior""" - - implements(IMyModel) - - @property - def __name__(self): - return self.xpath("@name")[0] - - def __getitem__(self, child_name): - xp = "*[@name='%s']" % child_name - matches = self.xpath(xp) - if len(matches) == 0: - raise KeyError('No child found for %s' % child_name) - elif len(matches) > 1: - raise KeyError('More than one child for %s' % child_name) - else: - return matches[0] - -def get_root(environ): - # Setup the custom parser with our BfgElement behavior - parser_lookup = etree.ElementDefaultClassLookup(element=BfgElement) - parser = etree.XMLParser() - parser.set_element_class_lookup(parser_lookup) - - # Now load the XML file - here = os.path.join(os.path.dirname(__file__)) - samplemodel = os.path.join(here, 'samplemodel.xml') - xmlstring = open(samplemodel).read() - root = etree.XML(xmlstring, parser) - - return root diff --git a/docs/tutorials/lxmlgraph/step03/myapp/samplemodel.xml b/docs/tutorials/lxmlgraph/step03/myapp/samplemodel.xml deleted file mode 100644 index bbe474c63..000000000 --- a/docs/tutorials/lxmlgraph/step03/myapp/samplemodel.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<site name="site"> - <document name="a"/> - <document name="b"/> -</site> diff --git a/docs/tutorials/lxmlgraph/step03/myapp/templates/default.pt b/docs/tutorials/lxmlgraph/step03/myapp/templates/default.pt deleted file mode 100644 index 3cc98ef92..000000000 --- a/docs/tutorials/lxmlgraph/step03/myapp/templates/default.pt +++ /dev/null @@ -1,8 +0,0 @@ -<html xmlns="http://www.w3.org/1999/xhtml" - xmlns:tal="http://xml.zope.org/namespaces/tal"> - <head></head> - <body> - <h1>My template is viewing item: ${name}</h1> - <p>The node has a tag name of: ${node.tag}.</p> - </body> -</html> diff --git a/docs/tutorials/lxmlgraph/step03/myapp/templates/xsltview.xsl b/docs/tutorials/lxmlgraph/step03/myapp/templates/xsltview.xsl deleted file mode 100644 index 4d759b15b..000000000 --- a/docs/tutorials/lxmlgraph/step03/myapp/templates/xsltview.xsl +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> - <xsl:template match="/document"> - <html> - <head/> - <body> - <h1>My template is viewing item: <xsl:value-of select="@name"/></h1> - <p>The node has a name of: <xsl:value-of select="name()"/>.</p> - </body> - </html> - </xsl:template> -</xsl:stylesheet> diff --git a/docs/tutorials/lxmlgraph/step03/myapp/views.py b/docs/tutorials/lxmlgraph/step03/myapp/views.py deleted file mode 100644 index e18c04415..000000000 --- a/docs/tutorials/lxmlgraph/step03/myapp/views.py +++ /dev/null @@ -1,10 +0,0 @@ -from repoze.bfg.chameleon_zpt import render_template_to_response -from repoze.bfg.xslt import render_transform_to_response - -def zpt_view(context, request): - return render_template_to_response("templates/default.pt", - name=context.__name__, - node=context) - -def xslt_view(context, request): - return render_transform_to_response('templates/xsltview.xsl', context) diff --git a/docs/tutorials/lxmlgraph/step04.rst b/docs/tutorials/lxmlgraph/step04.rst deleted file mode 100644 index f96a0712f..000000000 --- a/docs/tutorials/lxmlgraph/step04.rst +++ /dev/null @@ -1,250 +0,0 @@ -================================================ -Step 4: Hierarchical Rendering With XSLT -================================================ - -Now that we have basic templating for our XML graph in place, let's -start doing some fun stuff with it. As we walk through use cases and -build out patterns for implementing them, we'll get to leverage some -features available in XML processors. For better or worse. [wink] - -In this step we take a look at the following: - -- Build a nested, folder-like website - -- Render the HTML common to all pages, then render the part specific - to a certain page - -- Show contents of a folder when sitting on a folder, and content of a - document when sitting on a document - - -Pre-Flight Cleanup -==================== - -In the last example, we had a default template that used ZPT. We're -shifting the rest of the steps over to XSLT. Thus, our -``configure.zcml`` can now be madesimpler. Change your -``configure.zcml`` to lok like so: - -.. literalinclude:: step04/myapp/configure.zcml - :linenos: - :language: xml - -We'll also remove the ``zpt_view`` function from ``views.py``, as -we'll see in a moment. - -Design Change: Trees and Context IDs -======================================== - -In :mod:`repoze.bfg`, the ``context`` variable that is passed into our -view function equates to the Python object that was grabbed on the -current hop in the URL. For ``lxmlgraph``, that "context" object is a -node in the XML document, found by traversing node children. - -For the XSLT in Step 3, we passed in the context node. From the -XSLT's perpective, the universe started at the context node. It could -only see information in that node and the children beneath it. - -If we could see the entire tree, however, we could put the other -information to use: showing the name of the site in a header, listing -the breadcrumbs to reach the document, and other portal-style boxes. - -To enable this, we need the following: - -#. A way to pass in the entire XML document tree. - -#. A way to uniquely point at the item in the XML that we are - currently sitting on, with the fastest performance possible. - -We will thus make the following changes in our approach: - -#. The XML document will support an ``xml:id`` attribute on each node - that has a ``name`` attribute. The ``xml:id`` uniquely identifies - the resource within the document. Moreover, it leverages built-in - support for high-speed lookups in XPath. - -#. We change the view function to pass in the root of the tree, - instead of the context node. - -#. We also pass in, via an XSLT parameter, the ``xml:id`` of the - context node. - -#. The XSLT will start at the top of the tree, generate the site-wide - look and feel, then render the context node. - -That's the big picture. Each of these changes will be explained in -detail below. - -``samplemodel.xml`` -===================== - -The XML document with the information for our website has quite a -number of changes: - -.. literalinclude:: step04/myapp/samplemodel.xml - :linenos: - :language: xml - -#. Line 3 shows that our ``<site>`` now gets a ``<title>``. - -#. On Line 4 we make an index document at the root that contains a - document-wide unique value for its ``@xml:id``. - -#. In lines 5-11, our ``<document>`` gets some extra information: a - ``<title>``, plus some HTML-namespaced markup content inside a - ``<body>``. - -#. Lines 13-32 show a nested XML hierarchy. A ``<folder>`` gets an - ``@name``, making the folder itself published as a possible URL. - It also gets an ``@xml:id``, allowing it to be uniquely addressed - within the entire document. The ``<folder>`` gets a ``<title>`` - child node, but then gets two more ``__getitem__``-enabled child - nodes of type ``<document>``. ("Enabled", as in, has a ``@name`` - attribute.) - -Thus the major changes: - -- The root contains ``<folder>`` nodes which contain ``<document>`` - nodes. - -- The root could contain documents too, and the folder could contain - sub-folders. There's nothing special about the arrangement. - -- The only thing special is the presence of ``@name`` attributes, - which allow ``__getitem__`` (via XPath) to traverse to that child. - -- As we'll see in a second, the ``@xml:id`` allows jumping through the - hierarchy directly to a node. - -- Finally, for UI-framework-ish purposes, having a child ``<title>`` - allows us to show in a browser what we're looking at. - -The ``models.py`` hasn't changed, so let's move to the small changes -in the ``views.py``. - -``views.py`` -============ - -As noted above, we removed the ZPT views, and thus ``views.py`` is -shorter, and focused only on a function that provides an XSLT -template. Although there aren't many lines in that function, there -are some concepts to explain: - -.. literalinclude:: step04/myapp/views.py - :linenos: - -#. We are going to be using a feature from XML called ``xml:id``, - which we explained above in the ``samplemodel.xml`` section. In - lines 4 and 5, we make constants that point to the namespace - needed. - -#. As the comment says, line 9 grabs the "root" node of the site. - Inside this function, we are traversing, node-by-node, through a - hierarchy. Thus our context node is an lxml Element object, which - supports a method to grab the tree (and thus root) in which the - context sits. - -#. Next, to support the XSLT approach we show next, we want to let the - XSLT know the ``xml:id`` that we are sitting on. Since we are - passing it in as an XSLT paramter, we need some special handling: - - - The *value* of the parameter is the ``@xml:id`` of the node we are - sitting on. - - - Per lxml's needs, that value needs to be quoted. Thus, the value - of ``contextid`` will be something like ``"'n1'"`` - -#. Finally, on line 12, we call the XSLT processor, passing in keyword - arguments that become XSLT parameters. Unlike before, the node we - pass in is the top of the tree, rather than the current (context) - node. - -In summary, we render the XSLT by handing it the root node of the -tree, plus a flag that says which node we are currently sitting on. - -``xsltview.xsl`` -================= - -The XSLT template gets the most substantive changes, as we both have -to support this root-and-contextid idea, as well as some features that -put this to use: - -- Having a common look-and-feel across all pages, along with "rules" - that handle each content type - -- Show the context's ``<title>`` in the same place - -- Show some general information about the node - -The following XSLT accomplishes these features: - -.. literalinclude:: step04/myapp/xsltview.xsl - :linenos: - :language: xml - -#. Line 3 accepts the ``@xml:id`` passed in as a parameter of the XSLT - transformation. This can differ between requests, as different - nodes are traversed. - -#. Line 4 jumps directly to the tree node that has that ``@xml:id`` by - using XPath's ``id()`` function. This is a high-speed lookup, - similar to ``document.getElementById()`` in JavaScript. We then - assign the node to a global XSLT variable, to avoid paying that - price again. - -#. Line 5 gets into XSLT's rule-oriented mumbo-jumbo. This template - rule says: "Match on the root of the tree that was passed in, then - do some work." Think of this as a CSS rule that matches on ``body - {}``. - -#. Lines 7-11 output HTML for the document and ``<head>``. - -#. Line 9 (and line 14) inserts the value of the context node's - ``<title>`` using ``<xsl:value-of>``. - -#. Line 16 does some XSLT mumbo jumbo. It says "Find a rule that - handles the context node, which might be a ``<folder>`` or might be - a ``<document>``." Control is then passed to an ``<xsl:template>`` - that meets the conditions. Once that rule is finished, control - returns to line 17. - -#. Lines 17-42 then format some basic information about the context - node. The HTML generated for this, however, appears *after* the - type-specific handler in the resulting HTML. - -#. Line 46 is an ``<xsl:template>`` rule that handles ``<folder>`` - nodes. It only gets control when something else hands control to it. - - In this case, the rule makes a paragraph then lists the contents of - the folder. - -#. Line 50 checks to see if the folder contains any "publishable" - content. We wouldn't want a heading to appear saying "Folder - Contents" with empty space under it. - -#. Line 53 then iterates over all the child nodes which have an - ``@xml:id``. - -#. Lines 55-57 make an ``<li>`` with an ``<a>`` for each item in the - folder. Inside the ``<xsl:for-each``, the "current" node is the - current item in the iteration. The ``@href`` uses what XSLT calls - "attribute value template" (curly braces) to let the XSLT processor - operate inside an attribute. - -#. Line 63 handles ``<document>`` nodes when handed control. - -#. Line 67 recursively copies the nodes in the ``<document>`` content. - -To recap, this XSLT handles any node passed in, and generates a UI -that can handle the global styling, the navigational elements, and the -content for the current traversal hop. - -Conclusion -===================== - -Though not very much code, this is the basis for a useful amount of -features. A hierarchical website with templating that can handle -global styling and navigation, as well as type-driven templating, all -at reasonable (albeit in-memory) performance. - - diff --git a/docs/tutorials/lxmlgraph/step04/myapp/__init__.py b/docs/tutorials/lxmlgraph/step04/myapp/__init__.py deleted file mode 100644 index 792d60054..000000000 --- a/docs/tutorials/lxmlgraph/step04/myapp/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# diff --git a/docs/tutorials/lxmlgraph/step04/myapp/configure.zcml b/docs/tutorials/lxmlgraph/step04/myapp/configure.zcml deleted file mode 100644 index c2d59effb..000000000 --- a/docs/tutorials/lxmlgraph/step04/myapp/configure.zcml +++ /dev/null @@ -1,10 +0,0 @@ -<configure xmlns="http://namespaces.repoze.org/bfg"> - - <include package="repoze.bfg.includes" /> - - <view - for=".models.IMyModel" - view=".views.xslt_view" - /> - -</configure> diff --git a/docs/tutorials/lxmlgraph/step04/myapp/models.py b/docs/tutorials/lxmlgraph/step04/myapp/models.py deleted file mode 100644 index a0d64ef59..000000000 --- a/docs/tutorials/lxmlgraph/step04/myapp/models.py +++ /dev/null @@ -1,45 +0,0 @@ -import os - -from zope.interface import implements -from zope.interface import Attribute -from zope.interface import Interface -from lxml import etree - -class IMyModel(Interface): - __name__ = Attribute('Name of the model instance') - -class BfgElement(etree.ElementBase): - """Handle access control and getitem behavior""" - - implements(IMyModel) - - @property - def __name__(self): - return self.xpath("@name")[0] - - def __getitem__(self, child_name): - xp = "*[@name='%s']" % child_name - matches = self.xpath(xp) - if len(matches) == 0: - raise KeyError('No child found for %s' % child_name) - elif len(matches) > 1: - raise KeyError('More than one child for %s' % child_name) - else: - return matches[0] - -def get_root(environ): - # Setup the custom parser with our BfgElement behavior - parser_lookup = etree.ElementDefaultClassLookup(element=BfgElement) - parser = etree.XMLParser() - parser.set_element_class_lookup(parser_lookup) - - # Now load the XML file - here = os.path.join(os.path.dirname(__file__)) - samplemodel = os.path.join(here, 'samplemodel.xml') - xmlstring = open(samplemodel).read() - root = etree.XML(xmlstring, parser) - - return root - - - diff --git a/docs/tutorials/lxmlgraph/step04/myapp/samplemodel.xml b/docs/tutorials/lxmlgraph/step04/myapp/samplemodel.xml deleted file mode 100644 index 36ab335d2..000000000 --- a/docs/tutorials/lxmlgraph/step04/myapp/samplemodel.xml +++ /dev/null @@ -1,44 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<site> - <title>My XMLGRAPH Website</title> - <document xml:id="index" name="index.html"> - <title>Site Home Page</title> - <body> - <div xmlns="http://www.w3.org/1999/xhtml"> - <p>Welcome to the site. We have lots to say.</p> - <p>Or, <em>maybe</em> not.</p> - </div> - </body> - </document> - <folder xml:id="n1" name="folder1"> - <title>Folder One</title> - <document xml:id="n11" name="doc1"> - <title>doc1 in folder1</title> - <body> - <div xmlns="http://www.w3.org/1999/xhtml"> - <p>I am in an HTML <code>div</code> so I can do <strong>LOTS</strong> of - formatting.</p> - </div> - </body> - </document> - <document xml:id="n12" name="doc2"> - <title>doc2 in folder1</title> - <body> - <div xmlns="http://www.w3.org/1999/xhtml"> - <p>Keep this on one line.</p> - </div> - </body> - </document> - </folder> - <folder xml:id="n2" name="folder2"> - <title>The Second Folder</title> - <document xml:id="n21" name="doc1"> - <title>doc1 in folder2</title> - <body> - <div xmlns="http://www.w3.org/1999/xhtml"> - <p>This is a special folder. It's folder 2!</p> - </div> - </body> - </document> - </folder> -</site> diff --git a/docs/tutorials/lxmlgraph/step04/myapp/views.py b/docs/tutorials/lxmlgraph/step04/myapp/views.py deleted file mode 100644 index f079cea8c..000000000 --- a/docs/tutorials/lxmlgraph/step04/myapp/views.py +++ /dev/null @@ -1,13 +0,0 @@ -from repoze.bfg.xslt import render_transform_to_response - -# Some constants -XML_NAMESPACE='http://www.w3.org/XML/1998/namespace' -XML_PREFIX= '{%s}' % XML_NAMESPACE - -def xslt_view(context, request): - # Grab the root of the tree, which should be a <site> - site = context.getroottree().getroot() - # Jot down which node we're sitting on as the <context> - contextid = "'%s'" % context.get(XML_PREFIX+'id') - return render_transform_to_response("xsltview.xsl", site, - contextid=contextid) diff --git a/docs/tutorials/lxmlgraph/step04/myapp/xsltview.xsl b/docs/tutorials/lxmlgraph/step04/myapp/xsltview.xsl deleted file mode 100644 index 2406987d0..000000000 --- a/docs/tutorials/lxmlgraph/step04/myapp/xsltview.xsl +++ /dev/null @@ -1,69 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> - <xsl:param name="contextid">n1</xsl:param> - <xsl:variable name="contextnode" select="id($contextid)"/> - <xsl:template match="/"> - <html> - <head> - <title> - <xsl:value-of select="$contextnode/title"/> - </title> - </head> - <body> - <h2> - <xsl:value-of select="$contextnode/title"/> - </h2> - <xsl:apply-templates select="$contextnode"/> - <table border="1" cellpadding="6" cellspacing="0"> - <tr> - <th>Type</th> - <th>@xml:id</th> - <th>@name</th> - <th>Parent Type</th> - <th>Parent @name</th> - </tr> - <tr> - <td> - <xsl:value-of select="name($contextnode)"/> - </td> - <td> - <xsl:value-of select="$contextnode/@xml:id"/> - </td> - <td> - <xsl:value-of select="$contextnode/@name"/> - </td> - <td> - <xsl:value-of select="name($contextnode/..)"/> - </td> - <td> - <xsl:value-of select="$contextnode/../@name"/> - </td> - </tr> - </table> - </body> - </html> - </xsl:template> - <xsl:template match="folder"> - <p> - <em>Folders are special, they contain things.</em> - </p> - <xsl:if test="*[@xml:id]"> - <h2>Folder Contents</h2> - <ul> - <xsl:for-each select="*[@xml:id]"> - <li> - <a href="{../@name}/{@name}"> - <xsl:value-of select="title"/> - </a> - </li> - </xsl:for-each> - </ul> - </xsl:if> - </xsl:template> - <xsl:template match="document"> - <p> - <em>Documents contain text.</em> - </p> - <xsl:copy-of select="body/*"/> - </xsl:template> -</xsl:stylesheet> diff --git a/docs/tutorials/lxmlgraph/step04/run.py b/docs/tutorials/lxmlgraph/step04/run.py deleted file mode 100644 index 1eac209dc..000000000 --- a/docs/tutorials/lxmlgraph/step04/run.py +++ /dev/null @@ -1,8 +0,0 @@ -from paste import httpserver - -from repoze.bfg import make_app -from myapp.models import get_root -import myapp - -app = make_app(get_root, myapp) -httpserver.serve(app, host='0.0.0.0', port='5432') diff --git a/docs/tutorials/lxmlgraph/step05.rst b/docs/tutorials/lxmlgraph/step05.rst deleted file mode 100644 index c3ba037d2..000000000 --- a/docs/tutorials/lxmlgraph/step05.rst +++ /dev/null @@ -1,11 +0,0 @@ -================================================ -Step 5: Advanced Templating -================================================ - -- multiple "views" wired to the same function and template - -- breadcrumbs, sidebars - -- <query> support - -- type-based support for <document>, <folder>, <query>, <site> diff --git a/repoze/bfg/chameleon_genshi.py b/repoze/bfg/chameleon_genshi.py deleted file mode 100644 index 69047abc7..000000000 --- a/repoze/bfg/chameleon_genshi.py +++ /dev/null @@ -1,75 +0,0 @@ -from webob import Response - -from zope.component import queryUtility - -from zope.interface import implements -from zope.interface import classProvides -from zope.deprecation import deprecated - -from repoze.bfg.interfaces import IResponseFactory -from repoze.bfg.interfaces import ISettings -from repoze.bfg.interfaces import ITemplateRenderer -from repoze.bfg.interfaces import ITemplateRendererFactory - -from repoze.bfg.templating import renderer_from_cache - -from chameleon.genshi.template import GenshiTemplateFile - -class GenshiTemplateRenderer(object): - classProvides(ITemplateRendererFactory) - implements(ITemplateRenderer) - - def __init__(self, path, auto_reload=False): - self.template = GenshiTemplateFile(path, auto_reload=auto_reload) - - def implementation(self): - return self.template - - def __call__(self, **kw): - return self.template(**kw) - -GenshiTemplateFactory = GenshiTemplateRenderer -deprecated('GenshiTemplateFactory', - ('repoze.bfg.chameleon_genshi.GenshiTemplateFactory should now be ' - 'imported as repoze.bfg.chameleon_genshi.GenshiTemplateRenderer')) - -def _auto_reload(): - settings = queryUtility(ISettings) - auto_reload = settings and settings.reload_templates - return auto_reload - -def get_template(path): - """ Return a ``chameleon.genshi`` template object at the - package-relative path (may also be absolute)""" - auto_reload = _auto_reload() - renderer = renderer_from_cache(path, GenshiTemplateRenderer, - auto_reload=auto_reload) - return renderer.implementation() - -def get_renderer(path): - """ Return a ``chameleon.genshi`` template renderer at the - package-relative path (may also be absolute)""" - auto_reload = _auto_reload() - renderer = renderer_from_cache(path, GenshiTemplateRenderer, - auto_reload=auto_reload) - return renderer - -def render_template(path, **kw): - """ Render a ``chameleon.genshi`` template at the package-relative - path (may also be absolute) using the kwargs in ``*kw`` as - top-level names and return a string.""" - auto_reload = _auto_reload() - renderer = renderer_from_cache(path, GenshiTemplateRenderer, - auto_reload=auto_reload) - return renderer(**kw) - -def render_template_to_response(path, **kw): - """ Render a ``chameleon.genshi`` template at the package-relative - path (may also be absolute) using the kwargs in ``*kw`` as - top-level names and return a Response object.""" - auto_reload = _auto_reload() - renderer = renderer_from_cache(path, GenshiTemplateRenderer, - auto_reload=auto_reload) - result = renderer(**kw) - response_factory = queryUtility(IResponseFactory, default=Response) - return response_factory(result) diff --git a/repoze/bfg/interfaces.py b/repoze/bfg/interfaces.py index 537bb4455..8f75a4f4a 100644 --- a/repoze/bfg/interfaces.py +++ b/repoze/bfg/interfaces.py @@ -8,13 +8,7 @@ from zope.component.interfaces import IObjectEvent deprecated( '(repoze.bfg.interfaces.ITemplate should now be imported ' 'as repoze.bfg.interfaces.ITemplateRenderer)', - ITemplate = 'repoze.bfg.interfaces:INodeTemplateRenderer', - ) - -deprecated( - '(repoze.bfg.interfaces.INodeTemplate should now be imported ' - 'as repoze.bfg.interfaces.INodeTemplateRenderer)', - INodeTemplate = 'repoze.bfg.interfaces:INodeTemplateRenderer', + ITemplate = 'repoze.bfg.interfaces:ITemplateRenderer', ) deprecated( @@ -112,10 +106,6 @@ class ITemplateRendererFactory(Interface): def __call__(path, auto_reload=False): """ Return an object that implements ``ITemplateRenderer`` """ -class INodeTemplateRenderer(Interface): - def __call__(node, **kw): - """ Return a string result given a node and a template path """ - class ISecurityPolicy(Interface): """ A utility that provides a mechanism to check authorization using authentication data """ diff --git a/repoze/bfg/template.py b/repoze/bfg/template.py index 68a7f34d1..ad6d50a44 100644 --- a/repoze/bfg/template.py +++ b/repoze/bfg/template.py @@ -2,23 +2,19 @@ # compatibility; there are no plans to make this module itself go # away, but the ``get_template``, ``render_template``, and # ``render_template_to_response`` APIs should be imported from -# ``repoze.bfg.chameleon_zpt`` in the future for optimum correctness, -# while the ``render_transform`` and ``render_transform_to_response`` -# APIs should be imported from ``repoze.bfg.xslt``. +# ``repoze.bfg.chameleon_zpt`` in the future for optimum correctness. +# Two other functions named ``render_transform`` and +# ``render_transform_to_response`` APIs used to be here for XSLT +# support; those no longer exist here; you need to install and use the +# ``repoze.bfg.xslt`` package. from zope.deprecation import deprecated from repoze.bfg.chameleon_zpt import get_template from repoze.bfg.chameleon_zpt import render_template from repoze.bfg.chameleon_zpt import render_template_to_response -from repoze.bfg.xslt import render_transform -from repoze.bfg.xslt import render_transform_to_response for name in ('get_template', 'render_template', 'render_template_to_response'): deprecated(name, ('repoze.bfg.template.%s should now be imported as ' 'repoze.bfg.chameleon_zpt.%s' % (name, name))) -for name in ('render_transform', 'render_transform_to_response'): - deprecated(name, - ('repoze.bfg.template.%s should now be imported as ' - 'repoze.bfg.xslt.%s' % (name, name))) diff --git a/repoze/bfg/tests/test_chameleon_genshi.py b/repoze/bfg/tests/test_chameleon_genshi.py deleted file mode 100644 index 6d62891bf..000000000 --- a/repoze/bfg/tests/test_chameleon_genshi.py +++ /dev/null @@ -1,187 +0,0 @@ -import unittest - -from zope.testing.cleanup import cleanUp - -class Base(object): - def setUp(self): - cleanUp() - - def tearDown(self): - cleanUp() - - def _zcmlConfigure(self): - import repoze.bfg.includes - import zope.configuration.xmlconfig - zope.configuration.xmlconfig.file('configure.zcml', - package=repoze.bfg.includes) - - def _getTemplatePath(self, name): - import os - here = os.path.abspath(os.path.dirname(__file__)) - return os.path.join(here, 'fixtures', name) - -class GenshiTemplateRendererTests(Base, unittest.TestCase): - def _getTargetClass(self): - from repoze.bfg.chameleon_genshi import GenshiTemplateRenderer - return GenshiTemplateRenderer - - def _makeOne(self, *arg, **kw): - klass = self._getTargetClass() - return klass(*arg, **kw) - - def test_instance_implements_ITemplate(self): - from zope.interface.verify import verifyObject - from repoze.bfg.interfaces import ITemplateRenderer - path = self._getTemplatePath('minimal.genshi') - verifyObject(ITemplateRenderer, self._makeOne(path)) - - def test_class_implements_ITemplate(self): - from zope.interface.verify import verifyClass - from repoze.bfg.interfaces import ITemplateRenderer - verifyClass(ITemplateRenderer, self._getTargetClass()) - - def test_call(self): - self._zcmlConfigure() - minimal = self._getTemplatePath('minimal.genshi') - instance = self._makeOne(minimal) - result = instance() - self.failUnless(isinstance(result, str)) - self.assertEqual(result, - '<div xmlns="http://www.w3.org/1999/xhtml">\n</div>') - - def test_implementation(self): - self._zcmlConfigure() - minimal = self._getTemplatePath('minimal.genshi') - instance = self._makeOne(minimal) - result = instance.implementation()() - self.failUnless(isinstance(result, str)) - self.assertEqual(result, - '<div xmlns="http://www.w3.org/1999/xhtml">\n</div>') - -class RenderTemplateTests(Base, unittest.TestCase): - def _callFUT(self, name, **kw): - from repoze.bfg.chameleon_genshi import render_template - return render_template(name, **kw) - - def test_it(self): - minimal = self._getTemplatePath('minimal.genshi') - result = self._callFUT(minimal) - self.failUnless(isinstance(result, str)) - self.assertEqual(result, - '<div xmlns="http://www.w3.org/1999/xhtml">\n</div>') - -class RenderTemplateToResponseTests(Base, unittest.TestCase): - def _callFUT(self, name, **kw): - from repoze.bfg.chameleon_genshi import render_template_to_response - return render_template_to_response(name, **kw) - - def test_it(self): - minimal = self._getTemplatePath('minimal.genshi') - result = self._callFUT(minimal) - from webob import Response - self.failUnless(isinstance(result, Response)) - self.assertEqual(result.app_iter, - ['<div xmlns="http://www.w3.org/1999/xhtml">\n</div>']) - self.assertEqual(result.status, '200 OK') - self.assertEqual(len(result.headerlist), 2) - - def test_iresponsefactory_override(self): - from zope.component import getGlobalSiteManager - gsm = getGlobalSiteManager() - from webob import Response - class Response2(Response): - pass - from repoze.bfg.interfaces import IResponseFactory - gsm.registerUtility(Response2, IResponseFactory) - minimal = self._getTemplatePath('minimal.genshi') - result = self._callFUT(minimal) - self.failUnless(isinstance(result, Response2)) - -class GetRendererTests(Base, unittest.TestCase): - def _callFUT(self, name): - from repoze.bfg.chameleon_genshi import get_renderer - return get_renderer(name) - - def test_nonabs_registered(self): - from zope.component import getGlobalSiteManager - from zope.component import queryUtility - from repoze.bfg.chameleon_genshi import GenshiTemplateRenderer - from repoze.bfg.interfaces import ITemplateRenderer - minimal = self._getTemplatePath('minimal.genshi') - utility = GenshiTemplateRenderer(minimal) - gsm = getGlobalSiteManager() - gsm.registerUtility(utility, ITemplateRenderer, name=minimal) - result = self._callFUT(minimal) - self.assertEqual(result, utility) - self.assertEqual(queryUtility(ITemplateRenderer, minimal), utility) - - def test_nonabs_unregistered(self): - from zope.component import getGlobalSiteManager - from zope.component import queryUtility - from repoze.bfg.chameleon_genshi import GenshiTemplateRenderer - from repoze.bfg.interfaces import ITemplateRenderer - minimal = self._getTemplatePath('minimal.genshi') - self.assertEqual(queryUtility(ITemplateRenderer, minimal), None) - utility = GenshiTemplateRenderer(minimal) - gsm = getGlobalSiteManager() - gsm.registerUtility(utility, ITemplateRenderer, name=minimal) - result = self._callFUT(minimal) - self.assertEqual(result, utility) - self.assertEqual(queryUtility(ITemplateRenderer, minimal), utility) - - def test_explicit_registration(self): - from zope.component import getGlobalSiteManager - from repoze.bfg.interfaces import ITemplateRenderer - class Dummy: - template = object() - gsm = getGlobalSiteManager() - utility = Dummy() - gsm.registerUtility(utility, ITemplateRenderer, name='foo') - result = self._callFUT('foo') - self.failUnless(result is utility) - - -class GetTemplateTests(Base, unittest.TestCase): - def _callFUT(self, name): - from repoze.bfg.chameleon_genshi import get_template - return get_template(name) - - def test_nonabs_registered(self): - from zope.component import getGlobalSiteManager - from zope.component import queryUtility - from repoze.bfg.chameleon_genshi import GenshiTemplateRenderer - from repoze.bfg.interfaces import ITemplateRenderer - minimal = self._getTemplatePath('minimal.genshi') - utility = GenshiTemplateRenderer(minimal) - gsm = getGlobalSiteManager() - gsm.registerUtility(utility, ITemplateRenderer, name=minimal) - result = self._callFUT(minimal) - self.assertEqual(result.filename, minimal) - self.assertEqual(queryUtility(ITemplateRenderer, minimal), utility) - - def test_nonabs_unregistered(self): - from zope.component import getGlobalSiteManager - from zope.component import queryUtility - from repoze.bfg.chameleon_genshi import GenshiTemplateRenderer - from repoze.bfg.interfaces import ITemplateRenderer - minimal = self._getTemplatePath('minimal.genshi') - self.assertEqual(queryUtility(ITemplateRenderer, minimal), None) - utility = GenshiTemplateRenderer(minimal) - gsm = getGlobalSiteManager() - gsm.registerUtility(utility, ITemplateRenderer, name=minimal) - result = self._callFUT(minimal) - self.assertEqual(result.filename, minimal) - self.assertEqual(queryUtility(ITemplateRenderer, minimal), utility) - - def test_explicit_registration(self): - from zope.component import getGlobalSiteManager - from repoze.bfg.interfaces import ITemplateRenderer - class Dummy: - template = object() - def implementation(self): - return self.template - gsm = getGlobalSiteManager() - utility = Dummy() - gsm.registerUtility(utility, ITemplateRenderer, name='foo') - result = self._callFUT('foo') - self.failUnless(result is utility.template) diff --git a/repoze/bfg/tests/test_chameleon_zpt.py b/repoze/bfg/tests/test_chameleon_zpt.py index 114817994..e0ed74e5f 100644 --- a/repoze/bfg/tests/test_chameleon_zpt.py +++ b/repoze/bfg/tests/test_chameleon_zpt.py @@ -45,7 +45,7 @@ class ZPTTemplateRendererTests(Base, unittest.TestCase): minimal = self._getTemplatePath('minimal.pt') instance = self._makeOne(minimal) result = instance() - self.failUnless(isinstance(result, str)) + self.failUnless(isinstance(result, unicode)) self.assertEqual(result, '<div xmlns="http://www.w3.org/1999/xhtml">\n</div>') @@ -54,7 +54,7 @@ class ZPTTemplateRendererTests(Base, unittest.TestCase): minimal = self._getTemplatePath('minimal.pt') instance = self._makeOne(minimal) result = instance.implementation()() - self.failUnless(isinstance(result, str)) + self.failUnless(isinstance(result, unicode)) self.assertEqual(result, '<div xmlns="http://www.w3.org/1999/xhtml">\n</div>') @@ -68,7 +68,7 @@ class RenderTemplateTests(Base, unittest.TestCase): self._zcmlConfigure() minimal = self._getTemplatePath('minimal.pt') result = self._callFUT(minimal) - self.failUnless(isinstance(result, str)) + self.failUnless(isinstance(result, unicode)) self.assertEqual(result, '<div xmlns="http://www.w3.org/1999/xhtml">\n</div>') diff --git a/repoze/bfg/tests/test_template.py b/repoze/bfg/tests/test_template.py index 8d16972b8..78bd139c5 100644 --- a/repoze/bfg/tests/test_template.py +++ b/repoze/bfg/tests/test_template.py @@ -33,7 +33,7 @@ class RenderTemplateTests(Base, unittest.TestCase): self._zcmlConfigure() minimal = self._getTemplatePath('minimal.pt') result = self._callFUT(minimal) - self.failUnless(isinstance(result, str)) + self.failUnless(isinstance(result, unicode)) self.assertEqual(result, '<div xmlns="http://www.w3.org/1999/xhtml">\n</div>') diff --git a/repoze/bfg/tests/test_xslt.py b/repoze/bfg/tests/test_xslt.py deleted file mode 100644 index eed0fc808..000000000 --- a/repoze/bfg/tests/test_xslt.py +++ /dev/null @@ -1,221 +0,0 @@ -import unittest -from zope.testing.cleanup import cleanUp - -class Base(object): - def setUp(self): - cleanUp() - - def tearDown(self): - cleanUp() - - def _zcmlConfigure(self): - import repoze.bfg.includes - import zope.configuration.xmlconfig - zope.configuration.xmlconfig.file('configure.zcml', - package=repoze.bfg.includes) - - def _getTemplatePath(self, name): - import os - here = os.path.abspath(os.path.dirname(__file__)) - return os.path.join(here, 'fixtures', name) - -class XSLTemplateRendererTests(Base, unittest.TestCase): - def _getTargetClass(self): - from repoze.bfg.xslt import XSLTemplateRenderer - return XSLTemplateRenderer - - def _makeOne(self, *arg, **kw): - klass = self._getTargetClass() - return klass(*arg, **kw) - - def test_instance_implements_INodeTemplate(self): - from zope.interface.verify import verifyObject - from repoze.bfg.interfaces import INodeTemplateRenderer - path = self._getTemplatePath('minimal.xsl') - verifyObject(INodeTemplateRenderer, self._makeOne(path)) - - def test_class_implements_INodeTemplate(self): - from zope.interface.verify import verifyClass - from repoze.bfg.interfaces import INodeTemplateRenderer - verifyClass(INodeTemplateRenderer, self._getTargetClass()) - - def test_call(self): - self._zcmlConfigure() - minimal = self._getTemplatePath('minimal.xsl') - instance = self._makeOne(minimal) - from lxml import etree - info = etree.Element("info") - result = instance(node=info) - self.failUnless(isinstance(result, str)) - resultstr = """<?xml version="1.0"?>\n<div/>\n""" - self.assertEqual(result, resultstr) - -class GetTransformTests(Base, unittest.TestCase): - def _callFUT(self, path, node): - from repoze.bfg.xslt import get_transform - return get_transform(path, node) - - def test_nonabs_registered(self): - from zope.component import getGlobalSiteManager - from repoze.bfg.interfaces import INodeTemplateRenderer - renderer = {} - gsm = getGlobalSiteManager() - minimal = self._getTemplatePath('minimal.xsl') - gsm.registerUtility(renderer, INodeTemplateRenderer, name=minimal) - result = self._callFUT('fixtures/minimal.xsl', None) - self.failUnless(result is renderer) - - def test_abs_registered(self): - from zope.component import getGlobalSiteManager - from repoze.bfg.interfaces import INodeTemplateRenderer - renderer = {} - gsm = getGlobalSiteManager() - minimal = self._getTemplatePath('minimal.xsl') - gsm.registerUtility(renderer, INodeTemplateRenderer, name=minimal) - result = self._callFUT(minimal, None) - self.failUnless(result is renderer) - - def test_unregistered(self): - from zope.component import getGlobalSiteManager - from zope.component import queryUtility - from repoze.bfg.interfaces import INodeTemplateRenderer - minimal = self._getTemplatePath('minimal.xsl') - self.assertEqual(queryUtility(INodeTemplateRenderer, minimal), None) - gsm = getGlobalSiteManager() - result = self._callFUT(minimal, None) - self.assertEqual(queryUtility(INodeTemplateRenderer, minimal).path, - minimal) - - def test_unregistered_missing(self): - from zope.component import getGlobalSiteManager - minimal = self._getTemplatePath('notthere.xsl') - gsm = getGlobalSiteManager() - self.assertRaises(ValueError, self._callFUT, minimal, None) - -class RenderTransformToResponseTests(Base, unittest.TestCase): - def _callFUT(self, minimal, node): - from repoze.bfg.xslt import render_transform_to_response - return render_transform_to_response(minimal, node=node) - - def test_nonabs_unregistered(self): - self._zcmlConfigure() - from zope.component import queryUtility - from repoze.bfg.interfaces import INodeTemplateRenderer - minimal = self._getTemplatePath('minimal.xsl') - self.assertEqual(queryUtility(INodeTemplateRenderer, minimal), None) - from lxml import etree - info = etree.Element("info") - result = self._callFUT(minimal, node=info) - from webob import Response - self.failUnless(isinstance(result, Response)) - resultstr = """<?xml version="1.0"?>\n<div/>\n""" - self.assertEqual(result.app_iter, [resultstr]) - self.assertEqual(result.status, '200 OK') - self.assertEqual(len(result.headerlist), 2) - from repoze.bfg.xslt import XSLTemplateRenderer - self.failUnless(isinstance(queryUtility(INodeTemplateRenderer, minimal), - XSLTemplateRenderer)) - - def test_nonabs_registered(self): - self._zcmlConfigure() - from zope.component import getGlobalSiteManager - from zope.component import queryUtility - from repoze.bfg.xslt import XSLTemplateRenderer - from repoze.bfg.interfaces import INodeTemplateRenderer - minimal = self._getTemplatePath('minimal.xsl') - utility = XSLTemplateRenderer(minimal) - gsm = getGlobalSiteManager() - gsm.registerUtility(utility, INodeTemplateRenderer, name=minimal) - from lxml import etree - info = etree.Element("info") - result = self._callFUT(minimal, node=info) - from webob import Response - self.failUnless(isinstance(result, Response)) - resultstr = """<?xml version="1.0"?>\n<div/>\n""" - self.assertEqual(result.app_iter, [resultstr]) - self.assertEqual(result.status, '200 OK') - self.assertEqual(len(result.headerlist), 2) - self.assertEqual(queryUtility(INodeTemplateRenderer, minimal), utility) - - def test_alternate_iresponse_factory(self): - self._zcmlConfigure() - from repoze.bfg.interfaces import IResponseFactory - from zope.component import getGlobalSiteManager - gsm = getGlobalSiteManager() - from webob import Response - class Response2(Response): - pass - gsm.registerUtility(Response2, IResponseFactory) - from zope.component import getGlobalSiteManager - from repoze.bfg.xslt import XSLTemplateRenderer - from repoze.bfg.interfaces import INodeTemplateRenderer - minimal = self._getTemplatePath('minimal.xsl') - utility = XSLTemplateRenderer(minimal) - gsm = getGlobalSiteManager() - gsm.registerUtility(utility, INodeTemplateRenderer, name=minimal) - from lxml import etree - info = etree.Element("info") - result = self._callFUT(minimal, node=info) - self.failUnless(isinstance(result, Response2)) - - -class RenderTransformTests(Base, unittest.TestCase): - def _callFUT(self, path, node): - from repoze.bfg.xslt import render_transform - return render_transform(path, node=node) - - def test_nonabs_unregistered(self): - self._zcmlConfigure() - from zope.component import queryUtility - from repoze.bfg.interfaces import INodeTemplateRenderer - minimal = self._getTemplatePath('minimal.xsl') - self.assertEqual(queryUtility(INodeTemplateRenderer, minimal), None) - from lxml import etree - info = etree.Element("info") - result = self._callFUT(minimal, node=info) - self.failUnless(isinstance(result, str)) - resultstr = """<?xml version="1.0"?>\n<div/>\n""" - self.assertEqual(result, resultstr) - from repoze.bfg.xslt import XSLTemplateRenderer - self.failUnless(isinstance(queryUtility(INodeTemplateRenderer, minimal), - XSLTemplateRenderer)) - - def test_nonabs_registered(self): - self._zcmlConfigure() - from zope.component import getGlobalSiteManager - from zope.component import queryUtility - from repoze.bfg.xslt import XSLTemplateRenderer - from repoze.bfg.interfaces import INodeTemplateRenderer - minimal = self._getTemplatePath('minimal.xsl') - utility = XSLTemplateRenderer(minimal) - gsm = getGlobalSiteManager() - gsm.registerUtility(utility, INodeTemplateRenderer, name=minimal) - from lxml import etree - info = etree.Element("info") - result = self._callFUT(minimal, node=info) - self.failUnless(isinstance(result, str)) - resultstr = """<?xml version="1.0"?>\n<div/>\n""" - self.assertEqual(result, resultstr) - self.assertEqual(queryUtility(INodeTemplateRenderer, minimal), utility) - -class TestGetProcessor(Base, unittest.TestCase): - def _callFUT(self, fn, auto_reload=False): - from repoze.bfg.xslt import get_processor - return get_processor(fn, auto_reload) - - def test_no_processors(self): - from lxml.etree import XSLT - from repoze.bfg.xslt import xslt_pool - del xslt_pool.processors - path = self._getTemplatePath('minimal.xsl') - result = self._callFUT(path) - self.failUnless(isinstance(result, XSLT)) - - def test_empty_processors(self): - from lxml.etree import XSLT - from repoze.bfg.xslt import xslt_pool - xslt_pool.processors = {} - path = self._getTemplatePath('minimal.xsl') - result = self._callFUT(path) - self.failUnless(isinstance(result, XSLT)) - diff --git a/repoze/bfg/xslt.py b/repoze/bfg/xslt.py deleted file mode 100644 index 7dae7ca8e..000000000 --- a/repoze/bfg/xslt.py +++ /dev/null @@ -1,89 +0,0 @@ -import os - -from webob import Response - -from zope.component import queryUtility -from zope.component import getSiteManager -from zope.deprecation import deprecated - -from zope.interface import classProvides -from zope.interface import implements - -from repoze.bfg.path import caller_path - -from repoze.bfg.interfaces import INodeTemplateRenderer -from repoze.bfg.interfaces import IResponseFactory -from repoze.bfg.interfaces import ITemplateRendererFactory - -def get_transform(path, node): - """ Return a callable transform object. When called, the - transform will return a string. The ``path`` argument should be a - package-relative path (also may be absolute) to an XSLT file. - When called, the transform will use the kwargs in ``*kw`` as top - level names and the lxml node at ``node``.""" - # Render using XSLT - path = caller_path(path) - - renderer = queryUtility(INodeTemplateRenderer, path) - if renderer is None: - if not os.path.exists(path): - raise ValueError('Missing template file: %s' % path) - renderer = XSLTemplateRenderer(path) - sm = getSiteManager() - sm.registerUtility(renderer, INodeTemplateRenderer, name=path) - return renderer - -def render_transform(path, node, **kw): - """ Render a XSL template at the package-relative path (may also - be absolute) using the kwargs in ``*kw`` as top-level names and - the lxml node at ``node`` and return a string.""" - path = caller_path(path) - template = get_transform(path, node) - return template(node, **kw) - -def render_transform_to_response(path, node, **kw): - """ Render a XSL template at the package-relative path (may also - be absolute) using the kwargs in ``*kw`` as top-level names and - the lxml node at ``node`` and return a Response object.""" - path = caller_path(path) - result = render_transform(path, node, **kw) - response_factory = queryUtility(IResponseFactory, default=Response) - return response_factory(result) - -class XSLTemplateRenderer(object): - classProvides(ITemplateRendererFactory) - implements(INodeTemplateRenderer) - - def __init__(self, path, auto_reload=False): - self.path = path - self.auto_reload = auto_reload - - def __call__(self, node, **kw): - processor = get_processor(self.path, self.auto_reload) - result = str(processor(node, **kw)) - return result - -XSLTemplateFactory = XSLTemplateRenderer -deprecated('ZPTTemplateFactory', - ('repoze.bfg.xslt.XSLTemplateFactory should now be ' - 'imported as repoze.bfg.xslt.XSLTTemplateRenderer')) - - -# Manage XSLT processors on a per-thread basis -import threading -from lxml import etree -xslt_pool = threading.local() -def get_processor(xslt_fn, auto_reload=False): - if not auto_reload: - try: - return xslt_pool.processors[xslt_fn] - except AttributeError: - xslt_pool.processors = {} - except KeyError: - pass - - # Make a processor and add it to the pool - source = etree.ElementTree(file=xslt_fn) - proc = etree.XSLT(source) - xslt_pool.processors[xslt_fn] = proc - return proc @@ -1,6 +1,6 @@ [easy_install] zip_ok = false -index_url = http://dist.repoze.org/bfg/current/simple +index_url = http://dist.repoze.org/bfg/dev/simple [nosetests] match=^test @@ -12,7 +12,7 @@ # ############################################################################## -__version__ = '0.7.1' +__version__ = '0.8dev' import os @@ -30,15 +30,13 @@ except IOError: install_requires=[ 'setuptools', - 'chameleon.core [lxml] >= 1.0b13', - 'chameleon.genshi >= 1.0b2', - 'chameleon.zpt >= 1.0b8', + 'chameleon.core >= 1.0b32', # non-lxml version + 'chameleon.zpt >= 1.0b16', # newest version as of non-xml core release 'PasteScript', 'Routes', 'WebOb', - 'zope.interface', - 'zope.component', - 'zope.hookable', + 'zope.interface >= 3.5.1', # 3.5.0 comment: "allow to bootstrap on jython" + 'zope.component >= 3.6.0', # independent of zope.hookable 'zope.testing', 'zope.deferredimport', 'zope.deprecation', |
