diff options
| author | Chris McDonough <chrism@plope.com> | 2011-08-10 20:20:05 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2011-08-10 20:20:05 -0400 |
| commit | 995466c6bc0da04f50d2db83af653362a0dadd6f (patch) | |
| tree | e5e57108a3d751d9e02cbf06ad5eca8902f4a100 /docs | |
| parent | 9a8ba2f09fe3791febbfec2ac383c091aacfbf5b (diff) | |
| parent | 3e3fcdf1376218a4fa6dcffec4f27a41c63d1675 (diff) | |
| download | pyramid-995466c6bc0da04f50d2db83af653362a0dadd6f.tar.gz pyramid-995466c6bc0da04f50d2db83af653362a0dadd6f.tar.bz2 pyramid-995466c6bc0da04f50d2db83af653362a0dadd6f.zip | |
fix merge conflicts
Diffstat (limited to 'docs')
110 files changed, 2658 insertions, 1423 deletions
diff --git a/docs/api.rst b/docs/api.rst index be7942502..6ff6e9fb1 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -28,9 +28,11 @@ documentation is organized alphabetically by module name. api/security api/session api/settings + api/static api/testing api/threadlocal api/traversal + api/tweens api/url api/view api/wsgi diff --git a/docs/api/config.rst b/docs/api/config.rst index 71ef4a746..30c541905 100644 --- a/docs/api/config.rst +++ b/docs/api/config.rst @@ -44,7 +44,7 @@ .. automethod:: add_route - .. automethod:: add_static_view(name, path, cache_max_age=3600, permission='__no_permission_required__') + .. automethod:: add_static_view(name, path, cache_max_age=3600, permission=NO_PERMISSION_REQUIRED) .. automethod:: add_settings @@ -78,6 +78,8 @@ .. automethod:: set_view_mapper + .. automethod:: add_tween + .. automethod:: testing_securitypolicy .. automethod:: testing_resources @@ -86,3 +88,15 @@ .. automethod:: testing_add_renderer + .. attribute:: global_registries + + The set of registries that have been created for :app:`Pyramid` + applications, one per each call to + :meth:`pyramid.config.Configurator.make_wsgi_app` in the current + process. The object itself supports iteration and has a ``last`` + property containing the last registry loaded. + + The registries contained in this object are stored as weakrefs, + thus they will only exist for the lifetime of the actual + applications for which they are being used. + diff --git a/docs/api/interfaces.rst b/docs/api/interfaces.rst index 51a1963b5..9ab9eefc3 100644 --- a/docs/api/interfaces.rst +++ b/docs/api/interfaces.rst @@ -9,14 +9,19 @@ Event-Related Interfaces ++++++++++++++++++++++++ .. autointerface:: IApplicationCreated + :members: .. autointerface:: INewRequest + :members: .. autointerface:: IContextFound + :members: .. autointerface:: INewResponse + :members: .. autointerface:: IBeforeRender + :members: Other Interfaces ++++++++++++++++ diff --git a/docs/api/paster.rst b/docs/api/paster.rst index 9ecfa3d9c..2a32e07e9 100644 --- a/docs/api/paster.rst +++ b/docs/api/paster.rst @@ -3,11 +3,15 @@ :mod:`pyramid.paster` --------------------------- -.. module:: pyramid.paster +.. automodule:: pyramid.paster -.. function:: get_app(config_file, name) + .. function:: get_app(config_uri, name=None) - Return the WSGI application named ``name`` in the PasteDeploy - config file ``config_file``. + Return the WSGI application named ``name`` in the PasteDeploy + config file specified by ``config_uri``. - + If the ``name`` is None, this will attempt to parse the name from + the ``config_uri`` string expecting the format ``inifile#name``. + If no name is found, the name will default to "main". + + .. autofunction:: bootstrap diff --git a/docs/api/renderers.rst b/docs/api/renderers.rst index c13694219..15670c46e 100644 --- a/docs/api/renderers.rst +++ b/docs/api/renderers.rst @@ -13,3 +13,12 @@ .. autoclass:: JSONP +.. attribute:: null_renderer + + An object that can be used in advanced integration cases as input to the + view configuration ``renderer=`` argument. When the null renderer is used + as a view renderer argument, Pyramid avoids converting the view callable + result into a Response object. This is useful if you want to reuse the + view configuration and lookup machinery outside the context of its use by + the Pyramid router (e.g. the package named ``pyramid_rpc`` does this). + diff --git a/docs/api/request.rst b/docs/api/request.rst index 5dfb2ae9a..2ab3977d5 100644 --- a/docs/api/request.rst +++ b/docs/api/request.rst @@ -85,6 +85,17 @@ of ``request.exception`` will be ``None`` within response and finished callbacks. + .. attribute:: exc_info + + If an exception was raised by a :term:`root factory` or a :term:`view + callable`, or at various other points where :app:`Pyramid` executes + user-defined code during the processing of a request, result of + ``sys.exc_info()`` will be available as the ``exc_info`` attribute of + the request within a :term:`exception view`, a :term:`response callback` + or a :term:`finished callback`. If no exception occurred, the value of + ``request.exc_info`` will be ``None`` within response and finished + callbacks. + .. attribute:: response This attribute is actually a "reified" property which returns an @@ -180,12 +191,12 @@ object (exposed to view code as ``request.response``) to influence rendered response behavior. - .. attribute:: json + .. attribute:: json_body - If the request's ``content_type`` is ``application/json``, this - attribute will contain the JSON-decoded variant of the request body. - If the request's ``content_type`` is not ``application/json``, this - attribute will be ``None``. + This property will return the JSON-decoded variant of the request + body. If the request body is not well-formed JSON, or there is no + body associated with this request, this property will raise an + exception. See also :ref:`request_json_body`. .. note:: diff --git a/docs/api/response.rst b/docs/api/response.rst index e67b15568..8020b629a 100644 --- a/docs/api/response.rst +++ b/docs/api/response.rst @@ -9,3 +9,8 @@ :members: :inherited-members: +Functions +~~~~~~~~~ + +.. autofunction:: response_adapter + diff --git a/docs/api/scripting.rst b/docs/api/scripting.rst index 9d5bc2e58..51bd3c7a0 100644 --- a/docs/api/scripting.rst +++ b/docs/api/scripting.rst @@ -7,3 +7,5 @@ .. autofunction:: get_root + .. autofunction:: prepare + diff --git a/docs/api/security.rst b/docs/api/security.rst index de249355d..8cd9e5dae 100644 --- a/docs/api/security.rst +++ b/docs/api/security.rst @@ -57,6 +57,8 @@ Constants last ACE in an ACL in systems that use an "inheriting" security policy, representing the concept "don't inherit any other ACEs". +.. attribute:: NO_PERMISSION_REQUIRED + Return Values ------------- diff --git a/docs/api/static.rst b/docs/api/static.rst new file mode 100644 index 000000000..c28473584 --- /dev/null +++ b/docs/api/static.rst @@ -0,0 +1,11 @@ +.. _static_module: + +:mod:`pyramid.static` +--------------------- + +.. automodule:: pyramid.static + + .. autoclass:: static_view + :members: + :inherited-members: + diff --git a/docs/api/tweens.rst b/docs/api/tweens.rst new file mode 100644 index 000000000..ddacd2cde --- /dev/null +++ b/docs/api/tweens.rst @@ -0,0 +1,25 @@ +.. _tweens_module: + +:mod:`pyramid.tweens` +--------------------- + +.. automodule:: pyramid.tweens + + .. autofunction:: excview_tween_factory + + .. attribute:: MAIN + + Constant representing the main Pyramid handling function, for use in + ``under`` and ``over`` arguments to + :meth:`pyramid.config.Configurator.add_tween`. + + .. attribute:: INGRESS + + Constant representing the request ingress, for use in ``under`` and + ``over`` arguments to :meth:`pyramid.config.Configurator.add_tween`. + + .. attribute:: EXCVIEW + + Constant representing the exception view tween, for use in ``under`` + and ``over`` arguments to + :meth:`pyramid.config.Configurator.add_tween`. diff --git a/docs/authorintro.rst b/docs/authorintro.rst index fb34f1d34..f1a9d1484 100644 --- a/docs/authorintro.rst +++ b/docs/authorintro.rst @@ -165,6 +165,7 @@ others' technology. single: Shipman, John single: Beelby, Chris single: Paez, Patricio + single: Merickel, Michael Thanks ====== @@ -179,8 +180,9 @@ software which it details would exist: Paul Everitt, Tres Seaver, Andrew Sawyers, Malthe Borch, Carlos de la Guardia, Chris Rossi, Shane Hathaway, Daniel Holth, Wichert Akkerman, Georg Brandl, Blaise Laflamme, Ben Bangert, Casey Duncan, Hugues Laflamme, Mike Orr, John Shipman, Chris Beelby, Patricio -Paez, Simon Oram, Nat Hardwick, Ian Bicking, Jim Fulton, Tom Moroz of the -Open Society Institute, and Todd Koym of Environmental Health Sciences. +Paez, Simon Oram, Nat Hardwick, Ian Bicking, Jim Fulton, Michael Merickel, +Tom Moroz of the Open Society Institute, and Todd Koym of Environmental +Health Sciences. Thanks to Guido van Rossum and Tim Peters for Python. diff --git a/docs/conf.py b/docs/conf.py index f09cd63f5..5eacb257f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -93,7 +93,7 @@ copyright = '%s, Agendaless Consulting' % datetime.datetime.now().year # other places throughout the built documents. # # The short X.Y version. -version = '1.1a4' +version = '1.1' # The full version, including alpha/beta/rc tags. release = version diff --git a/docs/copyright.rst b/docs/copyright.rst index 1c7aa5844..4369a7a3f 100644 --- a/docs/copyright.rst +++ b/docs/copyright.rst @@ -1,7 +1,7 @@ Copyright, Trademarks, and Attributions ======================================= -*The Pyramid Web Application Development Framework, Version 1.0* +*The Pyramid Web Application Development Framework, Version 1.1* by Chris McDonough @@ -55,7 +55,11 @@ Contributors: Ben Bangert, Blaise Laflamme, Rob Miller, Mike Orr, Carlos de la Guardia, Paul Everitt, Tres Seaver, John Shipman, Marius Gedminas, Chris Rossi, Joachim Krebs, Xavier Spriet, Reed O'Brien, William Chambers, Charlie - Choiniere, Jamaludin Ahmad, Graham Higgins, Patricio Paez. + Choiniere, Jamaludin Ahmad, Graham Higgins, Patricio Paez, Michael + Merickel, Eric Ongerth, Niall O'Higgins, Christoph Zwerschke, John + Anderson, Atsushi Odagiri, Kirk Strauser, JD Navarro, Joe Dallago, + Savoir-Faire Linux, Łukasz Fidosz, Christopher Lambacher, Claus Conrad, + Chris Beelby, and a number of people with only psuedonyms on GitHub. Cover Designer: Hugues Laflamme of `Kemeneur <http://www.kemeneur.com/>`_. diff --git a/docs/designdefense.rst b/docs/designdefense.rst index ce3c507c5..4975ae2a0 100644 --- a/docs/designdefense.rst +++ b/docs/designdefense.rst @@ -711,9 +711,9 @@ Pyramid Has Too Many Dependencies This is true. At the time of this writing, the total number of Python package distributions that :app:`Pyramid` depends upon transitively is 18 if -you use Python 2.6 or 2.7, or 16 if you use Python 2.4 or 2.5. This is a lot -more than zero package distribution dependencies: a metric which various -Python microframeworks and Django boast. +you use Python 2.6 or 2.7, or 16 if you use Python 2.5. This is a lot more +than zero package distribution dependencies: a metric which various Python +microframeworks and Django boast. The :mod:`zope.component` and :mod:`zope.configuration` packages on which :app:`Pyramid` depends have transitive dependencies on several other packages @@ -1125,10 +1125,11 @@ Self-described "microframeworks" exist: `Bottle <http://bottle.paws.de>`_ and <http://bobo.digicool.com/>`_ doesn't describe itself as a microframework, but its intended userbase is much the same. Many others exist. We've actually even (only as a teaching tool, not as any sort of official project) -`created one using BFG <http://bfg.repoze.org/videos#groundhog1>`_ (the -precursor to Pyramid). Microframeworks are small frameworks with one common -feature: each allows its users to create a fully functional application that -lives in a single Python file. +`created one using Pyramid <http://bfg.repoze.org/videos#groundhog1>`_ (the +videos use BFG, a precursor to Pyramid, but the resulting code is `available +for Pyramid too <http://github.com/Pylons/groundhog>`_). Microframeworks are +small frameworks with one common feature: each allows its users to create a +fully functional application that lives in a single Python file. Some developers and microframework authors point out that Pyramid's "hello world" single-file program is longer (by about five lines) than the @@ -1394,8 +1395,8 @@ predictability. a registry in another module. This has the effect that double-registrations will never be performed. -Routes (Usually) Need Relative Ordering -+++++++++++++++++++++++++++++++++++++++ +Routes Need Relative Ordering ++++++++++++++++++++++++++++++ Consider the following simple `Groundhog <https://github.com/Pylons/groundhog>`_ application: @@ -1470,20 +1471,52 @@ the view associated with the ``/:action`` routing pattern will be invoked: it matches first. A 404 error is raised. This is not what we wanted; it just happened due to the order in which we defined our view functions. -You may be willing to maintain an ordering of your view functions which -reifies your routing policy. Your application may be small enough where this -will never cause an issue. If it becomes large enough to matter, however, I -don't envy you. Maintaining that ordering as your application grows larger -will be difficult. At some point, you will also need to start controlling -*import* ordering as well as function definition ordering. When your -application grows beyond the size of a single file, and when decorators are -used to register views, the non-``__main__`` modules which contain -configuration decorators must be imported somehow for their configuration to -be executed. - -Does that make you a little uncomfortable? It should, because +This is because "Groundhog" routes are added to the routing map in import +order, and matched in the same order when a request comes in. Bottle, like +Groundhog, as of this writing, matches routes in the order in which they're +defined at Python execution time. Flask, on the other hand, does not order +route matching based on import order; it reorders the routes you add to your +application based on their "complexity". Other microframeworks have varying +strategies to do route ordering. + +Your application may be small enough where route ordering will never cause an +issue. If your application becomes large enough, however, being able to +specify or predict that ordering as your application grows larger will be +difficult. At some point, you will likely need to more explicitly start +controlling route ordering, especially in applications that require +extensibility. + +If your microframework orders route matching based on "complexity", you'll +need to understand what that "complexity" ordering is and attempt to inject a +"less complex" route to have it get matched before any "more complex" one to +ensure that it's tried first. + +If your microframework orders its route matching based on relative +import/execution of function decorator definitions, you will need to ensure +you execute all of these statements in the "right" order, and you'll need to +be cognizant of this import/execution ordering as you grow your application +or try to extend it. This is a difficult invariant to maintain for all but +the smallest applications. + +In either case, your application must import the non-``__main__`` modules +which contain configuration decorations somehow for their configuration to be +executed. Does that make you a little uncomfortable? It should, because :ref:`you_dont_own_modulescope`. +Pyramid uses neither decorator import time ordering nor does it attempt to +divine the relative "complexity" of one route to another in order to define a +route match ordering. In Pyramid, you have to maintain relative route +ordering imperatively via the chronology of multiple executions of the +:meth:`pyramid.config.Configurator.add_route` method. The order in which you +repeatedly call ``add_route`` becomes the order of route matching. + +If needing to maintain this imperative ordering truly bugs you, you can use +:term:`traversal` instead of route matching, which is a completely +declarative (and completely predictable) mechanism to map code to URLs. +While URL dispatch is easier to understand for small non-extensible +applications, traversal is a great fit for very large applications and +applications that need to be arbitrarily extensible. + "Stacked Object Proxies" Are Too Clever / Thread Locals Are A Nuisance ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -1728,7 +1761,7 @@ If you can understand this hello world program, you can use Pyramid: Pyramid has ~ 650 pages of documentation (printed), covering topics from the very basic to the most advanced. *Nothing* is left undocumented, quite literally. It also has an *awesome*, very helpful community. Visit the -#repoze and/or #pylons IRC channels on freenode.net and see. +#pyramid and/or #pylons IRC channels on freenode.net and see. Hate Zope +++++++++ diff --git a/docs/glossary.rst b/docs/glossary.rst index e45317dae..f0ad81ded 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -23,6 +23,11 @@ Glossary a subclass such as :class:`pyramid.httpexceptions.HTTPFound`. See :ref:`webob_chapter` for information about response objects. + response adapter + A callable which accepts an arbitrary object and "converts" it to a + :class:`pyramid.response.Response` object. See :ref:`using_iresponse` + for more information. + Repoze "Repoze" is essentially a "brand" of software developed by `Agendaless Consulting <http://agendaless.com>`_ and a set of contributors. The @@ -326,7 +331,7 @@ Glossary :term:`ZODB` database. WebOb - `WebOb <http://pythonpaste.org/webob/>`_ is a WSGI request/response + `WebOb <http://webob.org>`_ is a WSGI request/response library created by Ian Bicking. Paste @@ -506,6 +511,9 @@ Glossary `JavaScript Object Notation <http://www.json.org/>`_ is a data serialization format. + jQuery + A popular `Javascript library <http://jquery.org>`_. + renderer A serializer that can be referred to via :term:`view configuration` which converts a non-:term:`Response` return @@ -589,8 +597,9 @@ Glossary declaration` required by your application. declarative configuration - The configuration mode in which you use :term:`ZCML` to make a set of - :term:`configuration declaration` statements. See :term:`pyramid_zcml`. + The configuration mode in which you use the combination of + :term:`configuration decoration` and a :term:`scan` to configure your + Pyramid application. Not Found view An :term:`exception view` invoked by :app:`Pyramid` when the @@ -904,3 +913,20 @@ Glossary A :term:`response` that is generated as the result of a raised exception being caught by an :term:`exception view`. + PyPy + PyPy is an "alternative implementation of the Python + language":http://pypy.org/ + + tween + A bit of code that sits between the Pyramid router's main request + handling function and the upstream WSGI component that uses + :app:`Pyramid` as its 'app'. The word "tween" is a contraction of + "between". A tween may be used by Pyramid framework extensions, to + provide, for example, Pyramid-specific view timing support, bookkeeping + code that examines exceptions before they are returned to the upstream + WSGI application, or a variety of other features. Tweens behave a bit + like :mod:`WSGI` 'middleware' but they have the benefit of running in a + context in which they have access to the Pyramid :term:`application + registry` as well as the Pyramid rendering machinery. See + :ref:`registering_tweens`. + diff --git a/docs/index.rst b/docs/index.rst index a4743af9b..85e733dc3 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -24,8 +24,8 @@ Front Matter .. toctree:: :maxdepth: 1 - whatsnew-1.0 whatsnew-1.1 + whatsnew-1.0 Narrative documentation ======================= @@ -43,23 +43,24 @@ Narrative documentation in chapter form explaining how to use narr/project narr/startup narr/urldispatch - narr/muchadoabouttraversal - narr/traversal narr/views narr/renderers narr/templates narr/viewconfig - narr/resources narr/assets narr/webob narr/sessions - narr/security - narr/hybrid - narr/i18n - narr/vhosting narr/events narr/environment + narr/commandline + narr/i18n + narr/vhosting narr/testing + narr/resources + narr/muchadoabouttraversal + narr/traversal + narr/security + narr/hybrid narr/hooks narr/advconfig narr/extending diff --git a/docs/latexindex.rst b/docs/latexindex.rst index a4926bf30..bdd923dbc 100644 --- a/docs/latexindex.rst +++ b/docs/latexindex.rst @@ -32,23 +32,24 @@ Narrative Documentation narr/firstapp narr/project narr/urldispatch - narr/muchadoabouttraversal - narr/traversal narr/views narr/renderers narr/templates narr/viewconfig - narr/resources narr/assets narr/webob narr/sessions - narr/security - narr/hybrid - narr/i18n - narr/vhosting narr/events narr/environment + narr/commandline + narr/i18n + narr/vhosting narr/testing + narr/resources + narr/muchadoabouttraversal + narr/traversal + narr/security + narr/hybrid narr/hooks narr/advconfig narr/extending diff --git a/docs/make_book b/docs/make_book index dc8381845..22883ac4a 100755 --- a/docs/make_book +++ b/docs/make_book @@ -1,4 +1,4 @@ #!/bin/sh -make clean latex SPHINXBUILD=../bookenv/bin/sphinx-build BOOK=1 +make clean latex SPHINXBUILD=../env26/bin/sphinx-build BOOK=1 cd _build/latex && make all-pdf diff --git a/docs/make_epub b/docs/make_epub new file mode 100755 index 000000000..868749e3b --- /dev/null +++ b/docs/make_epub @@ -0,0 +1,2 @@ +#!/bin/sh +make clean epub SPHINXBUILD=../env26/bin/sphinx-build diff --git a/docs/make_pdf b/docs/make_pdf new file mode 100755 index 000000000..558feb857 --- /dev/null +++ b/docs/make_pdf @@ -0,0 +1,4 @@ +#!/bin/sh +make clean latex SPHINXBUILD=../env26/bin/sphinx-build +cd _build/latex && make all-pdf + diff --git a/docs/narr/MyProject/development.ini b/docs/narr/MyProject/development.ini index 29486ce56..1818e387b 100644 --- a/docs/narr/MyProject/development.ini +++ b/docs/narr/MyProject/development.ini @@ -1,15 +1,16 @@ [app:MyProject] use = egg:MyProject -reload_templates = true -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = true -default_locale_name = en + +pyramid.reload_templates = true +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = true +pyramid.default_locale_name = en +pyramid.include = pyramid_debugtoolbar [pipeline:main] pipeline = - egg:WebError#evalerror MyProject [server:main] diff --git a/docs/narr/MyProject/myproject/templates/mytemplate.pt b/docs/narr/MyProject/myproject/templates/mytemplate.pt index 632c34876..97f1e1aa3 100644 --- a/docs/narr/MyProject/myproject/templates/mytemplate.pt +++ b/docs/narr/MyProject/myproject/templates/mytemplate.pt @@ -46,7 +46,7 @@ <div id="left" class="align-right"> <h2>Search documentation</h2> <form method="get" - action="http://docs.pylonsproject.org/pyramid/dev/search.html"> + action="http://docs.pylonsproject.org/pyramid/current/search.html"> <input type="text" id="q" name="q" value="" /> <input type="submit" id="x" value="Go" /> </form> @@ -60,32 +60,32 @@ </a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation"> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#narrative-documentation"> Narrative Documentation </a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation"> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#api-documentation"> API Documentation </a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials"> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#tutorials"> Tutorials </a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history"> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#change-history"> Change History </a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications"> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#sample-applications"> Sample Applications </a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development"> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#support-and-development"> Support and Development </a> </li> diff --git a/docs/narr/MyProject/production.ini b/docs/narr/MyProject/production.ini index c1d0eee82..7a5674d23 100644 --- a/docs/narr/MyProject/production.ini +++ b/docs/narr/MyProject/production.ini @@ -1,11 +1,12 @@ [app:MyProject] use = egg:MyProject -reload_templates = false -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = false -default_locale_name = en + +pyramid.reload_templates = false +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = false +pyramid.default_locale_name = en [filter:weberror] use = egg:WebError#error_catcher diff --git a/docs/narr/MyProject/setup.py b/docs/narr/MyProject/setup.py index a64d65ba6..a0b6fab9e 100644 --- a/docs/narr/MyProject/setup.py +++ b/docs/narr/MyProject/setup.py @@ -6,7 +6,7 @@ here = os.path.abspath(os.path.dirname(__file__)) README = open(os.path.join(here, 'README.txt')).read() CHANGES = open(os.path.join(here, 'CHANGES.txt')).read() -requires = ['pyramid', 'WebError'] +requires = ['pyramid', 'pyramid_debugtoolbar', 'WebError'] setup(name='MyProject', version='0.0', diff --git a/docs/narr/advconfig.rst b/docs/narr/advconfig.rst index 3bd9c2a4e..8040a465f 100644 --- a/docs/narr/advconfig.rst +++ b/docs/narr/advconfig.rst @@ -14,7 +14,7 @@ you to ignore relative configuration statement ordering in some circumstances. .. index:: - single: imperative configuration + pair: configuration; conflict detection .. _conflict_detection: @@ -299,6 +299,9 @@ These are the methods of the configurator which provide conflict detection: provides conflict detection, because it's implemented in terms of the conflict-aware ``add_route`` and ``add_view`` methods. +.. index:: + pair: configuration; including from external sources + .. _including_configuration: Including Configuration from External Sources @@ -397,6 +400,10 @@ constraints: the routes they imply require relative ordering. Such ordering constraints are not absolved by two-phase configuration. Routes are still added in configuration execution order. +.. index:: + single: add_directive + pair: configurator; adding directives + .. _add_directive: Adding Methods to the Configurator via ``add_directive`` diff --git a/docs/narr/assets.rst b/docs/narr/assets.rst index 0d50b0106..e609a3eab 100644 --- a/docs/narr/assets.rst +++ b/docs/narr/assets.rst @@ -35,6 +35,9 @@ static assets. For example, there's a ``static`` directory which contains ``.css``, ``.js``, and ``.gif`` files. These asset files are delivered when a user visits an application URL. +.. index:: + single: asset specifications + .. _asset_specifications: Understanding Asset Specifications @@ -85,6 +88,7 @@ individual documentation. .. index:: single: add_static_view + pair: assets; serving .. _static_assets_section: @@ -186,6 +190,7 @@ discussed in more detail later in this chapter. .. index:: single: generating static asset urls single: static asset urls + pair: assets; generating urls .. _generating_static_asset_urls: @@ -299,7 +304,7 @@ URLs against assets made accessible by registering a custom static view. Root-Relative Custom Static View (URL Dispatch Only) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The :class:`pyramid.view.static` helper class generates a Pyramid view +The :class:`pyramid.static.static_view` helper class generates a Pyramid view callable. This view callable can serve static assets from a directory. An instance of this class is actually used by the :meth:`~pyramid.config.Configurator.add_static_view` configuration method, so @@ -310,26 +315,27 @@ its behavior is almost exactly the same once it's configured. exclusively. The root-relative route we'll be registering will always be matched before traversal takes place, subverting any views registered via ``add_view`` (at least those without a ``route_name``). A - :class:`~pyramid.view.static` static view cannot be made root-relative when - you use traversal. + :class:`~pyramid.static.static_view` static view cannot be made + root-relative when you use traversal unless it's registered as a + :term:`Not Found view`. To serve files within a directory located on your filesystem at ``/path/to/static/dir`` as the result of a "catchall" route hanging from the root that exists at the end of your routing table, create an instance of the -:class:`~pyramid.view.static` class inside a ``static.py`` file in your -application root as below. +:class:`~pyramid.static.static_view` class inside a ``static.py`` file in +your application root as below. .. ignore-next-block .. code-block:: python :linenos: - from pyramid.view import static - static_view = static('/path/to/static/dir') + from pyramid.static import static + static_view = static_view('/path/to/static/dir', use_subpath=True) .. note:: For better cross-system flexibility, use an :term:`asset - specification` as the argument to :class:`~pyramid.view.static` instead of - a physical absolute filesystem path, e.g. ``mypackage:static`` instead of - ``/path/to/mypackage/static``. + specification` as the argument to :class:`~pyramid.static.static_view` + instead of a physical absolute filesystem path, e.g. ``mypackage:static`` + instead of ``/path/to/mypackage/static``. Subsequently, you may wire the files that are served by this view up to be accessible as ``/<filename>`` using a configuration method in your @@ -345,8 +351,8 @@ application's startup code. config.add_view('myapp.static.static_view', route_name='catchall_static') The special name ``*subpath`` above is used by the -:class:`~pyramid.view.static` view callable to signify the path of the file -relative to the directory you're serving. +:class:`~pyramid.static.static_view` view callable to signify the path of the +file relative to the directory you're serving. Registering A View Callable to Serve a "Static" Asset ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -425,10 +431,10 @@ feature, a :term:`Configurator` API exists named - A directory containing multiple Chameleon templates. - Individual static files served up by an instance of the - ``pyramid.view.static`` helper class. + ``pyramid.static.static_view`` helper class. - A directory of static files served up by an instance of the - ``pyramid.view.static`` helper class. + ``pyramid.static.static_view`` helper class. - Any other asset (or set of assets) addressed by code that uses the setuptools :term:`pkg_resources` API. diff --git a/docs/narr/commandline.rst b/docs/narr/commandline.rst new file mode 100644 index 000000000..0f23c153c --- /dev/null +++ b/docs/narr/commandline.rst @@ -0,0 +1,560 @@ +.. _command_line_chapter: + +Command-Line Pyramid +==================== + +Your :app:`Pyramid` application can be controlled and inspected using a +variety of command-line utilities. These utilities are documented in this +chapter. + +.. index:: + pair: matching views; printing + single: paster pviews + +.. _displaying_matching_views: + +Displaying Matching Views for a Given URL +----------------------------------------- + +For a big application with several views, it can be hard to keep the view +configuration details in your head, even if you defined all the views +yourself. You can use the ``paster pviews`` command in a terminal window to +print a summary of matching routes and views for a given URL in your +application. The ``paster pviews`` command accepts two arguments. The first +argument to ``pviews`` is the path to your application's ``.ini`` file and +section name inside the ``.ini`` file which points to your application. This +should be of the format ``config_file#section_name``. The second argument is +the URL to test for matching views. The ``section_name`` may be omitted; if +it is, it's considered to be ``main``. + +Here is an example for a simple view configuration using :term:`traversal`: + +.. code-block:: text + :linenos: + + $ ../bin/paster pviews development.ini#tutorial /FrontPage + + URL = /FrontPage + + context: <tutorial.models.Page object at 0xa12536c> + view name: + + View: + ----- + tutorial.views.view_page + required permission = view + +The output always has the requested URL at the top and below that all the +views that matched with their view configuration details. In this example +only one view matches, so there is just a single *View* section. For each +matching view, the full code path to the associated view callable is shown, +along with any permissions and predicates that are part of that view +configuration. + +A more complex configuration might generate something like this: + +.. code-block:: text + :linenos: + + $ ../bin/paster pviews development.ini#shootout /about + + URL = /about + + context: <shootout.models.RootFactory object at 0xa56668c> + view name: about + + Route: + ------ + route name: about + route pattern: /about + route path: /about + subpath: + route predicates (request method = GET) + + View: + ----- + shootout.views.about_view + required permission = view + view predicates (request_param testing, header X/header) + + Route: + ------ + route name: about_post + route pattern: /about + route path: /about + subpath: + route predicates (request method = POST) + + View: + ----- + shootout.views.about_view_post + required permission = view + view predicates (request_param test) + + View: + ----- + shootout.views.about_view_post2 + required permission = view + view predicates (request_param test2) + +In this case, we are dealing with a :term:`URL dispatch` application. This +specific URL has two matching routes. The matching route information is +displayed first, followed by any views that are associated with that route. +As you can see from the second matching route output, a route can be +associated with more than one view. + +For a URL that doesn't match any views, ``paster pviews`` will simply print +out a *Not found* message. + + +.. index:: + single: interactive shell + single: IPython + single: paster pshell + single: pshell + +.. _interactive_shell: + +The Interactive Shell +--------------------- + +Once you've installed your program for development using ``setup.py +develop``, you can use an interactive Python shell to execute expressions in +a Python environment exactly like the one that will be used when your +application runs "for real". To do so, use the ``paster pshell`` command. + +The argument to ``pshell`` follows the format ``config_file#section_name`` +where ``config_file`` is the path to your application's ``.ini`` file and +``section_name`` is the ``app`` section name inside the ``.ini`` file which +points to your application. For example, if your application ``.ini`` file +might have a ``[app:MyProject]`` section that looks like so: + +.. code-block:: ini + :linenos: + + [app:MyProject] + use = egg:MyProject + pyramid.reload_templates = true + pyramid.debug_authorization = false + pyramid.debug_notfound = false + pyramid.debug_templates = true + pyramid.default_locale_name = en + +If so, you can use the following command to invoke a debug shell using the +name ``MyProject`` as a section name: + +.. code-block:: text + + chrism@thinko env26]$ bin/paster pshell starter/development.ini#MyProject + Python 2.6.5 (r265:79063, Apr 29 2010, 00:31:32) + [GCC 4.4.3] on linux2 + Type "help" for more information. + + Environment: + app The WSGI application. + registry Active Pyramid registry. + request Active request object. + root Root of the default resource tree. + root_factory Default root factory used to create `root`. + >>> root + <myproject.resources.MyResource object at 0x445270> + >>> registry + <Registry myproject> + >>> registry.settings['pyramid.debug_notfound'] + False + >>> from myproject.views import my_view + >>> from pyramid.request import Request + >>> r = Request.blank('/') + >>> my_view(r) + {'project': 'myproject'} + +The WSGI application that is loaded will be available in the shell as the +``app`` global. Also, if the application that is loaded is the :app:`Pyramid` +app with no surrounding middleware, the ``root`` object returned by the +default :term:`root factory`, ``registry``, and ``request`` will be +available. + +You can also simply rely on the ``main`` default section name by omitting any +hash after the filename: + +.. code-block:: text + + chrism@thinko env26]$ bin/paster pshell starter/development.ini + +Press ``Ctrl-D`` to exit the interactive shell (or ``Ctrl-Z`` on Windows). + +.. index:: + pair: pshell; extending + +.. _extending_pshell: + +Extending the Shell +~~~~~~~~~~~~~~~~~~~ + +It is sometimes convenient when using the interactive shell often to have +some variables significant to your application already loaded as globals when +you start the ``pshell``. To facilitate this, ``pshell`` will look for a +special ``[pshell]`` section in your INI file and expose the subsequent +key/value pairs to the shell. Each key is a variable name that will be +global within the pshell session; each value is a :term:`dotted Python name`. + +For example, you want to expose your model to the shell, along with the +database session so that you can mutate the model on an actual database. +Here, we'll assume your model is stored in the ``myapp.models`` package. + +.. code-block:: ini + :linenos: + + [pshell] + m = myapp.models + session = myapp.models.DBSession + t = transaction + +When this INI file is loaded, the extra variables ``m``, ``session`` and +``t`` will be available for use immediately. For example: + +.. code-block:: text + + chrism@thinko env26]$ bin/paster pshell starter/development.ini + Python 2.6.5 (r265:79063, Apr 29 2010, 00:31:32) + [GCC 4.4.3] on linux2 + Type "help" for more information. + + Environment: + app The WSGI application. + registry Active Pyramid registry. + request Active request object. + root Root of the default resource tree. + root_factory Default root factory used to create `root`. + + Custom Variables: + m myapp.models + session myapp.models.DBSession + t transaction + >>> + +.. index:: + single: IPython + +IPython +~~~~~~~ + +If you have `IPython <http://en.wikipedia.org/wiki/IPython>`_ installed in +the interpreter you use to invoke the ``paster`` command, the ``pshell`` +command will use an IPython interactive shell instead of a standard Python +interpreter shell. If you don't want this to happen, even if you have +IPython installed, you can pass the ``--disable-ipython`` flag to the +``pshell`` command to use a standard Python interpreter shell +unconditionally. + +.. code-block:: text + + [chrism@vitaminf shellenv]$ ../bin/paster pshell --disable-ipython \ + development.ini#MyProject + + +.. index:: + pair: routes; printing + single: paster proutes + single: proutes + +.. _displaying_application_routes: + +Displaying All Application Routes +--------------------------------- + +You can use the ``paster proutes`` command in a terminal window to print a +summary of routes related to your application. Much like the ``paster +pshell`` command (see :ref:`interactive_shell`), the ``paster proutes`` +command accepts one argument with the format ``config_file#section_name``. +The ``config_file`` is the path to your application's ``.ini`` file, and +``section_name`` is the ``app`` section name inside the ``.ini`` file which +points to your application. By default, the ``section_name`` is ``main`` and +can be omitted. + +For example: + +.. code-block:: text + :linenos: + + [chrism@thinko MyProject]$ ../bin/paster proutes development.ini#MyProject + Name Pattern View + ---- ------- ---- + home / <function my_view> + home2 / <function my_view> + another /another None + static/ static/*subpath <static_view object> + catchall /*subpath <function static_view> + +``paster proutes`` generates a table. The table has three columns: a Name +column, a Pattern column, and a View column. The items listed in the +Name column are route names, the items listed in the Pattern column are route +patterns, and the items listed in the View column are representations of the +view callable that will be invoked when a request matches the associated +route pattern. The view column may show ``None`` if no associated view +callable could be found. If no routes are configured within your +application, nothing will be printed to the console when ``paster proutes`` +is executed. + +.. index:: + pair: tweens; printing + single: paster ptweens + single: ptweens + +.. _displaying_tweens: + +Displaying "Tweens" +------------------- + +A :term:`tween` is a bit of code that sits between the main Pyramid +application request handler and the WSGI application which calls it. A user +can get a representation of both the implicit tween ordering (the ordering +specified by calls to :meth:`pyramid.config.Configurator.add_tween`) and the +explicit tween ordering (specified by the ``pyramid.tweens`` configuration +setting) orderings using the ``paster ptweens`` command. Handler factories +which are functions or classes will show up as a standard Python dotted name +in the ``paster ptweens`` output. Tween factories which are *instances* will +show their module and class name; the Python object id of the instance will +be appended. + +For example, here's the ``paster pwteens`` command run against a system +configured without any explicit tweens: + +.. code-block:: text + :linenos: + + [chrism@thinko pyramid]$ paster ptweens development.ini + "pyramid.tweens" config value NOT set (implicitly ordered tweens used) + + Implicit Tween Chain + + Position Name Alias + -------- ---- ----- + - - INGRESS + 0 pyramid_debugtoolbar.toolbar.toolbar_tween_factory pdbt + 1 pyramid.tweens.excview_tween_factory excview + - - MAIN + +Here's the ``paster pwteens`` command run against a system configured *with* +explicit tweens defined in its ``development.ini`` file: + +.. code-block:: text + :linenos: + + [chrism@thinko pyramid]$ paster ptweens development.ini + "pyramid.tweens" config value set (explicitly ordered tweens used) + + Explicit Tween Chain (used) + + Position Name + -------- ---- + - INGRESS + 0 starter.tween_factory2 + 1 starter.tween_factory1 + 2 pyramid.tweens.excview_tween_factory + - MAIN + + Implicit Tween Chain (not used) + + Position Name Alias + -------- ---- ----- + - - INGRESS + 0 pyramid_debugtoolbar.toolbar.toolbar_tween_factory pdbt + 1 pyramid.tweens.excview_tween_factory excview + - - MAIN + +Here's the application configuration section of the ``development.ini`` used +by the above ``paster ptweens`` command which reprorts that the explicit +tween chain is used: + +.. code-block:: text + :linenos: + + [app:starter] + use = egg:starter + reload_templates = true + debug_authorization = false + debug_notfound = false + debug_routematch = false + debug_templates = true + default_locale_name = en + pyramid.include = pyramid_debugtoolbar + pyramid.tweens = starter.tween_factory2 + starter.tween_factory1 + pyramid.tweens.excview_tween_factory + +See :ref:`registering_tweens` for more information about tweens. + +.. _writing_a_script: + +Writing a Script +---------------- + +All web applications are, at their hearts, systems which accept a request and +return a response. When a request is accepted by a :app:`Pyramid` +application, the system receives state from the request which is later relied +on by your application code. For example, one :term:`view callable` may assume +it's working against a request that has a ``request.matchdict`` of a +particular composition, while another assumes a different composition of the +matchdict. + +In the meantime, it's convenient to be able to write a Python script that can +work "in a Pyramid environment", for instance to update database tables used +by your :app:`Pyramid` application. But a "real" Pyramid environment doesn't +have a completely static state independent of a request; your application +(and Pyramid itself) is almost always reliant on being able to obtain +information from a request. When you run a Python script that simply imports +code from your application and tries to run it, there just is no request +data, because there isn't any real web request. Therefore some parts of your +application and some Pyramid APIs will not work. + +For this reason, :app:`Pyramid` makes it possible to run a script in an +environment much like the environment produced when a particular +:term:`request` reaches your :app:`Pyramid` application. This is achieved by +using the :func:`pyramid.paster.bootstrap` command in the body of your +script. + +.. note:: This feature is new as of :app:`Pyramid` 1.1. + +In the simplest case, :func:`pyramid.paster.bootstrap` can be used with a +single argument, which accepts the :term:`PasteDeploy` ``.ini`` file +representing Pyramid your application configuration as a single argument: + +.. code-block:: python + + from pyramid.paster import bootstrap + env = bootstrap('/path/to/my/development.ini') + print env['request'].route_url('home') + +:func:`pyramid.paster.bootstrap` returns a dictionary containing +framework-related information. This dictionary will always contain a +:term:`request` object as its ``request`` key. + +The following keys are available in the ``env`` dictionary returned by +:func:`pyramid.paster.bootstrap`: + +request + + A :class:`pyramid.request.Request` object implying the current request + state for your script. + +app + + The :term:`WSGI` application object generated by bootstrapping. + +root + + The :term:`resource` root of your :app:`Pyramid` application. This is an + object generated by the :term:`root factory` configured in your + application. + +registry + + The :term:`application registry` of your :app:`Pyramid` application. + +closer + + A parameterless callable that can be used to pop an internal + :app:`Pyramid` threadlocal stack (used by + :func:`pyramid.threadlocal.get_current_registry` and + :func:`pyramid.threadlocal.get_current_request`) when your scripting job + is finished. + +Let's assume that the ``/path/to/my/development.ini`` file used in the +example above looks like so: + +.. code-block:: ini + + [pipeline:main] + pipeline = egg:WebError#evalerror + another + + [app:another] + use = egg:MyProject + +The configuration loaded by the above bootstrap example will use the +configuration implied by the ``[pipeline:main]`` section of your +configuration file by default. Specifying ``/path/to/my/development.ini`` is +logically equivalent to specifying ``/path/to/my/development.ini#main``. In +this case, we'll be using a configuration that includes an ``app`` object +which is wrapped in the WebError ``evalerror`` middleware. + +You can also specify a particular *section* of the PasteDeploy ``.ini`` file +to load instead of ``main``: + +.. code-block:: python + + from pyramid.paster import bootstrap + env = bootstrap('/path/to/my/development.ini#another') + print env['request'].route_url('home') + +The above example specifies the ``another`` ``app``, ``pipeline``, or +``composite`` section of your PasteDeploy configuration file. The ``app`` +object present in the ``env`` dictionary returned by +:func:`pyramid.paster.bootstrap` will be a :app:`Pyramid` :term:`router`. + +Changing the Request +~~~~~~~~~~~~~~~~~~~~ + +By default, Pyramid will generate a request object in the ``env`` dictionary +for the URL ``http://localhost:80/``. This means that any URLs generated +by Pyramid during the execution of your script will be anchored here. This +is generally not what you want. + +So how do we make Pyramid generate the correct URLs? + +Assuming that you have a route configured in your application like so: + +.. code-block:: python + + config.add_route('verify', '/verify/{code}') + +You need to inform the Pyramid environment that the WSGI application is +handling requests from a certain base. For example, we want to mount our +application at `example.com/prefix` and the generated URLs should use HTTPS. +This can be done by mutating the request object: + +.. code-block:: python + + from pyramid.paster import bootstrap + env = bootstrap('/path/to/my/development.ini#another') + env['request'].host = 'example.com' + env['request'].scheme = 'https' + env['request'].script_name = '/prefix' + print env['request'].application_url + # will print 'https://example.com/prefix/another/url' + +Now you can readily use Pyramid's APIs for generating URLs: + +.. code-block:: python + + route_url('verify', env['request'], code='1337') + # will return 'https://example.com/prefix/verify/1337' + +Cleanup +~~~~~~~ + +When your scripting logic finishes, it's good manners (but not required) to +call the ``closer`` callback: + +.. code-block:: python + + from pyramid.paster import bootstrap + env = bootstrap('/path/to/my/development.ini') + + # .. do stuff ... + + env['closer']() + +Setting Up Logging +~~~~~~~~~~~~~~~~~~ + +By default, :func:`pyramid.paster.bootstrap` does not configure logging +parameters present in the configuration file. If you'd like to configure +logging based on ``[logger]`` and related sections in the configuration file, +use the following command: + +.. code-block:: python + + import logging + logging.fileConfig('/path/to/my/development.ini') diff --git a/docs/narr/configuration.rst b/docs/narr/configuration.rst index 6360dc574..597d48b09 100644 --- a/docs/narr/configuration.rst +++ b/docs/narr/configuration.rst @@ -6,22 +6,20 @@ Application Configuration ========================= -Each deployment of an application written using :app:`Pyramid` implies a -specific *configuration* of the framework itself. For example, an -application which serves up MP3 files for your listening enjoyment might plug -code into the framework that manages song files, while an application that -manages corporate data might plug in code that manages accounting -information. The way in which code is plugged in to :app:`Pyramid` for a -specific application is referred to as "configuration". - -Most people understand "configuration" as coarse settings that inform the -high-level operation of a specific application deployment. For instance, -it's easy to think of the values implied by a ``.ini`` file parsed at -application startup time as "configuration". :app:`Pyramid` extends this -pattern to application development, using the term "configuration" to express -standardized ways that code gets plugged into a deployment of the framework -itself. When you plug code into the :app:`Pyramid` framework, you are -"configuring" :app:`Pyramid` to create a particular application. +Most people already understand "configuration" as settings that influence the +operation of an application. For instance, it's easy to think of the values +in a ``.ini`` file parsed at application startup time as "configuration". +However, if you're reasonably open-minded, it's easy to think of *code* as +configuration too. Since Pyramid, like most other web application platforms, +is a *framework*, it calls into code that you write (as opposed to a +*library*, which is code that exists purely for you to call). The act of +plugging application code that you've written into :app:`Pyramid` is also +referred to within this documentation as "configuration"; you are configuring +:app:`Pyramid` to call the code that makes up your application. + +There are two ways to configure a :app:`Pyramid` application: +:term:`imperative configuration` and :term:`declarative configuration`. Both +are described below. .. index:: single: imperative configuration @@ -31,8 +29,9 @@ itself. When you plug code into the :app:`Pyramid` framework, you are Imperative Configuration ------------------------ -Here's one of the simplest :app:`Pyramid` applications, configured -imperatively: +"Imperative configuration" just means configuration done by Python +statements, one after the next. Here's one of the simplest :app:`Pyramid` +applications, configured imperatively: .. code-block:: python :linenos: @@ -64,19 +63,17 @@ including conditionals, can be employed in this mode of configuration. .. _decorations_and_code_scanning: -Configuration Decorations and Code Scanning -------------------------------------------- +Declarative Configuration +------------------------- -A different mode of configuration gives more *locality of reference* to a -:term:`configuration declaration`. It's sometimes painful to have all -configuration done in imperative code, because often the code for a single -application may live in many files. If the configuration is centralized in -one place, you'll need to have at least two files open at once to see the -"big picture": the file that represents the configuration, and the file that -contains the implementation objects referenced by the configuration. To -avoid this, :app:`Pyramid` allows you to insert :term:`configuration -decoration` statements very close to code that is referred to by the -declaration itself. For example: +It's sometimes painful to have all configuration done by imperative code, +because often the code for a single application may live in many files. If +the configuration is centralized in one place, you'll need to have at least +two files open at once to see the "big picture": the file that represents the +configuration, and the file that contains the implementation objects +referenced by the configuration. To avoid this, :app:`Pyramid` allows you to +insert :term:`configuration decoration` statements very close to code that is +referred to by the declaration itself. For example: .. code-block:: python :linenos: @@ -135,6 +132,9 @@ the scanner, a set of calls are made to a :term:`Configurator` on your behalf: these calls replace the need to add imperative configuration statements that don't live near the code being configured. +The combination of :term:`configuration decoration` and the invocation of a +:term:`scan` is collectively known as :term:`declarative configuration`. + In the example above, the scanner translates the arguments to :class:`~pyramid.view.view_config` into a call to the :meth:`pyramid.config.Configurator.add_view` method, effectively: @@ -145,13 +145,10 @@ In the example above, the scanner translates the arguments to config.add_view(hello) -Declarative Configuration -------------------------- - -A third mode of configuration can be employed when you create a -:app:`Pyramid` application named *declarative configuration*. This mode uses -an XML language known as :term:`ZCML` to represent configuration statements -rather than Python. ZCML is not built-in to Pyramid, but almost everything -that can be configured imperatively can also be configured via ZCML if you -install the :term:`pyramid_zcml` package. +Summary +------- +There are two ways to configure a :app:`Pyramid` application: declaratively +and imperatively. You can choose the mode you're most comfortable with; both +are completely equivalent. Examples in this documentation will use both +modes interchangeably. diff --git a/docs/narr/environment.rst b/docs/narr/environment.rst index a57b316e1..6465c2a1e 100644 --- a/docs/narr/environment.rst +++ b/docs/narr/environment.rst @@ -8,9 +8,12 @@ single: debug_all single: reload_all single: debug settings + single: debug_routematch + single: prevent_http_cache single: reload settings single: default_locale_name single: environment variables + single: Mako environment settings single: ini file settings single: PasteDeploy settings @@ -44,14 +47,14 @@ changes to templates take effect immediately during development. This flag is meaningful to Chameleon and Mako templates, as well as most third-party template rendering extensions. -+---------------------------------+-----------------------------+ -| Environment Variable Name | Config File Setting Name | -+=================================+=============================+ -| ``PYRAMID_RELOAD_TEMPLATES`` | ``reload_templates`` | -| | | -| | | -| | | -+---------------------------------+-----------------------------+ ++---------------------------------+--------------------------------+ +| Environment Variable Name | Config File Setting Name | ++=================================+================================+ +| ``PYRAMID_RELOAD_TEMPLATES`` | ``pyramid.reload_templates`` | +| | | +| | | +| | | ++---------------------------------+--------------------------------+ Reloading Assets ---------------- @@ -62,7 +65,7 @@ also :ref:`overriding_assets_section`. +---------------------------------+-----------------------------+ | Environment Variable Name | Config File Setting Name | +=================================+=============================+ -| ``PYRAMID_RELOAD_ASSETS`` | ``reload_assets`` | +| ``PYRAMID_RELOAD_ASSETS`` | ``pyramid.reload_assets`` | | | | | | | | | | @@ -70,7 +73,7 @@ also :ref:`overriding_assets_section`. .. note:: For backwards compatibility purposes, aliases can be used for configurating asset reloading: ``PYRAMID_RELOAD_RESOURCES`` (envvar) - and ``reload_resources`` (config file). + and ``pyramid.reload_resources`` (config file). Debugging Authorization ----------------------- @@ -78,14 +81,14 @@ Debugging Authorization Print view authorization failure and success information to stderr when this value is true. See also :ref:`debug_authorization_section`. -+---------------------------------+-----------------------------+ -| Environment Variable Name | Config File Setting Name | -+=================================+=============================+ -| ``PYRAMID_DEBUG_AUTHORIZATION`` | ``debug_authorization`` | -| | | -| | | -| | | -+---------------------------------+-----------------------------+ ++---------------------------------+-----------------------------------+ +| Environment Variable Name | Config File Setting Name | ++=================================+===================================+ +| ``PYRAMID_DEBUG_AUTHORIZATION`` | ``pyramid.debug_authorization`` | +| | | +| | | +| | | ++---------------------------------+-----------------------------------+ Debugging Not Found Errors -------------------------- @@ -93,14 +96,14 @@ Debugging Not Found Errors Print view-related ``NotFound`` debug messages to stderr when this value is true. See also :ref:`debug_notfound_section`. -+---------------------------------+-----------------------------+ -| Environment Variable Name | Config File Setting Name | -+=================================+=============================+ -| ``PYRAMID_DEBUG_NOTFOUND`` | ``debug_notfound`` | -| | | -| | | -| | | -+---------------------------------+-----------------------------+ ++---------------------------------+------------------------------+ +| Environment Variable Name | Config File Setting Name | ++=================================+==============================+ +| ``PYRAMID_DEBUG_NOTFOUND`` | ``pyramid.debug_notfound`` | +| | | +| | | +| | | ++---------------------------------+------------------------------+ Debugging Route Matching ------------------------ @@ -108,14 +111,33 @@ Debugging Route Matching Print debugging messages related to :term:`url dispatch` route matching when this value is true. See also :ref:`debug_routematch_section`. -+---------------------------------+-----------------------------+ -| Environment Variable Name | Config File Setting Name | -+=================================+=============================+ -| ``PYRAMID_DEBUG_ROUTEMATCH`` | ``debug_routematch`` | -| | | -| | | -| | | -+---------------------------------+-----------------------------+ ++---------------------------------+--------------------------------+ +| Environment Variable Name | Config File Setting Name | ++=================================+================================+ +| ``PYRAMID_DEBUG_ROUTEMATCH`` | ``pyramid.debug_routematch`` | +| | | +| | | +| | | ++---------------------------------+--------------------------------+ + +.. _preventing_http_caching: + +Preventing HTTP Caching +------------------------ + +Prevent the ``http_cache`` view configuration argument from having any effect +globally in this process when this value is true. No http caching-related +response headers will be set by the Pyramid ``http_cache`` view configuration +feature when this is true. See also :ref:`influencing_http_caching`. + ++---------------------------------+----------------------------------+ +| Environment Variable Name | Config File Setting Name | ++=================================+==================================+ +| ``PYRAMID_PREVENT_HTTP_CACHE`` | ``pyramid.prevent_http_cache`` | +| | | +| | | +| | | ++---------------------------------+----------------------------------+ Debugging All ------------- @@ -125,7 +147,7 @@ Turns on all ``debug*`` settings. +---------------------------------+-----------------------------+ | Environment Variable Name | Config File Setting Name | +=================================+=============================+ -| ``PYRAMID_DEBUG_ALL`` | ``debug_all`` | +| ``PYRAMID_DEBUG_ALL`` | ``pyramid.debug_all`` | | | | | | | | | | @@ -139,7 +161,7 @@ Turns on all ``reload*`` settings. +---------------------------------+-----------------------------+ | Environment Variable Name | Config File Setting Name | +=================================+=============================+ -| ``PYRAMID_RELOAD_ALL`` | ``reload_all`` | +| ``PYRAMID_RELOAD_ALL`` | ``pyramid.reload_all`` | | | | | | | | | | @@ -154,14 +176,14 @@ The value supplied here is used as the default locale name when a :term:`locale negotiator` is not registered. See also :ref:`localization_deployment_settings`. -+---------------------------------+-----------------------------+ -| Environment Variable Name | Config File Setting Name | -+=================================+=============================+ -| ``PYRAMID_DEFAULT_LOCALE_NAME`` | ``default_locale_name`` | -| | | -| | | -| | | -+---------------------------------+-----------------------------+ ++---------------------------------+-----------------------------------+ +| Environment Variable Name | Config File Setting Name | ++=================================+===================================+ +| ``PYRAMID_DEFAULT_LOCALE_NAME`` | ``pyramid.default_locale_name`` | +| | | +| | | +| | | ++---------------------------------+-----------------------------------+ .. _mako_template_renderer_settings: @@ -324,8 +346,8 @@ an example of such a section: [app:main] use = egg:MyProject#app - reload_templates = true - debug_authorization = true + pyramid.reload_templates = true + pyramid.debug_authorization = true You can also use environment variables to accomplish the same purpose for settings documented as such. For example, you might start your @@ -342,18 +364,18 @@ respective settings in the ``[app:main]`` section of your application's ``.ini`` file. If you want to turn all ``debug`` settings (every setting that starts -with ``debug_``). on in one fell swoop, you can use +with ``pyramid.debug_``). on in one fell swoop, you can use ``PYRAMID_DEBUG_ALL=1`` as an environment variable setting or you may use -``debug_all=true`` in the config file. Note that this does not affect -settings that do not start with ``debug_*`` such as -``reload_templates``. +``pyramid.debug_all=true`` in the config file. Note that this does not affect +settings that do not start with ``pyramid.debug_*`` such as +``pyramid.reload_templates``. -If you want to turn all ``reload`` settings (every setting that starts -with ``reload_``) on in one fell swoop, you can use +If you want to turn all ``pyramid.reload`` settings (every setting that starts +with ``pyramid.reload_``) on in one fell swoop, you can use ``PYRAMID_RELOAD_ALL=1`` as an environment variable setting or you may use -``reload_all=true`` in the config file. Note that this does not -affect settings that do not start with ``reload_*`` such as -``debug_notfound``. +``pyramid.reload_all=true`` in the config file. Note that this does not +affect settings that do not start with ``pyramid.reload_*`` such as +``pyramid.debug_notfound``. .. note:: Specifying configuration settings via environment variables is generally @@ -370,35 +392,38 @@ affect settings that do not start with ``reload_*`` such as Understanding the Distinction Between ``reload_templates`` and ``reload_assets`` -------------------------------------------------------------------------------- -The difference between ``reload_assets`` and ``reload_templates`` is a bit -subtle. Templates are themselves also treated by :app:`Pyramid` as asset -files (along with other static files), so the distinction can be confusing. -It's helpful to read :ref:`overriding_assets_section` for some context -about assets in general. +The difference between ``pyramid.reload_assets`` and +``pyramid.reload_templates`` is a bit subtle. Templates are themselves also +treated by :app:`Pyramid` as asset files (along with other static files), so the +distinction can be confusing. It's helpful to read +:ref:`overriding_assets_section` for some context about assets in general. -When ``reload_templates`` is true, :app:`Pyramid` takes advantage of the +When ``pyramid.reload_templates`` is true, :app:`Pyramid` takes advantage of the underlying templating systems' ability to check for file modifications to an -individual template file. When ``reload_templates`` is true but -``reload_assets`` is *not* true, the template filename returned by the +individual template file. When ``pyramid.reload_templates`` is true but +``pyramid.reload_assets`` is *not* true, the template filename returned by the ``pkg_resources`` package (used under the hood by asset resolution) is cached by :app:`Pyramid` on the first request. Subsequent requests for the same template file will return a cached template filename. The underlying templating system checks for modifications to this particular file for every -request. Setting ``reload_templates`` to ``True`` doesn't affect performance -dramatically (although it should still not be used in production because it -has some effect). +request. Setting ``pyramid.reload_templates`` to ``True`` doesn't affect +performance dramatically (although it should still not be used in production +because it has some effect). -However, when ``reload_assets`` is true, :app:`Pyramid` will not cache the -template filename, meaning you can see the effect of changing the content of -an overridden asset directory for templates without restarting the server +However, when ``pyramid.reload_assets`` is true, :app:`Pyramid` will not cache +the template filename, meaning you can see the effect of changing the content +of an overridden asset directory for templates without restarting the server after every change. Subsequent requests for the same template file may return different filenames based on the current state of overridden asset -directories. Setting ``reload_assets`` to ``True`` affects performance +directories. Setting ``pyramid.reload_assets`` to ``True`` affects performance *dramatically*, slowing things down by an order of magnitude for each template rendering. However, it's convenient to enable when moving files -around in overridden asset directories. ``reload_assets`` makes the system -*very slow* when templates are in use. Never set ``reload_assets`` to -``True`` on a production system. +around in overridden asset directories. ``pyramid.reload_assets`` makes the +system *very slow* when templates are in use. Never set +``pyramid.reload_assets`` to ``True`` on a production system. + +.. index:: + par: settings; adding custom .. _adding_a_custom_setting: diff --git a/docs/narr/firstapp.rst b/docs/narr/firstapp.rst index f5adad905..66632e123 100644 --- a/docs/narr/firstapp.rst +++ b/docs/narr/firstapp.rst @@ -1,3 +1,6 @@ +.. index:: + single: hello world program + .. _firstapp_chapter: Creating Your First :app:`Pyramid` Application @@ -12,8 +15,7 @@ more detail how it works. Hello World, Goodbye World -------------------------- -Here's one of the very simplest :app:`Pyramid` applications, configured -imperatively: +Here's one of the very simplest :app:`Pyramid` applications: .. code-block:: python :linenos: @@ -151,7 +153,7 @@ defined imports and function definitions, placed within the confines of an app = config.make_wsgi_app() serve(app, host='0.0.0.0') -Let's break this down this piece-by-piece. +Let's break this down piece-by-piece. Configurator Construction ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -180,7 +182,7 @@ The ``config = Configurator()`` line above creates an instance of the :class:`~pyramid.config.Configurator` class. The resulting ``config`` object represents an API which the script uses to configure this particular :app:`Pyramid` application. Methods called on the Configurator will cause -registrations to be made in a :term:`application registry` associated with +registrations to be made in an :term:`application registry` associated with the application. .. _adding_configuration: @@ -320,6 +322,3 @@ see :class:`~pyramid.config.Configurator` . For more information about :term:`view configuration`, see :ref:`view_config_chapter`. -An example of using *declarative* configuration (:term:`ZCML`) instead of -imperative configuration to create a similar "hello world" is available -within the documentation for :term:`pyramid_zcml`. diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index 94701c9f9..f7ee82821 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -61,8 +61,8 @@ Here's some sample code that implements a minimal NotFound view callable: caused the not found view to be called. The value of ``request.exception.message`` will be a value explaining why the not found error was raised. This message will be different when the - ``debug_notfound`` environment setting is true than it is when it is - false. + ``pyramid.debug_notfound`` environment setting is true than it is when it + is false. .. warning:: When a NotFound view callable accepts an argument list as described in :ref:`request_and_context_view_definitions`, the ``context`` @@ -128,8 +128,8 @@ Here's some sample code that implements a minimal forbidden view: ``request.exception.message`` will be a value explaining why the forbidden was raised and ``request.exception.result`` will be extended information about the forbidden exception. These messages will be different when the - ``debug_authorization`` environment setting is true than it is when it is - false. + ``pyramid.debug_authorization`` environment setting is true than it is when + it is false. .. index:: single: request factory @@ -218,7 +218,7 @@ Another (deprecated) mechanism which allows event subscribers more control when adding renderer global values exists in :ref:`adding_renderer_globals`. .. index:: - single: renderer globals + single: adding renderer globals .. _adding_renderer_globals: @@ -284,8 +284,8 @@ Using Response Callbacks Unlike many other web frameworks, :app:`Pyramid` does not eagerly create a global response object. Adding a :term:`response callback` allows an -application to register an action to be performed against a response object -once it is created, usually in order to mutate it. +application to register an action to be performed against whatever response +object is returned by a view, usually in order to mutate the response. The :meth:`pyramid.request.Request.add_response_callback` method is used to register a response callback. @@ -528,6 +528,7 @@ The default context URL generator is available for perusal as the class .. index:: single: IResponse + single: special view responses .. _using_iresponse: @@ -536,7 +537,8 @@ Changing How Pyramid Treats View Responses It is possible to control how Pyramid treats the result of calling a view callable on a per-type basis by using a hook involving -:meth:`pyramid.config.Configurator.add_response_adapter`. +:meth:`pyramid.config.Configurator.add_response_adapter` or the +:class:`~pyramid.response.response_adapter` decorator. .. note:: This feature is new as of Pyramid 1.1. @@ -600,6 +602,9 @@ to make sure the object implements every attribute and method outlined in :class:`pyramid.interfaces.IResponse` and you'll have to ensure that it's marked up with ``zope.interface.implements(IResponse)``: +.. code-block:: python + :linenos: + from pyramid.interfaces import IResponse from zope.interface import implements @@ -620,6 +625,29 @@ startup time, as by their nature, instances of this class (and instances of subclasses of the class) will natively provide IResponse. The adapter registered for ``webob.Response`` simply returns the response object. +Instead of using :meth:`pyramid.config.Configurator.add_response_adapter`, +you can use the :class:`pyramid.response.response_adapter` decorator: + +.. code-block:: python + :linenos: + + from pyramid.response import Response + from pyramid.response import response_adapter + + @response_adapter(str) + def string_response_adapter(s): + response = Response(s) + return response + +The above example, when scanned, has the same effect as: + +.. code-block:: python + + config.add_response_adapter(string_response_adapter, str) + +The :class:`~pyramid.response.response_adapter` decorator will have no effect +until activated by a :term:`scan`. + .. index:: single: view mapper @@ -800,3 +828,260 @@ performed, enabling you to set up the utility in advance: For full details, please read the `Venusian documentation <http://docs.repoze.org/venusian>`_. +.. _registering_tweens: + +Registering "Tweens" +-------------------- + +.. note:: Tweens are a feature which were added in Pyramid 1.1.1. They are + not available in any previous version. + +A :term:`tween` (a contraction of the word "between") is a bit of code that +sits between the Pyramid router's main request handling function and the +upstream WSGI component that uses :app:`Pyramid` as its "app". This is a +feature that may be used by Pyramid framework extensions, to provide, for +example, Pyramid-specific view timing support bookkeeping code that examines +exceptions before they are returned to the upstream WSGI application. Tweens +behave a bit like :term:`WSGI` middleware but they have the benefit of +running in a context in which they have access to the Pyramid +:term:`application registry` as well as the Pyramid rendering machinery. + +To make use of tweens, you must construct a "tween factory". A tween factory +must be a callable (or a :term:`dotted Python name` to such a callable) which +accepts two arguments: ``handler`` and ``registry``. ``handler`` will be the +either the main Pyramid request handling function or another tween (if more +than one tween is configured into the request handling chain). ``registry`` +will be the Pyramid :term:`application registry` represented by this +Configurator. A tween factory must return a tween when it is called. + +A tween is a callable which accepts a :term:`request` object and returns a +two-tuple a :term:`response` object. + +Once you've created a tween factory, you can register it into the implicit +tween chain using the :meth:`pyramid.config.Configurator.add_tween` method. + +Here's an example creating a tween factory and registering it: + +.. code-block:: python + :linenos: + + import time + from pyramid.settings import asbool + import logging + + log = logging.getLogger(__name__) + + def timing_tween_factory(handler, registry): + if asbool(registry.settings.get('do_timing')): + # if timing support is enabled, return a wrapper + def timing_tween(request): + start = time.time() + try: + response = handler(request) + finally: + end = time.time() + log.debug('The request took %s seconds' % + (end - start)) + return response + return timing_tween + # if timing support is not enabled, return the original + # handler + return handler + + from pyramid.config import Configurator + + config = Configurator() + config.add_tween(timing_tween_factory) + +The ``request`` argument to a tween will be the request created by Pyramid's +router when it receives a WSGI request. + +If more than one call to :meth:`pyramid.config.Configurator.add_tween` is +made within a single application configuration, the tweens will be chained +together at application startup time. The *first* tween factory added via +``add_tween`` will be called with the Pyramid exception view tween factory as +its ``handler`` argument, then the tween factory added directly after that +one will be called with the result of the first tween factory as its +``handler`` argument, and so on, ad infinitum until all tween factories have +been called. The Pyramid router will use the outermost tween produced by this +chain (the tween generated by the very last tween factory added) as its +request handler function. For example: + +.. code-block:: python + :linenos: + + from pyramid.config import Configurator + + config = Configurator() + config.add_tween('myapp.tween_factory1') + config.add_tween('myapp.tween_factory2') + +The above example will generate an implicit tween chain that looks like +this:: + + INGRESS (implicit) + myapp.tween_factory2 + myapp.tween_factory1 + pyramid.tweens.excview_tween_factory (implicit) + MAIN (implicit) + +By default, as described above, the ordering of the chain is controlled +entirely by the relative ordering of calls to +:meth:`pyramid.config.Configurator.add_tween`. However, the caller of +add_tween can provide an optional hint that can influence the implicit tween +chain ordering by supplying ``under`` or ``over`` (or both) arguments to +:meth:`~pyramid.config.Configurator.add_tween`. These hints are only used +used when an explicit tween chain is not used (when the ``pyramid.tweens`` +configuration value is not set). + +Allowable values for ``under`` or ``over`` (or both) are: + +- ``None`` (the default). + +- A :term:`dotted Python name` to a tween factory: a string representing the + predicted dotted name of a tween factory added in a call to ``add_tween`` + in the same configuration session. + +- A "tween alias": a string representing the predicted value of ``alias`` in + a separate call to ``add_tween`` in the same configuration session + +- One of the constants :attr:`pyramid.tweens.MAIN`, + :attr:`pyramid.tweens.INGRESS`, or :attr:`pyramid.tweens.EXCVIEW`. + +Effectively, ``under`` means "closer to the main Pyramid application than", +``over`` means "closer to the request ingress than". + +For example, the following call to +:meth:`~pyramid.config.Configurator.add_tween` will attempt to place the +tween factory represented by ``myapp.tween_factory`` directly 'above' (in +``paster ptweens`` order) the main Pyramid request handler. + +.. code-block:: python + :linenos: + + import pyramid.tweens + + config.add_tween('myapp.tween_factory', over=pyramid.tweens.MAIN) + +The above example will generate an implicit tween chain that looks like +this:: + + INGRESS (implicit) + pyramid.tweens.excview_tween_factory (implicit) + myapp.tween_factory + MAIN (implicit) + +Likewise, calling the following call to +:meth:`~pyramid.config.Configurator.add_tween` will attempt to place this +tween factory 'above' the main handler but 'below' a separately added tween +factory: + +.. code-block:: python + :linenos: + + import pyramid.tweens + + config.add_tween('myapp.tween_factory1', + over=pyramid.tweens.MAIN) + config.add_tween('myapp.tween_factory2', + over=pyramid.tweens.MAIN, + under='myapp.tween_factory1') + +The above example will generate an implicit tween chain that looks like +this:: + + INGRESS (implicit) + pyramid.tweens.excview_tween_factory (implicit) + myapp.tween_factory1 + myapp.tween_factory2 + MAIN (implicit) + +Specifying neither ``over`` nor ``under`` is equivalent to specifying +``under=INGRESS``. + +If an ``under`` or ``over`` value is provided that does not match a tween +factory dotted name or alias in the current configuration, that value will be +ignored. It is not an error to provide an ``under`` or ``over`` value that +matches an unused tween factory. + +:meth:`~pyramid.config.Configurator.add_tween` also accepts an ``alias`` +argument. If ``alias`` is not ``None``, should be a string. The string will +represent a value that other callers of ``add_tween`` may pass as an +``under`` and ``over`` argument instead of a dotted name to a tween factory. +For example: + +.. code-block:: python + :linenos: + + import pyramid.tweens + + config.add_tween('myapp.tween_factory1', + alias='one' + over=pyramid.tweens.MAIN) + config.add_tween('myapp.tween_factory2', + alias='two' + over=pyramid.tweens.MAIN, + under='one') + +Alias names are only useful in relation to ``under`` and ``over`` values. +They cannot be used in explicit tween chain configuration, or anywhere else. + +Implicit tween ordering is obviously only best-effort. Pyramid will attempt +to provide an implicit order of tweens as best it can using hints provided by +calls to :meth:`~pyramid.config.Configurator.add_tween`, but because it's +only best-effort, if very precise tween ordering is required, the only +surefire way to get it is to use an explicit tween order. The deploying user +can override the implicit tween inclusion and ordering implied by calls to +:meth:`~pyramid.config.Configurator.add_tween` entirely by using the +``pyramid.tweens`` settings value. When used, this settings value must be a +list of Python dotted names which will override the ordering (and inclusion) +of tween factories in the implicit tween chain. For example: + +.. code-block:: ini + :linenos: + + [app:main] + use = egg:MyApp + pyramid.reload_templates = true + pyramid.debug_authorization = false + pyramid.debug_notfound = false + pyramid.debug_routematch = false + pyramid.debug_templates = true + pyramid.tweens = myapp.my_cool_tween_factory + pyramid.tweens.excview_tween_factory + +In the above configuration, calls made during configuration to +:meth:`pyramid.config.Configurator.add_tween` are ignored, and the user is +telling the system to use the tween factories he has listed in the +``pyramid.tweens`` configuration setting (each is a :term:`dotted Python +name` which points to a tween factory) instead of any tween factories added +via :meth:`pyramid.config.Configurator.add_tween`. The *first* tween factory +in the ``pyramid.tweens`` list will be used as the producer of the effective +:app:`Pyramid` request handling function; it will wrap the tween factory +declared directly "below" it, ad infinitum. The "main" Pyramid request +handler is implicit, and always "at the bottom". + +.. note:: Pyramid's own :term:`exception view` handling logic is implemented + as a tween factory function: :func:`pyramid.tweens.excview_tween_factory`. + If Pyramid exception view handling is desired, and tween factories are + specified via the ``pyramid.tweens`` configuration setting, the + :func:`pyramid.tweens.excview_tween_factory` function must be added to the + ``pyramid.tweens`` configuration setting list explicitly. If it is not + present, Pyramid will not perform exception view handling. + +Pyramid will prevent the same tween factory from being added to the tween +chain more than once using configuration conflict detection. If you wish to +add the same tween factory more than once in a configuration, you should +either: a) use a tween factory that is an instance rather than a function or +class, b) use a function or class as a tween factory with the same logic as +the other tween factory it conflicts with but with a different ``__name__`` +attribute or c) call :meth:`pyramid.config.Configurator.commit` between calls +to :meth:`pyramid.config.Configurator.add_tween`. + +If a cycle is detected in implicit tween ordering when ``over`` and ``under`` +are used in any call to "add_tween", an exception will be raised at startup +time. + +The ``paster ptweens`` command-line utility can be used to report the current +implict and explicit tween chains used by an application. See +:ref:`displaying_tweens`. diff --git a/docs/narr/hybrid.rst b/docs/narr/hybrid.rst index 97adaeafd..ab1bf20bb 100644 --- a/docs/narr/hybrid.rst +++ b/docs/narr/hybrid.rst @@ -79,6 +79,9 @@ Typically, an application that uses traversal exclusively won't perform any calls to :meth:`pyramid.config.Configurator.add_route` in its startup code. +.. index:: + single: hybrid applications + Hybrid Applications ------------------- @@ -177,6 +180,9 @@ match is straightforward. When a route is matched: root factory were explained previously within :ref:`the_resource_tree`. +.. index:: + pair: hybrid applications; *traverse route pattern + .. _using_traverse_in_a_route_pattern: Using ``*traverse`` In a Route Pattern @@ -400,6 +406,9 @@ Traversal will begin at the root object implied by this route (either the global root, or the object returned by the ``factory`` associated with this route). +.. index:: + pair: hybrid applications; global views + Making Global Views Match +++++++++++++++++++++++++ @@ -420,6 +429,7 @@ attribute. config.add_view('myproject.views.bazbuz', name='bazbuz') .. index:: + pair: hybrid applications; *subpath single: route subpath single: subpath (route) @@ -431,8 +441,9 @@ Using ``*subpath`` in a Route Pattern There are certain extremely rare cases when you'd like to influence the traversal :term:`subpath` when a route matches without actually performing traversal. For instance, the :func:`pyramid.wsgi.wsgiapp2` decorator and the -:class:`pyramid.view.static` helper attempt to compute ``PATH_INFO`` from the -request's subpath, so it's useful to be able to influence this value. +:class:`pyramid.static.static_view` helper attempt to compute ``PATH_INFO`` +from the request's subpath when its ``use_subpath`` argument is ``True``, so +it's useful to be able to influence this value. When ``*subpath`` exists in a pattern, no path is actually traversed, but the traversal algorithm will return a :term:`subpath` list implied @@ -442,12 +453,19 @@ commonly in route declarations that look like this: .. code-block:: python :linenos: + from pryamid.static import static_view + + www = static_view('mypackage:static', use_subpath=True) + config.add_route('static', '/static/*subpath') - config.add_view('mypackage.views.static_view', route_name='static') + config.add_view(www, route_name='static') -Where ``mypackage.views.static_view`` is an instance of -:class:`pyramid.view.static`. This effectively tells the static helper to -traverse everything in the subpath as a filename. +``mypackage.views.www`` is an instance of +:class:`pyramid.static.static_view`. This effectively tells the static +helper to traverse everything in the subpath as a filename. + +.. index:: + pair: hybrid applications; corner cases Corner Cases ------------ diff --git a/docs/narr/i18n.rst b/docs/narr/i18n.rst index c21a19b5b..ba5490b31 100644 --- a/docs/narr/i18n.rst +++ b/docs/narr/i18n.rst @@ -353,6 +353,9 @@ The message catalog ``.pot`` template will end up in: ``myapplication/locale/myapplication.pot``. +.. index:: + single: translation domains + Translation Domains +++++++++++++++++++ @@ -494,6 +497,8 @@ translations will be available to :app:`Pyramid`. .. index:: single: localizer single: get_localizer + single: translation + single: pluralization Using a Localizer ----------------- @@ -618,7 +623,7 @@ You can obtain the locale name related to a request by using the This returns the locale name negotiated by the currently active :term:`locale negotiator` or the :term:`default locale name` if the locale negotiator returns ``None``. You can change the default locale -name by changing the ``default_locale_name`` setting; see +name by changing the ``pyramid.default_locale_name`` setting; see :ref:`default_locale_name_setting`. Once :func:`~pyramid.i18n.get_locale_name` is first run, the locale @@ -744,6 +749,9 @@ this support out of the box and may need special code to do an equivalent. For those, you can always use the more manual translation facility described in :ref:`performing_a_translation`. +.. index:: + single: Mako i18n + Mako Pyramid I18N Support ------------------------- @@ -760,7 +768,7 @@ Internationalization" which explains how to add idiomatic I18N support to Localization-Related Deployment Settings ---------------------------------------- -A :app:`Pyramid` application will have a ``default_locale_name`` +A :app:`Pyramid` application will have a ``pyramid.default_locale_name`` setting. This value represents the :term:`default locale name` used when the :term:`locale negotiator` returns ``None``. Pass it to the :mod:`~pyramid.config.Configurator` constructor at startup @@ -770,9 +778,9 @@ time: :linenos: from pyramid.config import Configurator - config = Configurator(settings={'default_locale_name':'de'}) + config = Configurator(settings={'pyramid.default_locale_name':'de'}) -You may alternately supply a ``default_locale_name`` via an +You may alternately supply a ``pyramid.default_locale_name`` via an application's Paster ``.ini`` file: .. code-block:: ini @@ -780,10 +788,10 @@ application's Paster ``.ini`` file: [app:main] use = egg:MyProject#app - reload_templates = true - debug_authorization = false - debug_notfound = false - default_locale_name = de + pyramid.reload_templates = true + pyramid.debug_authorization = false + pyramid.debug_notfound = false + pyramid.default_locale_name = de If this value is not supplied via the Configurator constructor or via a Paste config file, it will default to ``en``. @@ -796,7 +804,10 @@ If this setting is supplied within the :app:`Pyramid` application from pyramid.threadlocal import get_current_registry settings = get_current_registry().settings - default_locale_name = settings['default_locale_name'] + default_locale_name = settings['pyramid.default_locale_name'] + +.. index:: + single: detecting langauges "Detecting" Available Languages ------------------------------- @@ -857,6 +868,9 @@ languages" configuration scheme as necessary. pair: locale; negotiator single: translation directory +.. index:: + pair: activating; translation + .. _activating_translation: Activating Translation @@ -869,6 +883,9 @@ To turn translation on, you must: - ensure that your application sets the :term:`locale name` correctly. +.. index:: + pair: translation directory; adding + .. _adding_a_translation_directory: Adding a Translation Directory @@ -906,6 +923,9 @@ will be merged into translations from a message catalog added earlier if both translation directories contain translations for the same locale and :term:`translation domain`. +.. index:: + pair: setting; locale + Setting the Locale ~~~~~~~~~~~~~~~~~~ @@ -936,6 +956,9 @@ things before any translations need to be performed: function into that application as required. See :ref:`custom_locale_negotiator`. +.. index:: + single: locale negotiator + .. _locale_negotiators: Locale Negotiators diff --git a/docs/narr/install.rst b/docs/narr/install.rst index fe8459c6f..f543753ce 100644 --- a/docs/narr/install.rst +++ b/docs/narr/install.rst @@ -9,21 +9,19 @@ Installing :app:`Pyramid` Before You Install ------------------ -You will need `Python <http://python.org>`_ version 2.4 or better to +You will need `Python <http://python.org>`_ version 2.5 or better to run :app:`Pyramid`. .. sidebar:: Python Versions - As of this writing, :app:`Pyramid` has been tested under Python - 2.4.6, Python 2.5.4 and Python 2.6.2, and Python 2.7. To ensure - backwards compatibility, development of :app:`Pyramid` is - currently done primarily under Python 2.4 and Python 2.5. - :app:`Pyramid` does not run under any version of Python before - 2.4, and does not yet run under Python 3.X. + As of this writing, :app:`Pyramid` has been tested under Python 2.5.5, + Python 2.6.6, and Python 2.7.2. :app:`Pyramid` does not run under any + version of Python before 2.5, and does not yet run under Python 3.X. :app:`Pyramid` is known to run on all popular Unix-like systems such as Linux, MacOS X, and FreeBSD as well as on Windows platforms. It is also -known to run on Google's App Engine and :term:`Jython`. +known to run on Google's App Engine, :term:`PyPy` (1.5), and :term:`Jython` +(2.5.2). :app:`Pyramid` installation does not require the compilation of any C code, so you need only a Python interpreter that meets the @@ -37,6 +35,9 @@ you can either install Python using your operating system's package manager *or* you can install Python from source fairly easily on any UNIX system that has development tools. +.. index:: + pair: install; Python (from package, UNIX) + Package Manager Method ++++++++++++++++++++++ @@ -55,6 +56,9 @@ command: Once these steps are performed, the Python interpreter will usually be invokable via ``python2.6`` from a shell prompt. +.. index:: + pair: install; Python (from source, UNIX) + Source Compile Method +++++++++++++++++++++ @@ -76,9 +80,9 @@ manager. For example, this works to do so on an Ubuntu Linux system: On Mac OS X, installing `XCode <http://developer.apple.com/tools/xcode/>`_ has much the same effect. -Once you've got development tools installed on your system, On the -same system, to install a Python 2.6 interpreter from *source*, use -the following commands: +Once you've got development tools installed on your system, you can +install a Python 2.6 interpreter from *source*, on the same system, +using the following commands: .. code-block:: text @@ -98,6 +102,9 @@ Once these steps are performed, the Python interpreter will be invokable via ``$HOME/opt/Python-2.6.4/bin/python`` from a shell prompt. +.. index:: + pair: install; Python (from package, Windows) + If You Don't Yet Have A Python Interpreter (Windows) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -143,15 +150,15 @@ setuptools`` within the Python interpreter you'd like to run .. code-block:: text [chrism@vitaminf pyramid]$ python - Python 2.4.5 (#1, Aug 29 2008, 12:27:37) - [GCC 4.0.1 (Apple Inc. build 5465)] on darwin + Python 2.6.5 (r265:79063, Apr 29 2010, 00:31:32) + [GCC 4.4.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import setuptools If running ``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. Note that above we're using a Python 2.4-series +setuptools manually. Note that above we're using a Python 2.6-series interpreter on Mac OS X; your output may differ if you're using a later Python version or a different platform. @@ -183,7 +190,7 @@ the script. To remediate this, you may need to do: $ sudo python ez_setup.py .. index:: - single: virtualenv + pair: install; virtualenv Installing the ``virtualenv`` Package ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -207,6 +214,7 @@ to install it as your system's administrative user. For example: .. index:: single: virtualenv + pair: Python; virtual environment Creating the Virtual Python Environment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -315,6 +323,9 @@ Installing :app:`Pyramid` on Google App Engine :ref:`appengine_tutorial` documents the steps required to install a :app:`Pyramid` application on Google App Engine. +.. index:: + single: installing on Jython + Installing :app:`Pyramid` on Jython -------------------------------------- diff --git a/docs/narr/introduction.rst b/docs/narr/introduction.rst index a0b682e25..63c31d340 100644 --- a/docs/narr/introduction.rst +++ b/docs/narr/introduction.rst @@ -10,11 +10,8 @@ ============================== :app:`Pyramid` is a general, open source, Python web application development -*framework*. Its primary goal is to make it easier for a developer to create -web applications. The type of application being created could be a -spreadsheet, a corporate intranet, or a social networking platform; Pyramid's -generality enables it to be used to build an unconstrained variety of web -applications. +*framework*. Its primary goal is to make it easier for a Python developer to +create web applications. .. sidebar:: Frameworks vs. Libraries @@ -33,34 +30,30 @@ applications. own via a set of libraries if the framework provides a set of facilities that fits your application requirements. -The first release of Pyramid's predecessor (named :mod:`repoze.bfg`) was made -in July of 2008. We have worked hard to ensure that Pyramid continues to -follow the design and engineering principles that we consider to be the core -characteristics of a successful framework: +Pyramid attempts to follow these design and engineering principles: Simplicity - :app:`Pyramid` takes a *"pay only for what you eat"* approach. This means - that you can get results even if you have only a partial understanding of - :app:`Pyramid`. It doesn’t force you to use any particular technology to - produce an application, and we try to keep the core set of concepts that - you need to understand to a minimum. + :app:`Pyramid` takes a *"pay only for what you eat"* approach. You can get + results even if you have only a partial understanding of :app:`Pyramid`. + It doesn’t force you to use any particular technology to produce an + application, and we try to keep the core set of concepts that you need to + understand to a minimum. Minimalism - :app:`Pyramid` concentrates on providing fast, high-quality solutions to - the fundamental problems of creating a web application: the mapping of URLs - to code, templating, security and serving static assets. We consider these - to be the core activities that are common to nearly all web applications. + :app:`Pyramid` tries to solve only the the fundamental problems of creating + a web application: the mapping of URLs to code, templating, security and + serving static assets. We consider these to be the core activities that are + common to nearly all web applications. Documentation - Pyramid's minimalism means that it is relatively easy for us to maintain - extensive and up-to-date documentation. It is our goal that no aspect of - Pyramid remains undocumented. + Pyramid's minimalism means that it is easier for us to maintain complete + and up-to-date documentation. It is our goal that no aspect of Pyramid + is undocumented. Speed :app:`Pyramid` is designed to provide noticeably fast execution for common - tasks such as templating and simple response generation. Although the - “hardware is cheap” mantra may appear to offer a ready solution to speed - problems, the limits of this approach become painfully evident when one + tasks such as templating and simple response generation. Although “hardware + is cheap", the limits of this approach become painfully evident when one finds him or herself responsible for managing a great many machines. Reliability @@ -74,16 +67,14 @@ Openness open source license <http://repoze.org/license.html>`_. .. index:: - single: Pylons - single: Agendaless Consulting - single: repoze namespace package + single: Pylons Project What Is The Pylons Project? --------------------------- :app:`Pyramid` is a member of the collection of software published under the Pylons Project. Pylons software is written by a loose-knit community of -contributors. The `Pylons Project website <http://docs.pylonsproject.org>`_ +contributors. The `Pylons Project website <http://pylonsproject.org>`_ includes details about how :app:`Pyramid` relates to the Pylons Project. .. index:: @@ -96,23 +87,22 @@ includes details about how :app:`Pyramid` relates to the Pylons Project. :app:`Pyramid` and Other Web Frameworks ------------------------------------------ -Until the end of 2010, :app:`Pyramid` was known as :mod:`repoze.bfg`; it was -merged into the Pylons project as :app:`Pyramid` in November of that year. +The first release of Pyramid's predecessor (named :mod:`repoze.bfg`) was made +in July of 2008. At the end of 2010, we changed the name of +:mod:`repoze.bfg` to :app:`Pyramid`. It was merged into the Pylons project +as :app:`Pyramid` in November of that year. :app:`Pyramid` was inspired by :term:`Zope`, :term:`Pylons` (version 1.0) and :term:`Django`. As a result, :app:`Pyramid` borrows several concepts and features from each, combining them into a unique web framework. -Many features of :app:`Pyramid` trace their origins back to -:term:`Zope`. Like Zope applications, :app:`Pyramid` applications -can be configured via a set of declarative configuration files. Like -Zope applications, :app:`Pyramid` applications can be easily -extended: if you obey certain constraints, the application you produce -can be reused, modified, re-integrated, or extended by third-party -developers without forking the original application. The concepts of -:term:`traversal` and declarative security in :app:`Pyramid` were -pioneered first in Zope. +Many features of :app:`Pyramid` trace their origins back to :term:`Zope`. +Like Zope applications, :app:`Pyramid` applications can be easily extended: +if you obey certain constraints, the application you produce can be reused, +modified, re-integrated, or extended by third-party developers without +forking the original application. The concepts of :term:`traversal` and +declarative security in :app:`Pyramid` were pioneered first in Zope. The :app:`Pyramid` concept of :term:`URL dispatch` is inspired by the :term:`Routes` system used by :term:`Pylons` version 1.0. Like Pylons @@ -127,15 +117,14 @@ The concept of :term:`view` is used by :app:`Pyramid` mostly as it would be by Django. :app:`Pyramid` has a documentation culture more like Django's than like Zope's. -Like :term:`Pylons` version 1.0, but unlike :term:`Zope`, a -:app:`Pyramid` application developer may use completely imperative -code to perform common framework configuration tasks such as adding a -view or a route. In Zope, :term:`ZCML` is typically required for -similar purposes. In :term:`Grok`, a Zope-based web framework, -:term:`decorator` objects and class-level declarations are used for -this purpose. :app:`Pyramid` supports :term:`ZCML` and -decorator-based configuration, but does not require either. See -:ref:`configuration_narr` for more information. +Like :term:`Pylons` version 1.0, but unlike :term:`Zope`, a :app:`Pyramid` +application developer may use completely imperative code to perform common +framework configuration tasks such as adding a view or a route. In Zope, +:term:`ZCML` is typically required for similar purposes. In :term:`Grok`, a +Zope-based web framework, :term:`decorator` objects and class-level +declarations are used for this purpose. :app:`Pyramid` supports :term:`ZCML` +and decorator-based :term:`declarative configuration`, but does not require +either. See :ref:`configuration_narr` for more information. Also unlike :term:`Zope` and unlike other "full-stack" frameworks such as :term:`Django`, :app:`Pyramid` makes no assumptions about which diff --git a/docs/narr/muchadoabouttraversal.rst b/docs/narr/muchadoabouttraversal.rst index a4709ef18..6ad33c1ce 100644 --- a/docs/narr/muchadoabouttraversal.rst +++ b/docs/narr/muchadoabouttraversal.rst @@ -39,6 +39,9 @@ web developer so you know when you might want to use them. :term:`Traversal` is actually a straightforward metaphor easily comprehended by anyone who's ever used a run-of-the-mill file system with folders and files. +.. index:: + single: URL dispatch + URL Dispatch ------------ @@ -100,12 +103,12 @@ from this process to the client as the final result. The server configuration specified which files would trigger some dynamic code, with the default case being to just serve the static file. +.. index:: + single: traversal + Traversal (aka Resource Location) --------------------------------- -.. index:: - single: traversal overview - Believe it or not, if you understand how serving files from a file system works, you understand traversal. And if you understand that a server might do something different based on what type of file a given request specifies, @@ -141,6 +144,9 @@ generated anywhere along the way, :app:`Pyramid` will return 404. (This isn't precisely true, as you'll see when we learn about view lookup below, but the basic idea holds.) +.. index:: + single: resource + What Is a "Resource"? --------------------- @@ -194,6 +200,9 @@ system. Traversal is in fact a superset of file system lookup. .. note:: See the chapter entitled :ref:`resources_chapter` for a more technical overview of resources. +.. index:: + single: view lookup + View Lookup ----------- diff --git a/docs/narr/project-debug.png b/docs/narr/project-debug.png Binary files differnew file mode 100644 index 000000000..d13a91736 --- /dev/null +++ b/docs/narr/project-debug.png diff --git a/docs/narr/project.png b/docs/narr/project.png Binary files differindex da5bc870b..fc00ec086 100644 --- a/docs/narr/project.png +++ b/docs/narr/project.png diff --git a/docs/narr/project.rst b/docs/narr/project.rst index 631412f42..baf4c86fa 100644 --- a/docs/narr/project.rst +++ b/docs/narr/project.rst @@ -12,9 +12,9 @@ A project is a directory that contains at least one Python :term:`package`. You'll use a scaffold to create a project, and you'll create your application logic within a package that lives inside the project. Even if your application is extremely simple, it is useful to place code that drives the -application within a package, because a package is more easily extended with -new code. An application that lives inside a package can also be distributed -more easily than one which does not live within a package. +application within a package, because: 1) a package is more easily extended +with new code and 2) an application that lives inside a package can also be +distributed more easily than one which does not live within a package. :app:`Pyramid` comes with a variety of scaffolds that you can use to generate a project. Each scaffold makes different configuration assumptions about @@ -99,19 +99,18 @@ We'll choose the ``pyramid_starter`` scaffold for this purpose. $ bin/paster create -t pyramid_starter -The above command uses the ``paster`` command to create a project using the -``pyramid_starter`` scaffold. The ``paster create`` command creates project -from a scaffold. To use a different scaffold, such as +The above command uses the ``paster create`` command to create a project with +the ``pyramid_starter`` scaffold. To use a different scaffold, such as ``pyramid_routesalchemy``, you'd just change the last argument. For example: .. code-block:: text $ bin/paster create -t pyramid_routesalchemy -``paster create`` will ask you a single question: the *name* of the -project. You should use a string without spaces and with only letters -in it. Here's sample output from a run of ``paster create`` for a -project we name ``MyProject``: +``paster create`` will ask you a single question: the *name* of the project. +You should use a string without spaces and with only letters in it. Here's +sample output from a run of ``paster create`` for a project we name +``MyProject``: .. code-block:: text @@ -177,7 +176,7 @@ command ``python setup.py develop`` The file named ``setup.py`` will be in the root of the paster-generated project directory. The ``python`` you're invoking should be the one that lives in the ``bin`` directory of your virtual Python environment. Your -terminal's current working directory *must* the the newly created project +terminal's current working directory *must* be the newly created project directory. For example: .. code-block:: text @@ -194,7 +193,8 @@ Elided output from a run of this command is shown below: This will install a :term:`distribution` representing your project into the interpreter's library set so it can be found by ``import`` statements and by -:term:`PasteDeploy` commands such as ``paster serve`` and ``paster pshell``. +:term:`PasteDeploy` commands such as ``paster serve``, ``paster pshell``, +``paster proutes`` and ``paster pviews``. .. index:: single: running tests @@ -244,115 +244,10 @@ create`` -generated project. Within a project generated by the ``pyramid_starter`` scaffold, a single sample test exists. .. index:: - single: interactive shell - single: IPython - single: paster pshell - -.. _interactive_shell: - -The Interactive Shell ---------------------- - -Once you've installed your program for development using ``setup.py -develop``, you can use an interactive Python shell to examine your -:app:`Pyramid` project's :term:`resource` and :term:`view` objects from a -Python prompt. To do so, use your virtualenv's ``paster pshell`` command. - -The first argument to ``pshell`` is the path to your application's ``.ini`` -file. The second is the ``app`` section name inside the ``.ini`` 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:MyProject]`` section that looks like so: - -.. code-block:: ini - :linenos: - - [app:MyProject] - use = egg:MyProject - reload_templates = true - debug_authorization = false - debug_notfound = false - debug_templates = true - default_locale_name = en - -If so, you can use the following command to invoke a debug shell using the -name ``MyProject`` as a section name: - -.. code-block:: text - - [chrism@vitaminf shellenv]$ ../bin/paster pshell development.ini MyProject - Python 2.4.5 (#1, Aug 29 2008, 12:27:37) - [GCC 4.0.1 (Apple Inc. build 5465)] on darwin - Type "help" for more information. "root" is the Pyramid app root object, - "registry" is the Pyramid registry object. - >>> root - <myproject.resources.MyResource object at 0x445270> - >>> registry - <Registry myproject> - >>> registry.settings['debug_notfound'] - False - >>> from myproject.views import my_view - >>> from pyramid.request import Request - >>> r = Request.blank('/') - >>> my_view(r) - {'project': 'myproject'} - -Two names are made available to the pshell user as globals: ``root`` and -``registry``. ``root`` is the the object returned by the default :term:`root -factory` in your application. ``registry`` is the :term:`application -registry` object associated with your project's application (often accessed -within view code as ``request.registry``). - -If you have `IPython <http://en.wikipedia.org/wiki/IPython>`_ installed in -the interpreter you use to invoke the ``paster`` command, the ``pshell`` -command will use an IPython interactive shell instead of a standard Python -interpreter shell. If you don't want this to happen, even if you have -IPython installed, you can pass the ``--disable-ipython`` flag to the -``pshell`` command to use a standard Python interpreter shell -unconditionally. - -.. code-block:: text - - [chrism@vitaminf shellenv]$ ../bin/paster pshell --disable-ipython \ - development.ini MyProject - -You should always use a section name argument that refers to the actual -``app`` section within the Paste configuration file that points at your -:app:`Pyramid` application *without any middleware wrapping*. In particular, -a section name is inappropriate as the second argument to ``pshell`` if the -configuration section it names is a ``pipeline`` rather than an ``app``. For -example, if you have the following ``.ini`` file content: - -.. code-block:: ini - :linenos: - - [app:MyProject] - use = egg:MyProject - reload_templates = true - debug_authorization = false - debug_notfound = false - debug_templates = true - default_locale_name = en - - [pipeline:main] - pipeline = - egg:WebError#evalerror - MyProject - -Use ``MyProject`` instead of ``main`` as the section name argument to -``pshell`` against the above ``.ini`` file (e.g. ``paster pshell -development.ini MyProject``). If you use ``main`` instead, an error will -occur. Use the most specific reference to your application within the -``.ini`` file possible as the section name argument. - -Press ``Ctrl-D`` to exit the interactive shell (or ``Ctrl-Z`` on Windows). - -.. index:: single: running an application single: paster serve single: reload single: startup - single: mod_wsgi Running The Project Application ------------------------------- @@ -398,6 +293,10 @@ For more detailed information about the startup process, see configuration file settings that influence startup and runtime behavior, see :ref:`environment_chapter`. +.. index:: + single: mod_wsgi + single: WSGI + Viewing the Application ----------------------- @@ -410,6 +309,45 @@ browser like what is displayed in the following image: This is the page shown by default when you visit an unmodified ``paster create`` -generated ``pyramid_starter`` application in a browser. +If you click on the image shown at the right hand top of the page ("^DT"), +you'll be presented with a debug toolbar that provides various niceties while +you're developing. This image will float above every HTML page served by +:app:`Pyramid` while you develop an application, and allows you show the +toolbar as necessary. Click on ``Hide`` to hide the toolbar and show the +image again. + +.. image:: project-debug.png + +For more information about what the debug toolbar allows you to do, see `the +documentation for pyramid_debugtoolbar +<http://docs.pylonsproject.org/projects/pyramid_debugtoolbar/dev/>`_. + +The debug toolbar will not be shown (and all debugging will be turned off) +when you use the ``production.ini`` file instead of the ``development.ini`` +ini file to run the application. + +You can also turn the debug toolbar off by editing ``development.ini`` and +commenting out the line ``pyramid.include = pyramid_debugtoolbar``. For +example, instead of: + +.. code-block:: ini + :linenos: + + [app:MyApp] + ... + pyramid.include = pyramid_debugtoolbar + +Put a hash mark in front of the ``pyramid.include`` line: + +.. code-block:: ini + :linenos: + + [app:MyApp] + ... + #pyramid.include = pyramid_debugtoolbar + +Then restart the application to see that the toolbar has been turned off. + .. sidebar:: Using an Alternate WSGI Server The code generated by a :app:`Pyramid` scaffold assumes that you @@ -520,14 +458,13 @@ serve``, as well as the deployment settings provided to that application. The generated ``development.ini`` file looks like so: -.. latexbroken? - .. literalinclude:: MyProject/development.ini :language: ini :linenos: This file contains several "sections" including ``[app:MyProject]``, -``[pipeline:main]``, and ``[server:main]``. +``[pipeline:main]``, ``[server:main]`` and several other sections related to +logging configuration. The ``[app:MyProject]`` section represents configuration for your application. This section name represents the ``MyProject`` application (and @@ -558,7 +495,7 @@ the default. point can thus be referred to as a "Paste application factory in the ``MyProject`` project which has the entry point named ``main`` where the entry point refers to a ``main`` function in the ``mypackage`` module". - If indeed if you open up the ``__init__.py`` module generated within the + Indeed, if you open up the ``__init__.py`` module generated within the ``myproject`` package, you'll see a ``main`` function. This is the function called by :term:`PasteDeploy` when the ``paster serve`` command is invoked against our application. It accepts a global configuration @@ -567,27 +504,35 @@ the default. The ``use`` setting is the only setting *required* in the ``[app:MyProject]`` section unless you've changed the callable referred to by the ``egg:MyProject`` entry point to accept more arguments: other settings you -add to this section are passed as keywords arguments to the callable +add to this section are passed as keyword arguments to the callable represented by this entry point (``main`` in our ``__init__.py`` module). You can provide startup-time configuration parameters to your application by adding more settings to this section. -The ``reload_templates`` setting in the ``[app:MyProject]`` section is a -:app:`Pyramid` -specific setting which is passed into the framework. If it +The ``pyramid.reload_templates`` setting in the ``[app:MyProject]`` section is +a :app:`Pyramid` -specific setting which is passed into the framework. If it exists, and its value is ``true``, :term:`Chameleon` and :term:`Mako` template changes will not require an application restart to be detected. See :ref:`reload_templates_section` for more information. -The ``debug_templates`` setting in the ``[app:MyProject]`` section is a +The ``pyramid.debug_templates`` setting in the ``[app:MyProject]`` section is a :app:`Pyramid` -specific setting which is passed into the framework. If it exists, and its value is ``true``, :term:`Chameleon` template exceptions will -contained more detailed and helpful information about the error than when +contain more detailed and helpful information about the error than when this value is ``false``. See :ref:`debug_templates_section` for more information. -.. warning:: The ``reload_templates`` and ``debug_templates`` options should - be turned off for production applications, as template rendering is slowed - when either is turned on. +.. warning:: The ``pyramid.reload_templates`` and ``pyramid.debug_templates`` + options should be turned off for production applications, as template + rendering is slowed when either is turned on. + +The ``pyramid.include`` setting in the ``[app:MyProject]`` section tells +Pyramid to "include" configuration from another package. In this case, the +line ``pyramid.include = pyramid_debugtoolbar`` tells Pyramid to include +configuration from the ``pyramid_debugtoolbar`` package. This turns on a +debugging panel in development mode which will be shown on the right hand +side of the screen. Including the debug toolbar will also make it possible +to interactively debug exceptions when an error occurs. Various other settings may exist in this section having to do with debugging or influencing runtime behavior of a :app:`Pyramid` application. See @@ -611,6 +556,16 @@ for each request. application be nonblocking as all application code will run in its own thread, provided by the server you're using. +The sections that live between the markers ``# Begin logging configuration`` +and ``# End logging configuration`` represent Python's standard library +:mod:`logging` module configuration for your application. The sections +between these two markers are passed to the `logging module's config file +configuration engine +<http://docs.python.org/howto/logging.html#configuring-logging>`_ when the +``paster serve`` or ``paster pshell`` commands are executed. The default +configuration sends application logging output to the standard error output +of your terminal. + See the :term:`PasteDeploy` documentation for more information about other types of things you can put into this ``.ini`` file, such as other applications, :term:`middleware` and alternate :term:`WSGI` server @@ -625,16 +580,21 @@ implementations. to your application's ``main`` function as ``global_config`` (see the reference to the ``main`` function in :ref:`init_py`). +.. index:: + single: production.ini + ``production.ini`` ~~~~~~~~~~~~~~~~~~~ The ``production.ini`` file is a :term:`PasteDeploy` configuration file with a purpose much like that of ``development.ini``. However, it disables the -WebError interactive debugger, replacing it with a logger which outputs -exception messages to ``stderr`` by default. It also turns off template -development options such that templates are not automatically reloaded when -changed, and turns off all debugging options. You can use this file instead -of ``development.ini`` when you put your application into production. +debug toolbar, replacing it with a logger which outputs exception messages to +``stderr`` by default. It also turns off template development options such +that templates are not automatically reloaded when changed, and turns off all +debugging options. It allows you to configure a ``weberror#error_catcher`` +section that will cause exceptions to be sent to an email address when they +are uncaught. You can use this file instead of ``development.ini`` when you +put your application into production. .. index:: single: MANIFEST.in @@ -750,6 +710,9 @@ who want to use your application. setuptools add-on such as ``setuptools-git`` or ``setuptools-hg`` for this behavior to work properly. +.. index:: + single: setup.cfg + ``setup.cfg`` ~~~~~~~~~~~~~ @@ -845,6 +808,9 @@ also informs Python that the directory which contains it is a *package*. Line 12 returns a :term:`WSGI` application to the caller of the function (Paste). +.. index:: + single: views.py + ``views.py`` ~~~~~~~~~~~~ @@ -876,14 +842,14 @@ file call to ``add_view``). See :ref:`views_which_use_a_renderer` for more information about how views, renderers, and templates relate and cooperate. -.. note:: Because our ``development.ini`` has a ``reload_templates = +.. note:: Because our ``development.ini`` has a ``pyramid.reload_templates = true`` directive indicating that templates should be reloaded when they change, you won't need to restart the application server to see changes you make to templates. During development, this is handy. If this directive had been ``false`` (or if the directive did not exist), you would need to restart the application server for each template change. For production applications, you should - set your project's ``reload_templates`` to ``false`` to increase + set your project's ``pyramid.reload_templates`` to ``false`` to increase the speed at which templates may be rendered. .. index:: @@ -915,6 +881,9 @@ about which sort of data storage you'll want to use, so the sample application uses an instance of :class:`myproject.resources.Root` to represent the root. +.. index:: + single: static directory + ``static`` ~~~~~~~~~~ @@ -924,7 +893,7 @@ template. It includes CSS and images. ``templates/mytemplate.pt`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The single :term:`Chameleon` template exists in the project. Its contents +The single :term:`Chameleon` template that exists in the project. Its contents are too long to show here, but it displays a default page when rendered. It is referenced by the call to ``add_view`` as the ``renderer`` attribute in the ``__init__`` file. See :ref:`views_which_use_a_renderer` for more @@ -955,6 +924,9 @@ example. See :ref:`testing_chapter` for more information about writing :app:`Pyramid` unit tests. +.. index:: + pair: modifying; package structure + .. _modifying_package_structure: Modifying Package Structure @@ -1024,4 +996,13 @@ This pattern can be used to rearrage code referred to by any Pyramid API argument which accepts a :term:`dotted Python name` or direct object reference. +Using the Interactive Shell +--------------------------- + +It is possible to use a Python interpreter prompt loaded with a similar +configuration as would be loaded if you were running your Pyramid application +via ``paster serve``. This can be a useful debugging tool. See +:ref:`interactive_shell` for more details. + + diff --git a/docs/narr/renderers.rst b/docs/narr/renderers.rst index f329a7af9..ed391f4fe 100644 --- a/docs/narr/renderers.rst +++ b/docs/narr/renderers.rst @@ -3,10 +3,10 @@ Renderers ========= -A view needn't *always* return a :term:`Response` object. If a view -happens to return something which does not implement the Pyramid -Response interface, :app:`Pyramid` will attempt to use a -:term:`renderer` to construct a response. For example: +A view callable needn't *always* return a :term:`Response` object. If a view +happens to return something which does not implement the Pyramid Response +interface, :app:`Pyramid` will attempt to use a :term:`renderer` to construct +a response. For example: .. code-block:: python :linenos: @@ -228,6 +228,9 @@ Views which use the JSON renderer can vary non-body response attributes by using the api of the ``request.response`` attribute. See :ref:`request_response_attr`. +.. index:: + pair: renderer; JSONP + .. _jsonp_renderer: JSONP Renderer @@ -422,8 +425,9 @@ The above configuration will use the file named ``foo.mak`` in the ``templates`` directory of the ``mypackage`` package. The ``Mako`` template renderer can take additional arguments beyond the -standard ``reload_templates`` setting, see the :ref:`environment_chapter` for -additional :ref:`mako_template_renderer_settings`. +standard ``pyramid.reload_templates`` setting, see the +:ref:`environment_chapter` for additional +:ref:`mako_template_renderer_settings`. .. index:: single: response headers (from a renderer) @@ -522,9 +526,6 @@ people with older code bases. returning various values in the ``response_headerlist``, this is purely a convenience. -.. index:: - single: renderer (adding) - .. _adding_and_overriding_renderers: Adding and Changing Renderers @@ -550,6 +551,9 @@ The first argument is the renderer name. The second argument is a reference to an implementation of a :term:`renderer factory` or a :term:`dotted Python name` referring to such an object. +.. index:: + pair: renderer; adding + .. _adding_a_renderer: Adding a New Renderer @@ -676,6 +680,9 @@ ending with ``.jinja2`` in its ``renderer`` value. The ``name`` passed to the ``MyJinja2Renderer`` constructor will be the full value that was set as ``renderer=`` in the view configuration. +.. index:: + pair: renderer; changing + Changing an Existing Renderer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -715,6 +722,9 @@ the ``name`` attribute to the renderer tag: config.add_renderer(None, 'mypackage.json_renderer_factory') +.. index:: + pair: renderer; overriding at runtime + Overriding A Renderer At Runtime -------------------------------- diff --git a/docs/narr/resources.rst b/docs/narr/resources.rst index fa8ccc549..0e0d00020 100644 --- a/docs/narr/resources.rst +++ b/docs/narr/resources.rst @@ -286,6 +286,9 @@ The shortcut method of the :term:`request` named For more information about generating resource URLs, see the documentation for :func:`pyramid.url.resource_url`. +.. index:: + pair: resource URL generation; overriding + .. _overriding_resource_url_generation: Overriding Resource URL Generation @@ -333,6 +336,9 @@ qualified, should end in a slash, and should not contain any query string or anchor elements (only path elements) to work best with :func:`~pyramid.url.resource_url`. +.. index:: + single: resource path generation + Generating the Path To a Resource --------------------------------- @@ -368,6 +374,9 @@ The resource passed in must be :term:`location`-aware. The presence or absence of a :term:`virtual root` has no impact on the behavior of :func:`~pyramid.traversal.resource_path`. +.. index:: + pair: resource; finding by path + Finding a Resource by Path -------------------------- @@ -404,6 +413,9 @@ tree does not exist), a :exc:`KeyError` will be raised. See the :func:`pyramid.traversal.find_resource` documentation for more information about resolving a path to a resource. +.. index:: + pair: resource; lineage + Obtaining the Lineage of a Resource ----------------------------------- @@ -471,6 +483,9 @@ parent (or one of its parent's parents, etc.) is an ancestor. See :func:`pyramid.location.inside` for more information. +.. index:: + pair: resource; finding root + Finding the Root Resource ------------------------- @@ -617,6 +632,9 @@ directly provided by an instance instead of overwriting them like For more information about how resource interfaces can be used by view configuration, see :ref:`using_resource_interfaces`. +.. index:: + pair: resource; finding by interface or class + Finding a Resource With a Class or Interface in Lineage ------------------------------------------------------- diff --git a/docs/narr/router.rst b/docs/narr/router.rst index 0812f7ec7..d08261b17 100644 --- a/docs/narr/router.rst +++ b/docs/narr/router.rst @@ -2,6 +2,7 @@ single: request processing single: request single: router + single: request lifecycle .. _router_chapter: diff --git a/docs/narr/security.rst b/docs/narr/security.rst index c7a07b857..a61578e21 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -168,6 +168,9 @@ normal application operations, the requesting user will need to possess the to invoke the ``blog_entry_add_view`` view. If he does not, the :term:`Forbidden view` will be invoked. +.. index:: + pair: permission; default + .. _setting_a_default_permission: Setting a Default Permission @@ -197,9 +200,9 @@ When a default permission is registered: permission is ignored for that view registration, and the view-configuration-named permission is used. -- If a view configuration names an explicit permission as the string - ``__no_permission_required__``, the default permission is ignored, - and the view is registered *without* a permission (making it +- If a view configuration names the permission + :data:`pyramid.security.NO_PERMISSION_REQUIRED`, the default permission + is ignored, and the view is registered *without* a permission (making it available to all callers regardless of their credentials). .. warning:: @@ -207,11 +210,13 @@ When a default permission is registered: When you register a default permission, *all* views (even :term:`exception view` views) are protected by a permission. For all views which are truly meant to be anonymously accessible, you will need to associate the view's - configuration with the ``__no_permission_required__`` permission. + configuration with the :data:`pyramid.security.NO_PERMISSION_REQUIRED` + permission. .. index:: single: ACL single: access control list + pair: resource; ACL .. _assigning_acls: @@ -513,7 +518,7 @@ which ACL permitted or denied the authorization based on authentication information. This behavior can also be turned on in the application ``.ini`` file -by setting the ``debug_authorization`` key to ``true`` within the +by setting the ``pyramid.debug_authorization`` key to ``true`` within the application's configuration section, e.g.: .. code-block:: ini @@ -521,7 +526,7 @@ application's configuration section, e.g.: [app:main] use = egg:MyProject#app - debug_authorization = true + pyramid.debug_authorization = true With this debug flag turned on, the response sent to the browser will also contain security debugging information in its body. @@ -562,7 +567,7 @@ that implements the following interface: .. code-block:: python :linenos: - class AuthenticationPolicy(object): + class IAuthenticationPolicy(object): """ An object representing a Pyramid authentication policy. """ def authenticated_userid(self, request): diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 97e3ebc55..6ff9e3dea 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -15,6 +15,9 @@ implementations :app:`Pyramid` provides out of the box, how to store and retrieve data from sessions, and two session-specific features: flash messages, and cross-site request forgery attack prevention. +.. index:: + single: session factory (default) + .. _using_the_default_session_factory: Using The Default Session Factory @@ -65,6 +68,9 @@ application by using the ``session_factory`` argument to the the server) for anything but the most basic of applications where "session security doesn't matter". +.. index:: + single: session object + Using a Session Object ---------------------- @@ -137,6 +143,7 @@ Some gotchas: .. index:: single: pyramid_beaker single: Beaker + single: session factory (alternates) .. _using_alternate_session_factories: @@ -153,7 +160,7 @@ based sessions, and encrypted cookie-based sessions. See ``pyramid_beaker``. .. index:: - single: session factory + single: session factory (custom) Creating Your Own Session Factory --------------------------------- @@ -184,6 +191,9 @@ log messages for single-time display without having direct access to an HTML template. The user interface consists of a number of methods of the :term:`session` object. +.. index:: + single: session.flash + Using the ``session.flash`` Method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -222,6 +232,9 @@ The ``allow_duplicate`` argument defaults to ``True``. If this is ``False``, and you attempt to add a message value which is already present in the queue, it will not be added. +.. index:: + single: session.pop_flash + Using the ``session.pop_flash`` Method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -255,6 +268,9 @@ been popped. >>> request.session.pop_flash() [] +.. index:: + single: session.peek_flash + Using the ``session.peek_flash`` Method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -288,7 +304,7 @@ Preventing Cross-Site Request Forgery Attacks `Cross-site request forgery <http://en.wikipedia.org/wiki/Cross-site_request_forgery>`_ attacks are a phenomenon whereby a user with an identity on your website might click on a -URL or button on another website which unwittingly redirects the user to your +URL or button on another website which secretly redirects the user to your application to perform some command that requires elevated privileges. You can avoid most of these attacks by making sure that the correct *CSRF @@ -298,6 +314,9 @@ post. To use CSRF token support, you must enable a :term:`session factory` as described in :ref:`using_the_default_session_factory` or :ref:`using_alternate_session_factories`. +.. index:: + single: session.get_csrf_token + Using the ``session.get_csrf_token`` Method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -330,6 +349,9 @@ input field named ``csrf_token``: if token != request.POST['csrf_token']: raise ValueError('CSRF token did not match') +.. index:: + single: session.new_csrf_token + Using the ``session.new_csrf_token`` Method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/narr/startup.rst b/docs/narr/startup.rst index e2c43b17e..c9ed01f83 100644 --- a/docs/narr/startup.rst +++ b/docs/narr/startup.rst @@ -53,6 +53,10 @@ Here's a high-level time-ordered overview of what happens when you press that particular composite to understand how to make it refer to your :app:`Pyramid` application. +#. The PasteDeploy framework finds all :mod:`logging` related configuration + in the ``.ini`` file and uses it to configure the Python standard library + logging system for this application. + #. The application's *constructor* (named by the entry point reference or dotted Python name on the ``use=`` line of the section representing your :app:`Pyramid` application) is passed the key/value parameters mentioned @@ -88,10 +92,10 @@ Here's a high-level time-ordered overview of what happens when you press In this case, the ``myproject.__init__:main`` function referred to by the entry point URI ``egg:MyProject`` (see :ref:`MyProject_ini` for more information about entry point URIs, and how they relate to callables), - will receive the key/value pairs ``{'reload_templates':'true', - 'debug_authorization':'false', 'debug_notfound':'false', - 'debug_routematch':'false', 'debug_templates':'true', - 'default_locale_name':'en'}``. + will receive the key/value pairs ``{'pyramid.reload_templates':'true', + 'pyramid.debug_authorization':'false', 'pyramid.debug_notfound':'false', + 'pyramid.debug_routematch':'false', 'pyramid.debug_templates':'true', + 'pyramid.default_locale_name':'en'}``. #. The ``main`` function first constructs a :class:`~pyramid.config.Configurator` instance, passing a root resource @@ -105,14 +109,14 @@ Here's a high-level time-ordered overview of what happens when you press The ``settings`` dictionary contains all the options in the ``[app:MyProject]`` section of our .ini file except the ``use`` option - (which is internal to Paste) such as ``reload_templates``, - ``debug_authorization``, etc. + (which is internal to Paste) such as ``pyramid.reload_templates``, + ``pyramid.debug_authorization``, etc. -#. The ``main`` function then calls various methods on the an instance of the - class :class:`~pyramid.config.Configurator` method. The intent of - calling these methods is to populate an :term:`application registry`, - which represents the :app:`Pyramid` configuration related to the - application. +#. The ``main`` function then calls various methods on the instance of the + class :class:`~pyramid.config.Configurator` created in the previous step. + The intent of calling these methods is to populate an + :term:`application registry`, which represents the :app:`Pyramid` + configuration related to the application. #. The :meth:`~pyramid.config.Configurator.make_wsgi_app` method is called. The result is a :term:`router` instance. The router is associated with @@ -136,6 +140,10 @@ Here's a high-level time-ordered overview of what happens when you press The server serves the application, and the application is running, waiting to receive requests. +.. index:: + pair: settings; deployment + single: custom settings + .. _deployment_settings: Deployment Settings diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst index 150b173e3..0f46f6422 100644 --- a/docs/narr/templates.rst +++ b/docs/narr/templates.rst @@ -241,6 +241,9 @@ of :func:`~pyramid.renderers.render` (a string): single: renderer (template) +.. index:: + pair: renderer; system values + .. _renderer_system_values: System Values Used During Rendering @@ -277,6 +280,9 @@ renderer itself, but most template renderers, including Chameleon and Mako renderers, make these names available as top-level template variables. +.. index:: + pair: renderer; templates + .. _templates_used_as_renderers: Templates Used as Renderers via Configuration @@ -426,7 +432,7 @@ See also :ref:`built_in_renderers` for more general information about renderers, including Chameleon ZPT renderers. .. index:: - single: sample template + single: ZPT template (sample) A Sample ZPT Template ~~~~~~~~~~~~~~~~~~~~~ @@ -448,7 +454,7 @@ Here's what a simple :term:`Chameleon` ZPT template used under <body> <h1 class="title">Welcome to <code>${project}</code>, an application generated by the <a - href="http://docs.pylonsproject.org/projects/pyramid/dev/" + href="http://docs.pylonsproject.org/projects/pyramid/current/" >pyramid</a> web application framework.</h1> </body> @@ -596,6 +602,9 @@ Note that I always name my Chameleon ZPT template files with a ``.pt`` extension and my Chameleon text template files with a ``.txt`` extension so that these ``svn:ignore`` patterns work. +.. index:: + pair: debugging; templates + .. _debug_templates_section: Nicer Exceptions in Chameleon Templates @@ -623,15 +632,15 @@ variable set to ``1``, For example: $ PYRAMID_DEBUG_TEMPLATES=1 bin/paster serve myproject.ini To use a setting in the application ``.ini`` file for the same -purpose, set the ``debug_templates`` key to ``true`` within the -application's configuration section, e.g.: +purpose, set the ``pyramid.debug_templates`` key to ``true`` within +the application's configuration section, e.g.: .. code-block:: ini :linenos: [app:MyProject] use = egg:MyProject#app - debug_templates = true + pyramid.debug_templates = true With template debugging off, a :exc:`NameError` exception resulting from rendering a template with an undefined variable @@ -668,7 +677,7 @@ displaying the arguments passed to the template itself. .. note:: - Turning on ``debug_templates`` has the same effect as using the + Turning on ``pyramid.debug_templates`` has the same effect as using the Chameleon environment variable ``CHAMELEON_DEBUG``. See `Chameleon Environment Variables <http://chameleon.repoze.org/docs/latest/config.html#environment-variables>`_ @@ -724,6 +733,9 @@ in the ``templates`` subdirectory of the ``mypackage`` Python package. See ``mako.directories`` setting and other Mako-related settings that can be placed into the application's ``ini`` file. +.. index:: + single: Mako template (sample) + A Sample Mako Template ~~~~~~~~~~~~~~~~~~~~~~ @@ -740,7 +752,7 @@ look like: <body> <h1 class="title">Welcome to <code>${project}</code>, an application generated by the <a - href="http://docs.pylonsproject.org/projects/pyramid/dev/" + href="http://docs.pylonsproject.org/projects/pyramid/current/" >pyramid</a> web application framework.</h1> </body> </html> @@ -781,7 +793,7 @@ variable set to ``1``, For example: $ PYRAMID_RELOAD_TEMPLATES=1 bin/paster serve myproject.ini To use a setting in the application ``.ini`` file for the same -purpose, set the ``reload_templates`` key to ``true`` within the +purpose, set the ``pyramid.reload_templates`` key to ``true`` within the application's configuration section, e.g.: .. code-block:: ini @@ -789,7 +801,7 @@ application's configuration section, e.g.: [app:main] use = egg:MyProject#app - reload_templates = true + pyramid.reload_templates = true .. index:: single: template system bindings diff --git a/docs/narr/traversal.rst b/docs/narr/traversal.rst index e1715dc25..aa36b4455 100644 --- a/docs/narr/traversal.rst +++ b/docs/narr/traversal.rst @@ -456,6 +456,103 @@ as the sole argument: ``request``; it is expected to return a response. -specific request attributes are also available as described in :ref:`special_request_attributes`. +.. index:: + single: resource interfaces + +.. _using_resource_interfaces: + +Using Resource Interfaces In View Configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Instead of registering your views with a ``context`` that names a Python +resource *class*, you can optionally register a view callable with a +``context`` which is an :term:`interface`. An interface can be attached +arbitrarily to any resource object. View lookup treats context interfaces +specially, and therefore the identity of a resource can be divorced from that +of the class which implements it. As a result, associating a view with an +interface can provide more flexibility for sharing a single view between two +or more different implementations of a resource type. For example, if two +resource objects of different Python class types share the same interface, +you can use the same view configuration to specify both of them as a +``context``. + +In order to make use of interfaces in your application during view dispatch, +you must create an interface and mark up your resource classes or instances +with interface declarations that refer to this interface. + +To attach an interface to a resource *class*, you define the interface and +use the :func:`zope.interface.implements` function to associate the interface +with the class. + +.. code-block:: python + :linenos: + + from zope.interface import Interface + from zope.interface import implements + + class IHello(Interface): + """ A marker interface """ + + class Hello(object): + implements(IHello) + +To attach an interface to a resource *instance*, you define the interface and +use the :func:`zope.interface.alsoProvides` function to associate the +interface with the instance. This function mutates the instance in such a +way that the interface is attached to it. + +.. code-block:: python + :linenos: + + from zope.interface import Interface + from zope.interface import alsoProvides + + class IHello(Interface): + """ A marker interface """ + + class Hello(object): + pass + + def make_hello(): + hello = Hello() + alsoProvides(hello, IHello) + return hello + +Regardless of how you associate an interface, with a resource instance, or a +resource class, the resulting code to associate that interface with a view +callable is the same. Assuming the above code that defines an ``IHello`` +interface lives in the root of your application, and its module is named +"resources.py", the interface declaration below will associate the +``mypackage.views.hello_world`` view with resources that implement, or +provide, this interface. + +.. code-block:: python + :linenos: + + # config is an instance of pyramid.config.Configurator + + config.add_view('mypackage.views.hello_world', name='hello.html', + context='mypackage.resources.IHello') + +Any time a resource that is determined to be the :term:`context` provides +this interface, and a view named ``hello.html`` is looked up against it as +per the URL, the ``mypackage.views.hello_world`` view callable will be +invoked. + +Note, in cases where a view is registered against a resource class, and a +view is also registered against an interface that the resource class +implements, an ambiguity arises. Views registered for the resource class take +precedence over any views registered for any interface the resource class +implements. Thus, if one view configuration names a ``context`` of both the +class type of a resource, and another view configuration names a ``context`` +of interface implemented by the resource's class, and both view +configurations are otherwise identical, the view registered for the context's +class will "win". + +For more information about defining resources with interfaces for use within +view configuration, see :ref:`resources_which_implement_interfaces`. + + References ---------- diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst index f94ed3ba8..61c9770c6 100644 --- a/docs/narr/urldispatch.rst +++ b/docs/narr/urldispatch.rst @@ -6,28 +6,12 @@ URL Dispatch ============ -:term:`URL dispatch` provides a simple way to map URLs to :term:`view` -code using a simple pattern matching language. An ordered set of -patterns is checked one-by-one. If one of the patterns matches the path -information associated with a request, a particular :term:`view -callable` is invoked. - -:term:`URL dispatch` is one of two ways to perform :term:`resource -location` in :app:`Pyramid`; the other way is using :term:`traversal`. -If no route is matched using :term:`URL dispatch`, :app:`Pyramid` falls -back to :term:`traversal` to handle the :term:`request`. - -It is the responsibility of the :term:`resource location` subsystem -(i.e., :term:`URL dispatch` or :term:`traversal`) to find the resource -object that is the :term:`context` of the :term:`request`. Once the -:term:`context` is determined, :term:`view lookup` is then responsible -for finding and invoking a :term:`view callable`. A view callable is a -specific bit of code, defined in your application, that receives the -:term:`request` and returns a :term:`response` object. - -Where appropriate, we will describe how view lookup interacts with -:term:`resource location`. The :ref:`view_config_chapter` chapter describes -the details of :term:`view lookup`. +:term:`URL dispatch` provides a simple way to map URLs to :term:`view` code +using a simple pattern matching language. An ordered set of patterns is +checked one-by-one. If one of the patterns matches the path information +associated with a request, a particular :term:`view callable` is invoked. A +view callable is a specific bit of code, defined in your application, that +receives the :term:`request` and returns a :term:`response` object. High-Level Operational Overview ------------------------------- @@ -37,18 +21,14 @@ If route configuration is present in an application, the :app:`Pyramid` matching patterns present in a *route map*. If any route pattern matches the information in the :term:`request`, -:app:`Pyramid` will invoke :term:`view lookup` using a :term:`context` -resource generated by the route match. +:app:`Pyramid` will invoke :term:`view lookup` to find a matching view. -However, if no route pattern matches the information in the :term:`request` -provided to :app:`Pyramid`, it will fail over to using :term:`traversal` to -perform resource location and view lookup. +If no route pattern in the route map matches the information in the +:term:`request` provided in your application, :app:`Pyramid` will fail over +to using :term:`traversal` to perform resource location and view lookup. -Technically, URL dispatch is a :term:`resource location` mechanism (it finds -a context object). But ironically, using URL dispatch (instead of -:term:`traversal`) allows you to avoid thinking about your application in -terms of "resources" entirely, because it allows you to directly map a -:term:`view callable` to a route. +.. index:: + single: route configuration Route Configuration ------------------- @@ -67,8 +47,8 @@ attributes. .. _config-add-route: -Configuring a Route via The ``add_route`` Configurator Method -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Configuring a Route to Match a View +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The :meth:`pyramid.config.Configurator.add_route` method adds a single :term:`route configuration` to the :term:`application registry`. Here's an @@ -84,90 +64,45 @@ example: config.add_route('myroute', '/prefix/{one}/{two}') config.add_view(myview, route_name='myroute') -.. versionchanged:: 1.0a4 - Prior to 1.0a4, routes allow for a marker starting with a ``:``, for - example ``/prefix/:one/:two``. This style is now deprecated - in favor of ``{}`` usage which allows for additional functionality. - -.. index:: - single: route configuration; view callable - -.. _add_route_view_config: - -Route Configuration That Names a View Callable -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. warning:: This section describes a feature which has been deprecated in - Pyramid 1.1 and higher. In order to reduce confusion and documentation - burden, passing view-related parameters to - :meth:`~pyramid.config.Configurator.add_route` is deprecated. - - In versions earlier than 1.1, a view was permitted to be connected to a - route using a set of ``view*`` parameters passed to the - :meth:`~pyramid.config.Configurator.add_route`. This was a shorthand - which replaced the need to perform a subsequent call to - :meth:`~pyramid.config.Configurator.add_view` as described in - :ref:`config-add-route`. For example, it was valid (and often recommended) - to do: +When a :term:`view callable` added to the configuration by way of +:meth:`~pyramid.config.Configurator.add_view` bcomes associated with a route +via its ``route_name`` predicate, that view callable will always be found and +invoked when the associated route pattern matches during a request. - .. code-block:: python +More commonly, you will not use any ``add_view`` statements in your project's +"setup" code, instead only using ``add_route`` statements using a +:term:`scan` for to associate view callables with routes. For example, if +this is a portion of your project's ``__init__.py``: - config.add_route('home', '/', view='mypackage.views.myview', - view_renderer='some/renderer.pt') - - Instead of the equivalent: - - .. code-block:: python - - config.add_route('home', '/') - config.add_view('mypackage.views.myview', route_name='home') - renderer='some/renderer.pt') - - Passing ``view*`` arguments to ``add_route`` as shown in the first - example above is now deprecated in favor of connecting a view to a - predefined route via :meth:`~pyramid.config.Configurator.add_view` using - the route's ``route_name`` parameter, as shown in the second example - above. +.. code-block:: python - A deprecation warning is now issued when any view-related parameter is - passed to ``Configurator.add_route``. The recommended way to associate a - view with a route is documented in :ref:`config-add-route`. + # in your project's __init__.py (mypackage.__init__) -When a route configuration declaration names a ``view`` attribute, the value -of the attribute will reference a :term:`view callable`. This view callable -will be invoked when the route matches. A view callable, as described in -:ref:`views_chapter`, is developer-supplied code that "does stuff" as the -result of a request. + config.add_route('myroute', '/prefix/{one}/{two}') + config.scan('mypackage') -Here's an example route configuration that references a view callable: +Note that we don't call :meth:`~pyramid.config.Configurator.add_view` in this +setup code. However, the above :term:`scan` execution +``config.scan('mypackage')`` will pick up all :term:`configuration +decoration`, including any objects decorated with the +:class:`pyramid.view.view_config` decorator in the ``mypackage`` Python +pakage. For example, if you have a ``views.py`` in your package, a scan will +pick up any of its configuration decorators, so we can add one there that +that references ``myroute`` as a ``route_name`` parameter: .. code-block:: python - :linenos: - # "config" below is presumed to be an instance of the - # pyramid.config.Configurator class; "myview" is assumed - # to be a "view callable" function - from myproject.views import myview - config.add_route('myroute', '/prefix/{one}/{two}', view=myview) - -You can also pass a :term:`dotted Python name` as the ``view`` argument -rather than an actual callable: - -.. code-block:: python - :linenos: + # in your project's views.py module (mypackage.views) - # "config" below is presumed to be an instance of the - # pyramid.config.Configurator class; "myview" is assumed - # to be a "view callable" function - config.add_route('myroute', '/prefix/{one}/{two}', - view='myproject.views.myview') + from pyramid.view import view_config + from pyramid.response import Response -When a route configuration names a ``view`` attribute, the :term:`view -callable` named as that ``view`` attribute will always be found and invoked -when the associated route pattern matches during a request. + @view_config(route_name='myroute') + def myview(request): + return Response('OK') -See :meth:`pyramid.config.Configurator.add_route` for a description of -view-related arguments. +THe above combination of ``add_route`` and ``scan`` is completely equivalent +to using the previous combination of ``add_route`` and ``add_view``. .. index:: single: route path pattern syntax @@ -365,12 +300,11 @@ Route Declaration Ordering Route configuration declarations are evaluated in a specific order when a request enters the system. As a result, the order of route configuration -declarations is very important. - -The order that routes declarations are evaluated is the order in which they -are added to the application at startup time. This is unlike -:term:`traversal`, which depends on emergent behavior which happens as a -result of traversing a resource tree. +declarations is very important. The order that routes declarations are +evaluated is the order in which they are added to the application at startup +time. (This is unlike a different way of mapping URLs to code that +:app:`Pyramid` provides, named :term:`traversal`, which does not depend on +pattern ordering). For routes added via the :mod:`~pyramid.config.Configurator.add_route` method, the order that routes are evaluated is the order in which they are added to @@ -426,6 +360,9 @@ a separate :term:`ACL`, as documented in combine URL dispatch with :term:`traversal` as documented within :ref:`hybrid_chapter`. +.. index:: + single: route configuration arguments + Route Configuration Arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -439,13 +376,17 @@ the associated route to be considered a match during the route matching process. Examples of route predicate arguments are ``pattern``, ``xhr``, and ``request_method``. -Other arguments are view configuration related arguments. These only have an -effect when the route configuration names a ``view``. These arguments have -been deprecated as of :app:`Pyramid` 1.1 (see :ref:`add_route_view_config`). - Other arguments are ``name`` and ``factory``. These arguments represent neither predicates nor view configuration information. +.. warning:: Some arguments are view-configuration related arguments, such as + ``view_renderer``. These only have an effect when the route configuration + names a ``view`` and these arguments have been deprecated as of + :app:`Pyramid` 1.1. + +.. index:: + single: route predicates (custom) + .. _custom_route_predicates: Custom Route Predicates @@ -578,32 +519,38 @@ that the year match argument is '2010' if and only if the route name is See also :class:`pyramid.interfaces.IRoute` for more API documentation about route objects. +.. index:: + single: route matching + Route Matching -------------- The main purpose of route configuration is to match (or not match) the ``PATH_INFO`` present in the WSGI environment provided during a request -against a URL path pattern. +against a URL path pattern. ``PATH_INFO`` represents the path portion of the +URL that was requested. The way that :app:`Pyramid` does this is very simple. When a request enters the system, for each route configuration declaration present in the system, -:app:`Pyramid` checks the ``PATH_INFO`` against the pattern declared. - -If any route matches, the route matching process stops. The :term:`request` -is decorated with a special :term:`interface` which describes it as a "route -request", the :term:`context` resource is generated, and the context and the -resulting request are handed off to :term:`view lookup`. During view lookup, -if a :term:`view callable` associated with the matched route is found, that -view is called. +:app:`Pyramid` checks the request's ``PATH_INFO`` against the pattern +declared. This checking happens in the order that the routes were declared +via :meth:`pyramid.config.Configurator.add_route`. When a route configuration is declared, it may contain :term:`route predicate` arguments. All route predicates associated with a route declaration must be ``True`` for the route configuration to be used for a -given request. - -If any predicate in the set of :term:`route predicate` arguments provided to -a route configuration returns ``False``, that route is skipped and route -matching continues through the ordered set of routes. +given request during a check. If any predicate in the set of :term:`route +predicate` arguments provided to a route configuration returns ``False`` +during a check, that route is skipped and route matching continues through +the ordered set of routes. + +If any route matches, the route matching process stops and the :term:`view +lookup` subsystem takes over to find the most reasonable view callable for +the matched route. Most often, there's only one view that will match (a view +configured with a ``route_name`` argument matching the matched route). To +gain a better understanding of how routes and views are associated in a real +application, you can use the ``paster pviews`` command, as documented in +:ref:`displaying_matching_views`. If no route matches after all route patterns are exhausted, :app:`Pyramid` falls back to :term:`traversal` to do :term:`resource location` and @@ -789,6 +736,9 @@ representing a :term:`SQLAlchemy` model. single: matching the root URL single: root url (matching) +.. index:: + pair: matching; root URL + Matching the Root URL --------------------- @@ -958,6 +908,9 @@ The ``notfound_view`` supplied must adhere to the two-argument view callable calling convention of ``(context, request)`` (``context`` will be the exception object). +.. index:: + single: cleaning up after request + .. _cleaning_up_after_a_request: Cleaning Up After a Request @@ -1041,6 +994,9 @@ our sample ``Article`` factory class is not very ambitious. .. note:: See :ref:`security_chapter` for more information about :app:`Pyramid` security and ACLs. +.. index:: + pair: debugging; route matching + .. _debug_routematch_section: Debugging Route Matching @@ -1049,7 +1005,7 @@ Debugging Route Matching It's useful to be able to take a peek under the hood when requests that enter your application arent matching your routes as you expect them to. To debug route matching, use the ``PYRAMID_DEBUG_ROUTEMATCH`` environment variable or the -``debug_routematch`` configuration file setting (set either to ``true``). +``pyramid.debug_routematch`` configuration file setting (set either to ``true``). Details of the route matching decision for a particular request to the :app:`Pyramid` application will be printed to the ``stderr`` of the console which you started the application from. For example: @@ -1072,45 +1028,12 @@ which you started the application from. For example: See :ref:`environment_chapter` for more information about how, and where to set these values. -.. index:: - pair: routes; printing - single: paster proutes - -.. _displaying_application_routes: - -Displaying All Application Routes ---------------------------------- - -You can use the ``paster proutes`` command in a terminal window to print a -summary of routes related to your application. Much like the ``paster -pshell`` command (see :ref:`interactive_shell`), the ``paster proutes`` -command accepts two arguments. The first argument to ``proutes`` is the path -to your application's ``.ini`` file. The second is the ``app`` section name -inside the ``.ini`` file which points to your application. +You can also use the ``paster proutes`` command to see a display of all the +routes configured in your application; for more information, see +:ref:`displaying_application_routes`. -For example: - -.. code-block:: text - :linenos: - - [chrism@thinko MyProject]$ ../bin/paster proutes development.ini MyProject - Name Pattern View - ---- ------- ---- - home / <function my_view> - home2 / <function my_view> - another /another None - static/ static/*subpath <static_view object> - catchall /*subpath <function static_view> - -``paster proutes`` generates a table. The table has three columns: a Name -name column, a Pattern column, and a View column. The items listed in the -Name column are route names, the items listen in the Pattern column are route -patterns, and the items listed in the View column are representations of the -view callable that will be invoked when a request matches the associated -route pattern. The view column may show ``None`` if no associated view -callable could be found. If no routes are configured within your -application, nothing will be printed to the console when ``paster proutes`` -is executed. +.. index:: + pair: route; view callable lookup details Route View Callable Registration and Lookup Details --------------------------------------------------- @@ -1139,24 +1062,28 @@ when the route pattern is matched during a request. To do so: object is decorated with the route-specific interface. - The fact that the request is decorated with a route-specific interface - causes the view lookup machinery to always use the view callable registered - using that interface by the route configuration to service requests that - match the route pattern. - -In this way, we supply a shortcut to the developer. Under the hood, the -:term:`resource location` and :term:`view lookup` subsystems provided by -:app:`Pyramid` are still being utilized, but in a way which does not require -a developer to understand either of them in detail. It also means that we -can allow a developer to combine :term:`URL dispatch` and :term:`traversal` -in various exceptional cases as documented in :ref:`hybrid_chapter`. - -To gain a better understanding of how routes and views are associated in a -real application, you can use the ``paster pviews`` command, as documented -in :ref:`displaying_matching_views`. + causes the :term:`view lookup` machinery to always use the view callable + registered using that interface by the route configuration to service + requests that match the route pattern. + +As we can see from the above description, technically, URL dispatch doesn't +actually map a URL pattern directly to a view callable. Instead, URL +dispatch is a :term:`resource location` mechanism. A :app:`Pyramid` +:term:`resource location` subsystem (i.e., :term:`URL dispatch` or +:term:`traversal`) finds a :term:`resource` object that is the +:term:`context` of a :term:`request`. Once the :term:`context` is determined, +a separate subsystem named :term:`view lookup` is then responsible for +finding and invoking a :term:`view callable` based on information available +in the context and the request. When URL dispatch is used, the resource +location and view lookup subsystems provided by :app:`Pyramid` are still +being utilized, but in a way which does not require a developer to understand +either of them in detail. + +If no route is matched using :term:`URL dispatch`, :app:`Pyramid` falls back +to :term:`traversal` to handle the :term:`request`. References ---------- A tutorial showing how :term:`URL dispatch` can be used to create a :app:`Pyramid` application exists in :ref:`bfg_sql_wiki_tutorial`. - diff --git a/docs/narr/vhosting.rst b/docs/narr/vhosting.rst index d3ff260e3..5679cc2e2 100644 --- a/docs/narr/vhosting.rst +++ b/docs/narr/vhosting.rst @@ -14,6 +14,9 @@ URL space that it does not "naturally" inhabit. a URL "prefix", as well as serving a *portion* of a :term:`traversal` based application under a root URL. +.. index:: + single: hosting an app under a prefix + Hosting an Application Under a URL Prefix ----------------------------------------- diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst index ec42446ff..a1b12ad2a 100644 --- a/docs/narr/viewconfig.rst +++ b/docs/narr/viewconfig.rst @@ -2,38 +2,27 @@ .. _view_configuration: +.. _view_lookup: + View Configuration ================== .. index:: single: view lookup -:term:`View configuration` controls how :term:`view lookup` operates in -your application. In earlier chapters, you have been exposed to a few -simple view configuration declarations without much explanation. In this -chapter we will explore the subject in detail. - -.. _view_lookup: +:term:`View lookup` is the :app:`Pyramid` subsystem responsible for finding +and invoking a :term:`view callable`. :term:`View configuration` controls how +:term:`view lookup` operates in your application. During any given request, +view configuration information is compared against request data by the view +lookup subsystem in order to find the "best" view callable for that request. -View Lookup and Invocation --------------------------- +In earlier chapters, you have been exposed to a few simple view configuration +declarations without much explanation. In this chapter we will explore the +subject in detail. -:term:`View lookup` is the :app:`Pyramid` subsystem responsible for finding -an invoking a :term:`view callable`. The view lookup subsystem is passed a -:term:`context` and a :term:`request` object. - -:term:`View configuration` information stored within in the -:term:`application registry` is compared against the context and request by -the view lookup subsystem in order to find the "best" view callable for the -set of circumstances implied by the context and request. - -:term:`View predicate` attributes are an important part of view -configuration that enables the :term:`View lookup` subsystem to find and -invoke the appropriate view. Predicate attributes can be thought of -like "narrowers". In general, the greater number of predicate -attributes possessed by a view's configuration, the more specific the -circumstances need to be before the registered view callable will be -invoked. +.. index:: + pair: resource; mapping to view callable + pair: URL pattern; mapping to view callable Mapping a Resource or URL Pattern to a View Callable ---------------------------------------------------- @@ -47,7 +36,7 @@ to be invoked. A view configuration statement is made about information present in the :term:`context` resource and the :term:`request`. -View configuration is performed in one of these ways: +View configuration is performed in one of two ways: - by running a :term:`scan` against application source code which has a :class:`pyramid.view.view_config` decorator attached to a Python object as @@ -56,16 +45,8 @@ View configuration is performed in one of these ways: - by using the :meth:`pyramid.config.Configurator.add_view` method as per :ref:`mapping_views_using_imperative_config_section`. -- By specifying a view within a :term:`route configuration`. View - configuration via a route configuration is performed by using the - :meth:`pyramid.config.Configurator.add_route` method, passing a ``view`` - argument specifying a view callable. This pattern of view configuration is - deprecated as of :app:`Pyramid` 1.1. - -.. note:: A package named ``pyramid_handlers`` (available from PyPI) provides - an analogue of :term:`Pylons` -style "controllers", which are a special - kind of view class which provides more automation when your application - uses :term:`URL dispatch` solely. +.. index:: + single: view configuration parameters .. _view_configuration_parameters: @@ -79,12 +60,15 @@ arguments. View predicate arguments used during view configuration are used to narrow the set of circumstances in which :term:`view lookup` will find a particular view callable. -In general, the fewer number of predicates which are supplied to a -particular view configuration, the more likely it is that the associated -view callable will be invoked. The greater the number supplied, the -less likely. A view with five predicates will always be found and -evaluated before a view with two, for example. All predicates must -match for the associated view to be called. +:term:`View predicate` attributes are an important part of view configuration +that enables the :term:`view lookup` subsystem to find and invoke the +appropriate view. The greater number of predicate attributes possessed by a +view's configuration, the more specific the circumstances need to be before +the registered view callable will be invoked. The fewer number of predicates +which are supplied to a particular view configuration, the more likely it is +that the associated view callable will be invoked. A view with five +predicates will always be found and evaluated before a view with two, for +example. All predicates must match for the associated view to be called. This does not mean however, that :app:`Pyramid` "stops looking" when it finds a view registration with predicates that don't match. If one set @@ -99,12 +83,14 @@ the request, :app:`Pyramid` will return an error to the user's browser, representing a "not found" (404) page. See :ref:`changing_the_notfound_view` for more information about changing the default notfound view. -Some view configuration arguments are non-predicate arguments. These tend to -modify the response of the view callable or prevent the view callable from +Other view configuration arguments are non-predicate arguments. These tend +to modify the response of the view callable or prevent the view callable from being invoked due to an authorization policy. The presence of non-predicate arguments in a view configuration does not narrow the circumstances in which the view callable will be invoked. +.. _nonpredicate_view_args: + Non-Predicate Arguments +++++++++++++++++++++++ @@ -249,8 +235,10 @@ arguments that are supplied, the more specific, and narrower the usage of the configured view. ``name`` - The :term:`view name` required to match this view callable. Read - :ref:`traversal_chapter` to understand the concept of a view name. + The :term:`view name` required to match this view callable. A ``name`` + argument is typically only used when your application uses + :term:`traversal`. Read :ref:`traversal_chapter` to understand the concept + of a view name. If ``name`` is not supplied, the empty string is used (implying the default view). @@ -405,29 +393,23 @@ configured view. .. _mapping_views_using_a_decorator_section: -View Configuration Using the ``@view_config`` Decorator -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -For better locality of reference, you may use the -:class:`pyramid.view.view_config` decorator to associate your view functions -with URLs instead of using imperative configuration for the same purpose. +Adding View Configuration Using the ``@view_config`` Decorator +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. warning:: Using this feature tends to slows down application startup slightly, as more work is performed at application startup to scan for view - declarations. + configuration declarations. For maximum startup performance, use the view + configuration method described in + :ref:`mapping_views_using_imperative_config_section` instead. -Usage of the ``view_config`` decorator is a form of :term:`declarative -configuration` in decorator form. :class:`~pyramid.view.view_config` can be -used to associate :term:`view configuration` information -- as done via the -equivalent imperative code -- with a function that acts as a :app:`Pyramid` -view callable. All arguments to the -:meth:`pyramid.config.Configurator.add_view` method (save for the ``view`` -argument) are available in decorator form and mean precisely the same thing. +The :class:`~pyramid.view.view_config` decorator can be used to associate +:term:`view configuration` information with a function, method, or class that +acts as a :app:`Pyramid` view callable. -An example of the :class:`~pyramid.view.view_config` decorator might reside in -a :app:`Pyramid` application module ``views.py``: +Here's an example of the :class:`~pyramid.view.view_config` decorator that +lives within a :app:`Pyramid` application module ``views.py``: .. ignore-next-block .. code-block:: python @@ -437,8 +419,7 @@ a :app:`Pyramid` application module ``views.py``: from pyramid.view import view_config from pyramid.response import Response - @view_config(name='my_view', request_method='POST', context=MyResource, - permission='read') + @view_config(route_name='ok', request_method='POST', permission='read') def my_view(request): return Response('OK') @@ -449,9 +430,8 @@ configuration stanza: .. code-block:: python :linenos: - config.add_view('mypackage.views.my_view', name='my_view', - request_method='POST', context=MyResource, - permission='read') + config.add_view('mypackage.views.my_view', route_name='ok', + request_method='POST', permission='read') All arguments to ``view_config`` may be omitted. For example: @@ -494,6 +474,17 @@ See :ref:`configuration_module` for additional API arguments to the allows you to supply a ``package`` argument to better control exactly *which* code will be scanned. +All arguments to the :class:`~pyramid.view.view_config` decorator mean +precisely the same thing as they would if they were passed as arguments to +the :meth:`pyramid.config.Configurator.add_view` method save for the ``view`` +argument. Usage of the :class:`~pyramid.view.view_config` decorator is a +form of :term:`declarative configuration`, while +:meth:`pyramid.config.Configurator.add_view` is a form of :term:`imperative +configuration`. However, they both do the same thing. + +.. index:: + single: view_config placement + ``@view_config`` Placement ++++++++++++++++++++++++++ @@ -508,7 +499,7 @@ If your view callable is a function, it may be used as a function decorator: from pyramid.view import view_config from pyramid.response import Response - @view_config(name='edit') + @view_config(route_name='edit') def edit(request): return Response('edited!') @@ -523,7 +514,7 @@ against a class as when they are applied against a function. For example: from pyramid.response import Response from pyramid.view import view_config - @view_config() + @view_config(route_name='hello') class MyView(object): def __init__(self, request): self.request = request @@ -548,7 +539,7 @@ decorator syntactic sugar, if you wish: def __call__(self): return Response('hello') - my_view = view_config()(MyView) + my_view = view_config(route_name='hello')(MyView) More than one :class:`~pyramid.view.view_config` decorator can be stacked on top of any number of others. Each decorator creates a separate view @@ -560,8 +551,8 @@ registration. For example: from pyramid.view import view_config from pyramid.response import Response - @view_config(name='edit') - @view_config(name='change') + @view_config(route_name='edit') + @view_config(route_name='change') def edit(request): return Response('edited!') @@ -579,7 +570,7 @@ The decorator can also be used against a method of a class: def __init__(self, request): self.request = request - @view_config(name='hello') + @view_config(route_name='hello') def amethod(self): return Response('hello') @@ -601,7 +592,7 @@ against the ``amethod`` method could be spelled equivalently as the below: from pyramid.response import Response from pyramid.view import view_config - @view_config(attr='amethod', name='hello') + @view_config(attr='amethod', route_name='hello') class MyView(object): def __init__(self, request): self.request = request @@ -614,13 +605,14 @@ against the ``amethod`` method could be spelled equivalently as the below: .. _mapping_views_using_imperative_config_section: -View Registration Using :meth:`~pyramid.config.Configurator.add_view` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Adding View Configuration Using :meth:`~pyramid.config.Configurator.add_view` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The :meth:`pyramid.config.Configurator.add_view` method within -:ref:`configuration_module` is used to configure a view imperatively. The -arguments to this method are very similar to the arguments that you provide -to the ``@view_config`` decorator. For example: +:ref:`configuration_module` is used to configure a view "imperatively" +(without a :class:`~pyramid.view.view_config` decorator). The arguments to +this method are very similar to the arguments that you provide to the +:class:`~pyramid.view.view_config` decorator. For example: .. code-block:: python :linenos: @@ -632,108 +624,17 @@ to the ``@view_config`` decorator. For example: # config is assumed to be an instance of the # pyramid.config.Configurator class - config.add_view(hello_world, name='hello.html') + config.add_view(hello_world, route_name='hello') The first argument, ``view``, is required. It must either be a Python object which is the view itself or a :term:`dotted Python name` to such an object. -All other arguments are optional. See -:meth:`pyramid.config.Configurator.add_view` for more information. - -.. index:: - single: resource interfaces - -.. _using_resource_interfaces: - -Using Resource Interfaces In View Configuration -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Instead of registering your views with a ``context`` that names a Python -resource *class*, you can optionally register a view callable with a -``context`` which is an :term:`interface`. An interface can be attached -arbitrarily to any resource object. View lookup treats context interfaces -specially, and therefore the identity of a resource can be divorced from that -of the class which implements it. As a result, associating a view with an -interface can provide more flexibility for sharing a single view between two -or more different implementations of a resource type. For example, if two -resource objects of different Python class types share the same interface, -you can use the same view configuration to specify both of them as a -``context``. - -In order to make use of interfaces in your application during view dispatch, -you must create an interface and mark up your resource classes or instances -with interface declarations that refer to this interface. - -To attach an interface to a resource *class*, you define the interface and -use the :func:`zope.interface.implements` function to associate the interface -with the class. - -.. code-block:: python - :linenos: +In the above example, ``view`` is the ``hello_world`` function. All other +arguments are optional. See :meth:`pyramid.config.Configurator.add_view` for +more information. - from zope.interface import Interface - from zope.interface import implements - - class IHello(Interface): - """ A marker interface """ - - class Hello(object): - implements(IHello) - -To attach an interface to a resource *instance*, you define the interface and -use the :func:`zope.interface.alsoProvides` function to associate the -interface with the instance. This function mutates the instance in such a -way that the interface is attached to it. - -.. code-block:: python - :linenos: - - from zope.interface import Interface - from zope.interface import alsoProvides - - class IHello(Interface): - """ A marker interface """ - - class Hello(object): - pass - - def make_hello(): - hello = Hello() - alsoProvides(hello, IHello) - return hello - -Regardless of how you associate an interface, with a resource instance, or a -resource class, the resulting code to associate that interface with a view -callable is the same. Assuming the above code that defines an ``IHello`` -interface lives in the root of your application, and its module is named -"resources.py", the interface declaration below will associate the -``mypackage.views.hello_world`` view with resources that implement, or -provide, this interface. - -.. code-block:: python - :linenos: - - # config is an instance of pyramid.config.Configurator - - config.add_view('mypackage.views.hello_world', name='hello.html', - context='mypackage.resources.IHello') - -Any time a resource that is determined to be the :term:`context` provides -this interface, and a view named ``hello.html`` is looked up against it as -per the URL, the ``mypackage.views.hello_world`` view callable will be -invoked. - -Note, in cases where a view is registered against a resource class, and a -view is also registered against an interface that the resource class -implements, an ambiguity arises. Views registered for the resource class take -precedence over any views registered for any interface the resource class -implements. Thus, if one view configuration names a ``context`` of both the -class type of a resource, and another view configuration names a ``context`` -of interface implemented by the resource's class, and both view -configurations are otherwise identical, the view registered for the context's -class will "win". - -For more information about defining resources with interfaces for use within -view configuration, see :ref:`resources_which_implement_interfaces`. +When you use only :meth:`~pyramid.config.Configurator.add_view` to add view +configurations, you don't need to issue a :term:`scan` in order for the view +configuration to take effect. .. index:: single: view security @@ -756,8 +657,9 @@ configuration using :meth:`~pyramid.config.Configurator.add_view`: # config is an instance of pyramid.config.Configurator - config.add_view('myproject.views.add_entry', name='add.html', - context='myproject.resources.IBlog', permission='add') + config.add_route('add', '/add.html', factory='mypackage.Blog') + config.add_view('myproject.views.add_entry', route_name='add', + permission='add') When an :term:`authorization policy` is enabled, this view will be protected with the ``add`` permission. The view will *not be called* if the user does @@ -777,105 +679,71 @@ per :ref:`protecting_views`. It's useful to be able to debug :exc:`NotFound` error responses when they occur unexpectedly due to an application registry misconfiguration. To debug these errors, use the ``PYRAMID_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. +``pyramid.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. .. index:: - pair: matching views; printing - single: paster pviews + single: HTTP caching -.. _displaying_matching_views: +.. _influencing_http_caching: -Displaying Matching Views for a Given URL ------------------------------------------ +Influencing HTTP Caching +------------------------ -For a big application with several views, it can be hard to keep the view -configuration details in your head, even if you defined all the views -yourself. You can use the ``paster pviews`` command in a terminal window to -print a summary of matching routes and views for a given URL in your -application. The ``paster pviews`` command accepts three arguments. The -first argument to ``pviews`` is the path to your application's ``.ini`` file. -The second is the ``app`` section name inside the ``.ini`` file which points -to your application. The third is the URL to test for matching views. +.. note:: This feature is new in Pyramid 1.1. -Here is an example for a simple view configuration using :term:`traversal`: +When a non-``None`` ``http_cache`` argument is passed to a view +configuration, Pyramid will set ``Expires`` and ``Cache-Control`` response +headers in the resulting response, causing browsers to cache the response +data for some time. See ``http_cache`` in :ref:`nonpredicate_view_args` for +the its allowable values and what they mean. -.. code-block:: text - :linenos: +Sometimes it's undesirable to have these headers set as the result of +returning a response from a view, even though you'd like to decorate the view +with a view configuration decorator that has ``http_cache``. Perhaps there's +an alternate branch in your view code that returns a response that should +never be cacheable, while the "normal" branch returns something that should +always be cacheable. If this is the case, set the ``prevent_auto`` attribute +of the ``response.cache_control`` object to a non-``False`` value. For +example, the below view callable is configured with a ``@view_config`` +decorator that indicates any response from the view should be cached for 3600 +seconds. However, the view itself prevents caching from taking place unless +there's a ``should_cache`` GET or POST variable: - $ ../bin/paster pviews development.ini tutorial /FrontPage +.. code-block:: python - URL = /FrontPage + from pyramid.view import view_config - context: <tutorial.models.Page object at 0xa12536c> - view name: + @view_config(http_cache=3600) + def view(request): + response = Response() + if not 'should_cache' in request.params: + response.cache_control.prevent_auto = True + return response - View: - ----- - tutorial.views.view_page - required permission = view +Note that the ``http_cache`` machinery will overwrite or add to caching +headers you set within the view itself unless you use ``preserve_auto``. -The output always has the requested URL at the top and below that all the -views that matched with their view configuration details. In this example -only one view matches, so there is just a single *View* section. For each -matching view, the full code path to the associated view callable is shown, -along with any permissions and predicates that are part of that view -configuration. +You can also turn of the effect of ``http_cache`` entirely for the duration +of a Pyramid application lifetime. To do so, set the +``PYRAMID_PREVENT_HTTP_CACHE`` environment variable or the +``pyramid.prevent_http_cache`` configuration value setting to a true value. +For more information, see :ref:`preventing_http_caching`. -A more complex configuration might generate something like this: +Note that setting ``pyramid.prevent_http_cache`` will have no effect on caching +headers that your application code itself sets. It will only prevent caching +headers that would have been set by the Pyramid HTTP caching machinery +invoked as the result of the ``http_cache`` argument to view configuration. -.. code-block:: text - :linenos: +.. index:: + pair: view configuration; debugging - $ ../bin/paster pviews development.ini shootout /about - - URL = /about - - context: <shootout.models.RootFactory object at 0xa56668c> - view name: about - - Route: - ------ - route name: about - route pattern: /about - route path: /about - subpath: - route predicates (request method = GET) - - View: - ----- - shootout.views.about_view - required permission = view - view predicates (request_param testing, header X/header) - - Route: - ------ - route name: about_post - route pattern: /about - route path: /about - subpath: - route predicates (request method = POST) - - View: - ----- - shootout.views.about_view_post - required permission = view - view predicates (request_param test) - - View: - ----- - shootout.views.about_view_post2 - required permission = view - view predicates (request_param test2) - -In this case, we are dealing with a :term:`URL dispatch` application. This -specific URL has two matching routes. The matching route information is -displayed first, followed by any views that are associated with that route. -As you can see from the second matching route output, a route can be -associated with more than one view. - -For a URL that doesn't match any views, ``paster pviews`` will simply print -out a *Not found* message. +Debugging View Configuration +---------------------------- +See :ref:`displaying_matching_views` for information about how to display +each of the view callables that might match for a given URL. This can be an +effective way to figure out why a particular view callable is being called +instead of the one you'd like to be called. diff --git a/docs/narr/views.rst b/docs/narr/views.rst index cbd8fcfb7..a3fd61098 100644 --- a/docs/narr/views.rst +++ b/docs/narr/views.rst @@ -3,10 +3,10 @@ Views ===== -One of the primary jobs of :app:`Pyramid` is to find and invoke a -:term:`view callable` when a :term:`request` reaches your application. View -callables are bits of code which do something interesting in response to a -request made to your application. +One of the primary jobs of :app:`Pyramid` is to find and invoke a :term:`view +callable` when a :term:`request` reaches your application. View callables +are bits of code which do something interesting in response to a request made +to your application. They are the "meat" of any interesting web application. .. note:: @@ -17,48 +17,32 @@ request made to your application. that implements a view *callable*, and the process of view *lookup*. -The :ref:`urldispatch_chapter`, and :ref:`traversal_chapter` chapters -describes how, using information from the :term:`request`, a -:term:`context` resource is computed. But the context resource itself -isn't very useful without an associated :term:`view callable`. A view -callable returns a response to a user, often using the context resource -to do so. +This chapter describes how view callables should be defined. We'll have to +wait until a following chapter (entitled :ref:`view_config_chapter`) to find +out how we actually tell :app:`Pyramid` to wire up view callables to +particular URL patterns and other request circumstances. -The job of actually locating and invoking the "best" :term:`view callable` is -the job of the :term:`view lookup` subsystem. The view lookup subsystem -compares the resource supplied by :term:`resource location` and information -in the :term:`request` against :term:`view configuration` statements made by -the developer to choose the most appropriate view callable for a specific -set of circumstances. - -This chapter describes how view callables work. In the -:ref:`view_config_chapter` chapter, there are details about performing -view configuration, and a detailed explanation of view lookup. +.. index:: + single: view callables View Callables -------------- View callables are, at the risk of sounding obvious, callable Python -objects. Specifically, view callables can be functions, classes, or -instances that implement an ``__call__`` method (making the -instance callable). +objects. Specifically, view callables can be functions, classes, or instances +that implement an ``__call__`` method (making the instance callable). View callables must, at a minimum, accept a single argument named ``request``. This argument represents a :app:`Pyramid` :term:`Request` -object. A request object encapsulates a WSGI environment provided to -:app:`Pyramid` by the upstream :term:`WSGI` server. As you might expect, -the request object contains everything your application needs to know -about the specific HTTP request being made. +object. A request object represents a :term:`WSGI` environment provided to +:app:`Pyramid` by the upstream WSGI server. As you might expect, the request +object contains everything your application needs to know about the specific +HTTP request being made. A view callable's ultimate responsibility is to create a :mod:`Pyramid` -:term:`Response` object. This can be done by creating the response object in -the view callable code and returning it directly, as we will be doing in this -chapter. However, if a view callable does not return a response itself, it -can be configured to use a :term:`renderer` that converts its return value -into a :term:`Response` object. Using renderers is the common way that -templates are used with view callables to generate markup: see the -:ref:`renderers_chapter` chapter for details. In some cases, a response may -also be generated by raising an exception within a view callable. +:term:`Response` object. This can be done by creating a :term:`Response` +object in the view callable code and returning it directly or by raising +special kinds of exceptions from within the body of a view callable. .. index:: single: view calling convention @@ -129,85 +113,6 @@ statements with different ``attr`` values, each pointing at a different method of the class if you'd like the class to represent a collection of related view callables. -.. note:: A package named :term:`pyramid_handlers` (available from PyPI) - provides an analogue of :term:`Pylons` -style "controllers", which are a - special kind of view class which provides more automation when your - application uses :term:`URL dispatch` solely. - -.. index:: - single: view calling convention - -.. _request_and_context_view_definitions: - -Alternate View Callable Argument/Calling Conventions ----------------------------------------------------- - -Usually, view callables are defined to accept only a single argument: -``request``. However, view callables may alternately be defined as classes, -functions, or any callable that accept *two* positional arguments: a -:term:`context` resource as the first argument and a :term:`request` as the -second argument. - -The :term:`context` and :term:`request` arguments passed to a view function -defined in this style can be defined as follows: - -context - - The :term:`resource` object found via tree :term:`traversal` or :term:`URL - dispatch`. - -request - A :app:`Pyramid` Request object representing the current WSGI request. - -The following types work as view callables in this style: - -#. Functions that accept two arguments: ``context``, and ``request``, - e.g.: - - .. code-block:: python - :linenos: - - from pyramid.response import Response - - def view(context, request): - return Response('OK') - -#. Classes that have an ``__init__`` method that accepts ``context, - request`` and a ``__call__`` method which accepts no arguments, e.g.: - - .. code-block:: python - :linenos: - - from pyramid.response import Response - - class view(object): - def __init__(self, context, request): - self.context = context - self.request = request - - def __call__(self): - return Response('OK') - -#. Arbitrary callables that have a ``__call__`` method that accepts - ``context, request``, e.g.: - - .. code-block:: python - :linenos: - - from pyramid.response import Response - - class View(object): - def __call__(self, context, request): - return Response('OK') - view = View() # this is the view callable - -This style of calling convention is most useful for :term:`traversal` based -applications, where the context object is frequently used within the view -callable code itself. - -No matter which view calling convention is used, the view code always has -access to the context via ``request.context``. - .. index:: single: view response single: response @@ -234,15 +139,16 @@ implements the :term:`Response` interface is to return a inherit from :class:`pyramid.response.Response`. For example, an instance of the class :class:`pyramid.httpexceptions.HTTPFound` is also a valid response object because it inherits from :class:`~pyramid.response.Response`. For -examples, see :ref:`http_exceptions` and ref:`http_redirect`. +examples, see :ref:`http_exceptions` and :ref:`http_redirect`. + +.. note:: -You can also return objects from view callables that aren't instances of (or -instances of classes which are subclasses of) -:class:`pyramid.response.Response` in various circumstances. This can be -helpful when writing tests and when attempting to share code between view -callables. See :ref:`renderers_chapter` for the common way to allow for -this. A much less common way to allow for view callables to return -non-Response objects is documented in :ref:`using_iresponse`. + You can also return objects from view callables that aren't instances of + :class:`pyramid.response.Response` in various circumstances. This can be + helpful when writing tests and when attempting to share code between view + callables. See :ref:`renderers_chapter` for the common way to allow for + this. A much less common way to allow for view callables to return + non-Response objects is documented in :ref:`using_iresponse`. .. index:: single: view exceptions @@ -483,7 +389,7 @@ various other clients. In :app:`Pyramid`, form submission handling logic is always part of a :term:`view`. For a general overview of how to handle form submission data using the :term:`WebOb` API, see :ref:`webob_chapter` and `"Query and POST variables" within the WebOb documentation -<http://pythonpaste.org/webob/reference.html#query-post-variables>`_. +<http://docs.webob.org/en/latest/reference.html#query-post-variables>`_. :app:`Pyramid` defers to WebOb for its request and response implementations, and handling form submission data is a property of the request implementation. Understanding WebOb's request API is the key to @@ -591,3 +497,88 @@ using your own response object, you will need to ensure you do this yourself. configuration. The keys are still (byte) strings. +.. index:: + single: view calling convention + +.. _request_and_context_view_definitions: + +Alternate View Callable Argument/Calling Conventions +---------------------------------------------------- + +Usually, view callables are defined to accept only a single argument: +``request``. However, view callables may alternately be defined as classes, +functions, or any callable that accept *two* positional arguments: a +:term:`context` resource as the first argument and a :term:`request` as the +second argument. + +The :term:`context` and :term:`request` arguments passed to a view function +defined in this style can be defined as follows: + +context + + The :term:`resource` object found via tree :term:`traversal` or :term:`URL + dispatch`. + +request + A :app:`Pyramid` Request object representing the current WSGI request. + +The following types work as view callables in this style: + +#. Functions that accept two arguments: ``context``, and ``request``, + e.g.: + + .. code-block:: python + :linenos: + + from pyramid.response import Response + + def view(context, request): + return Response('OK') + +#. Classes that have an ``__init__`` method that accepts ``context, + request`` and a ``__call__`` method which accepts no arguments, e.g.: + + .. code-block:: python + :linenos: + + from pyramid.response import Response + + class view(object): + def __init__(self, context, request): + self.context = context + self.request = request + + def __call__(self): + return Response('OK') + +#. Arbitrary callables that have a ``__call__`` method that accepts + ``context, request``, e.g.: + + .. code-block:: python + :linenos: + + from pyramid.response import Response + + class View(object): + def __call__(self, context, request): + return Response('OK') + view = View() # this is the view callable + +This style of calling convention is most useful for :term:`traversal` based +applications, where the context object is frequently used within the view +callable code itself. + +No matter which view calling convention is used, the view code always has +access to the context via ``request.context``. + +.. index:: + single: Pylons-style controller dispatch + +Pylons-1.0-Style "Controller" Dispatch +-------------------------------------- + +A package named :term:`pyramid_handlers` (available from PyPI) provides an +analogue of :term:`Pylons` -style "controllers", which are a special kind of +view class which provides more automation when your application uses +:term:`URL dispatch` solely. + diff --git a/docs/narr/webob.rst b/docs/narr/webob.rst index 0ff8e1de7..106024db3 100644 --- a/docs/narr/webob.rst +++ b/docs/narr/webob.rst @@ -22,9 +22,9 @@ of :class:`webob.Request`. The :term:`response` returned from a WebOb is a project separate from :app:`Pyramid` with a separate set of authors and a fully separate `set of documentation -<http://pythonpaste.org/webob/>`_. Pyramid adds some functionality to the -standard WebOb request, which is documented in the :ref:`request_module` API -documentation. +<http://docs.webob.org/en/latest/index.html>`_. Pyramid adds some +functionality to the standard WebOb request, which is documented in the +:ref:`request_module` API documentation. WebOb provides objects for HTTP requests and responses. Specifically it does this by wrapping the `WSGI <http://wsgi.org>`_ request environment and @@ -35,7 +35,7 @@ requests and forming WSGI responses. WebOb is a nice way to represent "raw" WSGI requests and responses; however, we won't cover that use case in this document, as users of :app:`Pyramid` don't typically need to use the WSGI-related features of WebOb directly. The `reference documentation -<http://pythonpaste.org/webob/reference.html>`_ shows many examples of +<http://docs.webob.org/en/latest/reference.html>`_ shows many examples of creating requests and using response objects in this manner, however. .. index:: @@ -78,6 +78,10 @@ object: ``PUT``. You can also get ``req.body_file`` for a file-like object. +``req.json_body`` + The JSON-decoded contents of the body of the request. See + :ref:`request_json_body`. + ``req.cookies``: A simple dictionary of all the cookies. @@ -239,6 +243,73 @@ tuples; all the keys are ordered, and all the values are ordered. API documentation for a multidict exists as :class:`pyramid.interfaces.IMultiDict`. +.. index:: + pair: json_body; request + +.. _request_json_body: + +Dealing With A JSON-Encoded Request Body +++++++++++++++++++++++++++++++++++++++++ + +.. note:: this feature is new as of Pyramid 1.1. + +:attr:`pyramid.request.Request.json_body` is a property that returns a +:term:`JSON` -decoded representation of the request body. If the request +does not have a body, or the body is not a properly JSON-encoded value, an +exception will be raised when this attribute is accessed. + +This attribute is useful when you invoke a Pyramid view callable via +e.g. jQuery's ``$.ajax`` function, which has the potential to send a request +with a JSON-encoded body. + +Using ``request.json_body`` is equivalent to: + +.. code-block:: python + + from json import loads + loads(request.body, encoding=request.charset) + +Here's how to construct an AJAX request in Javascript using :term:`jQuery` +that allows you to use the ``request.json_body`` attribute when the request +is sent to a Pyramid application: + +.. code-block:: javascript + + jQuery.ajax({type:'POST', + url: 'http://localhost:6543/', // the pyramid server + data: JSON.stringify({'a':1}), + contentType: 'application/json; charset=utf-8'}); + +When such a request reaches a view in your application, the +``request.json_body`` attribute will be available in the view callable body. + +.. code-block:: javascript + + @view_config(renderer='string') + def aview(request): + print request.json_body + return 'OK' + +For the above view, printed to the console will be: + +.. code-block:: python + + {u'a': 1} + +For bonus points, here's a bit of client-side code that will produce a +request that has a body suitable for reading via ``request.json_body`` using +Python's ``urllib2`` instead of a Javascript AJAX request: + +.. code-block:: python + + import urllib2 + import json + + json_payload = json.dumps({'a':1}) + headers = {'Content-Type':'application/json; charset=utf-8'} + req = urllib2.Request('http://localhost:6543/', json_payload, headers) + resp = urllib2.urlopen(req) + More Details ++++++++++++ @@ -246,8 +317,8 @@ More detail about the request object API is available in: - The :class:`pyramid.request.Request` API documentation. -- The `WebOb documentation <http://pythonpaste.org/webob>`_. All - methods and attributes of a ``webob.Request`` documented within the +- The `WebOb documentation <http://docs.webob.org/en/latest/index.html>`_. + All methods and attributes of a ``webob.Request`` documented within the WebOb documentation will work with request objects created by :app:`Pyramid`. @@ -331,7 +402,7 @@ properties. These are parsed, so you can do things like ``response.last_modified = os.path.getmtime(filename)``. The details are available in the `extracted Response documentation -<http://pythonpaste.org/webob/class-webob.Response.html>`_. +<http://docs.webob.org/en/latest/modules/webob.html#headers>`_. .. index:: single: response (creating) @@ -354,7 +425,7 @@ anything, though if you subclass :class:`pyramid.response.Response` and set ``default_content_type`` you can override this behavior. .. index:: - single: response exceptions + single: exception responses Exception Responses +++++++++++++++++++ @@ -390,5 +461,6 @@ More Details More details about the response object API are available in the :mod:`pyramid.response` documentation. More details about exception responses are in the :mod:`pyramid.httpexceptions` API documentation. The -`WebOb documentation <http://pythonpaste.org/webob>`_ is also useful. +`WebOb documentation <http://docs.webob.org/en/latest/index.html>`_ is also +useful. diff --git a/docs/narr/zca.rst b/docs/narr/zca.rst index a99fd8b24..96aac6a80 100644 --- a/docs/narr/zca.rst +++ b/docs/narr/zca.rst @@ -245,7 +245,6 @@ registry at startup time instead of constructing a new one: globalreg = getGlobalSiteManager() config = Configurator(registry=globalreg) config.setup_registry(settings=settings) - config.hook_zca() config.include('some.other.application') return config.make_wsgi_app() diff --git a/docs/remake b/docs/remake new file mode 100755 index 000000000..b236f2976 --- /dev/null +++ b/docs/remake @@ -0,0 +1 @@ +make clean html SPHINXBUILD=../env26/bin/sphinx-build diff --git a/docs/tutorials/modwsgi/index.rst b/docs/tutorials/modwsgi/index.rst index 6e3e4ce37..485eec169 100644 --- a/docs/tutorials/modwsgi/index.rst +++ b/docs/tutorials/modwsgi/index.rst @@ -102,8 +102,7 @@ commands and files. # play badly with C extensions. WSGIApplicationGroup %{GLOBAL} WSGIPassAuthorization On - WSGIDaemonProcess pyramid user=chrism group=staff processes=1 \ - threads=4 \ + WSGIDaemonProcess pyramid user=chrism group=staff threads=4 \ python-path=/Users/chrism/modwsgi/env/lib/python2.6/site-packages WSGIScriptAlias /myapp /Users/chrism/modwsgi/env/pyramid.wsgi diff --git a/docs/tutorials/wiki/src/authorization/development.ini b/docs/tutorials/wiki/src/authorization/development.ini index 1ba746d0e..8c60f4ea9 100644 --- a/docs/tutorials/wiki/src/authorization/development.ini +++ b/docs/tutorials/wiki/src/authorization/development.ini @@ -1,25 +1,22 @@ [app:tutorial] use = egg:tutorial -reload_templates = true -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = true -default_locale_name = en +pyramid.reload_templates = true +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = true +pyramid.default_locale_name = en +pyramid.include = pyramid_debugtoolbar + pyramid_tm +pyramid_tm.attempts = 3 + zodb_uri = file://%(here)s/Data.fs?connection_cache_size=20000 [pipeline:main] pipeline = - egg:WebError#evalerror egg:repoze.zodbconn#closer - egg:repoze.retry#retry - tm tutorial -[filter:tm] -use = egg:repoze.tm2#tm -commit_veto = repoze.tm:default_commit_veto - [server:main] use = egg:Paste#http host = 0.0.0.0 diff --git a/docs/tutorials/wiki/src/authorization/production.ini b/docs/tutorials/wiki/src/authorization/production.ini index 5c47ade9b..2cfca5f80 100644 --- a/docs/tutorials/wiki/src/authorization/production.ini +++ b/docs/tutorials/wiki/src/authorization/production.ini @@ -1,11 +1,14 @@ [app:tutorial] use = egg:tutorial -reload_templates = false -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = false -default_locale_name = en +pyramid.reload_templates = false +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = false +pyramid.default_locale_name = en +pyramid.include = pyramid_tm +pyramid_tm.attempts = 3 + zodb_uri = file://%(here)s/Data.fs?connection_cache_size=20000 [filter:weberror] @@ -22,16 +25,10 @@ debug = false ;smtp_use_tls = ;error_message = -[filter:tm] -use = egg:repoze.tm2#tm -commit_veto = repoze.tm:default_commit_veto - [pipeline:main] pipeline = weberror egg:repoze.zodbconn#closer - egg:repoze.retry#retry - tm tutorial [server:main] diff --git a/docs/tutorials/wiki/src/authorization/setup.py b/docs/tutorials/wiki/src/authorization/setup.py index adfa70c9f..f3b404516 100644 --- a/docs/tutorials/wiki/src/authorization/setup.py +++ b/docs/tutorials/wiki/src/authorization/setup.py @@ -9,8 +9,8 @@ CHANGES = open(os.path.join(here, 'CHANGES.txt')).read() requires = [ 'pyramid', 'repoze.zodbconn', - 'repoze.tm2>=1.0b1', # default_commit_veto - 'repoze.retry', + 'pyramid_tm', + 'pyramid_debugtoolbar', 'ZODB3', 'WebError', 'docutils', diff --git a/docs/tutorials/wiki/src/authorization/tutorial/static/pylons.css b/docs/tutorials/wiki/src/authorization/tutorial/static/pylons.css index fd1914d8d..c54499ddd 100644 --- a/docs/tutorials/wiki/src/authorization/tutorial/static/pylons.css +++ b/docs/tutorials/wiki/src/authorization/tutorial/static/pylons.css @@ -23,7 +23,7 @@ h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;} h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;} h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;} html,body{width:100%;height:100%;} -body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "Nobile","Lucida Grande",Lucida,Verdana,sans-serif;} +body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;} a{color:#1b61d6;text-decoration:none;} a:hover{color:#e88f00;text-decoration:underline;} body h1, @@ -31,7 +31,7 @@ body h2, body h3, body h4, body h5, -body h6{font-family:"Neuton","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;} +body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;} #wrap{min-height:100%;} #header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;} #header{background:#000000;top:0;font-size:14px;} diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt index d98420680..14b88d16a 100644 --- a/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt @@ -6,8 +6,9 @@ <meta name="keywords" content="python web application" /> <meta name="description" content="pyramid web application" /> <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" /> + <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/nobile/stylesheet.css" media="screen" /> + <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/neuton/stylesheet.css" media="screen" /> <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" /> - <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton|Nobile:regular,i,b,bi&subset=latin" type="text/css" media="screen" charset="utf-8" /> <!--[if lte IE 6]> <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" /> <![endif]--> @@ -31,7 +32,7 @@ <div class="bottom"> <div id="left" class="align-right"> <h2>Search documentation</h2> - <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/dev/search.html"> + <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/current/search.html"> <input type="text" id="q" name="q" value="" /> <input type="submit" id="x" value="Go" /> </form> @@ -43,22 +44,22 @@ <a href="http://pylonsproject.org">Pylons Website</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#narrative-documentation">Narrative Documentation</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#api-documentation">API Documentation</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#tutorials">Tutorials</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#change-history">Change History</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#sample-applications">Sample Applications</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#support-and-development">Support and Development</a> </li> <li> <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> diff --git a/docs/tutorials/wiki/src/basiclayout/development.ini b/docs/tutorials/wiki/src/basiclayout/development.ini index 555010bed..3913f45db 100644 --- a/docs/tutorials/wiki/src/basiclayout/development.ini +++ b/docs/tutorials/wiki/src/basiclayout/development.ini @@ -1,25 +1,22 @@ [app:tutorial] use = egg:tutorial -reload_templates = true -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = true -default_locale_name = en +pyramid.reload_templates = true +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = true +pyramid.default_locale_name = en +pyramid.include = pyramid_debugtoolbar + pyramid_tm +pyramid_tm.attempts = 3 + zodb_uri = file://%(here)s/Data.fs?connection_cache_size=20000 [pipeline:main] pipeline = - egg:WebError#evalerror egg:repoze.zodbconn#closer - egg:repoze.retry#retry - tm tutorial -[filter:tm] -use = egg:repoze.tm2#tm -commit_veto = repoze.tm:default_commit_veto - [server:main] use = egg:Paste#http host = 0.0.0.0 diff --git a/docs/tutorials/wiki/src/basiclayout/production.ini b/docs/tutorials/wiki/src/basiclayout/production.ini index 5c47ade9b..2cfca5f80 100644 --- a/docs/tutorials/wiki/src/basiclayout/production.ini +++ b/docs/tutorials/wiki/src/basiclayout/production.ini @@ -1,11 +1,14 @@ [app:tutorial] use = egg:tutorial -reload_templates = false -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = false -default_locale_name = en +pyramid.reload_templates = false +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = false +pyramid.default_locale_name = en +pyramid.include = pyramid_tm +pyramid_tm.attempts = 3 + zodb_uri = file://%(here)s/Data.fs?connection_cache_size=20000 [filter:weberror] @@ -22,16 +25,10 @@ debug = false ;smtp_use_tls = ;error_message = -[filter:tm] -use = egg:repoze.tm2#tm -commit_veto = repoze.tm:default_commit_veto - [pipeline:main] pipeline = weberror egg:repoze.zodbconn#closer - egg:repoze.retry#retry - tm tutorial [server:main] diff --git a/docs/tutorials/wiki/src/basiclayout/setup.py b/docs/tutorials/wiki/src/basiclayout/setup.py index 2d540d65b..31833dc7f 100644 --- a/docs/tutorials/wiki/src/basiclayout/setup.py +++ b/docs/tutorials/wiki/src/basiclayout/setup.py @@ -9,8 +9,8 @@ CHANGES = open(os.path.join(here, 'CHANGES.txt')).read() requires = [ 'pyramid', 'repoze.zodbconn', - 'repoze.tm2>=1.0b1', # default_commit_veto - 'repoze.retry', + 'pyramid_tm', + 'pyramid_debugtoolbar', 'ZODB3', 'WebError', ] diff --git a/docs/tutorials/wiki/src/basiclayout/tutorial/static/pylons.css b/docs/tutorials/wiki/src/basiclayout/tutorial/static/pylons.css index fd1914d8d..c54499ddd 100644 --- a/docs/tutorials/wiki/src/basiclayout/tutorial/static/pylons.css +++ b/docs/tutorials/wiki/src/basiclayout/tutorial/static/pylons.css @@ -23,7 +23,7 @@ h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;} h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;} h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;} html,body{width:100%;height:100%;} -body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "Nobile","Lucida Grande",Lucida,Verdana,sans-serif;} +body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;} a{color:#1b61d6;text-decoration:none;} a:hover{color:#e88f00;text-decoration:underline;} body h1, @@ -31,7 +31,7 @@ body h2, body h3, body h4, body h5, -body h6{font-family:"Neuton","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;} +body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;} #wrap{min-height:100%;} #header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;} #header{background:#000000;top:0;font-size:14px;} diff --git a/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt index c24daa711..f9f351c97 100644 --- a/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt @@ -6,8 +6,9 @@ <meta name="keywords" content="python web application" /> <meta name="description" content="pyramid web application" /> <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" /> + <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/nobile/stylesheet.css" media="screen" /> + <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/neuton/stylesheet.css" media="screen" /> <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" /> - <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton|Nobile:regular,i,b,bi&subset=latin" type="text/css" media="screen" charset="utf-8" /> <!--[if lte IE 6]> <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" /> <![endif]--> @@ -31,7 +32,7 @@ <div class="bottom"> <div id="left" class="align-right"> <h2>Search documentation</h2> - <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/dev/search.html"> + <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/current/search.html"> <input type="text" id="q" name="q" value="" /> <input type="submit" id="x" value="Go" /> </form> @@ -43,22 +44,22 @@ <a href="http://pylonsproject.org/">Pylons Website</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#narrative-documentation">Narrative Documentation</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#api-documentation">API Documentation</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#tutorials">Tutorials</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#change-history">Change History</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#sample-applications">Sample Applications</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#support-and-development">Support and Development</a> </li> <li> <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> diff --git a/docs/tutorials/wiki/src/models/development.ini b/docs/tutorials/wiki/src/models/development.ini index 1ba746d0e..8c60f4ea9 100644 --- a/docs/tutorials/wiki/src/models/development.ini +++ b/docs/tutorials/wiki/src/models/development.ini @@ -1,25 +1,22 @@ [app:tutorial] use = egg:tutorial -reload_templates = true -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = true -default_locale_name = en +pyramid.reload_templates = true +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = true +pyramid.default_locale_name = en +pyramid.include = pyramid_debugtoolbar + pyramid_tm +pyramid_tm.attempts = 3 + zodb_uri = file://%(here)s/Data.fs?connection_cache_size=20000 [pipeline:main] pipeline = - egg:WebError#evalerror egg:repoze.zodbconn#closer - egg:repoze.retry#retry - tm tutorial -[filter:tm] -use = egg:repoze.tm2#tm -commit_veto = repoze.tm:default_commit_veto - [server:main] use = egg:Paste#http host = 0.0.0.0 diff --git a/docs/tutorials/wiki/src/models/production.ini b/docs/tutorials/wiki/src/models/production.ini index 5c47ade9b..2cfca5f80 100644 --- a/docs/tutorials/wiki/src/models/production.ini +++ b/docs/tutorials/wiki/src/models/production.ini @@ -1,11 +1,14 @@ [app:tutorial] use = egg:tutorial -reload_templates = false -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = false -default_locale_name = en +pyramid.reload_templates = false +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = false +pyramid.default_locale_name = en +pyramid.include = pyramid_tm +pyramid_tm.attempts = 3 + zodb_uri = file://%(here)s/Data.fs?connection_cache_size=20000 [filter:weberror] @@ -22,16 +25,10 @@ debug = false ;smtp_use_tls = ;error_message = -[filter:tm] -use = egg:repoze.tm2#tm -commit_veto = repoze.tm:default_commit_veto - [pipeline:main] pipeline = weberror egg:repoze.zodbconn#closer - egg:repoze.retry#retry - tm tutorial [server:main] diff --git a/docs/tutorials/wiki/src/models/setup.py b/docs/tutorials/wiki/src/models/setup.py index 2d540d65b..31833dc7f 100644 --- a/docs/tutorials/wiki/src/models/setup.py +++ b/docs/tutorials/wiki/src/models/setup.py @@ -9,8 +9,8 @@ CHANGES = open(os.path.join(here, 'CHANGES.txt')).read() requires = [ 'pyramid', 'repoze.zodbconn', - 'repoze.tm2>=1.0b1', # default_commit_veto - 'repoze.retry', + 'pyramid_tm', + 'pyramid_debugtoolbar', 'ZODB3', 'WebError', ] diff --git a/docs/tutorials/wiki/src/models/tutorial/static/pylons.css b/docs/tutorials/wiki/src/models/tutorial/static/pylons.css index a9f49cc85..7e6ec739d 100644 --- a/docs/tutorials/wiki/src/models/tutorial/static/pylons.css +++ b/docs/tutorials/wiki/src/models/tutorial/static/pylons.css @@ -23,7 +23,7 @@ h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;} h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;} h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;} html,body{width:100%;height:100%;} -body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "Nobile","Lucida Grande",Lucida,Verdana,sans-serif;} +body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;} a{color:#1b61d6;text-decoration:none;} a:hover{color:#e88f00;text-decoration:underline;} body h1, @@ -31,7 +31,7 @@ body h2, body h3, body h4, body h5, -body h6{font-family:"Neuton","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;} +body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;} #wrap{min-height:100%;} #header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;} #header{background:#000000;top:0;font-size:14px;} diff --git a/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt index d98420680..14b88d16a 100644 --- a/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt @@ -6,8 +6,9 @@ <meta name="keywords" content="python web application" /> <meta name="description" content="pyramid web application" /> <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" /> + <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/nobile/stylesheet.css" media="screen" /> + <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/neuton/stylesheet.css" media="screen" /> <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" /> - <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton|Nobile:regular,i,b,bi&subset=latin" type="text/css" media="screen" charset="utf-8" /> <!--[if lte IE 6]> <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" /> <![endif]--> @@ -31,7 +32,7 @@ <div class="bottom"> <div id="left" class="align-right"> <h2>Search documentation</h2> - <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/dev/search.html"> + <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/current/search.html"> <input type="text" id="q" name="q" value="" /> <input type="submit" id="x" value="Go" /> </form> @@ -43,22 +44,22 @@ <a href="http://pylonsproject.org">Pylons Website</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#narrative-documentation">Narrative Documentation</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#api-documentation">API Documentation</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#tutorials">Tutorials</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#change-history">Change History</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#sample-applications">Sample Applications</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#support-and-development">Support and Development</a> </li> <li> <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> diff --git a/docs/tutorials/wiki/src/tests/development.ini b/docs/tutorials/wiki/src/tests/development.ini index 1ba746d0e..8c60f4ea9 100644 --- a/docs/tutorials/wiki/src/tests/development.ini +++ b/docs/tutorials/wiki/src/tests/development.ini @@ -1,25 +1,22 @@ [app:tutorial] use = egg:tutorial -reload_templates = true -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = true -default_locale_name = en +pyramid.reload_templates = true +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = true +pyramid.default_locale_name = en +pyramid.include = pyramid_debugtoolbar + pyramid_tm +pyramid_tm.attempts = 3 + zodb_uri = file://%(here)s/Data.fs?connection_cache_size=20000 [pipeline:main] pipeline = - egg:WebError#evalerror egg:repoze.zodbconn#closer - egg:repoze.retry#retry - tm tutorial -[filter:tm] -use = egg:repoze.tm2#tm -commit_veto = repoze.tm:default_commit_veto - [server:main] use = egg:Paste#http host = 0.0.0.0 diff --git a/docs/tutorials/wiki/src/tests/production.ini b/docs/tutorials/wiki/src/tests/production.ini index 5c47ade9b..2cfca5f80 100644 --- a/docs/tutorials/wiki/src/tests/production.ini +++ b/docs/tutorials/wiki/src/tests/production.ini @@ -1,11 +1,14 @@ [app:tutorial] use = egg:tutorial -reload_templates = false -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = false -default_locale_name = en +pyramid.reload_templates = false +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = false +pyramid.default_locale_name = en +pyramid.include = pyramid_tm +pyramid_tm.attempts = 3 + zodb_uri = file://%(here)s/Data.fs?connection_cache_size=20000 [filter:weberror] @@ -22,16 +25,10 @@ debug = false ;smtp_use_tls = ;error_message = -[filter:tm] -use = egg:repoze.tm2#tm -commit_veto = repoze.tm:default_commit_veto - [pipeline:main] pipeline = weberror egg:repoze.zodbconn#closer - egg:repoze.retry#retry - tm tutorial [server:main] diff --git a/docs/tutorials/wiki/src/tests/setup.py b/docs/tutorials/wiki/src/tests/setup.py index d2c8f5697..603bb6bac 100644 --- a/docs/tutorials/wiki/src/tests/setup.py +++ b/docs/tutorials/wiki/src/tests/setup.py @@ -9,8 +9,8 @@ CHANGES = open(os.path.join(here, 'CHANGES.txt')).read() requires = [ 'pyramid', 'repoze.zodbconn', - 'repoze.tm2>=1.0b1', - 'repoze.retry', + 'pyramid_tm', + 'pyramid_debugtoolbar', 'ZODB3', 'WebError', 'docutils', diff --git a/docs/tutorials/wiki/src/tests/tutorial/static/pylons.css b/docs/tutorials/wiki/src/tests/tutorial/static/pylons.css index fd1914d8d..c54499ddd 100644 --- a/docs/tutorials/wiki/src/tests/tutorial/static/pylons.css +++ b/docs/tutorials/wiki/src/tests/tutorial/static/pylons.css @@ -23,7 +23,7 @@ h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;} h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;} h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;} html,body{width:100%;height:100%;} -body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "Nobile","Lucida Grande",Lucida,Verdana,sans-serif;} +body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;} a{color:#1b61d6;text-decoration:none;} a:hover{color:#e88f00;text-decoration:underline;} body h1, @@ -31,7 +31,7 @@ body h2, body h3, body h4, body h5, -body h6{font-family:"Neuton","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;} +body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;} #wrap{min-height:100%;} #header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;} #header{background:#000000;top:0;font-size:14px;} diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt index d98420680..14b88d16a 100644 --- a/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt @@ -6,8 +6,9 @@ <meta name="keywords" content="python web application" /> <meta name="description" content="pyramid web application" /> <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" /> + <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/nobile/stylesheet.css" media="screen" /> + <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/neuton/stylesheet.css" media="screen" /> <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" /> - <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton|Nobile:regular,i,b,bi&subset=latin" type="text/css" media="screen" charset="utf-8" /> <!--[if lte IE 6]> <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" /> <![endif]--> @@ -31,7 +32,7 @@ <div class="bottom"> <div id="left" class="align-right"> <h2>Search documentation</h2> - <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/dev/search.html"> + <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/current/search.html"> <input type="text" id="q" name="q" value="" /> <input type="submit" id="x" value="Go" /> </form> @@ -43,22 +44,22 @@ <a href="http://pylonsproject.org">Pylons Website</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#narrative-documentation">Narrative Documentation</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#api-documentation">API Documentation</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#tutorials">Tutorials</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#change-history">Change History</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#sample-applications">Sample Applications</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#support-and-development">Support and Development</a> </li> <li> <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> diff --git a/docs/tutorials/wiki/src/views/development.ini b/docs/tutorials/wiki/src/views/development.ini index 555010bed..3913f45db 100644 --- a/docs/tutorials/wiki/src/views/development.ini +++ b/docs/tutorials/wiki/src/views/development.ini @@ -1,25 +1,22 @@ [app:tutorial] use = egg:tutorial -reload_templates = true -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = true -default_locale_name = en +pyramid.reload_templates = true +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = true +pyramid.default_locale_name = en +pyramid.include = pyramid_debugtoolbar + pyramid_tm +pyramid_tm.attempts = 3 + zodb_uri = file://%(here)s/Data.fs?connection_cache_size=20000 [pipeline:main] pipeline = - egg:WebError#evalerror egg:repoze.zodbconn#closer - egg:repoze.retry#retry - tm tutorial -[filter:tm] -use = egg:repoze.tm2#tm -commit_veto = repoze.tm:default_commit_veto - [server:main] use = egg:Paste#http host = 0.0.0.0 diff --git a/docs/tutorials/wiki/src/views/production.ini b/docs/tutorials/wiki/src/views/production.ini index 5c47ade9b..2cfca5f80 100644 --- a/docs/tutorials/wiki/src/views/production.ini +++ b/docs/tutorials/wiki/src/views/production.ini @@ -1,11 +1,14 @@ [app:tutorial] use = egg:tutorial -reload_templates = false -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = false -default_locale_name = en +pyramid.reload_templates = false +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = false +pyramid.default_locale_name = en +pyramid.include = pyramid_tm +pyramid_tm.attempts = 3 + zodb_uri = file://%(here)s/Data.fs?connection_cache_size=20000 [filter:weberror] @@ -22,16 +25,10 @@ debug = false ;smtp_use_tls = ;error_message = -[filter:tm] -use = egg:repoze.tm2#tm -commit_veto = repoze.tm:default_commit_veto - [pipeline:main] pipeline = weberror egg:repoze.zodbconn#closer - egg:repoze.retry#retry - tm tutorial [server:main] diff --git a/docs/tutorials/wiki/src/views/setup.py b/docs/tutorials/wiki/src/views/setup.py index daa5e5eb1..6acc004c0 100644 --- a/docs/tutorials/wiki/src/views/setup.py +++ b/docs/tutorials/wiki/src/views/setup.py @@ -9,8 +9,8 @@ CHANGES = open(os.path.join(here, 'CHANGES.txt')).read() requires = [ 'pyramid', 'repoze.zodbconn', - 'repoze.tm2>=1.0b1', # default_commit_veto - 'repoze.retry', + 'pyramid_tm', + 'pyramid_debugtoolbar', 'ZODB3', 'WebError', 'docutils', diff --git a/docs/tutorials/wiki/src/views/tutorial/static/pylons.css b/docs/tutorials/wiki/src/views/tutorial/static/pylons.css index fd1914d8d..c54499ddd 100644 --- a/docs/tutorials/wiki/src/views/tutorial/static/pylons.css +++ b/docs/tutorials/wiki/src/views/tutorial/static/pylons.css @@ -23,7 +23,7 @@ h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;} h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;} h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;} html,body{width:100%;height:100%;} -body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "Nobile","Lucida Grande",Lucida,Verdana,sans-serif;} +body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;} a{color:#1b61d6;text-decoration:none;} a:hover{color:#e88f00;text-decoration:underline;} body h1, @@ -31,7 +31,7 @@ body h2, body h3, body h4, body h5, -body h6{font-family:"Neuton","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;} +body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;} #wrap{min-height:100%;} #header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;} #header{background:#000000;top:0;font-size:14px;} diff --git a/docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt index d98420680..14b88d16a 100644 --- a/docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt @@ -6,8 +6,9 @@ <meta name="keywords" content="python web application" /> <meta name="description" content="pyramid web application" /> <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" /> + <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/nobile/stylesheet.css" media="screen" /> + <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/neuton/stylesheet.css" media="screen" /> <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" /> - <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton|Nobile:regular,i,b,bi&subset=latin" type="text/css" media="screen" charset="utf-8" /> <!--[if lte IE 6]> <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" /> <![endif]--> @@ -31,7 +32,7 @@ <div class="bottom"> <div id="left" class="align-right"> <h2>Search documentation</h2> - <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/dev/search.html"> + <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/current/search.html"> <input type="text" id="q" name="q" value="" /> <input type="submit" id="x" value="Go" /> </form> @@ -43,22 +44,22 @@ <a href="http://pylonsproject.org">Pylons Website</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#narrative-documentation">Narrative Documentation</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#api-documentation">API Documentation</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#tutorials">Tutorials</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#change-history">Change History</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#sample-applications">Sample Applications</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#support-and-development">Support and Development</a> </li> <li> <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> diff --git a/docs/tutorials/wiki2/authorization.rst b/docs/tutorials/wiki2/authorization.rst index 76ce4b83f..df5e228fd 100644 --- a/docs/tutorials/wiki2/authorization.rst +++ b/docs/tutorials/wiki2/authorization.rst @@ -54,7 +54,7 @@ inside our ``models.py`` file. Add the following statements to your ``models.py`` file: .. literalinclude:: src/authorization/tutorial/models.py - :lines: 3-4,45-49 + :lines: 3-4,45-50 :linenos: :language: python @@ -228,7 +228,7 @@ We'll then change the return value of these views to pass the `resulting .. code-block:: python :linenos: - return dict(page = context, + return dict(page = page, content = content, logged_in = logged_in, edit_url = edit_url) diff --git a/docs/tutorials/wiki2/basiclayout.rst b/docs/tutorials/wiki2/basiclayout.rst index 6151e0e25..0fd64fde4 100644 --- a/docs/tutorials/wiki2/basiclayout.rst +++ b/docs/tutorials/wiki2/basiclayout.rst @@ -57,7 +57,7 @@ The next step is to construct a :term:`Configurator`: ``settings`` is passed to the Configurator as a keyword argument with the dictionary values passed by PasteDeploy as the ``**settings`` argument. This will be a dictionary of settings parsed from the ``.ini`` file, which -contains deployment-related values such as ``reload_templates``, +contains deployment-related values such as ``pyramid.reload_templates``, ``db_string``, etc. We now can call :meth:`pyramid.config.Configurator.add_static_view` with the diff --git a/docs/tutorials/wiki2/src/authorization/development.ini b/docs/tutorials/wiki2/src/authorization/development.ini index 3b615f635..bd71cdba5 100644 --- a/docs/tutorials/wiki2/src/authorization/development.ini +++ b/docs/tutorials/wiki2/src/authorization/development.ini @@ -1,11 +1,11 @@ [app:tutorial] use = egg:tutorial -reload_templates = true -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = true -default_locale_name = en +pyramid.reload_templates = true +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = true +pyramid.default_locale_name = en sqlalchemy.url = sqlite:///%(here)s/tutorial.db [pipeline:main] diff --git a/docs/tutorials/wiki2/src/authorization/production.ini b/docs/tutorials/wiki2/src/authorization/production.ini index 0fdc38811..ed8eadacc 100644 --- a/docs/tutorials/wiki2/src/authorization/production.ini +++ b/docs/tutorials/wiki2/src/authorization/production.ini @@ -1,11 +1,11 @@ [app:tutorial] use = egg:tutorial -reload_templates = false -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = false -default_locale_name = en +pyramid.reload_templates = false +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = false +pyramid.default_locale_name = en sqlalchemy.url = sqlite:///%(here)s/tutorial.db [filter:weberror] diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/models.py b/docs/tutorials/wiki2/src/authorization/tutorial/models.py index 53c6d1122..832545cb1 100644 --- a/docs/tutorials/wiki2/src/authorization/tutorial/models.py +++ b/docs/tutorials/wiki2/src/authorization/tutorial/models.py @@ -41,7 +41,7 @@ def initialize_sql(engine): transaction.commit() except IntegrityError: # already created - pass + transaction.abort() class RootFactory(object): __acl__ = [ (Allow, Everyone, 'view'), diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/static/pylons.css b/docs/tutorials/wiki2/src/authorization/tutorial/static/pylons.css index fd1914d8d..c54499ddd 100644 --- a/docs/tutorials/wiki2/src/authorization/tutorial/static/pylons.css +++ b/docs/tutorials/wiki2/src/authorization/tutorial/static/pylons.css @@ -23,7 +23,7 @@ h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;} h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;} h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;} html,body{width:100%;height:100%;} -body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "Nobile","Lucida Grande",Lucida,Verdana,sans-serif;} +body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;} a{color:#1b61d6;text-decoration:none;} a:hover{color:#e88f00;text-decoration:underline;} body h1, @@ -31,7 +31,7 @@ body h2, body h3, body h4, body h5, -body h6{font-family:"Neuton","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;} +body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;} #wrap{min-height:100%;} #header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;} #header{background:#000000;top:0;font-size:14px;} diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/authorization/tutorial/templates/mytemplate.pt index d98420680..14b88d16a 100644 --- a/docs/tutorials/wiki2/src/authorization/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki2/src/authorization/tutorial/templates/mytemplate.pt @@ -6,8 +6,9 @@ <meta name="keywords" content="python web application" /> <meta name="description" content="pyramid web application" /> <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" /> + <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/nobile/stylesheet.css" media="screen" /> + <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/neuton/stylesheet.css" media="screen" /> <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" /> - <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton|Nobile:regular,i,b,bi&subset=latin" type="text/css" media="screen" charset="utf-8" /> <!--[if lte IE 6]> <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" /> <![endif]--> @@ -31,7 +32,7 @@ <div class="bottom"> <div id="left" class="align-right"> <h2>Search documentation</h2> - <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/dev/search.html"> + <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/current/search.html"> <input type="text" id="q" name="q" value="" /> <input type="submit" id="x" value="Go" /> </form> @@ -43,22 +44,22 @@ <a href="http://pylonsproject.org">Pylons Website</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#narrative-documentation">Narrative Documentation</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#api-documentation">API Documentation</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#tutorials">Tutorials</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#change-history">Change History</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#sample-applications">Sample Applications</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#support-and-development">Support and Development</a> </li> <li> <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> diff --git a/docs/tutorials/wiki2/src/basiclayout/development.ini b/docs/tutorials/wiki2/src/basiclayout/development.ini index 3b615f635..bd71cdba5 100644 --- a/docs/tutorials/wiki2/src/basiclayout/development.ini +++ b/docs/tutorials/wiki2/src/basiclayout/development.ini @@ -1,11 +1,11 @@ [app:tutorial] use = egg:tutorial -reload_templates = true -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = true -default_locale_name = en +pyramid.reload_templates = true +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = true +pyramid.default_locale_name = en sqlalchemy.url = sqlite:///%(here)s/tutorial.db [pipeline:main] diff --git a/docs/tutorials/wiki2/src/basiclayout/production.ini b/docs/tutorials/wiki2/src/basiclayout/production.ini index 0fdc38811..ed8eadacc 100644 --- a/docs/tutorials/wiki2/src/basiclayout/production.ini +++ b/docs/tutorials/wiki2/src/basiclayout/production.ini @@ -1,11 +1,11 @@ [app:tutorial] use = egg:tutorial -reload_templates = false -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = false -default_locale_name = en +pyramid.reload_templates = false +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = false +pyramid.default_locale_name = en sqlalchemy.url = sqlite:///%(here)s/tutorial.db [filter:weberror] diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py index 4fd010c5c..9b687931b 100644 --- a/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py +++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py @@ -40,4 +40,4 @@ def initialize_sql(engine): try: populate() except IntegrityError: - pass + transaction.abort() diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/static/pylons.css b/docs/tutorials/wiki2/src/basiclayout/tutorial/static/pylons.css index fd1914d8d..c54499ddd 100644 --- a/docs/tutorials/wiki2/src/basiclayout/tutorial/static/pylons.css +++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/static/pylons.css @@ -23,7 +23,7 @@ h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;} h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;} h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;} html,body{width:100%;height:100%;} -body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "Nobile","Lucida Grande",Lucida,Verdana,sans-serif;} +body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;} a{color:#1b61d6;text-decoration:none;} a:hover{color:#e88f00;text-decoration:underline;} body h1, @@ -31,7 +31,7 @@ body h2, body h3, body h4, body h5, -body h6{font-family:"Neuton","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;} +body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;} #wrap{min-height:100%;} #header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;} #header{background:#000000;top:0;font-size:14px;} diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt index d98420680..14b88d16a 100644 --- a/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt @@ -6,8 +6,9 @@ <meta name="keywords" content="python web application" /> <meta name="description" content="pyramid web application" /> <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" /> + <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/nobile/stylesheet.css" media="screen" /> + <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/neuton/stylesheet.css" media="screen" /> <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" /> - <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton|Nobile:regular,i,b,bi&subset=latin" type="text/css" media="screen" charset="utf-8" /> <!--[if lte IE 6]> <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" /> <![endif]--> @@ -31,7 +32,7 @@ <div class="bottom"> <div id="left" class="align-right"> <h2>Search documentation</h2> - <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/dev/search.html"> + <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/current/search.html"> <input type="text" id="q" name="q" value="" /> <input type="submit" id="x" value="Go" /> </form> @@ -43,22 +44,22 @@ <a href="http://pylonsproject.org">Pylons Website</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#narrative-documentation">Narrative Documentation</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#api-documentation">API Documentation</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#tutorials">Tutorials</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#change-history">Change History</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#sample-applications">Sample Applications</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#support-and-development">Support and Development</a> </li> <li> <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> diff --git a/docs/tutorials/wiki2/src/models/development.ini b/docs/tutorials/wiki2/src/models/development.ini index 3b615f635..bd71cdba5 100644 --- a/docs/tutorials/wiki2/src/models/development.ini +++ b/docs/tutorials/wiki2/src/models/development.ini @@ -1,11 +1,11 @@ [app:tutorial] use = egg:tutorial -reload_templates = true -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = true -default_locale_name = en +pyramid.reload_templates = true +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = true +pyramid.default_locale_name = en sqlalchemy.url = sqlite:///%(here)s/tutorial.db [pipeline:main] diff --git a/docs/tutorials/wiki2/src/models/production.ini b/docs/tutorials/wiki2/src/models/production.ini index 0fdc38811..ed8eadacc 100644 --- a/docs/tutorials/wiki2/src/models/production.ini +++ b/docs/tutorials/wiki2/src/models/production.ini @@ -1,11 +1,11 @@ [app:tutorial] use = egg:tutorial -reload_templates = false -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = false -default_locale_name = en +pyramid.reload_templates = false +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = false +pyramid.default_locale_name = en sqlalchemy.url = sqlite:///%(here)s/tutorial.db [filter:weberror] diff --git a/docs/tutorials/wiki2/src/models/tutorial/models.py b/docs/tutorials/wiki2/src/models/tutorial/models.py index ecc8d567b..30f77a0b9 100644 --- a/docs/tutorials/wiki2/src/models/tutorial/models.py +++ b/docs/tutorials/wiki2/src/models/tutorial/models.py @@ -39,4 +39,4 @@ def initialize_sql(engine): transaction.commit() except IntegrityError: # already created - pass + transaction.abort() diff --git a/docs/tutorials/wiki2/src/models/tutorial/static/pylons.css b/docs/tutorials/wiki2/src/models/tutorial/static/pylons.css index fd1914d8d..c54499ddd 100644 --- a/docs/tutorials/wiki2/src/models/tutorial/static/pylons.css +++ b/docs/tutorials/wiki2/src/models/tutorial/static/pylons.css @@ -23,7 +23,7 @@ h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;} h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;} h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;} html,body{width:100%;height:100%;} -body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "Nobile","Lucida Grande",Lucida,Verdana,sans-serif;} +body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;} a{color:#1b61d6;text-decoration:none;} a:hover{color:#e88f00;text-decoration:underline;} body h1, @@ -31,7 +31,7 @@ body h2, body h3, body h4, body h5, -body h6{font-family:"Neuton","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;} +body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;} #wrap{min-height:100%;} #header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;} #header{background:#000000;top:0;font-size:14px;} diff --git a/docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.pt index d98420680..14b88d16a 100644 --- a/docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.pt @@ -6,8 +6,9 @@ <meta name="keywords" content="python web application" /> <meta name="description" content="pyramid web application" /> <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" /> + <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/nobile/stylesheet.css" media="screen" /> + <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/neuton/stylesheet.css" media="screen" /> <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" /> - <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton|Nobile:regular,i,b,bi&subset=latin" type="text/css" media="screen" charset="utf-8" /> <!--[if lte IE 6]> <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" /> <![endif]--> @@ -31,7 +32,7 @@ <div class="bottom"> <div id="left" class="align-right"> <h2>Search documentation</h2> - <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/dev/search.html"> + <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/current/search.html"> <input type="text" id="q" name="q" value="" /> <input type="submit" id="x" value="Go" /> </form> @@ -43,22 +44,22 @@ <a href="http://pylonsproject.org">Pylons Website</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#narrative-documentation">Narrative Documentation</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#api-documentation">API Documentation</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#tutorials">Tutorials</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#change-history">Change History</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#sample-applications">Sample Applications</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#support-and-development">Support and Development</a> </li> <li> <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> diff --git a/docs/tutorials/wiki2/src/tests/development.ini b/docs/tutorials/wiki2/src/tests/development.ini index 3b615f635..bd71cdba5 100644 --- a/docs/tutorials/wiki2/src/tests/development.ini +++ b/docs/tutorials/wiki2/src/tests/development.ini @@ -1,11 +1,11 @@ [app:tutorial] use = egg:tutorial -reload_templates = true -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = true -default_locale_name = en +pyramid.reload_templates = true +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = true +pyramid.default_locale_name = en sqlalchemy.url = sqlite:///%(here)s/tutorial.db [pipeline:main] diff --git a/docs/tutorials/wiki2/src/tests/production.ini b/docs/tutorials/wiki2/src/tests/production.ini index 0fdc38811..ed8eadacc 100644 --- a/docs/tutorials/wiki2/src/tests/production.ini +++ b/docs/tutorials/wiki2/src/tests/production.ini @@ -1,11 +1,11 @@ [app:tutorial] use = egg:tutorial -reload_templates = false -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = false -default_locale_name = en +pyramid.reload_templates = false +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = false +pyramid.default_locale_name = en sqlalchemy.url = sqlite:///%(here)s/tutorial.db [filter:weberror] diff --git a/docs/tutorials/wiki2/src/tests/tutorial/models.py b/docs/tutorials/wiki2/src/tests/tutorial/models.py index 53c6d1122..832545cb1 100644 --- a/docs/tutorials/wiki2/src/tests/tutorial/models.py +++ b/docs/tutorials/wiki2/src/tests/tutorial/models.py @@ -41,7 +41,7 @@ def initialize_sql(engine): transaction.commit() except IntegrityError: # already created - pass + transaction.abort() class RootFactory(object): __acl__ = [ (Allow, Everyone, 'view'), diff --git a/docs/tutorials/wiki2/src/tests/tutorial/static/pylons.css b/docs/tutorials/wiki2/src/tests/tutorial/static/pylons.css index fd1914d8d..c54499ddd 100644 --- a/docs/tutorials/wiki2/src/tests/tutorial/static/pylons.css +++ b/docs/tutorials/wiki2/src/tests/tutorial/static/pylons.css @@ -23,7 +23,7 @@ h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;} h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;} h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;} html,body{width:100%;height:100%;} -body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "Nobile","Lucida Grande",Lucida,Verdana,sans-serif;} +body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;} a{color:#1b61d6;text-decoration:none;} a:hover{color:#e88f00;text-decoration:underline;} body h1, @@ -31,7 +31,7 @@ body h2, body h3, body h4, body h5, -body h6{font-family:"Neuton","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;} +body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;} #wrap{min-height:100%;} #header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;} #header{background:#000000;top:0;font-size:14px;} diff --git a/docs/tutorials/wiki2/src/tests/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/tests/tutorial/templates/mytemplate.pt index d98420680..14b88d16a 100644 --- a/docs/tutorials/wiki2/src/tests/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki2/src/tests/tutorial/templates/mytemplate.pt @@ -6,8 +6,9 @@ <meta name="keywords" content="python web application" /> <meta name="description" content="pyramid web application" /> <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" /> + <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/nobile/stylesheet.css" media="screen" /> + <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/neuton/stylesheet.css" media="screen" /> <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" /> - <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton|Nobile:regular,i,b,bi&subset=latin" type="text/css" media="screen" charset="utf-8" /> <!--[if lte IE 6]> <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" /> <![endif]--> @@ -31,7 +32,7 @@ <div class="bottom"> <div id="left" class="align-right"> <h2>Search documentation</h2> - <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/dev/search.html"> + <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/current/search.html"> <input type="text" id="q" name="q" value="" /> <input type="submit" id="x" value="Go" /> </form> @@ -43,22 +44,22 @@ <a href="http://pylonsproject.org">Pylons Website</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#narrative-documentation">Narrative Documentation</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#api-documentation">API Documentation</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#tutorials">Tutorials</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#change-history">Change History</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#sample-applications">Sample Applications</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#support-and-development">Support and Development</a> </li> <li> <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> diff --git a/docs/tutorials/wiki2/src/views/development.ini b/docs/tutorials/wiki2/src/views/development.ini index 3b615f635..bd71cdba5 100644 --- a/docs/tutorials/wiki2/src/views/development.ini +++ b/docs/tutorials/wiki2/src/views/development.ini @@ -1,11 +1,11 @@ [app:tutorial] use = egg:tutorial -reload_templates = true -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = true -default_locale_name = en +pyramid.reload_templates = true +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = true +pyramid.default_locale_name = en sqlalchemy.url = sqlite:///%(here)s/tutorial.db [pipeline:main] diff --git a/docs/tutorials/wiki2/src/views/production.ini b/docs/tutorials/wiki2/src/views/production.ini index 0fdc38811..ed8eadacc 100644 --- a/docs/tutorials/wiki2/src/views/production.ini +++ b/docs/tutorials/wiki2/src/views/production.ini @@ -1,11 +1,11 @@ [app:tutorial] use = egg:tutorial -reload_templates = false -debug_authorization = false -debug_notfound = false -debug_routematch = false -debug_templates = false -default_locale_name = en +pyramid.reload_templates = false +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.debug_templates = false +pyramid.default_locale_name = en sqlalchemy.url = sqlite:///%(here)s/tutorial.db [filter:weberror] diff --git a/docs/tutorials/wiki2/src/views/tutorial/models.py b/docs/tutorials/wiki2/src/views/tutorial/models.py index 960c14941..30506f67e 100644 --- a/docs/tutorials/wiki2/src/views/tutorial/models.py +++ b/docs/tutorials/wiki2/src/views/tutorial/models.py @@ -38,4 +38,4 @@ def initialize_sql(engine): transaction.commit() except IntegrityError: # already created - pass + transaction.abort() diff --git a/docs/tutorials/wiki2/src/views/tutorial/static/pylons.css b/docs/tutorials/wiki2/src/views/tutorial/static/pylons.css index fd1914d8d..c54499ddd 100644 --- a/docs/tutorials/wiki2/src/views/tutorial/static/pylons.css +++ b/docs/tutorials/wiki2/src/views/tutorial/static/pylons.css @@ -23,7 +23,7 @@ h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;} h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;} h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;} html,body{width:100%;height:100%;} -body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "Nobile","Lucida Grande",Lucida,Verdana,sans-serif;} +body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;} a{color:#1b61d6;text-decoration:none;} a:hover{color:#e88f00;text-decoration:underline;} body h1, @@ -31,7 +31,7 @@ body h2, body h3, body h4, body h5, -body h6{font-family:"Neuton","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;} +body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;} #wrap{min-height:100%;} #header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;} #header{background:#000000;top:0;font-size:14px;} diff --git a/docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt index d98420680..14b88d16a 100644 --- a/docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt @@ -6,8 +6,9 @@ <meta name="keywords" content="python web application" /> <meta name="description" content="pyramid web application" /> <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" /> + <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/nobile/stylesheet.css" media="screen" /> + <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/neuton/stylesheet.css" media="screen" /> <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" /> - <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton|Nobile:regular,i,b,bi&subset=latin" type="text/css" media="screen" charset="utf-8" /> <!--[if lte IE 6]> <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" /> <![endif]--> @@ -31,7 +32,7 @@ <div class="bottom"> <div id="left" class="align-right"> <h2>Search documentation</h2> - <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/dev/search.html"> + <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/current/search.html"> <input type="text" id="q" name="q" value="" /> <input type="submit" id="x" value="Go" /> </form> @@ -43,22 +44,22 @@ <a href="http://pylonsproject.org">Pylons Website</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#narrative-documentation">Narrative Documentation</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#api-documentation">API Documentation</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#tutorials">Tutorials</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#change-history">Change History</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#sample-applications">Sample Applications</a> </li> <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> + <a href="http://docs.pylonsproject.org/projects/pyramid/current/#support-and-development">Support and Development</a> </li> <li> <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> diff --git a/docs/whatsnew-1.0.rst b/docs/whatsnew-1.0.rst index 8602c5105..5cd822b0d 100644 --- a/docs/whatsnew-1.0.rst +++ b/docs/whatsnew-1.0.rst @@ -62,8 +62,8 @@ fail if you do nothing to your existing :mod:`repoze.bfg` application. However, you won't have to do much to use your existing BFG applications on Pyramid. There's automation which will change most of your import statements and ZCML declarations. See -http://docs.pylonshq.com/pyramid/dev/tutorials/bfg/index.html for upgrade -instructions. +http://docs.pylonsproject.org/projects/pyramid/current/tutorials/bfg/index.html +for upgrade instructions. Pylons 1 users will need to do more work to use Pyramid, as Pyramid shares no "DNA" with Pylons. It is hoped that over time documentation and upgrade code diff --git a/docs/whatsnew-1.1.rst b/docs/whatsnew-1.1.rst index fdf3b1c74..18d0aa0b1 100644 --- a/docs/whatsnew-1.1.rst +++ b/docs/whatsnew-1.1.rst @@ -29,6 +29,12 @@ The major feature additions in Pyramid 1.1 are: - Default HTTP exception view. +- ``http_cache`` view configuration parameter causes Pyramid to set HTTP + caching headers. + +- Features that make it easier to write scripts that work in a :app:`Pyramid` + environment. + ``request.response`` ~~~~~~~~~~~~~~~~~~~~ @@ -91,64 +97,109 @@ Default HTTP Exception View exception to that of Pyramid 1.0 (the exception will propagate to middleware and to the WSGI server). +``http_cache`` +~~~~~~~~~~~~~~ + +A new value ``http_cache`` can be used as a :term:`view configuration` +parameter. + +When you supply an ``http_cache`` value to a view configuration, the +``Expires`` and ``Cache-Control`` headers of a response generated by the +associated view callable are modified. The value for ``http_cache`` may be +one of the following: + +- A nonzero integer. If it's a nonzero integer, it's treated as a number + of seconds. This number of seconds will be used to compute the + ``Expires`` header and the ``Cache-Control: max-age`` parameter of + responses to requests which call this view. For example: + ``http_cache=3600`` instructs the requesting browser to 'cache this + response for an hour, please'. + +- A ``datetime.timedelta`` instance. If it's a ``datetime.timedelta`` + instance, it will be converted into a number of seconds, and that number + of seconds will be used to compute the ``Expires`` header and the + ``Cache-Control: max-age`` parameter of responses to requests which call + this view. For example: ``http_cache=datetime.timedelta(days=1)`` + instructs the requesting browser to 'cache this response for a day, + please'. + +- Zero (``0``). If the value is zero, the ``Cache-Control`` and + ``Expires`` headers present in all responses from this view will be + composed such that client browser cache (and any intermediate caches) are + instructed to never cache the response. + +- A two-tuple. If it's a two tuple (e.g. ``http_cache=(1, + {'public':True})``), the first value in the tuple may be a nonzero + integer or a ``datetime.timedelta`` instance; in either case this value + will be used as the number of seconds to cache the response. The second + value in the tuple must be a dictionary. The values present in the + dictionary will be used as input to the ``Cache-Control`` response + header. For example: ``http_cache=(3600, {'public':True})`` means 'cache + for an hour, and add ``public`` to the Cache-Control header of the + response'. All keys and values supported by the + ``webob.cachecontrol.CacheControl`` interface may be added to the + dictionary. Supplying ``{'public':True}`` is equivalent to calling + ``response.cache_control.public = True``. + +Providing a non-tuple value as ``http_cache`` is equivalent to calling +``response.cache_expires(value)`` within your view's body. + +Providing a two-tuple value as ``http_cache`` is equivalent to calling +``response.cache_expires(value[0], **value[1])`` within your view's body. + +If you wish to avoid influencing, the ``Expires`` header, and instead wish +to only influence ``Cache-Control`` headers, pass a tuple as ``http_cache`` +with the first element of ``None``, e.g.: ``(None, {'public':True})``. + +The environment setting ``PYRAMID_PREVENT_HTTP_CACHE`` and configuration +file value ``prevent_http_cache`` are synonymous and allow you to prevent +HTTP cache headers from being set by Pyramid's ``http_cache`` machinery +globally in a process. see :ref:`influencing_http_caching` and +:ref:`preventing_http_caching`. + +Easier Scripting Writing +~~~~~~~~~~~~~~~~~~~~~~~~ + +A new API function :func:`pyramid.paster.bootstrap` has been added to make +writing scripts that need to work under Pyramid environment easier, e.g.: + +.. code-block:: python + + from pyramid.paster import bootstrap + info = bootstrap('/path/to/my/development.ini') + request = info['request'] + print request.route_url('myroute') + +See :ref:`writing_a_script` for more details. + Minor Feature Additions ----------------------- -- New request attribute: ``json``. If the request's ``content_type`` is - ``application/json``, this attribute will contain the JSON-decoded - variant of the request body. If the request's ``content_type`` is not - ``application/json``, this attribute will be ``None``. - -- A new value ``http_cache`` can be used as a :term:`view configuration` - parameter. - - When you supply an ``http_cache`` value to a view configuration, the - ``Expires`` and ``Cache-Control`` headers of a response generated by the - associated view callable are modified. The value for ``http_cache`` may be - one of the following: - - - A nonzero integer. If it's a nonzero integer, it's treated as a number - of seconds. This number of seconds will be used to compute the - ``Expires`` header and the ``Cache-Control: max-age`` parameter of - responses to requests which call this view. For example: - ``http_cache=3600`` instructs the requesting browser to 'cache this - response for an hour, please'. - - - A ``datetime.timedelta`` instance. If it's a ``datetime.timedelta`` - instance, it will be converted into a number of seconds, and that number - of seconds will be used to compute the ``Expires`` header and the - ``Cache-Control: max-age`` parameter of responses to requests which call - this view. For example: ``http_cache=datetime.timedelta(days=1)`` - instructs the requesting browser to 'cache this response for a day, - please'. - - - Zero (``0``). If the value is zero, the ``Cache-Control`` and - ``Expires`` headers present in all responses from this view will be - composed such that client browser cache (and any intermediate caches) are - instructed to never cache the response. - - - A two-tuple. If it's a two tuple (e.g. ``http_cache=(1, - {'public':True})``), the first value in the tuple may be a nonzero - integer or a ``datetime.timedelta`` instance; in either case this value - will be used as the number of seconds to cache the response. The second - value in the tuple must be a dictionary. The values present in the - dictionary will be used as input to the ``Cache-Control`` response - header. For example: ``http_cache=(3600, {'public':True})`` means 'cache - for an hour, and add ``public`` to the Cache-Control header of the - response'. All keys and values supported by the - ``webob.cachecontrol.CacheControl`` interface may be added to the - dictionary. Supplying ``{'public':True}`` is equivalent to calling - ``response.cache_control.public = True``. - - Providing a non-tuple value as ``http_cache`` is equivalent to calling - ``response.cache_expires(value)`` within your view's body. - - Providing a two-tuple value as ``http_cache`` is equivalent to calling - ``response.cache_expires(value[0], **value[1])`` within your view's body. - - If you wish to avoid influencing, the ``Expires`` header, and instead wish - to only influence ``Cache-Control`` headers, pass a tuple as ``http_cache`` - with the first element of ``None``, e.g.: ``(None, {'public':True})``. +- It is now possible to invoke ``paster pshell`` even if the paste ini file + section name pointed to in its argument is not actually a Pyramid WSGI + application. The shell will work in a degraded mode, and will warn the + user. See "The Interactive Shell" in the "Creating a Pyramid Project" + narrative documentation section. + +- The ``paster pshell``, ``paster pviews``, and ``paster proutes`` commands + each now under the hood uses :func:`pyramid.paster.bootstrap`, which makes + it possible to supply an ``.ini`` file without naming the "right" section + in the file that points at the actual Pyramid application. Instead, you + can generally just run ``paster {pshell|proutes|pviews} development.ini`` + and it will do mostly the right thing. + +- It is now possible to add a ``[pshell]`` section to your application's .ini + configuration file, which influences the global names available to a pshell + session. See :ref:`extending_pshell`. + +- The :meth:`pyramid.config.Configurator.scan` method has grown a ``**kw`` + argument. ``kw`` argument represents a set of keyword arguments to pass to + the Venusian ``Scanner`` object created by Pyramid. (See the + :term:`Venusian` documentation for more information about ``Scanner``). + +- New request property: ``json_body``. This property will return the + JSON-decoded variant of the request body. If the request body is not + well-formed JSON, this property will raise an exception. - A `JSONP <http://en.wikipedia.org/wiki/JSONP>`_ renderer. See :ref:`jsonp_renderer` for more details. @@ -228,6 +279,54 @@ Minor Feature Additions preprocessor to be specified as a Python callable or Python dotted name. See https://github.com/Pylons/pyramid/pull/183 for rationale. +- New API class: :class:`pyramid.static.static_view`. This supersedes the + (now deprecated) :class:`pyramid.view.static` class. + :class:`pyramid.static.static_view`, by default, serves up documents as the + result of the request's ``path_info``, attribute rather than it's + ``subpath`` attribute (the inverse was true of + :class:`pyramid.view.static`, and still is). + :class:`pyramid.static.static_view` exposes a ``use_subpath`` flag for use + when you want the static view to behave like the older deprecated version. + +- A new api function :func:`pyramid.scripting.prepare` has been added. It is + a lower-level analogue of :func:`pyramid.paster.boostrap` that accepts a + request and a registry instead of a config file argument, and is used for + the same purpose: + + .. code-block:: python + + from pyramid.scripting import prepare + info = prepare(registry=myregistry) + request = info['request'] + print request.route_url('myroute') + +- A new API function :func:`pyramid.scripting.make_request` has been added. + The resulting request will have a ``registry`` attribute. It is meant to + be used in conjunction with :func:`pyramid.scripting.prepare` and/or + :func:`pyramid.paster.bootstrap` (both of which accept a request as an + argument): + + .. code-block:: python + + from pyramid.scripting import make_request + request = make_request('/') + +- New API attribute :attr:`pyramid.config.global_registries` is an iterable + object that contains references to every Pyramid registry loaded into the + current process via :meth:`pyramid.config.Configurator.make_app`. It also + has a ``last`` attribute containing the last registry loaded. This is used + by the scripting machinery, and is available for introspection. + +- Added the :attr:`pyramid.renderers.null_renderer` object as an API. The + null renderer is an object that can be used in advanced integration cases + as input to the view configuration ``renderer=`` argument. When the null + renderer is used as a view renderer argument, Pyramid avoids converting the + view callable result into a Response object. This is useful if you want to + reuse the view configuration and lookup machinery outside the context of + its use by the Pyramid router. (This feature was added for consumption by + the ``pyramid_rpc`` package, which uses view configuration and lookup + outside the context of a router in exactly this way.) + Backwards Incompatibilities --------------------------- @@ -291,6 +390,26 @@ Backwards Incompatibilities Deprecations and Behavior Differences ------------------------------------- +.. note:: Under Python 2.7+, it's necessary to pass the Python interpreter + the correct warning flags to see deprecation warnings emitted by Pyramid + when porting your application from an older version of Pyramid. Use the + ``PYTHONWARNINGS`` environment variable with the value ``all`` in the + shell you use to invoke ``paster serve`` to see these warnings, e.g. on + UNIX, ``PYTHONWARNINGS=all bin/paster serve development.ini``. Python 2.5 + and 2.6 show deprecation warnings by default, so this is unecessary there. + All deprecation warnings are emitted to the console. + +- The :class:`pyramid.view.static` class has been deprecated in favor of the + newer :class:`pyramid.static.static_view` class. A deprecation warning is + raised when it is used. You should replace it with a reference to + :class:`pyramid.static.static_view` with the ``use_subpath=True`` argument. + +- The ``paster pshell``, ``paster proutes``, and ``paster pviews`` commands + now take a single argument in the form ``/path/to/config.ini#sectionname`` + rather than the previous 2-argument spelling ``/path/to/config.ini + sectionname``. ``#sectionname`` may be omitted, in which case ``#main`` is + assumed. + - The default Mako renderer is now configured to escape all HTML in expression tags. This is intended to help prevent XSS attacks caused by rendering unsanitized input from users. To revert this behavior in user's @@ -360,7 +479,7 @@ Deprecations and Behavior Differences these methods will be removed entirely. - A custom request factory is now required to return a request object that - has a ``response`` attribute (or "reified"/lazy property) if they the + has a ``response`` attribute (or "reified"/lazy property) if the request is meant to be used in a view that uses a renderer. This ``response`` attribute should be an instance of the class :class:`pyramid.response.Response`. @@ -423,8 +542,8 @@ Deprecations and Behavior Differences - Deprecated the :meth:`pyramid.config.Configurator.set_renderer_globals_factory` method and the ``renderer_globals`` Configurator constructor parameter. Users should - use convert code using this feature to use a BeforeRender event als - :ref:`beforerender_event`. + convert code using this feature to use a BeforeRender event. See the section + :ref:`beforerender_event` in the Hooks chapter. - In Pyramid 1.0, the :class:`pyramid.events.subscriber` directive behaved contrary to the documentation when passed more than one interface object to @@ -449,6 +568,31 @@ Deprecations and Behavior Differences def expects_object_event(object, event): print object, event +- In 1.0, if a :class:`pyramid.events.BeforeRender` event subscriber added a + value via the ``__setitem__`` or ``update`` methods of the event object + with a key that already existed in the renderer globals dictionary, a + ``KeyError`` was raised. With the deprecation of the + "add_renderer_globals" feature of the configurator, there was no way to + override an existing value in the renderer globals dictionary that already + existed. Now, the event object will overwrite an older value that is + already in the globals dictionary when its ``__setitem__`` or ``update`` is + called (as well as the new ``setdefault`` method), just like a plain old + dictionary. As a result, for maximum interoperability with other + third-party subscribers, if you write an event subscriber meant to be used + as a BeforeRender subscriber, your subscriber code will now need to (using + ``.get`` or ``__contains__`` of the event object) ensure no value already + exists in the renderer globals dictionary before setting an overriding + value. + +- The :meth:`pyramid.config.Configurator.add_route` method allowed two routes + with the same route to be added without an intermediate call to + :meth:`pyramid.config.Configurator.commit`. If you now receive a + ``ConfigurationError`` at startup time that appears to be ``add_route`` + related, you'll need to either a) ensure that all of your route names are + unique or b) call ``config.commit()`` before adding a second route with the + name of a previously added name or c) use a Configurator that works in + ``autocommit`` mode. + Dependency Changes ------------------ @@ -461,6 +605,9 @@ Dependency Changes Documentation Enhancements -------------------------- +- Added a section entitled :ref:`writing_a_script` to the "Command-Line + Pyramid" chapter. + - The :ref:`bfg_wiki_tutorial` was updated slightly. - The :ref:`bfg_sql_wiki_tutorial` was updated slightly. |
