summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2008-07-28 05:31:47 +0000
committerChris McDonough <chrism@agendaless.com>2008-07-28 05:31:47 +0000
commit178623bbd8e9aab75b6206ef69f67b62edb3d12e (patch)
tree2442c1d41bdb13a41e4ab841fddcc091d5804ca2
parent96e65d8e6d47a1b806c4d281e6890f77f86407c3 (diff)
downloadpyramid-178623bbd8e9aab75b6206ef69f67b62edb3d12e.tar.gz
pyramid-178623bbd8e9aab75b6206ef69f67b62edb3d12e.tar.bz2
pyramid-178623bbd8e9aab75b6206ef69f67b62edb3d12e.zip
Tweaks.
-rw-r--r--docs/glossary.rst162
-rw-r--r--docs/narr/introduction.rst10
-rw-r--r--docs/narr/models.rst29
-rw-r--r--docs/narr/project.rst200
-rw-r--r--docs/narr/security.rst32
-rw-r--r--docs/narr/traversal.rst181
-rw-r--r--docs/tutorials/lxmlgraph/background.rst69
-rw-r--r--docs/tutorials/lxmlgraph/index.rst12
-rw-r--r--docs/tutorials/lxmlgraph/step01.rst7
-rw-r--r--docs/tutorials/lxmlgraph/step02.rst39
-rw-r--r--docs/tutorials/lxmlgraph/step03.rst17
11 files changed, 419 insertions, 339 deletions
diff --git a/docs/glossary.rst b/docs/glossary.rst
index b42d2cc7e..a3c377f49 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -16,7 +16,21 @@ Glossary
Setuptools
`Setuptools <http://peak.telecommunity.com/DevCenter/setuptools>`_
builds on Python's ``distutils`` to provide easier building,
- distribution, and installation of packages.
+ distribution, and installation of libraries and applications.
+ Package
+ A directory on disk which contains an ``__init__.py`` file, making
+ it recognizable to Python as a location which can be ``import`` -ed.
+ Project
+ (Setuptools/distutils terminology). A directory on disk which
+ contains a ``setup.py`` file and one or more Python packages. The
+ ``setup.py`` file contains code that allows the package(s) to be
+ installed, distributed, and tested.
+ Distribution
+ (Setuptools/distutils terminology). A file representing an
+ installable library or application. Distributions are usually
+ files that have the suffix of ``.egg``, ``.tar.gz``, or ``.zip``.
+ Distributions are the target of Setuptools commands such as
+ ``easy_install``.
View
A "view" is a callable which returns a response object. It should
accept two values: context and request.
@@ -33,80 +47,102 @@ Glossary
An object representing data in the system. A model is part of the
object graph traversed by the system. Models are traversed to
determine a context.
+ Traversal
+ The act of descending "down" a graph of model objects from a root
+ model in order to find a :term:`context`. The :mod:`repoze.bfg`
+ *router* performs traversal of model objects. See the
+ :ref:`traversal_chapter` chapter for more information.
+ URL dispatch
+ An alternative to graph traversal as a mechanism for locating a
+ :term:`context` for a :term:`view`. When you use :term:`Routes`
+ in your :mod:`repoze.bfg` application, you are using URL dispatch.
+ See the :ref:`urldispatch_module` for more information.
Context
- A model in the system that is found during traversal; it becomes
- the subject of a view.
+ A :term:`model` in the system that is "found" during
+ :term:`traversal` or :term:`URL dispatch`; it becomes the subject
+ of a :term:`view`. See the :ref:`traversal_chapter` chapter for
+ more information.
Application registry
A registry which maps model types to views, as well as performing
- other application-specific component registrations.
+ other application-specific component registrations. Every
+ :mod:`repoze.bfg` application has one (and only one) application
+ registry, which is represented on disk by its ``configure.zcml``
+ file.
Template
- A file that is capable of representing some text when rendered.
+ A file with replaceable parts that is capable of representing some
+ text, XML, or HTML when rendered.
Interface
- An attribute of a model object that determines its type.
+ An attribute of an object that determines its type.
Location
The path to an object in a model graph.
Security policy
An object that provides a mechanism to check authorization using
authentication data and a permission associated with a model. It
essentially returns "true" if the combination of the authorization
- information in the model (e.g. an ACL) and the authentication data
- in the request (e.g. the REMOTE_USER) allow the action implied by
- the permission associated with the view (e.g. "add").
+ information in the model (e.g. an :term:`ACL`) and the
+ authentication data in the request (e.g. the ``REMOTE_USER``
+ environment variable) allow the action implied by the permission
+ associated with the view (e.g. ``add`` or ``read``).
Principal
A user id or group id.
Permission
A string or unicode object that represents an action being taken
against a context. A permission is associated with a view name
and a model type by the developer. Models are decorated with
- security declarations (e.g. ACLs), which reference these tokens
- also. Permissions are used by the active to security policy to
- match the view permission against the model's statements about
- which permissions are granted to which principal in a context in
- order to to answer the question "is this user allowed to do this".
- Examples of permissions: "read", or "view_blog_entries".
+ security declarations (e.g. an :term:`ACL`), which reference these
+ tokens also. Permissions are used by the active to security
+ policy to match the view permission against the model's statements
+ about which permissions are granted to which principal in a
+ context in order to to answer the question "is this user allowed
+ to do this". Examples of permissions: ``read``, or
+ ``view_blog_entries``.
ACE
An *access control entry*. An access control entry is one element
- in an *ACL*. An access control entry is a three-tuple that
+ in an :term:`ACL`. An access control entry is a three-tuple that
describes three things: an *action* (one of either ``Allow`` or
- ``Deny``), a *principal* (a string describing a user or group), and
- a *permission*. For example the ACE, ``(Allow, 'bob', 'read')`` is
- a member of an ACL that indicates that the principal ``bob`` is
- allowed the permission ``read`` against the context the ACL is
- attached to.
+ ``Deny``), a :term:`principal` (a string describing a user or
+ group), and a :term:`permission`. For example the ACE, ``(Allow,
+ 'bob', 'read')`` is a member of an ACL that indicates that the
+ principal ``bob`` is allowed the permission ``read`` against the
+ context the ACL is attached to.
ACL
- An *access control list*. An ACL is a sequence of *ACE* s. An ACL
- is attached to a model instance. An example of an ACL is ``[
- (Allow, 'bob', 'read'), (Deny, 'fred', 'write')]``. If an ACL is
- attached to a model instance, and that model instance is findable
- via the context, it will be consulted by the security policy to
- determine wither a particular request can be fulfilled given the
- *authentication* information in the request.
+ An *access control list*. An ACL is a sequence of :term:`ACE`
+ tuples. An ACL is attached to a model instance. An example of an
+ ACL is ``[ (Allow, 'bob', 'read'), (Deny, 'fred', 'write')]``. If
+ an ACL is attached to a model instance, and that model instance is
+ findable via the context, it will be consulted any active security
+ policy to determine wither a particular request can be fulfilled
+ given the :term:`authentication` information in the request.
Authentication
- The act of determining that the credentials a user presents during a
- particular request are "good". ``repoze.bfg`` does not perfom
- authentication: it leaves it up to an upstream component such as
- ``repoze.who``. ``repoze.bfg`` uses the authentication data
- supplied by the upstream component as one input during
- authorization.
+ The act of determining that the credentials a user presents during
+ a particular request are "good". :mod:`repoze.bfg` does not
+ perfom authentication: it leaves it up to an upstream component
+ such as :term:`repoze.who`. :mod:`repoze.bfg` uses the
+ :term:`authentication` data supplied by the upstream component as
+ one input during :term:`authorization`.
Authorization
- The act of determining whether a user can perform a specific action.
- In bfg terms, this means determining whether, for a given context,
- the *principals* associated with the request have the requisite
- *permission* to allow the request to continue.
+ The act of determining whether a user can perform a specific
+ action. In bfg terms, this means determining whether, for a given
+ context, any :term:`principal` (or principals) associated with the
+ request have the requisite :term:`permission` to allow the request
+ to continue.
Principal
- A *principal* is a string or unicode object representing a user or a
- user's membership in a group. It is provided by the
- *authentication* machinery upstream, typically. For example, if a
- user had the user id "bob", and Bob was part of two groups named
- "group foo" and "group bar", the request might have information
- attached to it that would indictate that Bob was represented by
- three principals: "bob", "group foo" and "group bar".
+ A *principal* is a string or unicode object representing a user or
+ a user's membership in a group. It is provided by the
+ :term:`authentication` machinery "upstream", typically (such as
+ :term:`repoze.who`). For example, if a user had the user id
+ "bob", and Bob was part of two groups named "group foo" and "group
+ bar", the request might have information attached to it that would
+ indictate that Bob was represented by three principals: "bob",
+ "group foo" and "group bar".
Security Policy
A security policy in bfg terms is a bit of code which accepts a
- request, the *ACL* associated with a context, and the *permission*
- associated with a particular view, and determines whether or not the
- principals associated with the request can perform the action
- associated with the permission based on the ACL.
+ request, the :term:`ACL` associated with a context, and the
+ :term:`permission` associated with a particular view, and
+ subsequently determines whether or not the principals associated
+ with the request can perform the action associated with the
+ permission based on the ACL found on the :term:`context` (or any
+ of its parents).
WSGI
`Web Server Gateway Interface <http://wsgi.org/>`_. This is a
Python standard for connecting web applications to web servers,
@@ -120,9 +156,17 @@ Glossary
Paste
`Paste <http://pythonpaste.org>`_ is a WSGI development and
deployment system developed by Ian Bicking.
+ PasteDeploy
+ `PasteDeploy <http://pythonpaste.org>`_ is a library used by
+ :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.
z3c.pt
`z3c.pt <http://pypi.python.org/pypi/z3c.pt>`_ is an
implementation of the `Zope Page Template
@@ -137,3 +181,23 @@ Glossary
graph traversal when deciding which *view* should be called. See
:ref:`urldispatch_module` for more information about (optional)
Routes integration in bfg.
+ ZCML
+ `Zope Configuration Markup Language
+ <http://www.muthukadan.net/docs/zca.html#zcml>`_, the XML dialect
+ used by Zope and :mod:`repoze.bfg` to describe associating a view
+ with a model type. ZCML is capable of performing many different
+ registrations and declarations, but its primary purpose in
+ :mod:`repoze.bfg` is to perform view mappings via the ``bfg:view``
+ declaration. The ``configure.zcml`` file in a :mod:`repoze.bfg`
+ application represents the application's :term:`application
+ registry`.
+ repoze.who
+ `Authentication middleware
+ <http://svn.repoze.org/repoze.who/trunk/README.txt>`_ for
+ :term:`WSGI` applications. It can be used by :mod:`repoze.bfg` to
+ provide authentication information.
+ ReStructuredText
+ A `plain text format <http://docutils.sourceforge.net/rst.html>`_
+ that is the defacto standard for descriptive text shipped in
+ :term:`distribution` files, and Python docstrings.
+
diff --git a/docs/narr/introduction.rst b/docs/narr/introduction.rst
index 61b03b3dc..bf2f07e19 100644
--- a/docs/narr/introduction.rst
+++ b/docs/narr/introduction.rst
@@ -16,11 +16,15 @@ Similarities with Other Frameworks
:mod:`repoze.bfg` was inspired by Zope, Django, and Pylons.
-:mod:`repoze.bfg`'s traversal is inspired by Zope. :mod:`repoze.bfg`
+:mod:`repoze.bfg` traversal is inspired by Zope. :mod:`repoze.bfg`
uses the Zope Component Architecture ("CA") internally, as do Zope 2,
Zope 3, and Grok. Developers don't interact with the CA very much
during typical development, however; it's mostly used by the framework
-developer rather than the application developer.
+developer rather than the application developer. :mod:`repoze.bfg`
+developers use :term:`ZCML` (an XML dialect) to perform various
+configuration tasks; in particular, as in Zope3, one more more
+:term:`view` functions is associated with a :term:`model` type via
+ZCML.
Like Pylons, :mod:`repoze.bfg` is mostly policy-free. It makes no
assertions about which database you should use, and its built-in
@@ -62,7 +66,7 @@ happens to be true for :mod:`repoze.bfg`::
framework - that is, "model", "template", and "view." That breakdown
makes much more sense.
-:mod:`repoze.bfg` 's skeleton code generator generates a directory
+The skeleton code generator of :mod:`repoze.bfg` generates a directory
layout very simliar to the directory layout suggested by the `Django
Book <http://www.djangobook.com/>`_ . Additionally, as suggested
above, the concepts of :term:`view`, :term:`model` and
diff --git a/docs/narr/models.rst b/docs/narr/models.rst
index cff04ea18..1e5685ed6 100644
--- a/docs/narr/models.rst
+++ b/docs/narr/models.rst
@@ -1,9 +1,9 @@
Models
======
-*Models* are typically simple Python classes defined in a module.
- Model *instances* make up the graph that :mod:`repoze.bfg` is willing
- to traverse.
+A :term:`model` is typically a simple Python class defined in a
+module. Model *instances* make up the graph that :mod:`repoze.bfg` is
+willing to traverse.
Defining a Model
----------------
@@ -26,11 +26,11 @@ An example of a model describing a blog entry::
self.created = datetime.datetime.now()
A model consists of two things: the object which defines the model
-(above as the class ``IBlogEntry``), and an *interface* attached to
-the model object. An interface simply tags the model object with a
-"type" that can be referred to within view configuration. A model
-object can implement zero or more interfaces. The interface must be
-an instance of a class that inherits from
+(above as the class ``IBlogEntry``), and an :term:`interface` attached
+to the model object. An interface simply tags the model object with a
+"type" that can be referred to within the :term:`application
+registry`. A model object can implement zero or more interfaces. The
+interface must be an instance of a class that inherits from
``zope.interface.Interface``.
You specify that a model *implements* an interface by using the
@@ -67,13 +67,14 @@ Location-Aware Model Instances
by via ``__getitem__``.
If you choose not to manage the ``__name__`` and ``__parent__``
- attributes of your models "by hand", :mod:`repoze.bfg`` is willing
- to help you do this. If your "root" node claims it implements the
+ attributes of your models "by hand", :mod:`repoze.bfg`` is willing to
+ help you do this. If your "root" node claims it implements the
interface ``zope.location.interfaces.ILocation``, you don't need to
- manage these attributes by hand. During traversal, if the root node
- says it implements ``ILocation``, bfg will wrap each child in a
- LocationProxy which will dynamically assign a ``__name__`` and a
- ``__parent__`` to it, recursively.
+ manage these attributes by hand. During :term:`traversal`, if the
+ root node says it implements the ``ILocation`` :term:`interface`,
+ :mod:`repoze.bfg` will wrap each child in a ``LocationProxy`` which
+ will dynamically assign a ``__name__`` and a ``__parent__`` to it,
+ recursively.
If you choose to make use of the location-based dynamic assignment of
``__parent__`` and ``__name__``, the root node must have a
diff --git a/docs/narr/project.rst b/docs/narr/project.rst
index f67e28e1e..53ba15b74 100644
--- a/docs/narr/project.rst
+++ b/docs/narr/project.rst
@@ -10,8 +10,8 @@ creation of a new project by answering a series of questions.
Creating the Project
--------------------
-To start a :mod:`repoze.bfg` project, use the ``paster create``
-facility::
+To start a :mod:`repoze.bfg` :term:`project`, use the ``paster
+create`` facility::
$ paster create -t bfg
@@ -49,27 +49,26 @@ project we name ``myproject``::
Running /Users/chrism/projects/repoze-devel/bfg/bin/python setup.py egg_info
As a result of the above, a project is created in a directory named
-``myproject``. That directory is a :term:`setuptools` *project*
-directory from which a Python setuptools *distribution* can be
+``myproject``. That directory is a :term:`setuptools` :term:`project`
+directory from which a Python setuptools :term:`distribution` can be
created. The ``setup.py`` file in that directory can be used to
distribute your application, or install your application for
-deployment or development. A sample ``PasteDeploy`` ``.ini`` file
+deployment or development. A sample :term:`PasteDeploy` ``.ini`` file
named ``myproject.ini`` will also be created in the project directory.
-You can use this to run your application.
+You will use the ``paster serve`` command against this ``ini`` file to
+run your application.
-The main ``myproject`` contains an additional subdirectory (also named
-``myproject``) representing a Python pakckage which holds very simple
-bfg sample code. This is where you'll edit your application's Python
-code and templates.
+The main ``myproject`` directory contains an additional subdirectory
+(also named ``myproject``) representing a Python :term:`package` which
+holds very simple :mod:`repoze.bfg` sample code. This is where you'll
+edit your application's Python code and templates.
Installing your Newly Created Project for Development
-----------------------------------------------------
-Using your favorite Python interpreter (using a `virtualenv
-<http://pypi.python.org/pypi/virtualenv>`_ is suggested in order to
-isolate your application from your system Python's packages), invoke
-the following command when inside the project directory against the
-generated ``setup.py``::
+Using your favorite Python interpreter (or, better, the interpreter
+from a :term:`virtualenv`), invoke the following command when inside
+the project directory against the generated ``setup.py``::
$ python setup.py develop
@@ -79,8 +78,9 @@ Elided output from a run of this command is shown below::
...
Finished processing dependencies for myproject==0.1
-This will install your application 's package into the interpreter so
-it can be found and run as a WSGI application inside a WSGI server.
+This will install your application 's :term:`package` into the
+interpreter so it can be found and run as a :term:`WSGI` application
+inside a WSGI server.
Running The Tests For Your Application
--------------------------------------
@@ -139,20 +139,21 @@ port 5432.
Viewing the Application
-----------------------
-Visit http://localhost:5432/ in your browser. You will see::
+Visit *http://localhost:5432/* in your browser. You will see::
Welcome to myproject
-That's the page shown by default when you visit a generated
-application.
+That's the page shown by default when you visit an unmodified ``paster
+create``-generated application.
The Project Structure
---------------------
-Our generated :mod:`repoze.bfg` application is a setuptools *project*
-(named ``myproject``), which contains a Python package (which is
-*also* named ``myproject``; the paster template generates a project
-which contains a package that shares its name).
+Our generated :mod:`repoze.bfg` application is a setuptools
+:term:`project` (named ``myproject``), which contains a Python
+:term:`package` (which is *also* named ``myproject``; the paster
+template generates a project which contains a package that shares its
+name).
The ``myproject`` project has the following directory structure::
@@ -172,64 +173,71 @@ The ``myproject`` project has the following directory structure::
|-- myproject.ini
`-- setup.py
-The ``myproject`` *Project*
----------------------------
+The ``myproject`` :term:`Project`
+---------------------------------
-The ``myproject`` project is the distribution and deployment wrapper
-for your application. It contains both the ``myproject`` *package*
-representing your application as well as files used to describe, run,
-and test your application.
+The ``myproject`` :term:`project` is the distribution and deployment
+wrapper for your application. It contains both the ``myproject``
+:term:`package` representing your application as well as files used to
+describe, run, and test your application.
-#. ``CHANGES.txt`` describes the changes you've made to the application.
+#. ``CHANGES.txt`` describes the changes you've made to the
+ application. It is conventionally written in
+ :term:`ReStructuredText` format.
-#. ``README.txt`` describes the application in general.
+#. ``README.txt`` describes the application in general. It is
+ conventionally written in :term:`RestructuredText` format.
#. ``ez_setup.py`` is a file that is used by ``setup.py`` to install
- setuptools if the executing user does not have it installed.
+ :term:`setuptools` if the executing user does not have it
+ installed.
-#. ``myproject.ini`` is a PasteDeploy configuration file that can be
- used to execute your application.
+#. ``myproject.ini`` is a :term:`PasteDeploy` configuration file that
+ can be used to execute your application.
#. ``setup.py`` is the file you'll use to test and distribute your
- application. It is a standard distutils/setuptools ``setup.py`` file.
+ application. It is a standard :term:`setuptools` ``setup.py``
+ file.
-It also contains the ``myproject`` *package*, described below.
+It also contains the ``myproject`` :term:`package`, described below.
-The ``myproject`` *Package*
----------------------------
+The ``myproject`` :term:`Package`
+---------------------------------
-The ``myproject`` package lives inside the ``myproject`` project. It
-contains:
+The ``myproject`` :term:`package` lives inside the ``myproject``
+:term:`project`. It contains:
#. An ``__init__.py`` file which signifies that this is a Python
- package. It is conventionally empty, save for a single comment at
- the top.
+ :term:`package`. It is conventionally empty, save for a single
+ comment at the top.
-#. A ``configure.zcml`` file which maps view names to model types.
- This is also known as the "application registry", although it
- also often contains non-view-related declarations.
+#. A ``configure.zcml`` is a :term:`ZCML` file which maps view names
+ to model types. This is also known as the :term:`application
+ registry`.
-#. A ``models.py`` module, which contains model code.
+#. A ``models.py`` module, which contains :term:`model` code.
#. A ``run.py`` module, which contains code that helps users run the
application.
-#. A ``templates`` directory, which is full of zc3.pt and/or XSL
- templates.
+#. A ``templates`` directory, which is full of :term:`z3c.pt` and/or
+ :term:`XSLT` templates.
-#. A ``tests.py`` module, which contains test code.
+#. A ``tests.py`` module, which contains unit test code for the
+ application.
-#. A ``views.py`` module, which contains view code.
+#. A ``views.py`` module, which contains view code for the
+ application.
-These are purely conventions established by the Paster template:
+These are purely conventions established by the ``paster`` template:
:mod:`repoze.bfg` doesn't insist that you name things in any
particular way.
``configure.zcml``
~~~~~~~~~~~~~~~~~~
-The ``configure.zcml`` (representing the application registry) looks
-like so:
+The ``configure.zcml`` represents the :term:`application
+registry`. It looks like so:
.. literalinclude:: myproject/myproject/configure.zcml
:linenos:
@@ -244,7 +252,17 @@ like so:
#. Lines 8-11 register a single view. It is ``for`` model objects
that support the IMyModel interface. The ``view`` attribute points
- at a Python function that does all the work for this view.
+ at a Python function that does all the work for this view. Note
+ that the values of both the ``for`` attribute and the ``view``
+ attribute begin with a single period. Names that begin with a
+ period are "shortcuts" which point at files relative to the
+ :term:`package` in which the ``configure.zcml`` file lives. In
+ this case, since the ``configure.zcml`` file lives within the
+ ``myproject`` project, the shorcut ``.models.IMyModel`` could also
+ be spelled ``myproject.models.IMyModel`` (forming a full Python
+ dotted-path name to the ``IMyModel`` class). Likewise the shortcut
+ ``.views.my_view`` could be replaced with
+ ``myproject.views.my_view``.
``views.py``
~~~~~~~~~~~~
@@ -257,31 +275,36 @@ in the model, and the HTML given back to the browser.
:linenos:
#. Lines 3-5 provide the ``my_view`` that was registered as the view.
- ``configure.zcml`` said that the default URL for IMyModel content
- should run this ``my_view`` function.
+ ``configure.zcml`` said that the default URL for ``IMyModel``
+ content should run this ``my_view`` function.
- The function is handed two pieces of information: the ``context``
- and the ``request``. The ``context`` is the data at the current
- hop in the URL. (That data comes from the model.) The request is
- an instance of a WebOb request.
+ The function is handed two pieces of information: the
+ :term:`context` and the term:`request`. The *context* is the term
+ :term:`model` found via :term:`traversal` (or via :term:`URL
+ dispatch`). The *request* is an instance of the :term:`WebOb`
+ ``Request`` class representing the browser's request to our server.
-#. The model renders a template and returns the result as the
- response.
+#. The view renders a :term:`template` and returns the result as the
+ :term:`response`.
.. note::
- This example uses ``render_template_to_response`` which allows the
- view author to think only in terms of templates. If you want more
- control over the response, use ``render_template`` and create your
- own ``WebOb`` Response object to return.
+ This example uses ``render_template_to_response`` which is a
+ shortcut function. If you want more control over the response, use
+ the ``render_template`` function, also present in
+ :ref:`template_module`. You may then create your own :term:`WebOb`
+ Response object, using the result of ``render_template`` as the
+ response's body.
``models.py``
~~~~~~~~~~~~~
-In our sample app, the ``models.py`` module provides the model data.
-We create an interface ``IMyModel`` that gives us the "type" for our
-data. We then write a class ``MyModel`` that provides the behavior
-for instances of the ``IMyModel`` type.
+The ``models.py`` module provides the :term:`model` data for our
+application. We write a class named ``MyModel`` that provides the
+behavior. We then create an interface ``IMyModel`` that is a
+:term:`interface` which serves as the "type" for our data, and we
+associate it without our ``MyModel`` class by claiming that the class
+``implements`` the interface.
.. literalinclude:: myproject/myproject/models.py
:linenos:
@@ -303,29 +326,39 @@ make any assumption about which sort of datastore you'll want to use,
so the sample application uses an instance of ``MyModel`` to represent
the root.
+What will likely frighten new developers in the model file is the use
+of :term:`interface` classes. In their simplest form (which is the
+only form that :mod:`repoze.bfg` requires you to understand),
+interfaces are simply "marker" attributes indicating the *type* of a
+model object. These can be attached to classes (via the
+``implements`` function with one or more interfaces as arguments at
+class scope). In more advanced usage, they can be attached directly
+to instances. We do not demonstrate that here.
+
``run.py``
~~~~~~~~~~
We need a small Python module that configures our application and
-advertises itself to our Paste ``.ini`` file. For convenience, we
-also make it possible to run this module directory without the Paste
-configuration file:
+advertises itself to our :term:`PasteDeploy` ``.ini`` file. For
+convenience, we also make it possible to run this module directory
+without the PasteDeploy configuration file:
.. literalinclude:: myproject/myproject/run.py
:linenos:
#. Lines 1 - 7 define a function that returns a :mod:`repoze.bfg`
- Router application. This is meant to be called by the PasteDeploy
- framework as a result of running ``paster serve``.
+ Router application from :ref:`router_module` . This is meant to be
+ called by the :term:`PasteDeploy` framework as a result of running
+ ``paster serve``.
-#. Lines 9 - 12 allow this file to serve as a shortcut for executing
- our program if the ``run.py`` file is executed directly. It starts
- our application under a web server on port 5432.
+#. Lines 9 - 12 allow this file to serve optionally as a shortcut for
+ executing our program if the ``run.py`` file is executed directly.
+ It starts our application under a web server on port 5432.
``templates/mytemplate.pt``
~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The single template in the project looks like so:
+The single :term:`template` in the project looks like so:
.. literalinclude:: myproject/myproject/templates/mytemplate.pt
:linenos:
@@ -333,7 +366,8 @@ The single template in the project looks like so:
This is a :term:`z3c.pt` template. It displays the current project
name when it is rendered. It is referenced by the ``my_view``
-function in the ``views.py`` module.
+function in the ``views.py`` module. Templates are accessed and used
+by view functions.
``tests.py``
~~~~~~~~~~~~
@@ -345,5 +379,7 @@ The ``tests.py`` module includes unit tests for your application.
This sample ``tests.py`` file has a single unit test defined within
it. This is the code that is executed when you run ``setup.py test
--q``. You may add more tests here as you build your application.
+-q``. You may add more tests here as you build your application. You
+are not required to write tests to use :mod:`repoze.bfg`, this file is
+simply provided as convenience and example.
diff --git a/docs/narr/security.rst b/docs/narr/security.rst
index 7adeda3b9..36c0b618a 100644
--- a/docs/narr/security.rst
+++ b/docs/narr/security.rst
@@ -1,10 +1,10 @@
Security
========
-``repoze.bfg`` provides an optional declarative security system that
-prevents views that are protected by a :term:`permission` from being
-rendered when the user represented by the request does not have the
-appropriate level of access in a context.
+:mod:`repoze.bfg` provides an optional declarative security system
+that prevents views that are protected by a :term:`permission` from
+being rendered when the user represented by the request does not have
+the appropriate level of access in a context.
Security is enabled by adding configuration to your ``configure.zcml``
which specifies a :term:`security policy`.
@@ -12,8 +12,8 @@ which specifies a :term:`security policy`.
Enabling a Security Policy
--------------------------
-By default, ``repoze.bfg`` enables no security policy. All views are
-accessible by completely anonymous users.
+By default, :mod:`repoze.bfg` enables no security policy. All views
+are accessible by completely anonymous users.
However, if you add the following bit of code to your application's
``configure.zcml``, you will enable a security policy::
@@ -36,10 +36,11 @@ WSGI server.
Protecting Views with Permissions
---------------------------------
-You declaratively protected a particular view with a permisson via the
-``configure.zcml`` application registry. For example, the following
-declaration protects the view named ``add_entry.html`` when invoked
-against an ``IBlog`` context with the ``add`` permission::
+You declaratively protected a particular view with a
+:term:`permission` via the ``configure.zcml`` application registry.
+For example, the following declaration protects the view named
+``add_entry.html`` when invoked against an ``IBlog`` context with the
+``add`` permission::
<bfg:view
for=".models.IBlog"
@@ -59,7 +60,7 @@ to the system. You can name permissions whatever you like.
Assigning ACLs to your Model Objects
------------------------------------
-When ``repoze.bfg`` determines whether a user possesses a particular
+When :mod:`repoze.bfg` determines whether a user possesses a particular
permission in a :term:`context`, it examines the :term:`ACL`
associated with the context. An ACL is associated with a context by
virtue of the ``__acl__`` attribute of the model object representing
@@ -86,9 +87,10 @@ class::
]
implements(IBlog, ILocation)
-The above ACL indicates that the Everyone principal (a system-defined
-principal) is allowed to view the blog, the ``group:editors``
-principal is allowed to add to and edit the blog.
+The above ACL indicates that the ``Everyone`` principal (a special
+system-defined principal indicating, literally, everyone) is allowed
+to view the blog, the ``group:editors`` principal is allowed to add to
+and edit the blog.
A principal is usually a user id, however it also may be a group id if
your authentication system provides group information and the security
@@ -119,7 +121,7 @@ which points at their parent object. The root object's ``__parent__``
is ``None``. An object with a ``__parent__`` attribute and a
``__name__`` attribute is said to be *location-aware*.
-If the root object in a ``repoze.bfg`` application declares that it
+If the root object in a :mod:`repoze.bfg` application declares that it
implements the ``ILocation`` interface, it is assumed that the objects
in the rest of the model are location-aware. Even if they are not
explictly, if the root object is marked as ``ILocation``, the bfg
diff --git a/docs/narr/traversal.rst b/docs/narr/traversal.rst
index 64e92c570..673f94927 100644
--- a/docs/narr/traversal.rst
+++ b/docs/narr/traversal.rst
@@ -1,33 +1,30 @@
+.. _traversal_chapter:
+
Traversal
=========
-In many popular web frameworks, a "URL dispatcher" is used to
+In many popular web frameworks, :term:`URL dispatch` is used to
associate a particular URL with a bit of code (known somewhat
-ambiguously as a "controller" or "view" depending upon the particular
-vocabulary religion to which you subscribe). These systems allow the
-developer to create "urlconfs" or "routes" to controller/view Python
-code using pattern matching against URL components. Examples:
-`Django's URL dispatcher
+ambiguously as a "controller" or :term:`view` depending upon the
+particular vocabulary religion to which you subscribe). These systems
+allow the developer to create "urlconfs" or "routes" to
+controller/view Python code using pattern matching against URL
+components. Examples: `Django's URL dispatcher
<http://www.djangoproject.com/documentation/url_dispatch/>`_ and the
-`Routes URL mapping system <http://routes.groovie.org/>`_ .
-
-It is possible, however, to map URLs to code differently, using
-"object graph traversal". The venerable Zope and CherryPy web
-frameworks offer graph-traversal-based URL dispatch.
-:mod:`repoze.bfg` also provides graph-traversal-based dispatch of URLs
-to code. Graph-traversal based dispatching is useful if you like the
-URL to represent an arbitrary hierarchy of potentially heterogeneous
-items.
+:term:`Routes` URL mapping system.
-.. note::
+:mod:`repoze.bfg` supports :term:`URL dispatch` via :term:`Routes`.
+See the :ref:`urldispatch_module` for more information about using URL
+dispatch.
- :mod:`repoze.bfg` features graph traversal. However, via the
- inclusion of :term:`Routes`, URL dispatch is also supported for the
- parts of your URL space that better fit that model. See the
- :ref:`urldispatch_module` for more information about using URL
- dispatch.
+By default, however, :mod:`repoze.bfg` does not use URL dispatch to
+map URLs to code. Instead, it maps URLs to code slightly differently,
+using object graph :term:`traversal`. The venerable Zope and CherryPy
+web frameworks offer graph-traversal-based URL dispatch.
+Graph-traversal based dispatching is useful if you like the URL to
+represent an arbitrary hierarchy of potentially heterogeneous items.
-Non-graph traversal based URL dispatch can easily handle URLs such as
+:term:`URL dispatch` can easily handle URLs such as
``http://example.com/members/Chris``, where it's assumed that each
item "below" ``members`` in the URL represents a member in the system.
You just match everything "below" ``members`` to a particular view.
@@ -39,18 +36,18 @@ sets of URLs such as::
...wherein you'd like the ``document`` in the first URL to represent a
PDF document, and ``/stuff/page`` in the second to represent an
-OpenOffice document in a "stuff" folder. It takes more pattern
+*OpenOffice* document in a "stuff" folder. It takes more pattern
matching assertions to be able to make URLs like these work in
URL-dispatch based systems, and some assertions just aren't possible.
For example, URL-dispatch based systems don't deal very well with URLs
that represent arbitrary-depth hierarchies.
-Graph traversal works well if you need to divine meaning out of these
-types of "ambiguous" URLs and URLs that represent arbitrary-depth
-hierarchies. Each URL segment represents a single traversal through
-an edge of the graph. So a URL like ``http://example.com/a/b/c`` can
-be thought of as a graph traversal on the example.com site through the
-edges "a", "b", and "c".
+Graph :term:`traversal` works well if you need to divine meaning out
+of these types of "ambiguous" URLs and URLs that represent
+arbitrary-depth hierarchies. Each URL segment represents a single
+traversal through an edge of the graph. So a URL like
+``http://example.com/a/b/c`` can be thought of as a graph traversal on
+the example.com site through the edges ``a``, ``b``, and ``c``.
Finally, if you're willing to treat your application models as a graph
that can be traversed, it also becomes trivial to provide "row-level
@@ -62,10 +59,10 @@ Graph traversal is materially more complex than URL-based dispatch,
however, if only because it requires the construction and maintenance
of a graph, and it requires the developer to think about mapping URLs
to code in terms of traversing the graph. (How's *that* for
-self-referential! ;-) That said, for developers comfortable with Zope
-(and comfortable with hierarchical data stores like ZODB), mapping a
-URL to a graph traversal is a natural way to think about creating a
-web application.
+self-referential! ;-) ) That said, for developers comfortable with
+:term:`Zope` or comfortable with hierarchical data stores like *ZODB*
+or a filesystem, mapping a URL to a graph traversal is a natural way
+to think about creating a web application.
In essence, the choice to use graph traversal vs. URL dispatch is
largely religious in some sense. Graph traversal dispatch probably
@@ -74,30 +71,32 @@ stored in a relational database. However, when you have a
hierarchical data store, it can provide advantages over using
URL-based dispatch.
-Thus :mod:`repoze.bfg` provides support for both approaches, even
-though the focus is on object graph traversal.
+:mod:`repoze.bfg` provides support for both approaches. Graph
+traversal is described in detail below.
The Model Graph
---------------
-Users interact with your :mod:`repoze.bfg`-based application via a
+Users interact with your :mod:`repoze.bfg` -based application via a
"router", which is itself a WSGI application. At system startup time,
the router is configured with a root object from which all traversal
-will begin. The root object is a mapping object, such as a Python
-dictionary. In fact, all items contained in the graph are either leaf
-nodes (these have no ``__getitem__``) or container nodes (these do
-have a ``__getitem__``).
+will begin. The root object is usually a mapping object, such as a
+Python dictionary. Usually the root is a *container* node, and thus
+contains other items. In fact, all items contained in the graph are
+either *leaf* nodes (these have no ``__getitem__``) or *container*
+nodes (these do have a ``__getitem__``).
Items contained within the graph are analogous to the concept of
-``model`` objects used by many other frameworks (and :mod:`repoze.bfg`
-refers to them as models, as well). They are typically instances of
-classes. Each containerish instance is willing to return a child or
-raise a KeyError based on a name passed to its ``__getitem__``. No
-leaf-level instance is required to have a ``__getitem__``.
+:term:`model` objects used by many other frameworks (and
+:mod:`repoze.bfg` refers to them as models, as well). They are
+typically instances of Python classes. Each containerish instance is
+willing to return a child or raise a ``KeyError`` based on a name
+passed to its ``__getitem__``. No leaf-level instance is required to
+have a ``__getitem__``.
:mod:`repoze.bfg` traverses the model graph in order to find a
-*context*. It then attempts to find a *view* based on the type of the
-context.
+:term:`context`. It then attempts to find a :term`view` based on the
+type (specified by an :term:`interface`) of the context.
How :mod:`repoze.bfg` Processes a Request Using Traversal
---------------------------------------------------------
@@ -107,12 +106,12 @@ application, the system uses this algorithm to determine which Python
code to execute:
1. The request for the page is presented to :mod:`repoze.bfg`'s
- "router" in terms of a standard WSGI request, which is
+ "router" in terms of a standard :term:`WSGI` request, which is
represented by a WSGI environment and a ``start_response``
callable.
- 2. The router creates a `WebOb <http://pythonpaste.org/webob/>`_
- request object based on the WSGI environment.
+ 2. The router creates a :term:`WebOb` request object based on the
+ WSGI environment.
3. The router uses the WSGI environment's ``PATH_INFO`` variable to
determine the path segments to traverse. The leading slash is
@@ -121,59 +120,60 @@ code to execute:
request with a ``PATH_INFO`` variable of ``/a/b/c`` maps to the
traversal sequence ``['a', 'b', 'c']``.
- 4. Traversal begins at the root object. For the traversal sequence
- ``['a', 'b', 'c']``, the root object's ``__getitem__`` is called
- with the name ``a``. Traversal continues through the sequence.
- In our example, if the root object's ``__getitem__`` called with
- the name ``a`` returns an object (aka "object A"), that object's
- ``__getitem__`` is called with the name ``b``. If object A
- returns an object when asked for ``b``, object B's
+ 4. :term:`Traversal` begins at the root object. For the traversal
+ sequence ``['a', 'b', 'c']``, the root object's ``__getitem__``
+ is called with the name ``a``. Traversal continues through the
+ sequence. In our example, if the root object's ``__getitem__``
+ called with the name ``a`` returns an object (aka "object A"),
+ that object's ``__getitem__`` is called with the name ``b``. If
+ object A returns an object when asked for ``b``, object B's
``__getitem__`` is then asked for the name ``c``, and may return
object C.
5. Traversal ends when a) the entire path is exhausted or b) when
- any graph element raises a KeyError from its ``__getitem__`` or
- c) when any non-final path element traversal does not have a
- ``__getitem__`` method (resulting in a NameError) or d) when any
- path element is prefixed with the set of characters ``@@``
+ any graph element raises a ``KeyError`` from its ``__getitem__``
+ or c) when any non-final path element traversal does not have a
+ ``__getitem__`` method (resulting in a ``NameError``) or d) when
+ any path element is prefixed with the set of characters ``@@``
(indicating that the characters following the ``@@`` token should
be treated as a "view name").
6. When traversal ends for any of the reasons in the previous step,
the the last object found during traversal is deemed to be the
- "context". If the path has been exhausted when traversal ends,
- the "view name" is deemed to be the empty string (``''``).
+ :term:`context`. If the path has been exhausted when traversal
+ ends, the "view name" is deemed to be the empty string (``''``).
However, if the path was *not* exhausted before traversal
terminated, the first remaining path element is treated as the
view name.
Any subseqent path elements after the view name are deemed the
- "subpath". For instance, if ``PATH_INFO`` was ``/a/b`` and the
+ *subpath*. For instance, if ``PATH_INFO`` was ``/a/b`` and the
root returned an "A" object, and the "A" object returned a "B"
object, the router deems that the context is "object B", the view
name is the empty string, and the subpath is the empty sequence.
On the other hand, if ``PATH_INFO`` was ``/a/b/c`` and "object A"
- was found but raised a KeyError for the name ``b``, the router
- deems that the context is object A, the view name is ``b`` and
- the subpath is ``['c']``.
+ was found but raised a ``KeyError`` for the name ``b``, the
+ router deems that the context is object A, the view name is ``b``
+ and the subpath is ``['c']``.
- 7. If a security policy is configured, the router performs a
+ 7. If a :term:`security policy` is configured, the router performs a
permission lookup. If a permission declaration is found for the
view name and context implied by the current request, the
security policy is consulted to see if the "current user" (also
determined by the security policy) can perform the action. If he
- can, processing continues. If he cannot, an HTTPUnauthorized
+ can, processing continues. If he cannot, an ``HTTPUnauthorized``
error is raised.
8. Armed with the context, the view name, and the subpath, the
router performs a view lookup. It attemtps to look up a view
- from the :mod:`repoze.bfg` application registry using the view
- name and the context. If a view function is found, it is called
- with the context and the request. It returns a response, which
- is fed back upstream. If a view is not found, a generic WSGI
- ``NotFound`` application is constructed.
+ from the :mod:`repoze.bfg` :term:`application registry` using the
+ view name and the context. If a view function is found, it is
+ called with the context and the request. It returns a response,
+ which is fed back upstream. If a view is not found, a generic
+ WSGI ``NotFound`` application is constructed.
-In either case, the result is returned upstream via the WSGI protocol.
+In either case, the result is returned upstream via the :term:`WSGI`
+protocol.
A Traversal Example
-------------------
@@ -209,19 +209,20 @@ error condition. It signifies that:
- the "subpath" is ``['biz', 'buz.txt']``
-Because it's the "context", bfg examimes "baz" to find out what "type"
+Because it's the "context", bfg examimes "bar" to find out what "type"
it is. Let's say it finds that the context is an ``IBar`` type
(because "bar" happens to have an attribute attached to it that
indicates it's an ``IBar``).
-Using the "view name" ("baz") and the type, it asks the "application
-registry" (configured separately, via "configure.zcml") this question:
+Using the "view name" ("baz") and the type, it asks the
+:term:`application registry` (configured separately, via
+``configure.zcml``) this question:
- - Please find me a "view" (controller in some religions) with the
- name "baz" that can be used for the type ``IBar``.
+ - Please find me a :term:`view` (aka *controller* in some religions)
+ with the name "baz" that can be used for the type ``IBar``.
-Let's say it finds no matching view type. It then returns a NotFound.
-The request ends. Everyone is sad.
+Let's say it finds no matching view type. It then returns a
+``NotFound``. The request ends. Everyone is sad.
But! For this graph::
@@ -246,7 +247,7 @@ The user asks for ``http://example.com/foo/bar/baz/biz/buz.txt``
- bfg traverses biz, and attemtps to find "buz.txt" which it does
not find.
-The fact that it does not find "biz.txt" at this point does not
+The fact that it does not find "buz.txt" at this point does not
signify an error condition. It signifies that:
- the "context" is biz (the context is the last item found during traversal).
@@ -261,16 +262,16 @@ it is. Let's say it finds that the context an ``IBiz`` type (because
indicates it's an ``IBiz``).
Using the "view name" ("buz.txt") and the type, it asks the
-"application registry" (configured separately, in "configure.zcml")
-this question:
+:term:`application registry` this question:
- - Please find me a "view" (controller in some religions) with the
- name "buz.txt" that can be used for type ``IBiz``.
+ - Please find me a :term:`view` (*controller* in some religions)
+ with the name "buz.txt" that can be used for type ``IBiz``.
Let's say that question is answered "here you go, here'a a bit of code
-that is willing to deal with that case", and returns a view. It is
-passed the "biz" object as the "context" and the current WebOb request
-as the "request". It returns a response.
+that is willing to deal with that case", and returns a :term:`view`.
+It is passed the "biz" object as the "context" and the current
+:term:`WebOb` :term:`request` as the "request". It returns a
+term:`response`.
There are two special cases:
diff --git a/docs/tutorials/lxmlgraph/background.rst b/docs/tutorials/lxmlgraph/background.rst
index e4fdc5034..aec4cda26 100644
--- a/docs/tutorials/lxmlgraph/background.rst
+++ b/docs/tutorials/lxmlgraph/background.rst
@@ -1,31 +1,29 @@
Background
====================
-This demo application presumes that you have an interest in XML
-technologies and might want to leverage them for a fast, but rich and
-dynamic, website. In this demo application, we build up, bit-by-bit,
-the functionality. Thus, you don't have to know squatola about XML to
-follow along.
-
-In fact, the real purpose of this demo app is to teach its author how
-to use the stack (repoze.bfg, Paster, eggs, etc.)
-
-In summary:
-
- - Represent a hierarchical site as hierarchical XML
-
- - Inject ``repoze.bfg`` semantics into elements using :term:`lxml`
-
- - Support flexible-but-fast rendering with XSLT
+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, ``repoze.bfg`` is in no way dependent on XML.
- On the other hand, ``repoze.bfg`` happens to make XML publishing
+ 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
-------------------
@@ -44,7 +42,7 @@ 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 ``repoze.bfg``, of course. More specifically, with an XML file
+Using :mod:`repoze.bfg`, of course. More specifically, with an XML file
that models that hierarchy:
.. literalinclude:: step00/simplemodel.xml
@@ -53,8 +51,8 @@ that models that hierarchy:
How It Works
-------------------
-To coerce ``repoze.bfg`` into publishing this model, I just need to
-sprinkle in some Python behavior. For example, ``repoze.bfg`` uses
+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
@@ -64,11 +62,9 @@ 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 ``repoze.bfg``
+The interface then lets me glue back into the standard :mod:`repoze.bfg`
machinery, such as associating views and permissions into the model.
-Neato torpedo. And stinking fast.
-
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.
@@ -85,28 +81,3 @@ 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.
-What It Might Do
---------------------
-
-This demo application has the potential to show some other interesting
-investigations:
-
-#. **Authorization**. By hooking up support for an ``__acl__``
- property, I can store ACL information on a single node, on an
- ancestor, on the ``<site>`` root, on the Python class, or any
- combination thereof. Additionally, I can wire up the
- ``__parent__`` attribute as a property that makes an :term:`lxml`
- ``node.getparent()`` call.
-
-#. **Multiple views**. Instead of just having a single default view
- on a node, I can allow other view names, all pointing at the same
- view function and XSLT. I simple grab that name and pass it in as
- a paramter to the XSLT, which will run a different rule for
- rendering. Adding a view would no longer required editing ZCML and
- adding a function.
-
-#. **Forms**. To edit data in the model, I need to render a form,
- then handle post data on the way back in. For the former, it's
- *really* easy in XSLT to make a very powerful, flexible, and
- extensisible form rendering system. For the latter, I'll have to
- learn more about POST handlers in ``repoze.bfg``.
diff --git a/docs/tutorials/lxmlgraph/index.rst b/docs/tutorials/lxmlgraph/index.rst
index a4d0016cc..cc79f7e73 100644
--- a/docs/tutorials/lxmlgraph/index.rst
+++ b/docs/tutorials/lxmlgraph/index.rst
@@ -1,10 +1,10 @@
-``lxmlgraph``: Publishing An XML Tree with ``repoze.bfg``
-==========================================================
+``lxmlgraph``: Publishing An XML Tree with :mod:`repoze.bfg`
+============================================================
-Hierarchical websites are easy to develop with ``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 ``repoze.bfg`` that
+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::
diff --git a/docs/tutorials/lxmlgraph/step01.rst b/docs/tutorials/lxmlgraph/step01.rst
index 6c6f93191..578f13608 100644
--- a/docs/tutorials/lxmlgraph/step01.rst
+++ b/docs/tutorials/lxmlgraph/step01.rst
@@ -3,10 +3,9 @@ Step 1: Getting Started
=======================
To get started, using the ``paster`` command from a :term:`virtualenv`
-you've created that has ``repoze.bfg`` installed, run ``paster create
--t bfg`` as described in :ref:`project_narr` to create your lxmlgraph
-project::
-
+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
diff --git a/docs/tutorials/lxmlgraph/step02.rst b/docs/tutorials/lxmlgraph/step02.rst
index 94aca07e4..1dc1ebcd3 100644
--- a/docs/tutorials/lxmlgraph/step02.rst
+++ b/docs/tutorials/lxmlgraph/step02.rst
@@ -6,7 +6,7 @@ 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 ``repoze.bfg`` machinery:
+data. We will leverage the following :mod:`repoze.bfg` machinery:
- Model data with interfaces that define "types"
@@ -14,11 +14,11 @@ data. We will leverage the following ``repoze.bfg`` machinery:
Our application will need to do these things:
- - Use :term:`lxml` Element classes to inject ``repoze.bfg`` behavior into
- ``lxml`` nodes
+ - Use :term:`lxml` Element classes to inject :mod:`repoze.bfg`
+ behavior into ``lxml`` nodes
- - That model class needs to implement the ``repoze.bfg`` publishing
- contract
+ - 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*.
@@ -40,18 +40,17 @@ your package:
#. 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 ``repoze.bfg`` is concerned.
+ 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 ``repoze.bfg`` in during traversal *must* have a ``name``
-attribute. (The use of ``@name`` corresponds to ``__name__`` in the
-``repoze.bfg`` sense of ``repoze.bfg`` :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.
-
+"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``
------------------------------
@@ -64,7 +63,7 @@ class with the parser. Replace the contents of the autogenerated
.. literalinclude:: step02/myapp/models.py
:linenos:
-#. Line 4 imports ``lxml``.
+#. Line 4 imports :term:`lxml`.
#. Line 9 creates the custom class we are going to use to extend
etree.ElementBase. The `<lxml website
@@ -75,20 +74,20 @@ class with the parser. Replace the contents of the autogenerated
certain content type (interface.) In our case, instances will be
XML nodes.
-#. ``repoze.bfg`` has a "protocol" where model data should have an
+#. :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 ``repoze.bfg`` works via the ``__getitem__``
+#. 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 ``lxml`` magic to get the
- custom Python class registered. We then load some XML and return
- the top of the tree.
+ 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``
-----------------------------
@@ -124,7 +123,9 @@ 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
diff --git a/docs/tutorials/lxmlgraph/step03.rst b/docs/tutorials/lxmlgraph/step03.rst
index 5e7911889..9edc77af3 100644
--- a/docs/tutorials/lxmlgraph/step03.rst
+++ b/docs/tutorials/lxmlgraph/step03.rst
@@ -60,8 +60,9 @@ Also add a function in ``views.py`` that looks like the following:
This function is relatively simple:
-#. Line 1 imports a ``repoze.bfg`` function that renders ZPT templates
- to a response. ``repoze.bfg`` uses the ``z3c.pt`` ZPT engine.
+#. Line 1 imports a :mod:`repoze.bfg` function that renders ZPT
+ templates to a response. :mod:`repoze.bfg` uses the ``z3c.pt`` ZPT
+ engine.
#. Line 2, like our other view functions, gets passed a ``context``
(the current hop in the URL) and WebOb ``request`` object.
@@ -160,11 +161,12 @@ to your ``views.py`` file:
#. Line 10 implements the difference. We call
``render_transform_to_response`` instead of
- ``render_template_to_response``. This tells ``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.
+ ``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``
@@ -190,7 +192,6 @@ directory and give it the following contents:
#. Line 8 shows the element name of the current node.
-
Viewing the XSLT
--------------------