summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-07-03 01:41:04 +0000
committerChris McDonough <chrism@agendaless.com>2009-07-03 01:41:04 +0000
commit7bc20e11b5ed7314e5aaed000242d4d5950fc775 (patch)
tree6cb253ea95617ca4f24aa365f145ec2f81bf53fc /docs
parentc43c358c7ec7d352fd4792b993e4609cbab37dba (diff)
downloadpyramid-7bc20e11b5ed7314e5aaed000242d4d5950fc775.tar.gz
pyramid-7bc20e11b5ed7314e5aaed000242d4d5950fc775.tar.bz2
pyramid-7bc20e11b5ed7314e5aaed000242d4d5950fc775.zip
General editing walkthrough.
Diffstat (limited to 'docs')
-rw-r--r--docs/narr/events.rst7
-rw-r--r--docs/narr/extending.rst8
-rw-r--r--docs/narr/hooks.rst4
-rw-r--r--docs/narr/hybrid.rst15
-rw-r--r--docs/narr/install.rst54
-rw-r--r--docs/narr/introduction.rst35
-rw-r--r--docs/narr/models.rst5
-rw-r--r--docs/narr/project.rst72
-rw-r--r--docs/narr/security.rst52
-rw-r--r--docs/narr/startup.rst47
-rw-r--r--docs/narr/templates.rst51
-rw-r--r--docs/narr/traversal.rst111
-rw-r--r--docs/narr/urldispatch.rst25
-rw-r--r--docs/narr/urlmapping.rst26
-rw-r--r--docs/narr/views.rst37
15 files changed, 307 insertions, 242 deletions
diff --git a/docs/narr/events.rst b/docs/narr/events.rst
index e54c97a88..ca3ecf3d6 100644
--- a/docs/narr/events.rst
+++ b/docs/narr/events.rst
@@ -4,7 +4,7 @@ Using Events
=============
An *event* is an object broadcast by the :mod:`repoze.bfg` framework
-at particularly interesting points during the lifetime of your
+at particularly interesting points during the lifetime of an
application. You don't need to use, know about, or care about events
in order to create most :mod:`repoze.bfg` applications, but they can
be useful when you want to do slightly advanced operations, such as
@@ -12,7 +12,7 @@ be useful when you want to do slightly advanced operations, such as
hostname used to reach the site.
Events in :mod:`repoze.bfg` are always broadcast by the framework.
-They only become useful when you register a *subscriber*. A
+However, they only become useful when you register a *subscriber*. A
subscriber is a function that accepts a single argument named `event`:
.. code-block:: python
@@ -86,7 +86,8 @@ must. Likewise, we know that ``INewResponse`` events have a
``response`` attribute, which is a response object constructed by your
application, because the interface defined at
``repoze.bfg.interfaces.INewResponse`` says it must. These particular
-interfaces are documented in the :ref:`events_module` API chapter.
+interfaces, along with others, are documented in the
+:ref:`events_module` API chapter.
.. note::
diff --git a/docs/narr/extending.rst b/docs/narr/extending.rst
index cbfaeda6a..128e75b26 100644
--- a/docs/narr/extending.rst
+++ b/docs/narr/extending.rst
@@ -39,10 +39,10 @@ declarations out of the decorators and into :term:`ZCML`. Once this
is done, you should be able to extend or modify the application like
any other.
-To extend or change the behavior of an existing application, the only
-hard-and-fast rule is that you need to write some :term:`ZCML`, and
-perhaps some implementations of the types of things you'd like to
-override (such as views), which is referred to within that ZCML.
+To extend or change the behavior of an existing application, you will
+need to write some :term:`ZCML`, and perhaps some implementations of
+the types of things you'd like to override (such as views), which are
+referred to within that ZCML.
The general pattern for extending an application looks something like this:
diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst
index 086dc16ad..c2f6966de 100644
--- a/docs/narr/hooks.rst
+++ b/docs/narr/hooks.rst
@@ -6,6 +6,8 @@ Using ZCML Hooks
ZCML "hooks" can be used to influence the behavior of the
:mod:`repoze.bfg` framework in various ways.
+.. _changing_the_notfound_view:
+
Changing the Not Found View
---------------------------
@@ -38,6 +40,8 @@ implements a minimal NotFound view:
This error will be different when the ``debug_notfound``
environment setting is true than it is when it is false.
+.. _changing_the_forbidden_view:
+
Changing the Forbidden View
---------------------------
diff --git a/docs/narr/hybrid.rst b/docs/narr/hybrid.rst
index 70a233005..129d76732 100644
--- a/docs/narr/hybrid.rst
+++ b/docs/narr/hybrid.rst
@@ -13,14 +13,15 @@ However, for some problems, it's useful to use both traversal *and*
URL dispatch within the same application. :mod:`repoze.bfg` makes
this possible.
-Reasoning about a "hybrid" URL dispatch + traversal model is difficult
-because the combination of the two concepts seems to break the law of
-`the magical number seven plus or minus 2
+Reasoning about a "hybrid" URL dispatch + traversal model can be
+difficult because the combination of the two concepts seems to fall
+outside the sweet spot of `the magical number seven plus or minus 2
<http://en.wikipedia.org/wiki/The_Magical_Number_Seven,_Plus_or_Minus_Two>`_.
-This is because, as a user, you need to understand 1) URL pattern
-matching, 2) root factories and 3) the traversal algorithm, and the
-interactions between all of them. Therefore, use of this pattern is
-not recommended unless you *really* need to use it.
+To reason successfully about using URL dispatch and traversal
+together, you need to understand 1) URL pattern matching, 2) root
+factories and 3) the traversal algorithm, and the interactions between
+all of them. Therefore, use of this pattern is not recommended unless
+you *really* need to use it.
This is a advanced topic that has non-trivial corner cases; you may
need to understand more deeply how :mod:`repoze.bfg` works to
diff --git a/docs/narr/install.rst b/docs/narr/install.rst
index 4ba4eee06..26d409e7f 100644
--- a/docs/narr/install.rst
+++ b/docs/narr/install.rst
@@ -20,19 +20,20 @@ run under Python 3.X.
.. note:: Installation of :mod:`repoze.bfg` does not require the
compilation of any C code, so as long as you have a Python
interpreter that meets the above requirements, you do not need to
- have development tools installed on the target machine to run
+ have development tools installed on the target machine to install
:mod:`repoze.bfg`.
-BFG is known to run properly on all popular (and even some
-less-popular) Unix-like systems such as Linux, MacOS X, and FreeBSD.
+BFG is known to run properly on all popular Unix-like systems such as
+Linux, MacOS X, and FreeBSD.
-:mod:`repoze.bfg` runs on Windows systems. However, none of its main
-developers use the Windows platform. Therefor, most of the
-platform-specific documentation (excepting this chapter) assumes
-you're using a UNIX system. If you're using a Windows system, you'll
-need to transliterate command lines in the documentation to their
-Windows equivalents. :mod:`repoze.bfg` is also known to run on
-Google's App Engine.
+:mod:`repoze.bfg` does run on Windows systems. However, none of its
+developers use Windows as a primary development platform. Therefore,
+most of the platform-specific documentation (excepting this chapter)
+assumes you're using a UNIX system. If you're using a Windows system,
+you'll need to transliterate command lines in the documentation to
+their Windows equivalents.
+
+:mod:`repoze.bfg` is also known to run on Google's App Engine.
It is not known whether :mod:`repoze.bfg` will or will not run under
Jython or IronPython.
@@ -72,10 +73,12 @@ invokable via ``python2.5`` from a shell prompt.
Source Compile Method
+++++++++++++++++++++
-It's useful to use a Python that *isn't* the "system" Python to
-develop your software (the authors of BFG never use the system Python
-to run BFG; always a self-compiled one). Often the "system" Python is
-compiled with options that aren't optimal for web development.
+It's useful to use a Python interpreter that *isn't* the "system"
+Python interpreter to develop your software. The authors of
+:mod:`repoze.bfg` never use the system Python for development
+purposes; always a self-compiled one. Compiling Python is easy, and
+often the "system" Python is compiled with options that aren't optimal
+for web development.
To compile software on your UNIX system, typically you need
development tools. Often these can be installed via the package
@@ -117,6 +120,8 @@ interpreter executable from `<python.org
http://python.org/download/>`_ (the files labeled "Windows
Installer"). Once you've downloaded it, double click on the
executable and accept the defaults during the installation process.
+You may also need to download and install the `Python for Windows
+extensions <http://sourceforge.net/projects/pywin32/files/>`_.
Installing :mod:`repoze.bfg` on a UNIX System
---------------------------------------------
@@ -128,9 +133,9 @@ installed in your Python version (and likewise, to prevent
are not compatible with your system Python).
To set up a virtualenv to install :mod:`repoze.bfg` within, first
-ensure that setuptools is installed. Invoke ``import setuptools``
-within the Python interpreter you'd like to run :mod:`repoze.bfg`
-with.
+ensure that :term:`setuptools` is installed. Invoke ``import
+setuptools`` within the Python interpreter you'd like to run
+:mod:`repoze.bfg` under:
.. code-block:: bash
@@ -143,9 +148,11 @@ with.
If ``import setuptools`` does not raise an ``ImportError``, it means
that setuptools is already installed into your Python interpreter. If
``import setuptools`` fails, you will need to install setuptools
-manually. If you are using a "system" Python (one installed by your
-OS distributor or a 3rd-party packager such as Fink or MacPorts), you
-can usually install a setuptools package using your system's package
+manually.
+
+If you are using a "system" Python (one installed by your OS
+distributor or a 3rd-party packager such as Fink or MacPorts), you 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,
@@ -169,7 +176,6 @@ the script. To remediate this, you may need to do:
$ sudo python ez_setup.py
-
Installing the ``virtualenv`` Package
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -247,9 +253,9 @@ Installing :mod:`repoze.bfg` on a Windows System
<http://python.org/download/releases/2.5.4/>`_ for your system.
#. Install the `Python for Windows extensions
- <http://www.sourceforge.net/project/showfiles.php?group_id=78018>`_.
- Make sure to pick the right download for Python 2.5 and install it
- using the same Python installation from the previous step.
+ <http://sourceforge.net/projects/pywin32/files/>`_. Make sure to
+ pick the right download for Python 2.5 and install it using the
+ same Python installation from the previous step.
#. Install latest `setuptools` into the Python you
obtained/installed/found in the step above: download `ez_setup.py
diff --git a/docs/narr/introduction.rst b/docs/narr/introduction.rst
index e96d74543..c863b499e 100644
--- a/docs/narr/introduction.rst
+++ b/docs/narr/introduction.rst
@@ -9,18 +9,18 @@ and responses.
Similarities to Other Frameworks
--------------------------------
-:mod:`repoze.bfg` was inspired by :term:`Zope`, :term:`Django`, and
-:term:`Pylons`.
+:mod:`repoze.bfg` was inspired by :term:`Zope`, :term:`Pylons` and
+:term:`Django`.
The :mod:`repoze.bfg` concept of traversal is inspired by
:term:`Zope`. Additionally, :mod:`repoze.bfg` uses the Zope Component
Architecture ("CA") internally, as do Zope 2, Zope 3, and
-:term:`Grok`. Application :mod:`repoze.bfg` developers use either
+:term:`Grok`. :mod:`repoze.bfg` application developers may use either
:term:`ZCML` (an XML dialect, used in Zope) or decorators to perform
-various configuration tasks. The decorator support is provided by the
-:term:`Grok` project. Like Zope, :mod:`repoze.bfg` allows you to
-create applications which do not need to be forked to be extended by a
-third party developer.
+various application configuration tasks. The decorator support is
+provided by the :term:`Grok` project. Like Zope, :mod:`repoze.bfg`
+allows you to create applications which do not need to be forked or
+otherwise modified to be extended by a third party developer.
Like :term:`Pylons`, :mod:`repoze.bfg` is mostly policy-free. It
makes no assertions about which database you should use, and its
@@ -76,8 +76,8 @@ To learn more about the concepts used by :mod:`repoze.bfg`, visit the
Differences from Other Frameworks
---------------------------------
-Like :term:`Zope`, the :mod:`repoze.bfg` framework imposes slightly
-more `control inversion <http://plope.com/control_inversion>`_ upon
+Like :term:`Zope`, the :mod:`repoze.bfg` framework imposes more
+`control inversion <http://plope.com/control_inversion>`_ upon
application developers than other Python frameworks such as
:term:`Pylons`. For example :mod:`repoze.bfg` allows you to
explicitly resolve a URL to a :term:`context` object before invoking a
@@ -107,7 +107,7 @@ CA behind special-purpose API functions.
Also unlike :term:`Zope` and unlike other "full-featured" frameworks
such as :term:`Django`, :mod:`repoze.bfg` makes no assumptions about
-what persistence mechanisms you want to use to build an application.
+which persistence mechanisms you should use to build an application.
Zope applications are typically reliant on :term:`ZODB`;
:mod:`repoze.bfg` allows you to build :term:`ZODB` applications, but
it has no reliance on the ZODB package. Likewise, :term:`Django`
@@ -121,8 +121,8 @@ Why?
----
*Familiarity*: As web developers, we've become accustomed to working
-in very particular ways (primarily using Zope 2) over the years. This
-framework is a canonization of practices that "fit our brains".
+in very particular ways over the years. This framework is a
+canonization of practices that "fit our brains".
*Simplicity*: :mod:`repoze.bfg` attempts to be a *"pay only for what
you eat"* framework in which you can be productive quickly with
@@ -130,14 +130,13 @@ partial knowledge. We contrast this with *"pay up front for what
anyone might eventually want to eat"* frameworks, which tend to expect
you to understand a great many concepts and technologies fully before
you can be truly productive. :mod:`repoze.bfg` doesn't force you to
-use any particular technology to get your application written, and we
-try to keep the core set of concepts you need to understand to a
-minimum.
+use any particular technology to produce an application, and we try to
+keep the core set of concepts you need to understand to a minimum.
*Minimalism*: :mod:`repoze.bfg` provides only the very basics: *URL to
-code mapping*, *templating*, and *security*. There is not much more
-to the framework than these pieces: you are expected to provide the
-rest.
+code mapping*, *templating*, *security*, and *resources*. There is
+not much more to the framework than these pieces: you are expected to
+provide the rest.
*Documentation*: Because :mod:`repoze.bfg` is minimal, it's relatively
easy to keep its documentation up-to-date, which is helpful to bring
diff --git a/docs/narr/models.rst b/docs/narr/models.rst
index b865bcb53..a3613c77c 100644
--- a/docs/narr/models.rst
+++ b/docs/narr/models.rst
@@ -99,8 +99,9 @@ interface (as opposed to its class). To do so, use the
entry = BlogEntry()
directlyProvides(IBlogEntry, entry)
-If a model object already has instance interface declarations that you
-don't want to disturb, use the ``zope.interface.alsoProvides`` API:
+If a model object already has instance-level interface declarations
+that you don't want to disturb, use the
+``zope.interface.alsoProvides`` API:
.. code-block:: python
:linenos:
diff --git a/docs/narr/project.rst b/docs/narr/project.rst
index a8b0ccdd4..4b0de4a0e 100644
--- a/docs/narr/project.rst
+++ b/docs/narr/project.rst
@@ -3,9 +3,9 @@
Creating a :mod:`repoze.bfg` Project
====================================
-You can use :mod:`repoze.bfg` 's sample application generator to get
-started. This generator uses :term:`Paste` templates to allow
-creation of a new project by answering a series of questions.
+You can use the :mod:`repoze.bfg` sample application generator to get
+started. This generator uses :term:`Paste` templates to aid in
+the creation of a new project.
.. _creating_a_project:
@@ -69,15 +69,15 @@ project we name ``MyProject``:
Copying setup.py_tmpl to ./MyProject/setup.py
Running /Users/chrism/projects/repoze/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` :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 :term:`PasteDeploy` ``.ini`` file
-named ``MyProject.ini`` will also be created in the project directory.
-You will use the ``paster serve`` command against this ``.ini`` file
-to run your application.
+As a result of invoking ``paster create``, a project is created in a
+directory named ``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
+:term:`PasteDeploy` ``.ini`` file named ``MyProject.ini`` will also be
+created in the project directory. You will use the ``paster serve``
+command against this ``.ini`` file to run your application.
The ``MyProject`` project directory contains an additional
subdirectory named ``myproject`` (note the case difference)
@@ -164,14 +164,27 @@ The Interactive Shell
---------------------
Once you've installed your program for development using ``setup.py
-develop``, you can use an interactive shell to examine your BFG
-application from a Python prompt. To do so, use the ``paster``
-shell command with the ``bfgshell`` argument:
+develop``, you can use an interactive shell to examine your
+:mod:`repoze.bfg` application :term:`model` objects from a Python
+prompt. To do so, use the ``paster`` shell command with the
+``bfgshell`` argument:
The first argument to ``bfgshell`` is the path to your application's
``.ini`` file. The second is the section name inside the ``.ini``
-file which points to your application.
+file which points to your *application* as opposed to any other
+section within the ``.ini`` file. For example, if your application
+``.ini`` file might have a ``[app:main]`` section that looks like so:
+.. code-block:
+
+ [app:main]
+ use = egg:MyProject#app
+ reload_templates = true
+ debug_authorization = false
+ debug_notfound = false
+
+If so, you can use the following command to invoke a debug shell using
+the name ``main`` as a section name:
.. code-block:: bash
:linenos:
@@ -194,7 +207,7 @@ before the filename:
[chrism@vitaminf bfgshellenv]$ ../bin/paster --plugin=repoze.bfg bfgshell MyProject.ini main
-Press Ctrl-D to exit the interactive shell.
+Press "Ctrl-D" to exit the interactive shell.
You should always use a section name argument that refers to the
actual ``app`` section within the config file that points at your BFG
@@ -302,7 +315,7 @@ We won't describe the ``CHANGES.txt`` or ``README.txt`` files.
``ez_setup.py`` is a file only used by ``setup.py`` in case a user who
wants to install your package does not have :term:`Setuptools` already
installed. It is only imported by and used by ``setup.py``, so we
-won't describe it here.
+won't describe it here either.
.. _MyProject_ini:
@@ -388,8 +401,9 @@ not require an application restart to be detected. See
turned on.
Various other settings may exist in this section having to do with
-debugging a :mod:`repoze.bfg` application. See
-:ref:`environment_chapter` for more information about these settings.
+debugging or influencing runtime behavior of a :mod:`repoze.bfg`
+application. See :ref:`environment_chapter` for more information
+about these settings.
The ``[server:main]`` section of the configuration file configures a
WSGI server which listens on port 6543. It is configured to listen on
@@ -398,10 +412,10 @@ new thread for each request.
.. note::
- In general, ``repoze.bfg`` applications should be threading-aware.
- It is not required that a ``repoze.bfg`` application be nonblocking
- as all application code will run in its own thread, provided by the
- server you're using.
+ In general, :mod:`repoze.bfg` applications should be
+ threading-aware. It is not required that a :mod:`repoze.bfg`
+ application be nonblocking as all application code will run in its
+ own thread, provided by the server you're using.
See the :term:`PasteDeploy` documentation for more information about
other types of things you can put into this ``.ini`` file, such as
@@ -450,8 +464,8 @@ fields which probably don't need any description. ``url`` is a field
that should point at your application project's URL (if any).
``packages=find_packages()`` causes all packages within the project to
be found when packaging the application. ``include_package_data``
-will include non-Python files when the application is packaged (if
-those files are checked into version control). ``zip_safe`` indicates
+will include non-Python files when the application is packaged if
+those files are checked into version control. ``zip_safe`` indicates
that this package is not safe to ship as a zipped egg (it will unpack
as a directory, which is more convenient). ``install_requires`` and
``tests_require`` indicate that this package depends on the
@@ -688,8 +702,8 @@ The ``tests.py`` module includes unit tests for your application.
This sample ``tests.py`` file has a single unit test and a single
integration test defined within it. These two tests are executed when
-you run ``setup.py test -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
+you run ``python setup.py test -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 e86451570..cd2dc9a50 100644
--- a/docs/narr/security.rst
+++ b/docs/narr/security.rst
@@ -6,10 +6,11 @@ Security
:mod:`repoze.bfg` provides an optional declarative authorization
system that prevents a :term:`view` from being invoked when the user
represented by credentials in the :term:`request` does not have an
-appropriate level of access in a specific context.
+appropriate level of access with respect to a specific
+:term:`context`.
Authorization is enabled by modifying your :term:`application
-registry` (aka "configure.zcml").
+registry` (aka ``configure.zcml``).
Enabling an Authorization Policy
--------------------------------
@@ -65,11 +66,10 @@ and :ref:`creating_an_authorization_policy`.
Protecting Views with Permissions
---------------------------------
-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 a ``Blog`` context with the
-``add`` permission:
+You declaratively protect a particular view using a :term:`permission`
+name via the ``configure.zcml`` application registry. For example,
+the following declaration protects the view named ``add_entry.html``
+when invoked against a ``Blog`` context with the ``add`` permission:
.. code-block:: xml
:linenos:
@@ -81,9 +81,9 @@ For example, the following declaration protects the view named
permission="add"
/>
-The equivalent view registration including the 'add' permission may be
-performed via the ``bfg_view`` decorator within the "views" module of
-your project's package
+The equivalent view registration including the 'add' permission name
+may be performed via the ``bfg_view`` decorator within the "views"
+module of your project's package
.. code-block:: python
:linenos:
@@ -101,21 +101,22 @@ normal application operations, the user will need to possess the
``add`` permission against the context to be able to invoke the
``blog_entry_add_view`` view.
-Permission names are just strings. They hold no special significance
-to the system. You can name permissions whatever you like.
+Permission names are usually just strings. They hold no special
+significance to the system. You can name permissions whatever you
+like.
.. _assigning_acls:
Assigning ACLs to your Model Objects
------------------------------------
-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
-the context. This attribute can be defined on the model *instance*
-(if you need instance-level security), or it can be defined on the
-model *class* (if you just need type-level security).
+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 the context. This attribute can be defined on the model
+*instance* (if you need instance-level security), or it can be defined
+on the model *class* (if you just need type-level security).
For example, an ACL might be attached to model for a blog via its
class:
@@ -184,7 +185,7 @@ and edit the blog.
The third argument in an ACE can also be a sequence of permission
names instead of a single permission name. So instead of creating
multiple ACEs representing a number of different permission grants to
-a single ``group.editors`` group, we can collapse this into a single
+a single ``group:editors`` group, we can collapse this into a single
ACE, as below.
.. code-block:: python
@@ -340,6 +341,16 @@ root object's ``__parent__`` is ``None``.
See :ref:`location_module` for documentations of functions which use
location-awareness. See also :ref:`location_aware`.
+Changing the Forbidden View
+---------------------------
+
+When :mod:`repoze.bfg` denies a view invocation due to an
+authorization denial, the special ``forbidden`` view is invoked. "Out
+of the box", this forbidden view is very plain. See
+:ref:`changing_the_forbidden_view` within :ref:`hooks_chapter` for
+instructions on how to create a custom forbidden view and arrange for
+it to be called when view authorization is denied.
+
.. _debug_authorization_section:
Debugging View Authorization Failures
@@ -612,3 +623,4 @@ examples of how to create a directive. Authorization policy ZCML
directives should use the ZCML discriminator value
"authorization_policy" in their actions to allow for conflict
detection.
+
diff --git a/docs/narr/startup.rst b/docs/narr/startup.rst
index 1d8206f14..f657b44c7 100644
--- a/docs/narr/startup.rst
+++ b/docs/narr/startup.rst
@@ -3,8 +3,8 @@
Startup
=======
-When you cause :mod:`repoze.bfg` to start up in the foreground, you'll
-see something much like this show up on your console::
+When you cause :mod:`repoze.bfg` to start up in a console window,
+you'll see something much like this show up on the console::
$ paster serve myproject/MyProject.ini
Starting server in PID 16601.
@@ -12,8 +12,8 @@ see something much like this show up on your console::
This chapter explains what happens between the time you press the
"Return" key on your keyboard after typing ``paster serve
-myproject/MyProject.ini`` and the resulting output of the line
-``serving on 0.0.0:6543 ...`` to your console.
+myproject/MyProject.ini`` and the the time the line ``serving on
+0.0.0:6543 ...`` is output to your console.
The Startup Process
-------------------
@@ -99,15 +99,15 @@ press ``return`` after running ``paster serve MyProject.ini``.
.. literalinclude:: MyProject/myproject/run.py
:linenos:
- Note that the app function imports the ``get_root`` root factory
- function from the ``myproject.models`` Python module. It then also
- imports the "bare" ``myproject`` package, and passes ``get_root``,
- ``myproject``, and the ``options`` keyword as the ``app``
- function's extra keyword args to the ``make_app`` function of the
- ``repoze.bfg.router`` module. ``**kw`` here contains all the
- options in the ``[app:main]`` section of our .ini file except the
- "use" option (which is internal to paste). In this case, ``**kw``
- will be something like ``{'reload_templates':'true',
+ Note that the ``app`` function imports the ``get_root`` :term:`root
+ factory` function from the ``myproject.models`` Python module. It
+ then also imports the "bare" ``myproject`` package, and passes
+ ``get_root``, ``myproject``, and the ``options`` keyword as the
+ ``app`` function's extra keyword args to the ``make_app`` function
+ of the ``repoze.bfg.router`` module. ``**kw`` here contains all
+ the options in the ``[app:main]`` section of our .ini file except
+ the "use" option (which is internal to paste). In this case,
+ ``**kw`` will be something like ``{'reload_templates':'true',
'debug_authorization':'false', 'debug_notfound':'false'}``.
``get_root`` is the first argument to ``make_app``, and it is a
@@ -119,12 +119,13 @@ press ``return`` after running ``paster serve MyProject.ini``.
callback knows where to look for the :term:`application registry`
file (conventially named ``configure.zcml``). ``make_app`` will
use the package's path and look for ``configure.zcml`` within that
- package's filesystem directory. If you for some reason need or
- want to load a different application registry filename for your
- application, you can pass an optional ``filename=`` paramter to
- make_app (e.g. ``make_app(get_root, myproject,
- filename='meta.zcml', options=options``). If the filename is
- absolute, the ``package`` argument is ignored.
+ package's filesystem directory.
+
+ If you for some reason need or want to load a different application
+ registry filename for your application, you can pass an optional
+ ``filename=`` paramter to make_app (e.g. ``make_app(get_root,
+ myproject, filename='meta.zcml', options=options``). If the
+ filename is absolute, the ``package`` argument is ignored.
#. The ``make_app`` function does its work. It finds and parses the
ZCML represented by the application registry file. If it fails to
@@ -140,10 +141,10 @@ press ``return`` after running ``paster serve MyProject.ini``.
#. A ``WSGIApplicationCreatedEvent`` event is emitted (see
:ref:`events_chapter` for more informations about events).
-#. Assuming there were no errors, our ``myproject`` ``app`` function
- returns the router instance created by ``make_app`` back to
- PasteDeploy. As far as PasteDeploy is concerned, it is "just
- another WSGI application".
+#. Assuming there were no errors, the ``app`` function in
+ ``myproject`` returns the router instance created by ``make_app``
+ back to PasteDeploy. As far as PasteDeploy is concerned, it is
+ "just another WSGI application".
#. PasteDeploy starts the WSGI *server* defined within the
``[server:main]`` section. In our case, this is the ``Paste#http``
diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst
index c3a49da68..316bd3016 100644
--- a/docs/narr/templates.rst
+++ b/docs/narr/templates.rst
@@ -1,11 +1,11 @@
Templates
=========
-A :term:`template` is a usually file on disk which can be used to
-render data provided by a :term:`view`, surrounded by more static
-information. :mod:`repoze.bfg` offers a number of ways to perform
-templating tasks "out of the box", and provides alternative templating
-language support via add-on "bindings" packages.
+A :term:`template` is a file on disk which can be used to render
+dynamic data provided by a :term:`view`, usually surrounded by
+information that is static. :mod:`repoze.bfg` offers a number of ways
+to perform templating tasks "out of the box", and provides alternative
+templating language support via add-on "bindings" packages.
Templating With :term:`Chameleon` ZPT Page Templates
----------------------------------------------------
@@ -16,8 +16,8 @@ language. However, :mod:`repoze.bfg` uses a different implementation
of the :term:`ZPT` specification than Zope does: the :term:`Chameleon`
:term:`chameleon.zpt` templating engine. This templating engine
complies largely with the `Zope Page Template
-<http://wiki.zope.org/ZPT/FrontPage>`_ template specification and is
-significantly faster.
+<http://wiki.zope.org/ZPT/FrontPage>`_ template specification, however
+it is significantly faster.
.. note:: The language definition documentation for Chameleon
ZPT-style templates is available from `the Chameleon website
@@ -25,17 +25,6 @@ significantly faster.
<http://chameleon.repoze.org/docs/zpt/>`_ for the Chameleon ZPT
language specification.
-.. 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. See
- :ref:`available_template_system_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. See
- :ref:`available_template_system_bindings`.
-
Given that there is a :term:`chameleon.zpt` template named ``foo.pt``
in a directory in your application named ``templates``, you can render
the template from a view like so:
@@ -55,11 +44,12 @@ Relative to the directory in which the ``views.py`` file which names
it lives, which is usually the :mod:`repoze.bfg` application's
:term:`package` directory.
-A path passed to ``render_template_to_response`` can also be absolute
-(starting with a slash on UNIX or a drive letter prefix on Windows).
-It can also be a "specification" in the form
-``another.dotted.package_name:relative/path`` if the resources lives in
-another package.
+Although a path is usually just a simple relative pathname, a path
+passed to ``render_template_to_response`` can be absolute, starting
+with a slash on UNIX or a drive letter prefix on Windows. The path
+can alternately be a :term:`resource` "specification" in the form
+``some.dotted.package_name:relative/path``, making it possible to
+address template resources which live in another package.
``render_template_to_response`` always returns a Response object which
has a *status code* of ``200 OK`` and a *content-type* of
@@ -248,8 +238,8 @@ environment so that a change to a template will be automatically
detected, and the template will be reloaded on the next rendering.
.. warning:: auto-template-reload behavior is not recommended for
- production sites as it slows rendering; it's usually only
- desirable during development.
+ production sites as it slows rendering slightly; it's
+ usually only desirable during development.
In order to turn on automatic reloading of templates, you can use an
environment variable setting or a configuration file setting.
@@ -268,6 +258,13 @@ application's configuration section, e.g.::
use = egg:MyProject#app
reload_templates = true
+:term:`Chameleon` Template Internationalization
+-----------------------------------------------
+
+See `the internationalization chapter
+<http://chameleon.repoze.org/docs/zpt/narr/i18n.html>`_ of the
+Chameleon documentation for information about supporting
+internationalized units of text within Chameleon templates.
Templating with other Templating Languages
------------------------------------------
@@ -301,7 +298,9 @@ installed, here's an example of using Mako from within a
Note that if you use third-party templating languages without
cooperating BFG bindings, the auto-template-reload strategy explained
-in :ref:`reload_templates_section` will not be available.
+in :ref:`reload_templates_section` will not be available, nor will the
+template resource overriding capability explained in
+:ref:`overriding_resources_section` be available.
.. _available_template_system_bindings:
diff --git a/docs/narr/traversal.rst b/docs/narr/traversal.rst
index cfc484cf0..8e21150c1 100644
--- a/docs/narr/traversal.rst
+++ b/docs/narr/traversal.rst
@@ -3,12 +3,13 @@
Traversal
=========
-When :term:`traversal` is used, the :mod:`repoze.bfg` *Router* parses
-the URL associated with the request and splits the URL into path
-segments. Based on these path segments, :mod:`repoze.bfg` traverses a
-*model graph* in order to find a :term:`context`. It then attempts to
-find a :term:`view` based on the *type* of the context (specified by
-its Python class type or any :term:`interface` attached to it). If
+When :term:`traversal` is used within a :mod:`repoze.bfg` application,
+the :mod:`repoze.bfg` *Router* parses the URL associated with the
+request. It splits the URL into individual path segments. Based on
+these path segments, :mod:`repoze.bfg` traverses a *model graph* in
+order to find a :term:`context`. It then attempts to find a
+:term:`view` based on the *type* of the context (specified by its
+Python class type or any :term:`interface` attached to it). If
:mod:`repoze.bfg` finds a :term:`view` for the context, it calls it
and returns a response to the user.
@@ -81,8 +82,8 @@ application, the system uses this algorithm to determine which Python
code to execute:
#. The request for the page is presented to the :mod:`repoze.bfg`
- "router" in terms of a standard :term:`WSGI` request, which is
- represented by a WSGI environment and a ``start_response``
+ :term:`router` in terms of a standard :term:`WSGI` request, which
+ is represented by a WSGI environment and a ``start_response``
callable.
#. The router creates a :term:`WebOb` request object based on the
@@ -145,15 +146,16 @@ code to execute:
request, an :term:`authorization policy` is consulted to see if
the "current user" (al determined by the the authentication
policy) can perform the action. If he can, processing continues.
- If he cannot, an ``HTTPUnauthorized`` error is raised.
+ If he cannot, the ``forbidden`` view is called (see
+ :ref:`changing_the_forbidden_view`).
#. 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` :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 and returned.
+ back upstream. If a view is not found, the ``notfound`` view is
+ called (see :ref:`changing_the_notfound_view`).
In either case, the result is returned upstream via the :term:`WSGI`
protocol.
@@ -167,10 +169,10 @@ It's useful to be able to debug ``NotFound`` errors when they occur
unexpectedly due to an application registry misconfiguration. To
debug these errors, use the ``BFG_DEBUG_NOTFOUND`` environment
variable or the ``debug_notfound`` configuration file setting.
-Details of why a view was not found will be printed to stderr, and the
-browser representation of the error will include the same information.
-See :ref:`environment_chapter` for more information about how and
-where to set these values.
+Details of why a view was not found will be printed to ``stderr``, and
+the browser representation of the error will include the same
+information. See :ref:`environment_chapter` for more information
+about how and where to set these values.
A Traversal Example
-------------------
@@ -189,27 +191,29 @@ traversing the follwing graph::
Here's what happens:
-- bfg traverses the root, and attempts to find foo, which it finds.
+- :mod:`repoze.bfg` traverses the root, and attempts to find foo,
+ which it finds.
-- bfg traverses foo, and attempts to find bar, which it finds.
+- :mod:`repoze.bfg` traverses foo, and attempts to find bar, which it
+ finds.
-- bfg traverses bar, and attempts to find baz, which it does not
- find ('bar' raises a ``KeyError`` when asked for baz).
+- :mod:`repoze.bfg` traverses bar, and attempts to find baz, which it
+ does not find ('bar' raises a ``KeyError`` when asked for baz).
The fact that it does not find "baz" at this point does not signify an
error condition. It signifies that:
-- the "context" is bar (the context is the last item found during
- traversal).
+- the :term:`context` is bar (the context is the last item found
+ during traversal).
-- the "view name" is ``baz``
+- the :term:`view name` is ``baz``
-- the "subpath" is ``('biz', 'buz.txt')``
+- the :term:`subpath` is ``('biz', 'buz.txt')``
-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``).
+Because it's the "context", :mod:`repoze.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
:term:`application registry` (configured separately, via
@@ -218,8 +222,8 @@ Using the "view name" ("baz") and the type, it asks the
- Please find me a :term:`view` 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 the result
+of the ``notfound`` view. The request ends. Everyone is sad.
But! For this graph::
@@ -235,28 +239,32 @@ But! For this graph::
The user asks for ``http://example.com/foo/bar/baz/biz/buz.txt``
-- bfg traverses foo, and attempts to find bar, which it finds.
+- :mod:`repoze.bfg` traverses foo, and attempts to find bar, which it
+ finds.
-- bfg traverses bar, and attempts to find baz, which it finds.
+- :mod:`repoze.bfg` traverses bar, and attempts to find baz, which it
+ finds.
-- bfg traverses baz, and attempts to find biz, which it finds.
+- :mod:`repoze.bfg` traverses baz, and attempts to find biz, which it
+ finds.
-- bfg traverses biz, and attemtps to find "buz.txt" which it does
- not find.
+- :mod:`repoze.bfg` traverses biz, and attemtps to find "buz.txt"
+ which it does not find.
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).
+- the :term:`context` is biz (the context is the last item found
+ during traversal).
-- the "view name" is "buz.txt"
+- the :term:`view name` is "buz.txt"
-- the "subpath" is an empty sequence ( ``()`` ).
+- the :term:`subpath` is an empty sequence ( ``()`` ).
-Because it's the "context", bfg examimes "biz" to find out what "type"
-it is. Let's say it finds that the context an ``IBiz`` type (because
-"biz" happens to have an attribute attached to it that happens
-indicates it's an ``IBiz``).
+Because it's the "context", :mod:`repoze.bfg` examimes "biz" to find
+out what "type" it is. Let's say it finds that the context an ``IBiz``
+type (because "biz" happens to have an attribute attached to it that
+happens indicates it's an ``IBiz``).
Using the "view name" ("buz.txt") and the type, it asks the
:term:`application registry` this question:
@@ -272,9 +280,9 @@ It is passed the "biz" object as the "context" and the current
There are two special cases:
-- During traversal you will often end up with a "view name" that is
- the empty string. This indicates that :mod:`repoze.bfg` should look
- up the *default view*. The default view is a view that is
+- During traversal you will often end up with a :term:`view name` that
+ is the empty string. This indicates that :mod:`repoze.bfg` should
+ look up the *default view*. The default view is a view that is
registered with no name or a view which is registered with a name
that equals the empty string.
@@ -326,10 +334,13 @@ used to traverse to the virtual root object. See
Unicode and Traversal
---------------------
-The traversal machinery by default attempts to decode each path
-element in ``PATH_INFO`` from its natural byte string (``str`` type)
-representation into Unicode using the UTF-8 encoding before passing it
-to the ``__getitem__`` of a model object. If any path segment in
-``PATH_INFO`` is not decodeable using the UTF-8 decoding, a TypeError
-is raised.
+The traversal machinery by default attempts to first URL-unquote and
+then Unicode-decode each path element in ``PATH_INFO`` from its
+natural byte string (``str`` type) representation. URL unquoting is
+performed using the Python stdlib ``urllib.unquote`` function.
+Conversion from a URL-decoded string into Unicode is attempted using
+the UTF-8 encoding. If any URL-unquoted path segment in ``PATH_INFO``
+is not decodeable using the UTF-8 decoding, a TypeError is raised. A
+segment will be fully URL-unquoted and UTF8-decoded before it is
+passed it to the ``__getitem__`` of any model object during traversal.
diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst
index ccfbdff58..90ddd6672 100644
--- a/docs/narr/urldispatch.rst
+++ b/docs/narr/urldispatch.rst
@@ -195,8 +195,14 @@ Will generate the following matchdict::
{'traverse':(u'La Pe\xf1a', u'a', u'b', u'c')}
+``<route>`` Statement Examples
+------------------------------
+
+Let's check out some examples of how ``<route>`` statements might be
+commonly declared.
+
Example 1
----------
+~~~~~~~~~
The simplest route delcaration:
@@ -231,7 +237,7 @@ specified in the ``route`` declaration. It is a mapping object, a lot
like a dictionary.
Example 2
----------
+~~~~~~~~~
Below is an example of some more complicated route statements you
might add to your ``configure.zcml``:
@@ -273,7 +279,7 @@ view available at the dotted Python pathname
``mypackage.views.idea_view``.
Example 3
----------
+~~~~~~~~~
The context object passed to a view found as the result of URL
dispatch will by default be an instance of the object returned by the
@@ -322,7 +328,7 @@ during ``make_app`. If the "fallback" root factory is None, a
not used then.
Example 4
----------
+~~~~~~~~~
An example of configuring a ``view`` declaration in ``configure.zcml``
that maps a context found via URL dispatch to a view function is as
@@ -392,6 +398,17 @@ declaration:
view=".views.root_view"
/>
+Or provide the literal string ``/`` as the path:
+
+.. code-block:: xml
+ :linenos:
+
+ <route
+ path="/"
+ name="root"
+ view=".views.root_view"
+ />
+
Generating Route URLs
---------------------
diff --git a/docs/narr/urlmapping.rst b/docs/narr/urlmapping.rst
index 269061e40..1c9cde888 100644
--- a/docs/narr/urlmapping.rst
+++ b/docs/narr/urlmapping.rst
@@ -4,12 +4,13 @@ Mapping URLs to Code
====================
Many popular web frameworks today use :term:`URL dispatch` to
-associate a particular URL with a bit of code (known somewhat
-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
+associate a particular URL with a bit of code. In these systems, the
+bit of code associated with a URL is known somewhat ambiguously as a
+"controller" or :term:`view` depending upon the particular vocabulary
+religion to which you subscribe. Such 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
:term:`Routes` URL mapping system.
@@ -62,12 +63,13 @@ 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 :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``.
+Graph :term:`traversal` works well if you need to divine meaning from
+of these types of "ambiguous" URLs and from URLs that represent
+arbitrary-depth hierarchies. When traversal is used, each URL segment
+represents a single traversal step through an edge of a 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``.
If you're willing to treat your application models as a graph that can
be traversed, it also becomes easy to provide "row-level security" (in
diff --git a/docs/narr/views.rst b/docs/narr/views.rst
index d68f5cd3d..4435bbceb 100644
--- a/docs/narr/views.rst
+++ b/docs/narr/views.rst
@@ -4,9 +4,10 @@ Views
=====
A :term:`view` is a callable which is invoked when a request enters
-your application. :mod:`repoze.bfg's` primary job is to find and call
-a view when a :term:`request` reaches it. The view's return value
-must implement the :term:`WebOb` ``Response`` object interface.
+your application. The primary job of any :mod:`repoze.bfg`
+application is is to find and call a :term:`view` when a
+:term:`request` reaches it. The value returned by a :term:`view` must
+implement the :term:`WebOb` ``Response`` object interface.
.. _function_as_view:
@@ -267,7 +268,8 @@ route_name
referred to by ``route_name`` usually has a ``*traverse`` token in
the value of its ``path`` attribute, representing a part of the path
that will be used by traversal against the result of the route's
- :term:`root factory`.
+ :term:`root factory`. See :ref:`hybrid_chapter` for more
+ information on using this advanced feature.
.. _mapping_views_to_urls_using_a_decorator_section:
@@ -295,12 +297,12 @@ decorator to do this work.
.. warning:: using this feature tends to slows down application
startup slightly, as more work is performed at application startup
- to scan for view declarations. Also, if you use decorators, it
- means that other people will not be able to override your view
- declarations externally using ZCML: this is a common requirement if
- you're developing an exensible application (e.g. a framework). See
- :ref:`extending_chapter` for more information about building
- extensible applications.
+ to scan for view declarations. Additionally, if you use
+ decorators, it means that other people will not be able to override
+ your view declarations externally using ZCML: this is a common
+ requirement if you're developing an exensible application (e.g. a
+ framework). See :ref:`extending_chapter` for more information
+ about building extensible applications.
The ``bfg_view`` Decorator
~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -591,8 +593,9 @@ specifying a permission in a ``view`` declaration:
When an authentication policy is enabled, this view will be protected
with the ``add`` permission. The view will *not be called* if the
user does not possess the ``add`` permission relative to the current
-:term:`context` and an authorization policy is enabled. Instead an
-HTTP ``Unauthorized`` status will be returned to the client.
+:term:`context` and an authorization policy is enabled. Instead the
+``forbidden`` view result will be returned to the client (see
+:ref:`changing_the_forbidden_view`).
.. note::
@@ -621,8 +624,8 @@ slightly different response.
return HTTPFound(location='http://example.com')
All exception types from the :mod:`webob.exc` module implement the
-``IResponse`` interface; any can be returned as the response from a
-view. See :term:`WebOb` for the documentation for this module; it
+Webob ``Response`` interface; any can be returned as the response from
+a view. See :term:`WebOb` for the documentation for this module; it
includes other response types for Unauthorized, etc.
.. _static_resources_section:
@@ -686,12 +689,6 @@ these will be resolved by the static view as you would expect.
``/static/foo.js``. See :ref:`traversal_chapter` for information
about "goggles" (``@@``).
-.. note:: Under the hood, the ``repoze.bfg.view.static`` class employs
- the ``urlparser.StaticURLParser`` WSGI application to serve static
- files. See `the Paste documentation for urlparser
- <http://pythonpaste.org/modules/urlparser.html>`_ for more
- information about ``urlparser.StaticURLParser``.
-
Using Views to Handle Form Submissions (Unicode and Character Set Issues)
-------------------------------------------------------------------------