diff options
Diffstat (limited to 'docs')
81 files changed, 1750 insertions, 2660 deletions
diff --git a/docs/_static/latex-note.png b/docs/_static/latex-note.png Binary files differindex 7e1647837..95d00a973 100644 --- a/docs/_static/latex-note.png +++ b/docs/_static/latex-note.png diff --git a/docs/_static/latex-warning.png b/docs/_static/latex-warning.png Binary files differindex 747b24529..6707bc362 100644 --- a/docs/_static/latex-warning.png +++ b/docs/_static/latex-warning.png diff --git a/docs/api/registry.rst b/docs/api/registry.rst index 5f61b1122..4d327370a 100644 --- a/docs/api/registry.rst +++ b/docs/api/registry.rst @@ -9,6 +9,8 @@ .. attribute:: settings - The :term:`deployment settings` object. See :ref:`deployment_settings` - for information. + The dictionary-like :term:`deployment settings` object. See + :ref:`deployment_settings` for information. This object is often + accessed as ``request.registry.settings`` or + ``config.registry.settings`` in a typical Pyramid application. diff --git a/docs/api/testing.rst b/docs/api/testing.rst index fdcdadee8..f388dc263 100644 --- a/docs/api/testing.rst +++ b/docs/api/testing.rst @@ -5,26 +5,6 @@ .. automodule:: pyramid.testing - .. autofunction:: registerDummySecurityPolicy - - .. autofunction:: registerResources - - .. autofunction:: registerEventListener - - .. autofunction:: registerTemplateRenderer - - .. autofunction:: registerView - - .. autofunction:: registerUtility - - .. autofunction:: registerAdapter - - .. autofunction:: registerSubscriber - - .. autofunction:: registerRoute - - .. autofunction:: registerSettings - .. autofunction:: setUp .. autofunction:: tearDown diff --git a/docs/authorintro.rst b/docs/authorintro.rst index bbcde68e6..b36a5a308 100644 --- a/docs/authorintro.rst +++ b/docs/authorintro.rst @@ -158,9 +158,11 @@ others' technology. single: Hathaway, Shane single: Akkerman, Wichert single: Laflamme, Blaise + single: Laflamme, Hugues single: Bangert, Ben single: Duncan, Casey single: Orr, Mike + single: Shipman, John Thanks ====== @@ -174,10 +176,9 @@ software. Without the help of these folks, neither this book nor the 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, Mike Orr, Simon Oram and Nat Hardwick of Electrosoup, Ian -Bicking of the Open Planning Project, Jim Fulton of Zope Corporation, Tom -Moroz of the Open Society Institute, and Todd Koym of Environmental Health -Sciences. +Casey Duncan, Hugues Laflamme, Mike Orr, John Shipman, Simon Oram, Nat +Hardwick, Ian Bicking, Jim Fulton, 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 fe28bacdf..a987106d4 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -61,20 +61,20 @@ extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.doctest', 'repoze.sphinx.autointerface', - 'sphinx.ext.intersphinx' +# 'sphinx.ext.intersphinx' ] # Looks for objects in other Pyramid projects -intersphinx_mapping = { - 'cookbook': - ('http://docs.pylonsproject.org/projects/pyramid_cookbook/dev/', None), - 'handlers': - ('http://docs.pylonsproject.org/projects/pyramid_handlers/dev/', None), - 'zcml': - ('http://docs.pylonsproject.org/projects/pyramid_zcml/dev/', None), - 'jinja2': - ('http://docs.pylonsproject.org/projects/pyramid_jinja2/dev/', None), - } +## intersphinx_mapping = { +## 'cookbook': +## ('http://docs.pylonsproject.org/projects/pyramid_cookbook/dev/', None), +## 'handlers': +## ('http://docs.pylonsproject.org/projects/pyramid_handlers/dev/', None), +## 'zcml': +## ('http://docs.pylonsproject.org/projects/pyramid_zcml/dev/', None), +## 'jinja2': +## ('http://docs.pylonsproject.org/projects/pyramid_jinja2/dev/', None), +## } # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -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.0b2' +version = '1.0' # The full version, including alpha/beta/rc tags. release = version @@ -466,7 +466,7 @@ epub_scheme = 'ISBN' # The unique identifier of the text. This can be a ISBN number # or the project homepage. -epub_identifier = '0615345379' +epub_identifier = '0615445675' # A unique identification for the text. epub_uid = 'The Pyramid Web Application Development Framework, Version 1.0' diff --git a/docs/copyright.rst b/docs/copyright.rst index 3cdddbf3a..64f84879a 100644 --- a/docs/copyright.rst +++ b/docs/copyright.rst @@ -9,11 +9,11 @@ by Chris McDonough Copyright |copy| 2008-2011, Agendaless Consulting. -.. ISBN-10: 0615345379 +ISBN-10: 0615445675 -.. ISBN-13: 978-0-615-34537-6 +ISBN-13: 978-0615445670 -.. First print publishing: February, 2010 +First print publishing: February, 2011 All rights reserved. This material may be copied or distributed only subject to the terms and conditions set forth in the `Creative Commons @@ -52,14 +52,13 @@ Editor: Casey Duncan 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. -.. Cover Designer: -.. Nat Hardwick of `Electrosoup <http://www.electrosoup.co.uk>`_. +Cover Designer: + Hugues Laflamme of `Kemeneur <http://www.kemeneur.com/>`_. Used with permission: @@ -69,15 +68,12 @@ Used with permission: The :ref:`much_ado_about_traversal_chapter` chapter is adapted, with permission, from an article written by Rob Miller. - The :ref:`wiki2_flow_of_authentication` section was contributed by John - Shipman. - -.. Print Production -.. ---------------- +Print Production +---------------- -.. The print version of this book was produced using the `Sphinx -.. <http://sphinx.pocoo.org/>`_ documentation generation system and the -.. `LaTeX <http://www.latex-project.org/>`_ typesetting system. +The print version of this book was produced using the `Sphinx +<http://sphinx.pocoo.org/>`_ documentation generation system and the +`LaTeX <http://www.latex-project.org/>`_ typesetting system. Contacting The Publisher ------------------------ diff --git a/docs/coversizing.py b/docs/coversizing.py new file mode 100644 index 000000000..054a741eb --- /dev/null +++ b/docs/coversizing.py @@ -0,0 +1,19 @@ +# see https://www.createspace.com/Products/Book/#content4 +# https://www.createspace.com/Help/Index.jsp?orgId=00D300000001Sh9&id=50170000000I7be + +page_count = 600 +bleed = .125 +spine_width = .002252 * page_count +trim_width = 7.5 +trim_height = 9.25 +min_cover_width = bleed + trim_width + spine_width + trim_width + bleed +min_cover_height = bleed + trim_height + bleed + +print "spine width ", spine_width, "inches" +print "min cover width ", min_cover_width, "inches" +print "min cover height ", min_cover_height, "inches" + +print "barcode placeholder width: 2 inches" +print "barcode placeholder height: 1.2 inches" +print "bottom of barcode must be .25 inches from bottom trim line of cover" +print "right side of barcode must be .25 inches to left of spine" diff --git a/docs/designdefense.rst b/docs/designdefense.rst index bb3e59ff9..455e354e9 100644 --- a/docs/designdefense.rst +++ b/docs/designdefense.rst @@ -30,7 +30,7 @@ much more insidious and harmful set of duplication at higher levels in the Python web community. :app:`Pyramid` began its life as :mod:`repoze.bfg`, written by a team of -people with many years of prior :ref:`Zope` experience. The idea of +people with many years of prior :term:`Zope` experience. The idea of :term:`traversal` and the way :term:`view lookup` works was stolen entirely from Zope. The authorization subsystem provided by :app:`Pyramid` is a derivative of Zope's. The idea that an application can be *extended* without @@ -418,9 +418,6 @@ method was ``POST`` and that the remote user agent passed "Under the hood", these features make no use of interfaces. -For more information about predicates, see -:ref:`view_predicates_in_1dot1` and :ref:`route_predicates_in_1dot1`. - Many "prebaked" predicates exist. However, use of only "prebaked" predicates, however, doesn't entirely meet Ian's criterion. He would like to be able to match a request using a lambda or another function which interrogates the @@ -1297,7 +1294,7 @@ Routes (Usually) Need Relative Ordering +++++++++++++++++++++++++++++++++++++++ Consider the following simple `Groundhog -<http://bfg.repoze.org/videos#groundhog1>`_ application: +<https://github.com/Pylons/groundhog>`_ application: .. code-block:: python :linenos: diff --git a/docs/foreword.rst b/docs/foreword.rst index 9ae7eda60..aa8d7c77b 100644 --- a/docs/foreword.rst +++ b/docs/foreword.rst @@ -8,70 +8,74 @@ Foreword Creations*, which later became *Zope Corporation*. He has been a widely respected member of the Python community since 1994. -Fortunate. +Some times amazing things can actually happen. -As I reflect upon the BFG web framework and this book by Chris to -document it, I keep coming back to the same word. Certainly the -conventional wisdom is clear: "Don't we have too many web frameworks, -paired with outdated books?" Yes we do, but to the contrary and for -that very reason, we are fortunate to have this book and this -framework. +In the world of web frameworks, the rate of radioactive decay is very high. +Projects are starting, splintering, folding, and clashing constantly. For +Python, there are over 50 listed web frameworks. In some ways this shows +health and experimentation. Yet others have started to ask: "Is this really +good for Python developers?" -Chris McDonough first came to work with us at Digital Creations almost -a decade ago, just after there existed a Zope. We were all pioneers: -the first open source application server, one of the first open source -web companies to get serious investment, and entrants in nearly every -book and article about the open source space. Zope wasn't just a -unique business model, though. It really was, as quoted at the time, -one of the places where open source delivered fresh ideas in design -and architecture. +This book is the result of an event which bucked this trend, an event which +Armin Ronacher wrote was "one of the greatest moves in Python's web framework +history." Two projects merged and are bringing in a third. Consolidation +won a victory over splintering. -Then a decade happened. Bubbles burst and the new new thing became -the old new thing, many times in succession. All of us changed jobs, -worked on a variety of endeavors, and big dreams yielded to small -realities. Somehow, though the trajectory was unforeseen, we have -orbited back to the same spot. Older, wiser, but with similar ideas -and familiar faces. Back to dream again. +As someone from the Zope world, I had a strong interest in repoze.bfg. I +viewed it as the escape hatch for Zope, teleporting us into the modern world +of Python development, permitting but not requiring Zope-style idioms. Chris +McDonough established a great brand for repoze.bfg: small, documented, +tested, fast, stable, friendly. As the project manager for a very large +repoze.bfg application, I can strongly attest that it was a home run on those +points. -We are fortunate to have BFG. It really does carve out a unique spot -in the Python web frameworks landscape. It permits the core good -ideas from Zope, while not requiring them. Moreover, the reason -you'll love it has less to do with Zope and more to do with the old -fashioned stuff: +But in a crowded web frameworks landscape, repoze.bfg was a long-shot to get +critical mass. It had a lot to offer, but was missing critical pieces such +as momentum and name recognition. -- A superb commitment to outstanding and constantly updated documentation +Pylons has long been viewed as holding the number two spot in Python web +frameworks. It is one of (if not the) first "modern" web framework. With +lots of users, and a "full-stack" framework atop it (TurboGears), Pylons had +momentum and name recognition aplenty. But it needed more resources to +accomplish its goals of an architectural transition, and Ben Bangert needed +to share the load as architect during the transition. -- An equal commitment to quality: test coverage, performance, and - documented compatibility +Ben and Chris started talking during 2011 about architectural patterns and +discovered Pylons and repoze.bfg covered almost exactly the same surface +area. After some experiments, it became clear that, technically at least, +the next version of Pylons could be the same as the next version of +repoze.bfg. -- Adult supervision and minimalism in the design, with "pay only for - what you eat" simplicity +But what about the non-technical parts? It was one thing to consolidate +code. Consolidating projects was new territory. -For those of us from the Zope world, BFG permits our still-unique -ideas while teleporting us into the modern world of Python web -programming. It is fascinating, liberating, and rejuvenating. We are -able to cast off old sins and legitimately reclaim the title of best -damn game in town. Quite a coup: whether you considered Zope but -turned away, or became an adopter, you'll find BFG the new new new -thing. +I was fortunate to meet with the principals in Las Vegas and watch as they +hashed out the idea. The projects would merge and keep the Pylons identity. +repoze.bfg would sacrifice its identity, but provide the technical +foundation. All the resources from the two projects would be combined. -We are also fortunate to have this book. We never had such a resource -in Zope, even though we funded the writing of the first book a decade -ago. In retrospect, the answer is obvious: a second group tried to -retrofit a book onto code created by the first group. The true magic -in BFG is that the top-notch documentation is written by the same -person as the top-notch code, a person with equal passion and -commitment to both. Rarely are we so fortunate. +I'll confess, I had high hopes for the outcome. Now that the merge has +happened and 1.0 released, I can honestly say it has done better than I could +have imagined. The story of "consolidation" is catching on, and interest in +working together is growing. Pyramid 1.0 is very, very high quality and +ready to go for PyCon 2011. People interested in "simple, fast, documented, +tested" have a strong framework and healthy project. -Which brings us to the final point. We are fortunate to have Chris. -I personally consider myself lucky to have worked with him and to be -his friend this past decade. He has changed my thinking in numerous -ways, fundamentally improving the way I view many things. He's the -best person I know in the world of open source, and I get to be in -business with him. Fortunate indeed. +It took humility, patience, and pragmatism to reach this point of obvious +success. Certainly by the project leaders, who each had to give up some of +their sovereignty and sacred cows. But as well, each community had to +discuss the challenges, the various alternatives for going forward, and the +pros and cons of consolidation in general but also this particular +consolidation. That such a conversation and change could happen in a +responsible, adult fashion speaks volumes about the strength and maturity of +each community. -I very much hope you enjoy this book and get involved with BFG. We -use it for applications as small as "hello world" demos up to -scalable, re-usable, half-a-million-dollar projects. May you find -BFG, and the book, to be a high-quality, honest, and durable framework -choice for your work as well. +What might happen in 2011? TurboGears is considering a move into the +umbrella Pylons Project. As Armin writes in his post, there is fertile +ground for consolidation at other layers. In my own interests, I hope the +worlds of Zope and Plone view Pyramid as the base for the next decade of +their ideas. But also, the Pylons Project as a vibrant home for such ideas. + +Congratulations, Pylons Project. Not only have you accelerated your spot on +the Python web frameworks chart, but you have injected the word +"consolidation" into the lexicon of hot ideas for 2011. diff --git a/docs/glossary.rst b/docs/glossary.rst index fc9f6a729..0aef7672b 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -24,12 +24,13 @@ Glossary information about response objects. Repoze - "Repoze" is essentially a "brand" of software developed by - `Agendaless Consulting <http://agendaless.com>`_ and a set of - contributors. The term has no special intrinsic meaning. The - project's `website <http://repoze.org>`_ has more information. - The software developed "under the brand" is available in a - `Subversion repository <http://svn.repoze.org>`_. + "Repoze" is essentially a "brand" of software developed by `Agendaless + Consulting <http://agendaless.com>`_ and a set of contributors. The + term has no special intrinsic meaning. The project's `website + <http://repoze.org>`_ has more information. The software developed + "under the brand" is available in a `Subversion repository + <http://svn.repoze.org>`_. Pyramid was originally known as + :mod:`repoze.bfg`. setuptools `Setuptools <http://peak.telecommunity.com/DevCenter/setuptools>`_ @@ -181,10 +182,10 @@ Glossary :ref:`urldispatch_chapter` for more information. context - An resource in the resource tree that is found during :term:`traversal` + A resource in the resource tree that is found during :term:`traversal` or :term:`URL dispatch` based on URL data; if it's found via traversal, it's usually a :term:`resource` object that is part of a resource tree; - if it's found via :term:`URL dispatch`, it's a object manufactured on + if it's found via :term:`URL dispatch`, it's an object manufactured on behalf of the route's "factory". A context resource becomes the subject of a :term:`view`, and often has security information attached to it. See the :ref:`traversal_chapter` chapter and the @@ -311,7 +312,8 @@ Glossary `A full-featured Python web framework <http://djangoproject.com>`_. Pylons - `A lightweight Python web framework <http://pylonshq.com>`_. + `A lightweight Python web framework <http://pylonshq.com>`_ and a + predecessor of Pyramid. ZODB `Zope Object Database <http://zodb.org>`_, a @@ -459,8 +461,7 @@ Glossary An indexing and search facility (fielded and full-text) based on `zope.index <http://pypi.python.org/pypi/zope.index>`_. See `the documentation <http://docs.repoze.org/catalog>`_ for more - information. A tutorial for its usage in :app:`Pyramid` - exists in :ref:`catalog_tutorial`. + information. repoze.who `Authentication middleware <http://docs.repoze.org/who>`_ for @@ -487,7 +488,7 @@ Glossary available as its ``__parent__`` attribute. root factory - The "root factory" of an :app:`Pyramid` application is called + The "root factory" of a :app:`Pyramid` application is called on every request sent to the application. The root factory returns the traversal root of an application. It is conventionally named ``get_root``. An application may supply a @@ -498,7 +499,7 @@ Glossary all URL-to-view code mappings. SQLAlchemy - `SQLAlchemy' <http://www.sqlalchemy.org/>`_ is an object + `SQLAlchemy <http://www.sqlalchemy.org/>`_ is an object relational mapper used in tutorials within this documentation. JSON @@ -618,16 +619,15 @@ Glossary information. thread local - A thread-local variable is one which is essentially a global - variable in terms of how it is accessed and treated, however, - each `thread - <http://en.wikipedia.org/wiki/Thread_(computer_science)>` used by - the application may have a different value for this same "global" - variable. :app:`Pyramid` uses a small number of thread local - variables, as described in :ref:`threadlocals_chapter`. See also - the `threading.local documentation - <http://docs.python.org/library/threading.html#threading.local>` - for more information. + A thread-local variable is one which is essentially a global variable + in terms of how it is accessed and treated, however, each `thread + <http://en.wikipedia.org/wiki/Thread_(computer_science)>`_ used by the + application may have a different value for this same "global" variable. + :app:`Pyramid` uses a small number of thread local variables, as + described in :ref:`threadlocals_chapter`. See also the `threading.local + documentation + <http://docs.python.org/library/threading.html#threading.local>`_ for + more information. multidict An ordered dictionary that can have multiple values for each @@ -644,11 +644,11 @@ Glossary and Chris McDonough. See also http://agendaless.com . Jython - A `Python implementation <http://www.jython.org/>` written for + A `Python implementation <http://www.jython.org/>`_ written for the Java Virtual Machine. Python - The `programming language <http://python.org>` in which + The `programming language <http://python.org>`_ in which :app:`Pyramid` is written. CPython @@ -863,8 +863,7 @@ Glossary pyramid_handlers An add-on package which allows :app:`Pyramid` users to create classes that are analogues of Pylons 1 "controllers". See - `http://docs.pylonsproject.org/projects/pyramid_handlers/dev/ - <http://docs.pylonsproject.org/projects/pyramid_handlers/dev/>`_. + http://docs.pylonsproject.org/projects/pyramid_handlers/dev/ . pyramid_jinja2 :term:`Jinja2` templating system bindings for Pyramid, documented at @@ -881,9 +880,9 @@ Glossary information. Pyramid Cookbook - An `additional documentation resource - <http://docs.pylonsproject.org/projects/pyramid_cookbook/dev/index.html>`_ - for Pyramid which presents topical, practical usages of Pyramid. + An additional documentation resource for Pyramid which presents topical, + practical usages of Pyramid available via + http://docs.pylonsproject.org/ . distutils The standard system for packaging and distributing Python packages. See diff --git a/docs/index.rst b/docs/index.rst index 8717542f1..d55daccfe 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -81,8 +81,6 @@ applications to various platforms. tutorials/bfg/index.rst tutorials/gae/index.rst tutorials/modwsgi/index.rst - tutorials/zeo/index.rst - tutorials/catalog/index.rst Reference Material ================== diff --git a/docs/latexindex.rst b/docs/latexindex.rst index 077283228..a4926bf30 100644 --- a/docs/latexindex.rst +++ b/docs/latexindex.rst @@ -64,13 +64,11 @@ Tutorials .. toctree:: :maxdepth: 1 - tutorials/bfg/index.rst tutorials/wiki/index.rst tutorials/wiki2/index.rst + tutorials/bfg/index.rst tutorials/gae/index.rst tutorials/modwsgi/index.rst - tutorials/zeo/index.rst - tutorials/catalog/index.rst .. _api_reference: diff --git a/docs/make_book b/docs/make_book new file mode 100755 index 000000000..dc8381845 --- /dev/null +++ b/docs/make_book @@ -0,0 +1,4 @@ +#!/bin/sh +make clean latex SPHINXBUILD=../bookenv/bin/sphinx-build BOOK=1 +cd _build/latex && make all-pdf + diff --git a/docs/narr/MyProject/development.ini b/docs/narr/MyProject/development.ini index 154e2c418..29486ce56 100644 --- a/docs/narr/MyProject/development.ini +++ b/docs/narr/MyProject/development.ini @@ -44,6 +44,6 @@ level = NOTSET formatter = generic [formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s +format = %(asctime)s %(levelname)-5.5s [%(name)s] %(message)s # End logging configuration diff --git a/docs/narr/MyProject/myproject/templates/mytemplate.pt b/docs/narr/MyProject/myproject/templates/mytemplate.pt index 03e7d9091..632c34876 100644 --- a/docs/narr/MyProject/myproject/templates/mytemplate.pt +++ b/docs/narr/MyProject/myproject/templates/mytemplate.pt @@ -4,103 +4,103 @@ xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>The Pyramid Web Application Development Framework</title> - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> - <meta name="keywords" content="python web application" /> - <meta name="description" content="pyramid web application" /> - <link rel="shortcut icon" - href="${request.static_url('myproject:static/favicon.ico')}" /> - <link rel="stylesheet" - href="${request.static_url('myproject: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('myproject:static/ie6.css')}" - type="text/css" media="screen" charset="utf-8" /> - <![endif]--> + <title>The Pyramid Web Application Development Framework</title> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> + <meta name="keywords" content="python web application" /> + <meta name="description" content="pyramid web application" /> + <link rel="shortcut icon" + href="${request.static_url('myproject:static/favicon.ico')}" /> + <link rel="stylesheet" + href="${request.static_url('myproject: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('myproject:static/ie6.css')}" + type="text/css" media="screen" charset="utf-8" /> + <![endif]--> </head> <body> - <div id="wrap"> - <div id="top"> - <div class="top align-center"> - <div> - <img src="${request.static_url('myproject:static/pyramid.png')}" - width="750" height="169" alt="pyramid"/> - </div> - </div> + <div id="wrap"> + <div id="top"> + <div class="top align-center"> + <div> + <img src="${request.static_url('myproject:static/pyramid.png')}" + width="750" height="169" alt="pyramid"/> </div> - <div id="middle"> - <div class="middle align-center"> - <p class="app-welcome"> - Welcome to <span class="app-name">${project}</span>, - an application generated by<br/> - the Pyramid web application development framework. - </p> - </div> + </div> + </div> + <div id="middle"> + <div class="middle align-center"> + <p class="app-welcome"> + Welcome to <span class="app-name">${project}</span>, + an application generated by<br/> + the Pyramid web application development framework. + </p> + </div> + </div> + <div id="bottom"> + <div class="bottom"> + <div id="left" class="align-right"> + <h2>Search documentation</h2> + <form method="get" + action="http://docs.pylonsproject.org/pyramid/dev/search.html"> + <input type="text" id="q" name="q" value="" /> + <input type="submit" id="x" value="Go" /> + </form> </div> - <div id="bottom"> - <div class="bottom"> - <div id="left" class="align-right"> - <h2>Search documentation</h2> - <form method="get" - action="http://docs.pylonsproject.org/pyramid/dev/search.html"> - <input type="text" id="q" name="q" value="" /> - <input type="submit" id="x" value="Go" /> - </form> - </div> - <div id="right" class="align-left"> - <h2>Pyramid links</h2> - <ul class="links"> - <li> - <a href="http://pylonsproject.org"> - Pylons Website - </a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation"> - Narrative Documentation - </a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation"> - API Documentation - </a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials"> - Tutorials - </a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history"> - Change History - </a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications"> - Sample Applications - </a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development"> - Support and Development - </a> - </li> - <li> - <a href="irc://irc.freenode.net#pyramid"> - IRC Channel - </a> - </li> - </ul> - </div> - </div> + <div id="right" class="align-left"> + <h2>Pyramid links</h2> + <ul class="links"> + <li> + <a href="http://pylonsproject.org"> + Pylons Website + </a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation"> + Narrative Documentation + </a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation"> + API Documentation + </a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials"> + Tutorials + </a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history"> + Change History + </a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications"> + Sample Applications + </a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development"> + Support and Development + </a> + </li> + <li> + <a href="irc://irc.freenode.net#pyramid"> + IRC Channel + </a> + </li> + </ul> </div> + </div> </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2010, Agendaless Consulting.</div> - </div> + </div> + <div id="footer"> + <div class="footer">© Copyright 2008-2010, Agendaless Consulting.</div> + </div> </body> </html> diff --git a/docs/narr/advconfig.rst b/docs/narr/advconfig.rst index 20316dc77..099bce35f 100644 --- a/docs/narr/advconfig.rst +++ b/docs/narr/advconfig.rst @@ -163,7 +163,7 @@ Using ``config.commit()`` +++++++++++++++++++++++++ You can manually commit a configuration by using the -:meth:`pyramid.config.Configurator.commit` method between configuration +:meth:`~pyramid.config.Configurator.commit` method between configuration calls. For example, we prevent conflicts from occurring in the application we examined previously as the result of adding a ``commit``. Here's the application that generates conflicts: @@ -255,7 +255,7 @@ conflict detection (and :ref:`twophase_config`) is disabled. Configuration statements will be executed immediately, and succeeding statements will override preceding ones. -:meth:`pyramid.config.Configurator.commit` has no effect when ``autocommit`` +:meth:`~pyramid.config.Configurator.commit` has no effect when ``autocommit`` is ``True``. If you use a Configurator in code that performs unit testing, it's usually a @@ -267,7 +267,7 @@ unconcerned about conflict detection or two-phase configuration in test code. Automatic Conflict Resolution ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -If your code uses the :meth:`pyramid.config.Configurator.include` method to +If your code uses the :meth:`~pyramid.config.Configurator.include` method to include external configuration, some conflicts are automatically resolved. Configuration statements that are made as the result of an "include" will be overridden by configuration statements that happen within the caller of @@ -332,7 +332,7 @@ Instead, use :meth:`pyramid.config.Configuration.include`: Using ``include`` rather than calling the function directly will allow :ref:`automatic_conflict_resolution` to work. -:meth:`pyramid.config.Configuration.include` can also accept a :term:`module` +:meth:`~pyramid.config.Configuration.include` can also accept a :term:`module` as an argument: .. code-block:: python @@ -346,11 +346,11 @@ For this to work properly, the ``myapp`` module must contain a callable with the special name ``includeme``, which should perform configuration (like the ``add_routes`` callable we showed above as an example). -:meth:`pyramid.config.Configuration.include` can also accept a :term:`dotted +:meth:`~pyramid.config.Configuration.include` can also accept a :term:`dotted Python name` to a function or a module. .. note: See :ref:`the_include_tag` for a declarative alternative to - :meth:`pyramid.config.Configurator.include`. + the :meth:`~pyramid.config.Configurator.include` method. .. _twophase_config: @@ -368,8 +368,8 @@ to do conflict detection. Due to this, for configuration methods that have no internal ordering constraints, execution order of configuration method calls is not important. For example, the relative ordering of -:meth:`pyramid.config.Configurator.add_view` and -:meth:`pyramid.config.Configurator.add_renderer` is unimportant when a +:meth:`~pyramid.config.Configurator.add_view` and +:meth:`~pyramid.config.Configurator.add_renderer` is unimportant when a non-autocommitting configurator is used. This code snippet: .. code-block:: python @@ -398,7 +398,7 @@ used, two-phase configuration is disabled, and configuration statements must be ordered in dependency order. Some configuration methods, such as -:meth:`pyramid.config.Configurator.add_route` have internal ordering +:meth:`~pyramid.config.Configurator.add_route` have internal ordering 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. diff --git a/docs/narr/assets.rst b/docs/narr/assets.rst index ee2e0440e..74fa7723e 100644 --- a/docs/narr/assets.rst +++ b/docs/narr/assets.rst @@ -142,7 +142,7 @@ see :ref:`advanced_static`. Here's another example that uses an :term:`asset specification` instead of an absolute path as the ``path`` argument. To convince -:meth:`pyramid.config.Configurator.add_static_view` to serve files up under +:meth:`~pyramid.config.Configurator.add_static_view` to serve files up under the ``/static`` URL from the ``a/b/c/static`` directory of the Python package named ``some_package``, we can use a fully qualified :term:`asset specification` as the ``path``: @@ -153,17 +153,17 @@ specification` as the ``path``: # config is an instance of pyramid.config.Configurator config.add_static_view(name='static', path='some_package:a/b/c/static') -The ``path`` provided to :meth:`pyramid.config.Configurator.add_static_view` +The ``path`` provided to :meth:`~pyramid.config.Configurator.add_static_view` may be a fully qualified :term:`asset specification` or an *absolute path*. Instead of representing a URL prefix, the ``name`` argument of a call to -:meth:`pyramid.config.Configurator.add_static_view` can alternately be a +:meth:`~pyramid.config.Configurator.add_static_view` can alternately be a *URL*. Each of examples we've seen so far have shown usage of the ``name`` argument as a URL prefix. However, when ``name`` is a *URL*, static assets can be served from an external webserver. In this mode, the ``name`` is used as the URL prefix when generating a URL using :func:`pyramid.url.static_url`. -For example, :meth:`pyramid.config.Configurator.add_static_view` may +For example, :meth:`~pyramid.config.Configurator.add_static_view` may be fed a ``name`` argument which is ``http://example.com/images``: .. code-block:: python @@ -173,23 +173,16 @@ be fed a ``name`` argument which is ``http://example.com/images``: config.add_static_view(name='http://example.com/images', path='mypackage:images') -Because :meth:`pyramid.config.Configurator.add_static_view` is provided with +Because :meth:`~pyramid.config.Configurator.add_static_view` is provided with a ``name`` argument that is the URL ``http://example.com/images``, subsequent -calls to :func:`pyramid.url.static_url` with paths that start with the +calls to :func:`~pyramid.url.static_url` with paths that start with the ``path`` argument passed to -:meth:`pyramid.config.Configurator.add_static_view` will generate a URL +:meth:`~pyramid.config.Configurator.add_static_view` will generate a URL something like ``http://example.com/images/logo.png``. The external webserver listening on ``example.com`` must be itself configured to respond -properly to such a request. The :func:`pyramid.url.static_url` API is +properly to such a request. The :func:`~pyramid.url.static_url` API is discussed in more detail later in this chapter. -.. note:: - - The :ref:`static_directive` ZCML directive offers an declarative - equivalent to :meth:`pyramid.config.Configurator.add_static_view`. Use of - the :ref:`static_directive` ZCML directive is completely equivalent to - using imperative configuration for the same purpose. - .. index:: single: generating static asset urls single: static asset urls @@ -199,7 +192,7 @@ discussed in more detail later in this chapter. Generating Static Asset URLs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -When a :meth:`pyramid.config.Configurator.add_static_view` method is used to +When a :meth:`~pyramid.config.Configurator.add_static_view` method is used to register a static asset directory, a special helper API named :func:`pyramid.url.static_url` can be used to generate the appropriate URL for an asset that lives in one of the directories named by the static @@ -221,7 +214,7 @@ visits a URL which begins with ``/static1``, and the assets in the visits a URL which begins with ``/static2``. You needn't generate the URLs to static assets "by hand" in such a -configuration. Instead, use the :func:`pyramid.url.static_url` API to +configuration. Instead, use the :func:`~pyramid.url.static_url` API to generate them for you. For example: .. code-block:: python @@ -242,15 +235,15 @@ If the request "application URL" of the running system is ``http://example.com/static1/foo.css``. The ``js_url`` generated above would be ``http://example.com/static2/foo.js``. -One benefit of using the :func:`pyramid.url.static_url` function rather than +One benefit of using the :func:`~pyramid.url.static_url` function rather than constructing static URLs "by hand" is that if you need to change the ``name`` of a static URL declaration, the generated URLs will continue to resolve properly after the rename. -URLs may also be generated by :func:`pyramid.url.static_url` to static assets +URLs may also be generated by :func:`~pyramid.url.static_url` to static assets that live *outside* the :app:`Pyramid` application. This will happen when -the :meth:`pyramid.config.Configurator.add_static_view` API associated with -the path fed to :func:`pyramid.url.static_url` is a *URL* instead of a view +the :meth:`~pyramid.config.Configurator.add_static_view` API associated with +the path fed to :func:`~pyramid.url.static_url` is a *URL* instead of a view name. For example, the ``name`` argument may be ``http://example.com`` while the the ``path`` given may be ``mypackage:images``: @@ -270,13 +263,13 @@ assets which begin with ``mypackage:images`` will be prefixed with static_url('mypackage:images/logo.png', request) # -> http://example.com/images/logo.png -Using :func:`pyramid.url.static_url` in conjunction with a -:meth:`pyramid.configuration.Configurator.add_static_view` makes it possible +Using :func:`~pyramid.url.static_url` in conjunction with a +:meth:`~pyramid.configuration.Configurator.add_static_view` makes it possible to put static media on a separate webserver during production (if the -``name`` argument to :meth:`pyramid.config.Configurator.add_static_view` is a +``name`` argument to :meth:`~pyramid.config.Configurator.add_static_view` is a URL), while keeping static media package-internal and served by the development webserver during development (if the ``name`` argument to -:meth:`pyramid.config.Configurator.add_static_view` is a URL prefix). To +:meth:`~pyramid.config.Configurator.add_static_view` is a URL prefix). To create such a circumstance, we suggest using the :attr:`pyramid.registry.Registry.settings` API in conjunction with a setting in the application ``.ini`` file named ``media_location``. Then set the @@ -300,7 +293,7 @@ dispatch`, you may want static assets to only be available as a fallback if no previous route matches. Alternately, you might like to serve a particular static asset manually, because its download requires authentication. -Note that you cannot use the :func:`pyramid.url.static_url` API to generate +Note that you cannot use the :func:`~pyramid.url.static_url` API to generate URLs against assets made accessible by registering a custom static view. Root-Relative Custom Static View (URL Dispatch Only) @@ -309,7 +302,7 @@ Root-Relative Custom Static View (URL Dispatch Only) The :class:`pyramid.view.static` 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 +:meth:`~pyramid.config.Configurator.add_static_view` configuration method, so its behavior is almost exactly the same once it's configured. .. warning:: The following example *will not work* for applications that use @@ -317,13 +310,13 @@ 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 + :class:`~pyramid.view.static` static view cannot be made root-relative when you use traversal. 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 +:class:`~pyramid.view.static` class inside a ``static.py`` file in your application root as below. .. ignore-next-block @@ -334,7 +327,7 @@ application root as below. static_view = static('/path/to/static/dir') .. note:: For better cross-system flexibility, use an :term:`asset - specification` as the argument to :class:`pyramid.view.static` instead of + 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``. @@ -351,7 +344,7 @@ application's startup code. config.add_route('catchall_static', '/*subpath', 'myapp.static.static_view') The special name ``*subpath`` above is used by the -:class:`pyramid.view.static` view callable to signify the path of the file +:class:`~pyramid.view.static` 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 @@ -440,7 +433,7 @@ feature, a :term:`Configurator` API exists named setuptools :term:`pkg_resources` API. .. note:: The :term:`ZCML` directive named ``asset`` serves the same purpose - as the :meth:`pyramid.config.Configurator.override_asset` method. + as the :meth:`~pyramid.config.Configurator.override_asset` method. .. index:: single: override_asset @@ -450,7 +443,7 @@ feature, a :term:`Configurator` API exists named The ``override_asset`` API ~~~~~~~~~~~~~~~~~~~~~~~~~~ -An individual call to :meth:`pyramid.config.Configurator.override_asset` +An individual call to :meth:`~pyramid.config.Configurator.override_asset` can override a single asset. For example: .. ignore-next-block @@ -503,7 +496,7 @@ if you want to override assets for both ``some.package:templates``, and The package name in a specification may start with a dot, meaning that the package is relative to the package in which the configuration construction file resides (or the ``package`` argument to the -:class:`pyramid.config.Configurator` class construction). +:class:`~pyramid.config.Configurator` class construction). For example: .. ignore-next-block diff --git a/docs/narr/configuration.rst b/docs/narr/configuration.rst index 05bc4d6cc..6360dc574 100644 --- a/docs/narr/configuration.rst +++ b/docs/narr/configuration.rst @@ -127,7 +127,7 @@ The scanning machinery imports each module and subpackage in a package or module recursively, looking for special attributes attached to objects defined within a module. These special attributes are typically attached to code via the use of a :term:`decorator`. For example, the -:class:`pyramid.view.view_config` decorator can be attached to a function or +:class:`~pyramid.view.view_config` decorator can be attached to a function or instance method. Once scanning is invoked, and :term:`configuration decoration` is found by @@ -136,7 +136,7 @@ behalf: these calls replace the need to add imperative configuration statements that don't live near the code being configured. In the example above, the scanner translates the arguments to -:class:`pyramid.view.view_config` into a call to the +:class:`~pyramid.view.view_config` into a call to the :meth:`pyramid.config.Configurator.add_view` method, effectively: .. ignore-next-block diff --git a/docs/narr/events.rst b/docs/narr/events.rst index 224eeca16..929208083 100644 --- a/docs/narr/events.rst +++ b/docs/narr/events.rst @@ -43,7 +43,7 @@ Configuring an Event Listener Imperatively You can imperatively configure a subscriber function to be called for some event type via the -:meth:`pyramid.config.Configurator.add_subscriber` +:meth:`~pyramid.config.Configurator.add_subscriber` method (see also :term:`Configurator`): .. code-block:: python @@ -59,7 +59,7 @@ method (see also :term:`Configurator`): config.add_subscriber(mysubscriber, NewRequest) The first argument to -:meth:`pyramid.config.Configurator.add_subscriber` is the +:meth:`~pyramid.config.Configurator.add_subscriber` is the subscriber function (or a :term:`dotted Python name` which refers to a subscriber callable); the second argument is the event type. @@ -79,10 +79,9 @@ type via the :func:`pyramid.events.subscriber` function. def mysubscriber(event): event.request.foo = 1 -When the :func:`pyramid.subscriber` decorator is used a +When the :func:`~pyramid.events.subscriber` decorator is used a :term:`scan` must be performed against the package containing the -decorated function for the decorator to have any effect. See -:func:`pyramid.subscriber` for more information. +decorated function for the decorator to have any effect. Either of the above registration examples implies that every time the :app:`Pyramid` framework emits an event object that supplies an diff --git a/docs/narr/extending.rst b/docs/narr/extending.rst index c709e1f8f..416207584 100644 --- a/docs/narr/extending.rst +++ b/docs/narr/extending.rst @@ -115,15 +115,14 @@ Fundamental Plugpoints The fundamental "plug points" of an application developed using :app:`Pyramid` are *routes*, *views*, and *assets*. Routes are declarations -made using the :meth:`pyramid.config.Configurator.add_route` method (or the -ZCML ``<route>`` directive). Views are declarations made using the -:meth:`pyramid.config.Configurator.add_view` method (or the ZCML ``<view>`` -directive). Assets are files that are accessed by :app:`Pyramid` using the -:term:`pkg_resources` API such as static files and templates via a -:term:`asset specification`. Other directives and configurator methods also -deal in routes, views, and assets. For example, ``add_handler`` directive of -the ``pyramid_handlers`` package adds a single route, and some number of -views. +made using the :meth:`pyramid.config.Configurator.add_route` method. Views +are declarations made using the :meth:`pyramid.config.Configurator.add_view` +method. Assets are files that are +accessed by :app:`Pyramid` using the :term:`pkg_resources` API such as static +files and templates via a :term:`asset specification`. Other directives and +configurator methods also deal in routes, views, and assets. For example, +``add_handler`` directive of the ``pyramid_handlers`` package adds a single +route, and some number of views. .. index:: single: extending an existing application @@ -270,7 +269,7 @@ Overriding Routes ~~~~~~~~~~~~~~~~~ Route setup is currently typically performed in a sequence of ordered calls -to :meth:`pyramid.config.Configurator.add_route`. Because these calls are +to :meth:`~pyramid.config.Configurator.add_route`. Because these calls are ordered relative to each other, and because this ordering is typically important, you should retain their relative ordering when performing an override. Typically, this means *copying* all the ``add_route`` statements diff --git a/docs/narr/firstapp.rst b/docs/narr/firstapp.rst index a82119b73..f5adad905 100644 --- a/docs/narr/firstapp.rst +++ b/docs/narr/firstapp.rst @@ -7,13 +7,6 @@ In this chapter, we will walk through the creation of a tiny :app:`Pyramid` application. After we're finished creating the application, we'll explain in more detail how it works. -.. note:: - - If you're a "theory-first" kind of person, you might choose to read - :ref:`urldispatch_chapter` and :ref:`views_chapter` before diving into - the code that follows, but it's not necessary if -- like many programmers - -- you're willing to "go with the flow". - .. _helloworld_imperative: Hello World, Goodbye World @@ -122,7 +115,7 @@ A view callable is required to return a :term:`response` object because a response object has all the information necessary to formulate an actual HTTP response; this object is then converted to text by the upstream :term:`WSGI` server and sent back to the requesting browser. To return a response, each -view callable creates an instance of the :class:`pyramid.response.Response` +view callable creates an instance of the :class:`~pyramid.response.Response` class. In the ``hello_world`` function, the string ``'Hello world!'`` is passed to the ``Response`` constructor as the *body* of the response. In the ``goodbye_world`` function, the string ``'Goodbye world!'`` is passed. @@ -247,7 +240,7 @@ predicates) is always invoked. In this application, :app:`Pyramid` chooses the most specific view callable based only on view :term:`predicate` applicability. The ordering of calls to -:meth:`pyramid.config.Configurator.add_view` is never very important. We can +:meth:`~pyramid.config.Configurator.add_view` is never very important. We can register ``goodbye_world`` first and ``hello_world`` second; :app:`Pyramid` will still give us the most specific callable when a request is dispatched to it. @@ -322,7 +315,7 @@ References ---------- For more information about the API of a :term:`Configurator` object, -see :class:`pyramid.config.Configurator` . +see :class:`~pyramid.config.Configurator` . For more information about :term:`view configuration`, see :ref:`view_config_chapter`. diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index b3b41046f..d2eaf8215 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -42,7 +42,7 @@ Like any other view, the notfound view must accept at least a ``request`` parameter, or both ``context`` and ``request``. The ``request`` is the current :term:`request` representing the denied action. The ``context`` (if used in the call signature) will be the instance of the -:exc:`pyramid.exceptions.NotFound` exception that caused the view to be +:exc:`~pyramid.exceptions.NotFound` exception that caused the view to be called. Here's some sample code that implements a minimal NotFound view callable: @@ -57,7 +57,7 @@ Here's some sample code that implements a minimal NotFound view callable: .. note:: When a NotFound view callable is invoked, it is passed a :term:`request`. The ``exception`` attribute of the request will - be an instance of the :exc:`pyramid.exceptions.NotFound` + be an instance of the :exc:`~pyramid.exceptions.NotFound` exception that caused the not found view to be called. The value of ``request.exception.args[0]`` will be a value explaining why the not found error was raised. This message will be different when @@ -67,7 +67,7 @@ Here's some sample code that implements a minimal NotFound view callable: .. warning:: When a NotFound view callable accepts an argument list as described in :ref:`request_and_context_view_definitions`, the ``context`` passed as the first argument to the view callable will be the - :exc:`pyramid.exceptions.NotFound` exception instance. If available, the + :exc:`~pyramid.exceptions.NotFound` exception instance. If available, the resource context will still be available as ``request.context``. .. index:: @@ -122,7 +122,7 @@ Here's some sample code that implements a minimal forbidden view: .. note:: When a forbidden view callable is invoked, it is passed a :term:`request`. The ``exception`` attribute of the request will - be an instance of the :exc:`pyramid.exceptions.Forbidden` + be an instance of the :exc:`~pyramid.exceptions.Forbidden` exception that caused the forbidden view to be called. The value of ``request.exception.args[0]`` will be a value explaining why the forbidden was raised. This message will be different when the @@ -253,7 +253,7 @@ that can be used for this purpose. For example: An object of this type is sent as an event just before a :term:`renderer` is invoked (but *after* the application-level renderer globals factory added via -:class:`pyramid.config.Configurator.set_renderer_globals_factory`, if any, +:class:`~pyramid.config.Configurator.set_renderer_globals_factory`, if any, has injected its own keys into the renderer globals dictionary). If a subscriber attempts to add a key that already exist in the renderer @@ -263,7 +263,7 @@ keys added to the renderer globals dictionary by all :class:`pyramid.events.BeforeRender` subscribers and renderer globals factories must be unique. -See the API documentation for the :class:`pyramid.events.BeforeRender` event +See the API documentation for the :class:`~pyramid.events.BeforeRender` event interface at :class:`pyramid.interfaces.IBeforeRender`. Another mechanism which allows event subscribers more control when adding @@ -307,14 +307,14 @@ callback will be an exception object instead of its default value of Response callbacks are called in the order they're added (first-to-most-recently-added). All response callbacks are called *after* -the :class:`pyramid.events.NewResponse` event is sent. Errors raised by +the :class:`~pyramid.events.NewResponse` event is sent. Errors raised by response callbacks are not handled specially. They will be propagated to the caller of the :app:`Pyramid` router application. A response callback has a lifetime of a *single* request. If you want a response callback to happen as the result of *every* request, you must re-register the callback into every new request (perhaps within a subscriber -of a :class:`pyramid.events.NewRequest` event). +of a :class:`~pyramid.events.NewRequest` event). .. index:: single: finished callback @@ -377,7 +377,7 @@ application. A finished callback has a lifetime of a *single* request. If you want a finished callback to happen as the result of *every* request, you must re-register the callback into every new request (perhaps within a subscriber -of a :class:`pyramid.events.NewRequest` event). +of a :class:`~pyramid.events.NewRequest` event). .. index:: single: traverser @@ -472,7 +472,7 @@ However, since the way traversal is done will have been modified, the URLs it generates by default may be incorrect. If you've added a traverser, you can change how -:func:`pyramid.url.resource_url` generates a URL for a specific type of +:func:`~pyramid.url.resource_url` generates a URL for a specific type of resource by adding a registerAdapter call for :class:`pyramid.interfaces.IContextURL` to your application: @@ -488,7 +488,7 @@ resource by adding a registerAdapter call for IContextURL) In the above example, the ``myapp.traversal.URLGenerator`` class will be used -to provide services to :func:`pyramid.url.resource_url` any time the +to provide services to :func:`~pyramid.url.resource_url` any time the :term:`context` passed to ``resource_url`` is of class ``myapp.resources.MyRoot``. The second argument in the ``(MyRoot, Interface)`` tuple represents the type of interface that must be possessed by @@ -496,7 +496,7 @@ the :term:`request` (in this case, any interface, represented by ``zope.interface.Interface``). The API that must be implemented by a class that provides -:class:`pyramid.interfaces.IContextURL` is as follows: +:class:`~pyramid.interfaces.IContextURL` is as follows: .. code-block:: python :linenos: @@ -611,7 +611,7 @@ to set a *default* view mapper (overriding the superdefault view mapper used by Pyramid itself). A *single* view registration can use a view mapper by passing the mapper as -the ``mapper`` argument to :meth:`pyramid.config.Configuration.add_view`. +the ``mapper`` argument to :meth:`~pyramid.config.Configuration.add_view`. .. index:: single: configuration decorator @@ -621,7 +621,7 @@ the ``mapper`` argument to :meth:`pyramid.config.Configuration.add_view`. Registering Configuration Decorators ------------------------------------ -Decorators such as :class:`pyramid.view.view_config` don't change the +Decorators such as :class:`~pyramid.view.view_config` don't change the behavior of the functions or classes they're decorating. Instead, when a :term:`scan` is performed, a modified version of the function or class is registered with :app:`Pyramid`. diff --git a/docs/narr/hybrid.rst b/docs/narr/hybrid.rst index 181ae1285..780cb0975 100644 --- a/docs/narr/hybrid.rst +++ b/docs/narr/hybrid.rst @@ -156,12 +156,12 @@ match is straightforward. When a route is matched: - If the route's configuration does not have a ``factory`` argument, the *global* :term:`root factory` will be called to generate a :term:`root` object. The global root factory is the - callable implied by the ``root_factory`` argument passed to - :class:`pyramid.config.Configurator` at application + callable implied by the ``root_factory`` argument passed to the + :class:`~pyramid.config.Configurator` at application startup time. - If a ``root_factory`` argument is not provided to the - :class:`pyramid.config.Configurator` at startup time, a + :class:`~pyramid.config.Configurator` at startup time, a *default* root factory is used. The default root factory is used to generate a root object. @@ -260,7 +260,7 @@ route statement is a reasonable thing to do. We could have also used our ``root_factory`` callable as the ``root_factory`` argument of the - :class:`pyramid.config.Configurator` constructor, instead + :class:`~pyramid.config.Configurator` constructor, instead of associating it with a particular route inside the route's configuration. Every hybrid route configuration that is matched but which does *not* name a ``factory`` attribute will use the use @@ -300,13 +300,13 @@ invoked after a route matches: config.add_view('mypackage.views.myview', route_name='home') Note that the above call to -:meth:`pyramid.config.Configurator.add_view` includes a ``route_name`` +:meth:`~pyramid.config.Configurator.add_view` includes a ``route_name`` argument. View configurations that include a ``route_name`` argument are meant to associate a particular view declaration with a route, using the route's name, in order to indicate that the view should *only be invoked when the route matches*. -Calls to :meth:`pyramid.config.Configurator.add_view` may pass a +Calls to :meth:`~pyramid.config.Configurator.add_view` may pass a ``route_name`` attribute, which refers to the value of an existing route's ``name`` argument. In the above example, the route name is ``home``, referring to the name of the route defined above it. @@ -357,7 +357,7 @@ Using the ``traverse`` Argument In a Route Definition Rather than using the ``*traverse`` remainder marker in a pattern, you can use the ``traverse`` argument to the -:meth:`pyramid.config.Configurator.add_route` method. +:meth:`~pyramid.config.Configurator.add_route` method. When you use the ``*traverse`` remainder marker, the traversal path is limited to being the remainder segments of a request URL when a route @@ -365,7 +365,7 @@ matches. However, when you use the ``traverse`` argument or attribute, you have more control over how to compose a traversal path. Here's a use of the ``traverse`` pattern in a call to -:meth:`pyramid.config.Configurator.add_route`: +:meth:`~pyramid.config.Configurator.add_route`: .. code-block:: python :linenos: @@ -472,7 +472,7 @@ startup time. config.add_view('myproject.views.another', route_name='home') This is because the ``view`` argument to the -:meth:`pyramid.config.Configurator.add_route` above is an *implicit* +:meth:`~pyramid.config.Configurator.add_route` above is an *implicit* default view when that route matches. ``add_route`` calls don't *need* to supply a view attribute. For example, this ``add_route`` call: diff --git a/docs/narr/i18n.rst b/docs/narr/i18n.rst index 7bfd29631..e7a4f61c0 100644 --- a/docs/narr/i18n.rst +++ b/docs/narr/i18n.rst @@ -59,7 +59,7 @@ This creates a Unicode-like object that is a TranslationString. :term:`Django` i18n, using a TranslationString is a lot like using "lazy" versions of related gettext APIs. -The first argument to :class:`pyramid.i18n.TranslationString` is +The first argument to :class:`~pyramid.i18n.TranslationString` is the ``msgid``; it is required. It represents the key into the translation mappings provided by a particular localization. The ``msgid`` argument must be a Unicode object or an ASCII string. The @@ -139,7 +139,7 @@ Using the ``TranslationStringFactory`` Class ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Another way to generate a translation string is to use the -:attr:`pyramid.i18n.TranslationStringFactory` object. This object +:attr:`~pyramid.i18n.TranslationStringFactory` object. This object is a *translation string factory*. Basically a translation string factory presets the ``domain`` value of any :term:`translation string` generated by using it. For example: @@ -156,11 +156,11 @@ generated by using it. For example: file generation tools. After assigning ``_`` to the result of a -:func:`pyramid.i18n.TranslationStringFactory`, the subsequent result -of calling ``_`` will be a :class:`pyramid.i18n.TranslationString` +:func:`~pyramid.i18n.TranslationStringFactory`, the subsequent result +of calling ``_`` will be a :class:`~pyramid.i18n.TranslationString` instance. Even though a ``domain`` value was not passed to ``_`` (as would have been necessary if the -:class:`pyramid.i18n.TranslationString` constructor were used instead +:class:`~pyramid.i18n.TranslationString` constructor were used instead of a translation string factory), the ``domain`` attribute of the resulting translation string will be ``pyramid``. As a result, the previous code example is completely equivalent (except for spelling) @@ -175,7 +175,7 @@ to: You can set up your own translation string factory much like the one provided above by using the -:class:`pyramid.i18n.TranslationStringFactory` class. For example, +:class:`~pyramid.i18n.TranslationStringFactory` class. For example, if you'd like to create a translation string factory which presets the ``domain`` value of generated translation strings to ``form``, you'd do something like this: @@ -344,7 +344,8 @@ which reside in your :app:`Pyramid` application. You run a $ mkdir -p myapplication/locale $ python setup.py extract_messages -The message catalog ``.pot`` template will end up in +The message catalog ``.pot`` template will end up in: + ``myapplication/locale/myapplication.pot``. Translation Domains @@ -432,7 +433,8 @@ init_catalog`` command: $ cd /place/where/myapplication/setup.py/lives $ python setup.py init_catalog -l es -By default, the message catalog ``.po`` file will end up in +By default, the message catalog ``.po`` file will end up in: + ``myapplication/locale/es/LC_MESSAGES/myapplication.po``. Once the file is there, it can be worked on by a human translator. @@ -491,13 +493,12 @@ translations will be available to :app:`Pyramid`. Using a Localizer ----------------- -A :term:`localizer` is an object that allows you to perform -translation or pluralization "by hand" in an application. You may use -the :func:`pyramid.i18n.get_localizer` function to obtain a -:term:`localizer`. :func:`pyramid.i18n.get_localizer`. This -function will return either the localizer object implied by the active -:term:`locale negotiator` or a default localizer object if no explicit -locale negotiator is registered. +A :term:`localizer` is an object that allows you to perform translation or +pluralization "by hand" in an application. You may use the +:func:`pyramid.i18n.get_localizer` function to obtain a :term:`localizer`. +This function will return either the localizer object implied by the active +:term:`locale negotiator` or a default localizer object if no explicit locale +negotiator is registered. .. code-block:: python :linenos: @@ -534,7 +535,7 @@ translation in a view component of an application might look like so: translated = localizer.translate(ts) # translation string # ... use translated ... -The :func:`pyramid.i18n.get_localizer` function will return a +The :func:`~pyramid.i18n.get_localizer` function will return a :class:`pyramid.i18n.Localizer` object bound to the locale name represented by the request. The translation returned from its :meth:`pyramid.i18n.Localizer.translate` method will depend on the @@ -612,9 +613,9 @@ locale negotiator returns ``None``. You can change the default locale name by changing the ``default_locale_name`` setting; see :ref:`default_locale_name_setting`. -Once :func:`pyramid.i18n.get_locale_name` is first run, the locale +Once :func:`~pyramid.i18n.get_locale_name` is first run, the locale name is stored on the request object. Subsequent calls to -:func:`pyramid.i18n.get_locale_name` will return the stored locale +:func:`~pyramid.i18n.get_locale_name` will return the stored locale name without invoking the :term:`locale negotiator`. To avoid this caching, you can use the :func:`pyramid.i18n.negotiate_locale_name` function: @@ -641,7 +642,7 @@ You can also obtain the locale name related to a request using the Obtaining the locale name as an attribute of a localizer is equivalent to obtaining a locale name by calling the -:func:`pyramid.i18n.get_locale_name` function. +:func:`~pyramid.i18n.get_locale_name` function. .. index:: single: date and currency formatting (i18n) @@ -738,8 +739,9 @@ facility described in :ref:`performing_a_translation`. Mako Pyramid I18N Support ------------------------- -:ref:`mako_i18n` is a recipe within the :term:`Pyramid Cookbook` which -explains how to add idiomatic I18N support to :term:`Mako` templates. +There exists a recipe within the :term:`Pyramid Cookbook` named "Mako +Internationalization" which explains how to add idiomatic I18N support to +:term:`Mako` templates. .. index:: single: localization deployment settings @@ -753,7 +755,7 @@ Localization-Related Deployment Settings A :app:`Pyramid` application will have a ``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 +:mod:`~pyramid.config.Configurator` constructor at startup time: .. code-block:: python @@ -891,7 +893,7 @@ application startup. For example: 'another.application:locale/') A message catalog in a translation directory added via -:meth:`pyramid.config.Configurator.add_translation_dirs` +:meth:`~pyramid.config.Configurator.add_translation_dirs` 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`. @@ -937,8 +939,8 @@ a particular request. A locale negotiator is a bit of code which accepts a request and which returns a :term:`locale name`. It is consulted when :meth:`pyramid.i18n.Localizer.translate` or :meth:`pyramid.i18n.Localizer.pluralize` is invoked. It is also -consulted when :func:`pyramid.i18n.get_locale_name` or -:func:`pyramid.i18n.negotiate_locale_name` is invoked. +consulted when :func:`~pyramid.i18n.get_locale_name` or +:func:`~pyramid.i18n.negotiate_locale_name` is invoked. .. _default_locale_negotiator: @@ -949,7 +951,7 @@ Most applications can make use of the default locale negotiator, which requires no additional coding or configuration. The default locale negotiator implementation named -:class:`pyramid.i18n.default_locale_negotiator` uses the following +:class:`~pyramid.i18n.default_locale_negotiator` uses the following set of steps to dermine the locale name. - First, the negotiator looks for the ``_LOCALE_`` attribute of the @@ -1000,7 +1002,7 @@ You may add your newly created locale negotiator to your application's configuration by passing an object which can act as the negotiator (or a :term:`dotted Python name` referring to the object) as the ``locale_negotiator`` argument of the -:class:`pyramid.config.Configurator` instance during application +:class:`~pyramid.config.Configurator` instance during application startup. For example: .. code-block:: python diff --git a/docs/narr/muchadoabouttraversal.rst b/docs/narr/muchadoabouttraversal.rst index 467a9e601..a4709ef18 100644 --- a/docs/narr/muchadoabouttraversal.rst +++ b/docs/narr/muchadoabouttraversal.rst @@ -6,8 +6,7 @@ Much Ado About Traversal .. note:: This chapter was adapted, with permission, from a blog post by `Rob Miller <http://blog.nonsequitarian.org/>`_, originally published at - `http://blog.nonsequitarian.org/2010/much-ado-about-traversal/ - <http://blog.nonsequitarian.org/2010/much-ado-about-traversal/>`_. + http://blog.nonsequitarian.org/2010/much-ado-about-traversal/ . Traversal is an alternative to :term:`URL dispatch` which allows :app:`Pyramid` applications to map URLs to code. @@ -269,14 +268,14 @@ It might be possible, but it certainly won't be easy. The matching patterns are going to become complex quickly as you try to handle all of the edge cases. -With traversal, however, it's straightforward. 20 layers of nesting would be -no problem. :app:`Pyramid` will happily call ``__getitem__`` as many times -as it needs to, until it runs out of path segments or until a resource raises -a :exc:`KeyError`. Each resource only needs to know how to fetch its -immediate children, the traversal algorithm takes care of the rest. Also, -since the structure of the resource tree can live in the database and not in -the code, it's simple to let users modify the tree at runtime to set up their -own personalized "directory" structures. +With traversal, however, it's straightforward. Twenty layers of nesting +would be no problem. :app:`Pyramid` will happily call ``__getitem__`` as +many times as it needs to, until it runs out of path segments or until a +resource raises a :exc:`KeyError`. Each resource only needs to know how to +fetch its immediate children, the traversal algorithm takes care of the rest. +Also, since the structure of the resource tree can live in the database and +not in the code, it's simple to let users modify the tree at runtime to set +up their own personalized "directory" structures. Another use case in which traversal shines is when there is a need to support a context-dependent security policy. One example might be a document @@ -305,7 +304,6 @@ don't require it, great: stick with :term:`URL dispatch`. But if you're using :app:`Pyramid` and you ever find that you *do* need to support one of these use cases, you'll be glad you have traversal in your toolkit. -.. note:: - It is even possible to mix and match :term:`traversal` with +.. note:: It is even possible to mix and match :term:`traversal` with :term:`URL dispatch` in the same :app:`Pyramid` application. See the :ref:`hybrid_chapter` chapter for details. diff --git a/docs/narr/project.rst b/docs/narr/project.rst index c076c67ac..7e2730e97 100644 --- a/docs/narr/project.rst +++ b/docs/narr/project.rst @@ -137,16 +137,11 @@ project we name ``MyProject``: name during ``paster create`` by adding the project name to the command line, e.g. ``paster create -t pyramid_starter MyProject``. -.. note:: You may encounter an error when using ``paster create`` - if a dependent Python package is not installed. This will - result in a traceback ending in: - - .. code-block:: text - - pkg_resources.DistributionNotFound: <package name> - - Simply run ``bin/easy_install``, with the missing package - name from the error message, to work around this issue. +.. note:: You may encounter an error when using ``paster create`` if a + dependent Python package is not installed. This will result in a traceback + ending in ``pkg_resources.DistributionNotFound: <package name>``. + Simply run ``bin/easy_install``, with the missing package name from the + error message to work around this issue. As a result of invoking the ``paster create`` command, a project is created in a directory named ``MyProject``. That directory is a :term:`project` @@ -325,37 +320,34 @@ unconditionally. [chrism@vitaminf shellenv]$ ../bin/paster pshell --disable-ipython \ development.ini MyProject -.. warning:: +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 - 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:: guess - :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. +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). @@ -511,8 +503,8 @@ describe, run, and test your application. ``setup.py``. #. ``MANIFEST.in`` is a :term:`distutils` "manifest" file, naming which files - should be included in a source distribution of the package when ``python - setup.py sdist`` is run. + should be included in a source distribution of the package when ``python + setup.py sdist`` is run. #. ``setup.py`` is the file you'll use to test and distribute your application. It is a standard :term:`setuptools` ``setup.py`` file. @@ -532,8 +524,10 @@ 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: guess + :language: ini :linenos: This file contains several "sections" including ``[app:MyProject]``, diff --git a/docs/narr/renderers.rst b/docs/narr/renderers.rst index 91c00057b..0b7cdb834 100644 --- a/docs/narr/renderers.rst +++ b/docs/narr/renderers.rst @@ -23,7 +23,7 @@ dictionary does not implement the Pyramid response interface, so you might believe that this example would fail. However, since a ``renderer`` is associated with the view callable through its :term:`view configuration` (in this case, using a ``renderer`` argument passed to -:func:`pyramid.view.view_config`), if the view does *not* return a Response +:func:`~pyramid.view.view_config`), if the view does *not* return a Response object, the renderer will attempt to convert the result of the view to a response on the developer's behalf. @@ -60,7 +60,7 @@ object serialization techniques. View configuration can vary the renderer associated with a view callable via the ``renderer`` attribute. For example, this call to -:meth:`pyramid.config.Configurator.add_view` associates the ``json`` renderer +:meth:`~pyramid.config.Configurator.add_view` associates the ``json`` renderer with a view callable: .. code-block:: python @@ -187,7 +187,7 @@ values serializable by :func:`json.dumps`. You can configure a view to use the JSON renderer by naming ``json`` as the ``renderer`` argument of a view configuration, e.g. by using -:meth:`pyramid.config.Configurator.add_view`: +:meth:`~pyramid.config.Configurator.add_view`: .. code-block:: python :linenos: @@ -428,21 +428,20 @@ following interface: class RendererFactory: def __init__(self, info): - """ Constructor: ``info`` will be an object having the - the following attributes: ``name`` (the renderer name), ``package`` - (the package that was 'current' at the time the renderer was - registered), ``type`` (the renderer type name), ``registry`` - (the current application registry) and ``settings`` (the - deployment settings dictionary). - """ + """ Constructor: info will be an object having the the + following attributes: name (the renderer name), package + (the package that was 'current' at the time the + renderer was registered), type (the renderer type + name), registry (the current application registry) and + settings (the deployment settings dictionary). """ def __call__(self, value, system): - """ Call a the renderer implementation with the value and - the system value passed in as arguments and return the - result (a string or unicode object). The value is the - return value of a view. The system value is a dictionary - containing available system values (e.g. ``view``, - ``context``, and ``request``). """ + """ Call a the renderer implementation with the value + and the system value passed in as arguments and return + the result (a string or unicode object). The value is + the return value of a view. The system value is a + dictionary containing available system values + (e.g. view, context, and request). """ The formal interface definition of the ``info`` object passed to a renderer factory constructor is available as :class:`pyramid.interfaces.IRendererInfo`. @@ -457,14 +456,14 @@ There are essentially two different kinds of renderer factories: such as a template. - A renderer factory which expects to accept a token that does not represent - a filesystem path or a asset specification in the ``name`` + a filesystem path or an asset specification in the ``name`` attribute of the ``info`` object fed to its constructor. These renderer factories are registered with a ``name`` value that does not begin with a dot. These renderer factories are typically object serializers. .. sidebar:: Asset Specifications - A asset specification is a colon-delimited identifier for an + An asset specification is a colon-delimited identifier for an :term:`asset`. The colon separates a Python :term:`package` name from a package subpath. For example, the asset specification ``my.package:static/baz.css`` identifies the file named @@ -472,7 +471,7 @@ There are essentially two different kinds of renderer factories: :term:`package`. Here's an example of the registration of a simple renderer factory via -:meth:`pyramid.config.Configurator.add_renderer`: +:meth:`~pyramid.config.Configurator.add_renderer`: .. code-block:: python :linenos: @@ -539,9 +538,6 @@ 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. -See also :ref:`renderer_directive` and -:meth:`pyramid.config.Configurator.add_renderer`. - Changing an Existing Renderer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -595,7 +591,7 @@ user instructing the view to use a template renderer with one that uses an XML-RPC renderer. This renderer would produce an XML-RPC representation of the data returned by an arbitrary view callable. -To use this feature, create a :class:`pyramid.events.NewRequest` +To use this feature, create a :class:`~pyramid.events.NewRequest` :term:`subscriber` which sniffs at the request data and which conditionally sets an ``override_renderer`` attribute on the request itself, which is the *name* of a registered renderer. For example: diff --git a/docs/narr/resources.rst b/docs/narr/resources.rst index 895d6c1c6..a11466a87 100644 --- a/docs/narr/resources.rst +++ b/docs/narr/resources.rst @@ -36,8 +36,8 @@ application. Also: - The ``context`` and ``containment`` predicate arguments to - :meth:`pyramid.config.Configurator.add_view` (or a - :func:`pyramid.view.view_config` decorator) reference a resource class + :meth:`~pyramid.config.Configurator.add_view` (or a + :func:`~pyramid.view.view_config` decorator) reference a resource class or resource :term:`interface`. - A :term:`root factory` returns a resource. @@ -46,7 +46,7 @@ Also: view. - Various helpful :app:`Pyramid` API methods expect a resource as an - argument (e.g. :func:`pyramid.url.resource_url` and others). + argument (e.g. :func:`~pyramid.url.resource_url` and others). .. index:: single: resource tree @@ -162,9 +162,9 @@ you will reach the filesystem root directory. .. warning:: If your root resource has a ``__name__`` argument that is not ``None`` or the empty string, URLs returned by the - :func:`pyramid.url.resource_url` function and paths generated by - the :func:`pyramid.traversal.resource_path` and - :func:`pyramid.traversal.resource_path_tuple` APIs will be + :func:`~pyramid.url.resource_url` function and paths generated by + the :func:`~pyramid.traversal.resource_path` and + :func:`~pyramid.traversal.resource_path_tuple` APIs will be generated improperly. The value of ``__name__`` will be prepended to every path and URL generated (as opposed to a single leading slash or empty tuple element). @@ -205,12 +205,12 @@ In general, since so much :app:`Pyramid` infrastructure depends on location-aware resources, it's a good idea to make each resource in your tree location-aware. -.. _generating_the_url_of_a_resource: - .. index:: single: resource_url pair: generating; resource url +.. _generating_the_url_of_a_resource: + Generating The URL Of A Resource -------------------------------- @@ -231,7 +231,7 @@ The simplest call to :func:`~pyramid.url.resource_url` looks like this: url = resource_url(resource, request) The ``request`` passed to ``resource_url`` in the above example is an -instance of an :app:`Pyramid` :term:`request` object. +instance of a :app:`Pyramid` :term:`request` object. If the resource referred to as ``resource`` in the above example was the root resource, and the host that was used to contact the server was @@ -281,7 +281,7 @@ about virtually rooting a resource. The shortcut method of the :term:`request` named :meth:`pyramid.request.Request.resource_url` can be used instead of -:func:`pyramid.url.resource_url` to generate a resource URL. +:func:`~pyramid.url.resource_url` to generate a resource URL. For more information about generating resource URLs, see the documentation for :func:`pyramid.url.resource_url`. @@ -292,13 +292,13 @@ Overriding Resource URL Generation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If a resource object implements a ``__resource_url__`` method, this method -will be called when :func:`pyramid.url.resource_url` is called to generate a +will be called when :func:`~pyramid.url.resource_url` is called to generate a URL for the resource, overriding the default URL returned for the resource by :func:`~pyramid.url.resource_url`. The ``__resource_url__`` hook is passed two arguments: ``request`` and ``info``. ``request`` is the :term:`request` object passed to -:func:`pyramid.url.resource_url`. ``info`` is a dictionary with two +:func:`~pyramid.url.resource_url`. ``info`` is a dictionary with two keys: ``physical_path`` @@ -331,7 +331,7 @@ or port number of the generated URL. Note that the URL generated by ``__resource_url__`` should be fully 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`. +:func:`~pyramid.url.resource_url`. Generating the Path To a Resource --------------------------------- @@ -350,7 +350,7 @@ character. If ``resource`` in the example above was accessible in the tree as ``root['a']['b']``, the above example would generate the string ``/a/b``. -Any positional arguments passed in to :func:`pyramid.traversal.resource_path` +Any positional arguments passed in to :func:`~pyramid.traversal.resource_path` will be appended as path segments to the end of the resource path. .. code-block:: python @@ -618,7 +618,7 @@ configuration, see :ref:`using_resource_interfaces`. Finding a Resource With a Class or Interface in Lineage ------------------------------------------------------- -Use the :func:`pyramid.traversal.find_interface` API to locate a parent that +Use the :func:`~pyramid.traversal.find_interface` API to locate a parent that is of a particular Python class, or which implements some :term:`interface`. For example, if your resource tree is composed as follows: @@ -669,7 +669,7 @@ These can be used to walk down a resource tree, or conveniently locate one resource "inside" another. Some APIs in :ref:`security_module` accept a resource object as a parameter. -For example, the :func:`pyramid.security.has_permission` API accepts a +For example, the :func:`~pyramid.security.has_permission` API accepts a resource object as one of its arguments; the ACL is obtained from this resource or one of its ancestors. Other APIs in the :mod:`pyramid.security` module also accept :term:`context` as an argument, and a context is always a diff --git a/docs/narr/router.rst b/docs/narr/router.rst index 782098bac..11f84d4ea 100644 --- a/docs/narr/router.rst +++ b/docs/narr/router.rst @@ -29,10 +29,10 @@ processing? #. The :term:`application registry` and the :term:`request` object created in the last step are pushed on to the :term:`thread local` stack that :app:`Pyramid` uses to allow the functions named - :func:`pyramid.threadlocal.get_current_request` and - :func:`pyramid.threadlocal.get_current_registry` to work. + :func:`~pyramid.threadlocal.get_current_request` and + :func:`~pyramid.threadlocal.get_current_registry` to work. -#. A :class:`pyramid.events.NewRequest` :term:`event` is sent to any +#. A :class:`~pyramid.events.NewRequest` :term:`event` is sent to any subscribers. #. If any :term:`route` has been defined within application @@ -46,7 +46,7 @@ processing? ``matched_route`` attributes are added to the request object; the former contains a dictionary representing the matched dynamic elements of the request's ``PATH_INFO`` value, the latter contains - the :class:`pyramid.interfaces.IRoute` object representing the + the :class:`~pyramid.interfaces.IRoute` object representing the route which matched. The root object associated with the route found is also generated: if the :term:`route configuration` which matched has an associated a ``factory`` argument, this factory is @@ -74,7 +74,7 @@ processing? they can be accessed via e.g. ``request.context`` within :term:`view` code. -#. A :class:`pyramid.events.ContextFound` :term:`event` is +#. A :class:`~pyramid.events.ContextFound` :term:`event` is sent to any subscribers. #. :app:`Pyramid` looks up a :term:`view` callable using the @@ -83,7 +83,7 @@ processing? the context, the type of the request, and the value of the view name, and any :term:`predicate` attributes applied to the view configuration), :app:`Pyramid` raises a - :class:`pyramid.exceptions.NotFound` exception, which is meant + :class:`~pyramid.exceptions.NotFound` exception, which is meant to be caught by a surrounding exception handler. #. If a view callable was found, :app:`Pyramid` attempts to call @@ -97,14 +97,14 @@ processing? security information attached to the context. If it returns ``True``, :app:`Pyramid` calls the view callable to obtain a response. If it returns ``False``, it raises a - :class:`pyramid.exceptions.Forbidden` exception, which is meant + :class:`~pyramid.exceptions.Forbidden` exception, which is meant to be called by a surrounding exception handler. #. If any exception was raised within a :term:`root factory`, by :term:`traversal`, by a :term:`view callable` or by :app:`Pyramid` itself (such as when it raises - :class:`pyramid.exceptions.NotFound` or - :class:`pyramid.exceptions.Forbidden`), the router catches the + :class:`~pyramid.exceptions.NotFound` or + :class:`~pyramid.exceptions.Forbidden`), the router catches the exception, and attaches it to the request as the ``exception`` attribute. It then attempts to find a :term:`exception view` for the exception that was caught. If it finds an exception view @@ -116,15 +116,15 @@ processing? successfully generated by a normal :term:`view callable` or an :term:`exception view` callable. :app:`Pyramid` will attempt to execute any :term:`response callback` functions attached via - :meth:`pyramid.request.Request.add_response_callback`. A - :class:`pyramid.events.NewResponse` :term:`event` is then sent to any + :meth:`~pyramid.request.Request.add_response_callback`. A + :class:`~pyramid.events.NewResponse` :term:`event` is then sent to any subscribers. The response object's ``app_iter``, ``status``, and ``headerlist`` attributes are then used to generate a WSGI response. The response is sent back to the upstream WSGI server. #. :app:`Pyramid` will attempt to execute any :term:`finished callback` functions attached via - :meth:`pyramid.request.Request.add_finished_callback`. + :meth:`~pyramid.request.Request.add_finished_callback`. #. The :term:`thread local` stack is popped. diff --git a/docs/narr/security.rst b/docs/narr/security.rst index 10a6c3db3..6e07c9338 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -72,14 +72,14 @@ Enabling an Authorization Policy Imperatively ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Passing an ``authorization_policy`` argument to the constructor of the -:class:`pyramid.config.Configurator` class enables an +:class:`~pyramid.config.Configurator` class enables an authorization policy. You must also enable an :term:`authentication policy` in order to enable the authorization policy. This is because authorization, in general, depends upon authentication. Use the ``authentication_policy`` argument to the -:class:`pyramid.config.Configurator` class during +:class:`~pyramid.config.Configurator` class during application setup to specify an authentication policy. For example: @@ -97,7 +97,7 @@ For example: authorization_policy=authorization_policy) .. note:: the ``authentication_policy`` and ``authorization_policy`` - arguments may also be passed to the Configurator as :ref:`dotted + arguments may also be passed to the Configurator as :term:`dotted Python name` values, each representing the dotted name path to a suitable implementation global defined at Python module scope. @@ -187,11 +187,9 @@ These APIs are in support of configuring a default permission for an application: - The ``default_permission`` constructor argument to the - :mod:`pyramid.config.Configurator` constructor. + :mod:`~pyramid.config.Configurator` constructor. -- The - :meth:`pyramid.config.Configurator.set_default_permission` - method. +- The :meth:`pyramid.config.Configurator.set_default_permission` method. When a default permission is registered: @@ -204,6 +202,13 @@ When a default permission is registered: and the view is registered *without* a permission (making it available to all callers regardless of their credentials). +.. warning:: + + 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. + .. index:: single: ACL single: access control list @@ -306,9 +311,7 @@ authentication system provides group information and the effective :term:`authentication policy` policy is written to respect group information. For example, the :class:`pyramid.authentication.RepozeWho1AuthenicationPolicy` respects group -information if you configure it with a ``callback``. See -:ref:`authentication_policies_directives_section` for more information about -the ``callback`` attribute. +information if you configure it with a ``callback``. Each ACE in an ACL is processed by an authorization policy *in the order dictated by the ACL*. So if you have an ACL like this: @@ -539,7 +542,7 @@ one of :data:`pyramid.security.ACLAllowed`, ``msg`` attribute, which is a string indicating why the permission was denied or allowed. Introspecting this information in the debugger or via print statements when a call to -:func:`pyramid.security.has_permission` fails is often useful. +:func:`~pyramid.security.has_permission` fails is often useful. .. index:: single: authentication policy (creating) @@ -584,7 +587,7 @@ that implements the following interface: current user on subsequent requests. """ After you do so, you can pass an instance of such a class into the -:class:`pyramid.config.Configurator` class at configuration +:class:`~pyramid.config.Configurator` class at configuration time as ``authentication_policy`` to use it. .. index:: @@ -603,7 +606,7 @@ otherwise specified. In some cases, it's useful to be able to use a different authorization policy than the default -:class:`pyramid.authorization.ACLAuthorizationPolicy`. For +:class:`~pyramid.authorization.ACLAuthorizationPolicy`. For example, it might be desirable to construct an alternate authorization policy which allows the application to use an authorization mechanism that does not involve :term:`ACL` objects. @@ -634,5 +637,5 @@ following interface: used.""" After you do so, you can pass an instance of such a class into the -:class:`pyramid.config.Configurator` class at configuration +:class:`~pyramid.config.Configurator` class at configuration time as ``authorization_policy`` to use it. diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 0ed52b563..97e3ebc55 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -42,7 +42,7 @@ tampered with. You can configure this session factory in your :app:`Pyramid` application by using the ``session_factory`` argument to the -:class:`pyramid.config.Configurator` class: +:class:`~pyramid.config.Configurator` class: .. code-block:: python :linenos: diff --git a/docs/narr/startup.rst b/docs/narr/startup.rst index 1b21cb516..e2c43b17e 100644 --- a/docs/narr/startup.rst +++ b/docs/narr/startup.rst @@ -82,7 +82,7 @@ Here's a high-level time-ordered overview of what happens when you press Our generated ``development.ini`` file looks like so: .. literalinclude:: MyProject/development.ini - :language: guess + :language: ini :linenos: In this case, the ``myproject.__init__:main`` function referred to by the @@ -94,7 +94,7 @@ Here's a high-level time-ordered overview of what happens when you press 'default_locale_name':'en'}``. #. The ``main`` function first constructs a - :class:`pyramid.config.Configurator` instance, passing a root resource + :class:`~pyramid.config.Configurator` instance, passing a root resource factory (constructor) to it as its ``root_factory`` argument, and ``settings`` dictionary captured via the ``**settings`` kwarg as its ``settings`` argument. @@ -109,18 +109,18 @@ Here's a high-level time-ordered overview of what happens when you press ``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 + 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 :meth:`pyramid.config.Configurator.make_wsgi_app` method is called. +#. The :meth:`~pyramid.config.Configurator.make_wsgi_app` method is called. The result is a :term:`router` instance. The router is associated with the :term:`application registry` implied by the configurator previously populated by other methods run against the Configurator. The router is a WSGI application. -#. A :class:`pyramid.events.ApplicationCreated` event is emitted (see +#. A :class:`~pyramid.events.ApplicationCreated` event is emitted (see :ref:`events_chapter` for more information about events). #. Assuming there were no errors, the ``main`` function in ``myproject`` @@ -142,7 +142,7 @@ Deployment Settings ------------------- Note that an augmented version of the values passed as ``**settings`` to the -:class:`pyramid.config.Configurator` constructor will be available in +:class:`~pyramid.config.Configurator` constructor will be available in :app:`Pyramid` :term:`view callable` code as ``request.registry.settings``. You can create objects you wish to access later from view code, and put them into the dictionary you pass to the configurator as ``settings``. They will diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst index f50f6c173..a9cdc13fb 100644 --- a/docs/narr/templates.rst +++ b/docs/narr/templates.rst @@ -203,7 +203,7 @@ may set attributes on the response that influence these values. Here's an example of changing the content-type and status of the response object returned by -:func:`pyramid.renderers.render_to_response`: +:func:`~pyramid.renderers.render_to_response`: .. code-block:: python :linenos: @@ -219,7 +219,7 @@ response object returned by return response Here's an example of manufacturing a response object using the result -of :func:`pyramid.renderers.render` (a string): +of :func:`~pyramid.renderers.render` (a string): .. code-block:: python :linenos: @@ -247,8 +247,8 @@ System Values Used During Rendering ----------------------------------- When a template is rendered using -:func:`pyramid.renderers.render_to_response` or -:func:`pyramid.renderers.render`, the renderer representing the +:func:`~pyramid.renderers.render_to_response` or +:func:`~pyramid.renderers.render`, the renderer representing the template will be provided with a number of *system* values. These values are provided in a dictionary to the renderer and include: @@ -282,7 +282,7 @@ variables. Templates Used as Renderers via Configuration --------------------------------------------- -An alternative to using :func:`pyramid.renderers.render_to_response` +An alternative to using :func:`~pyramid.renderers.render_to_response` to render templates manually in your view callable code, is to specify the template as a :term:`renderer` in your *view configuration*. This can be done with any of the @@ -299,7 +299,7 @@ The association of a template as a renderer for a :term:`view configuration` makes it possible to replace code within a :term:`view callable` that handles the rendering of a template. -Here's an example of using a :class:`pyramid.view.view_config` +Here's an example of using a :class:`~pyramid.view.view_config` decorator to specify a :term:`view configuration` that names a template renderer: @@ -448,7 +448,8 @@ 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/">pyramid</a> web + href="http://docs.pylonsproject.org/projects/pyramid/dev/" + >pyramid</a> web application framework.</h1> </body> </html> @@ -456,8 +457,8 @@ Here's what a simple :term:`Chameleon` ZPT template used under Note the use of :term:`Genshi` -style ``${replacements}`` above. This is one of the ways that :term:`Chameleon` ZPT differs from standard ZPT. The above template expects to find a ``project`` key in the set -of keywords passed in to it via :func:`pyramid.renderers.render` or -:func:`pyramid.renderers.render_to_response`. Typical ZPT +of keywords passed in to it via :func:`~pyramid.renderers.render` or +:func:`~pyramid.renderers.render_to_response`. Typical ZPT attribute-based syntax (e.g. ``tal:content`` and ``tal:replace``) also works in these templates. @@ -480,7 +481,7 @@ passing the macro template, or even the macro itself, *into* the rendered template. To do this you can use the :func:`pyramid.renderers.get_renderer` API to retrieve the macro template, and pass it into the template being rendered via the dictionary returned by the view. For example, using a -:term:`view configuration` via a :class:`pyramid.view.view_config` decorator +:term:`view configuration` via a :class:`~pyramid.view.view_config` decorator that uses a :term:`renderer`: .. code-block:: python @@ -606,7 +607,7 @@ configure your application development environment so that exceptions generated by Chameleon during template compilation and execution will contain nicer debugging information. -.. warning:: template-debugging behavior is not recommended for +.. warning:: Template-debugging behavior is not recommended for production sites as it slows renderings; it's usually only desirable during development. @@ -740,8 +741,8 @@ 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/">pyramid</a> web - application framework.</h1> + href="http://docs.pylonsproject.org/projects/pyramid/dev/" + >pyramid</a> web application framework.</h1> </body> </html> @@ -765,7 +766,7 @@ appear immediately without needing to restart the application process. environment so that a change to a template will be automatically detected, and the template will be reloaded on the next rendering. -.. warning:: auto-template-reload behavior is not recommended for +.. warning:: Auto-template-reload behavior is not recommended for production sites as it slows rendering slightly; it's usually only desirable during development. diff --git a/docs/narr/testing.rst b/docs/narr/testing.rst index e166962f2..bd45388c2 100644 --- a/docs/narr/testing.rst +++ b/docs/narr/testing.rst @@ -118,7 +118,7 @@ of using this feature: testing.tearDown() The above will make sure that -:func:`pyramid.threadlocal.get_current_registry` called within a test +:func:`~pyramid.threadlocal.get_current_registry` called within a test case method of ``MyTest`` will return the :term:`application registry` associated with the ``config`` Configurator instance. Each test case method attached to ``MyTest`` will use an isolated registry. @@ -128,7 +128,7 @@ functions accepts various arguments that influence the environment of the test. See the :ref:`testing_module` chapter for information about the extra arguments supported by these functions. -If you also want to make :func:`pyramid.get_current_request` return something +If you also want to make :func:`~pyramid.get_current_request` return something other than ``None`` during the course of a single test, you can pass a :term:`request` object into the :func:`pyramid.testing.setUp` within the ``setUp`` method of your test: @@ -150,9 +150,9 @@ other than ``None`` during the course of a single test, you can pass a If you pass a :term:`request` object into :func:`pyramid.testing.setUp` within your test case's ``setUp``, any test method attached to the ``MyTest`` test case that directly or indirectly calls -:func:`pyramid.threadlocal.get_current_request` will receive the request +:func:`~pyramid.threadlocal.get_current_request` will receive the request object. Otherwise, during testing, -:func:`pyramid.threadlocal.get_current_request` will return ``None``. +:func:`~pyramid.threadlocal.get_current_request` will return ``None``. We use a "dummy" request implementation supplied by :class:`pyramid.testing.DummyRequest` because it's easier to construct than a "real" :app:`Pyramid` request object. @@ -163,8 +163,8 @@ What? Thread local data structures are always a bit confusing, especially when they're used by frameworks. Sorry. So here's a rule of thumb: if you don't *know* whether you're calling code that uses the -:func:`pyramid.threadlocal.get_current_registry` or -:func:`pyramid.threadlocal.get_current_request` functions, or you don't care +:func:`~pyramid.threadlocal.get_current_registry` or +:func:`~pyramid.threadlocal.get_current_request` functions, or you don't care about any of this, but you still want to write test code, just always call :func:`pyramid.testing.setUp` in your test's ``setUp`` method and :func:`pyramid.testing.tearDown` in your tests' ``tearDown`` method. This @@ -199,7 +199,7 @@ function. return {'greeting':'hello'} Without doing anything special during a unit test, the call to -:func:`pyramid.security.has_permission` in this view function will always +:func:`~pyramid.security.has_permission` in this view function will always return a ``True`` value. When a :app:`Pyramid` application starts normally, it will populate a :term:`application registry` using :term:`configuration declaration` calls made against a :term:`Configurator`. But if this @@ -255,7 +255,7 @@ be found when ``setup.py test`` is run. It has two test methods. The first test method, ``test_view_fn_forbidden`` tests the ``view_fn`` when the authentication policy forbids the current user the ``edit`` permission. Its third line registers a "dummy" "non-permissive" authorization policy -using the :meth:`pyramid.config.Configurator.testing_securitypolicy` method, +using the :meth:`~pyramid.config.Configurator.testing_securitypolicy` method, which is a special helper method for unit testing. We then create a :class:`pyramid.testing.DummyRequest` object which simulates @@ -264,13 +264,13 @@ request object that requires less setup than a "real" :app:`Pyramid` request. We call the function being tested with the manufactured request. When the function is called, :func:`pyramid.security.has_permission` will call the "dummy" authentication policy we've registered through -:meth:`pyramid.config.Configuration.testing_securitypolicy`, which denies +:meth:`~pyramid.config.Configuration.testing_securitypolicy`, which denies access. We check that the view function raises a :exc:`Forbidden` error. The second test method, named ``test_view_fn_allowed`` tests the alternate case, where the authentication policy allows access. Notice that we pass different values to -:meth:`pyramid.config.Configurator.testing_securitypolicy` to obtain this +:meth:`~pyramid.config.Configurator.testing_securitypolicy` to obtain this result. We assert at the end of this that the view function returns a value. Note that the test calls the :func:`pyramid.testing.setUp` function in its @@ -278,7 +278,7 @@ Note that the test calls the :func:`pyramid.testing.setUp` function in its ``tearDown`` method. We assign the result of :func:`pyramid.testing.setUp` as ``config`` on the unittest class. This is a :term:`Configurator` object and all methods of the configurator can be called as necessary within -tests. If you use any of the :class:`pyramid.config.Configurator` APIs during +tests. If you use any of the :class:`~pyramid.config.Configurator` APIs during testing, be sure to use this pattern in your test case's ``setUp`` and ``tearDown``; these methods make sure you're using a "fresh" :term:`application registry` per test run. @@ -357,7 +357,7 @@ after accessing some values that require a fully set up environment. str(len(body)))) Unless you cannot avoid it, you should prefer writing unit tests that use the -:class:`pyramid.config.Configurator` API to set up the right "mock" +:class:`~pyramid.config.Configurator` API to set up the right "mock" registrations rather than creating an integration test. Unit tests will run faster (because they do less for each test) and the result of a unit test is usually easier to make assertions about. diff --git a/docs/narr/threadlocals.rst b/docs/narr/threadlocals.rst index 13bfe41cb..909f643a0 100644 --- a/docs/narr/threadlocals.rst +++ b/docs/narr/threadlocals.rst @@ -32,7 +32,7 @@ bad idea, at least if code readability counts as an important concern. For historical reasons, however, thread local variables are indeed consulted by various :app:`Pyramid` API functions. For example, the implementation of the :mod:`pyramid.security` function named -:func:`pyramid.security.authenticated_userid` retrieves the thread +:func:`~pyramid.security.authenticated_userid` retrieves the thread local :term:`application registry` as a matter of course to find an :term:`authentication policy`. It uses the :func:`pyramid.threadlocal.get_current_registry` function to @@ -43,8 +43,8 @@ allows arbitrary authentication policies to be "plugged in". When they need to do so, :app:`Pyramid` internals use two API functions to retrieve the :term:`request` and :term:`application -registry`: :func:`pyramid.threadlocal.get_current_request` and -:func:`pyramid.threadlocal.get_current_registry`. The former +registry`: :func:`~pyramid.threadlocal.get_current_request` and +:func:`~pyramid.threadlocal.get_current_registry`. The former returns the "current" request; the latter returns the "current" registry. Both ``get_current_*`` functions retrieve an object from a thread-local data structure. These API functions are documented in @@ -88,17 +88,17 @@ the :mod:`pyramid.scripting` API will never cause any Router code to be executed. However, the :mod:`pyramid.scripting` APIs also push some values on to the thread locals stack as a matter of course. Such scripts should expect the -:func:`pyramid.threadlocal.get_current_request` function to always +:func:`~pyramid.threadlocal.get_current_request` function to always return ``None``, and should expect the -:func:`pyramid.threadlocal.get_current_registry` function to return +:func:`~pyramid.threadlocal.get_current_registry` function to return exactly the same :term:`application registry` for every request. Why You Shouldn't Abuse Thread Locals ------------------------------------- You probably should almost never use the -:func:`pyramid.threadlocal.get_current_request` or -:func:`pyramid.threadlocal.get_current_registry` functions, except +:func:`~pyramid.threadlocal.get_current_request` or +:func:`~pyramid.threadlocal.get_current_registry` functions, except perhaps in tests. In particular, it's almost always a mistake to use ``get_current_request`` or ``get_current_registry`` in application code because its usage makes it possible to write code that can be @@ -134,7 +134,7 @@ follows: application depend upon it) means you're forming a dependency in the wrong direction. -Use of the :func:`pyramid.threadlocal.get_current_request` function +Use of the :func:`~pyramid.threadlocal.get_current_request` function in application code *is* still useful in very limited circumstances. As a rule of thumb, usage of ``get_current_request`` is useful **within code which is meant to eventually be removed**. For @@ -151,7 +151,7 @@ time, the older implementation code is disused and the hack that uses ``get_current_request`` is removed. This would be an appropriate place to use the ``get_current_request``. -Use of the :func:`pyramid.threadlocal.get_current_registry` +Use of the :func:`~pyramid.threadlocal.get_current_registry` function should be limited to testing scenarios. The registry made current by use of the :meth:`pyramid.config.Configurator.begin` method during a diff --git a/docs/narr/traversal.rst b/docs/narr/traversal.rst index a858644ca..b3747be61 100644 --- a/docs/narr/traversal.rst +++ b/docs/narr/traversal.rst @@ -127,7 +127,7 @@ passing it to an instance of a :term:`Configurator` named ``config``: config = Configurator(root_factory=Root) The ``root_factory`` argument to the -:class:`pyramid.config.Configurator` constructor registers this root +:class:`~pyramid.config.Configurator` constructor registers this root factory to be called to generate a root resource whenever a request enters the application. The root factory registered this way is also known as the global root factory. A root factory can alternately be @@ -236,8 +236,8 @@ because they are almost always used together. A Description of The Traversal Algorithm ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -When a user requests a page from your :mod:`traversal` -powered application, -the system uses this algorithm to find a :term:`context` resource and a +When a user requests a page from your traversal-powered application, the +system uses this algorithm to find a :term:`context` resource and a :term:`view name`. #. The request for the page is presented to the :app:`Pyramid` diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst index 44396e024..cab5f85fa 100644 --- a/docs/narr/urldispatch.rst +++ b/docs/narr/urldispatch.rst @@ -95,9 +95,8 @@ Route Configuration That Names a View Callable 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:`view_chapter`, is developer-supplied code that "does stuff" as the -result of a request. For more information about how to create view -callables, see :ref:`views_chapter`. +:ref:`views_chapter`, is developer-supplied code that "does stuff" as the +result of a request. Here's an example route configuration that references a view callable: @@ -126,49 +125,6 @@ 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. -Route View Callable Registration and Lookup Details -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -The purpose of making it possible to specify a view callable within a route -configuration is to prevent developers from needing to deeply understand the -details of :term:`resource location` and :term:`view lookup`. When a route -names a view callable as a ``view`` argument, and a request enters the system -which matches the pattern of the route, the result is simple: the view -callable associated with the route is invoked with the request that caused -the invocation. - -For most usage, you needn't understand more than this; how it works is an -implementation detail. In the interest of completeness, however, we'll -explain how it *does* work in the this section. You can skip it if you're -uninterested. - -When a ``view`` attribute is attached to a route configuration, -:app:`Pyramid` ensures that a :term:`view configuration` is registered that -will always be found when the route pattern is matched during a request. To -do so: - -- A special route-specific :term:`interface` is created at startup time for - each route configuration declaration. - -- When a route configuration declaration mentions a ``view`` attribute, a - :term:`view configuration` is registered at startup time. This view - configuration uses the route-specific interface as a :term:`request` type. - -- At runtime, when a request causes any route to match, the :term:`request` - 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`. - .. index:: single: route path pattern syntax @@ -202,12 +158,12 @@ replacement marker (e.g. ``{foo}``) or a certain combination of both. A replacement marker does not need to be preceded by a ``/`` character. A replacement marker is in the format ``{name}``, where this means "accept -any characters up to the next non-alphanumeric character and use this as the -``name`` :term:`matchdict` value." A matchdict is the dictionary -representing the dynamic parts extracted from a URL based on the routing -pattern. It is available as ``request.matchdict``. For example, the -following pattern defines one literal segment (``foo``) and two replacement -markers (``baz``, and ``bar``): +any characters up to the next slash character and use this as the ``name`` +:term:`matchdict` value." A matchdict is the dictionary representing the +dynamic parts extracted from a URL based on the routing pattern. It is +available as ``request.matchdict``. For example, the following pattern +defines one literal segment (``foo``) and two replacement markers (``baz``, +and ``bar``): .. code-block:: text @@ -258,11 +214,12 @@ that a replacement marker should match only a specific set of characters as defined by a regular expression, you must use a slightly extended form of replacement marker syntax. Within braces, the replacement marker name must be followed by a colon, then directly thereafter, the regular expression. -For example, under the hood, the replacement marker ``{foo}`` can more -verbosely be spelled as ``{foo:[^/]+}``. The *default* regular expression -associated with a replacement marker ``[^/]+`` matches one or more characters -which are not a slash. You can use an arbitrary regular expression here to -match a sequence of characters. +The *default* regular expression associated with a replacement marker +``[^/]+`` matches one or more characters which are not a slash. For example, +under the hood, the replacement marker ``{foo}`` can more verbosely be +spelled as ``{foo:[^/]+}``. You can change this to be an arbitrary regular +expression to match an arbitrary sequence of characters, such as +``{foo:\d+}`` to match only digits. It is possible to use two replacement markers without any literal characters between them, for instance ``/{foo}{bar}``. However, this would be a @@ -371,7 +328,7 @@ 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. -For routes added via the :mod:`pyramid.config.Configurator.add_route` method, +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 the configuration imperatively. @@ -428,12 +385,14 @@ Route Configuration Arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Route configuration ``add_route`` statements may specify a large number of -arguments. +arguments. They are documented as part of the API documentation at +:meth:`pyramid.config.Configurator.add_route`. Many of these arguments are :term:`route predicate` arguments. A route predicate argument specifies that some aspect of the request must be true for the associated route to be considered a match during the route matching -process. +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``. @@ -441,201 +400,13 @@ effect when the route configuration names a ``view``. Other arguments are ``name`` and ``factory``. These arguments represent neither predicates nor view configuration information. -**Non-Predicate Arguments** - -``name`` - The name of the route, e.g. ``myroute``. This attribute is required. It - must be unique among all defined routes in a given application. - -``factory`` - A Python object (often a function or a class) or a :term:`dotted Python - name` to such an object that will generate a :app:`Pyramid` resource object - as the :term:`root` when this route matches. For example, - ``mypackage.resources.MyFactoryClass``. If this argument is not specified, - the traversal root factory will be used. - -``traverse`` - If you would like to cause the :term:`context` resource to be something - other than the :term:`root` resource object when this route matches, you - can spell a traversal pattern as the ``traverse`` argument. This traversal - pattern will be used as the traversal path: 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). - - The syntax of the ``traverse`` argument is the same as it is for - ``pattern``. For example, if the ``pattern`` provided is - ``articles/{article}/edit``, and the ``traverse`` argument provided is - ``/{article}``, when a request comes in that causes the route to match in - such a way that the ``article`` match value is '1' (when the request URI is - ``/articles/1/edit``), the traversal path will be generated as ``/1``. - This means that the root object's ``__getitem__`` will be called with the - name ``1`` during the traversal phase. If the ``1`` object exists, it will - become the :term:`context` resource of the request. - :ref:`traversal_chapter` has more information about traversal. - - If the traversal path contains segment marker names which are not present - in the ``pattern`` argument, a runtime error will occur. The ``traverse`` - pattern should not contain segment markers that do not exist in the - ``pattern``. - - A similar combining of routing and traversal is available when a route is - matched which contains a ``*traverse`` remainder marker in its pattern (see - :ref:`using_traverse_in_a_route_pattern`). The ``traverse`` argument - allows you to associate route patterns with an arbitrary traversal path - without using a a ``*traverse`` remainder marker; instead you can use other - match information. - - Note that the ``traverse`` argument is ignored when attached to a route - that has a ``*traverse`` remainder marker in its pattern. - -**Predicate Arguments** - -``pattern`` - The path of the route e.g. ``ideas/{idea}``. This argument is required. - See :ref:`route_path_pattern_syntax` for information about the syntax of - route paths. If the path doesn't match the current URL, route matching - continues. - - .. note:: In earlier releases of this framework, this argument existed - as ``path``. ``path`` continues to work as an alias for - ``pattern``. - -``xhr`` - This value should be either ``True`` or ``False``. If this value is - specified and is ``True``, the :term:`request` must possess an - ``HTTP_X_REQUESTED_WITH`` (aka ``X-Requested-With``) header for this route - to match. This is useful for detecting AJAX requests issued from jQuery, - Prototype and other Javascript libraries. If this predicate returns - ``False``, route matching continues. - -``request_method`` - A string representing an HTTP method name, e.g. ``GET``, ``POST``, - ``HEAD``, ``DELETE``, ``PUT``. If this argument is not specified, this - route will match if the request has *any* request method. If this - predicate returns ``False``, route matching continues. - -``path_info`` - This value represents a regular expression pattern that will be tested - against the ``PATH_INFO`` WSGI environment variable. If the regex matches, - this predicate will return ``True``. If this predicate returns ``False``, - route matching continues. - -``request_param`` - This value can be any string. A view declaration with this argument - ensures that the associated route will only match when the request has a - key in the ``request.params`` dictionary (an HTTP ``GET`` or ``POST`` - variable) that has a name which matches the supplied value. If the value - supplied as the argument has a ``=`` sign in it, - e.g. ``request_params="foo=123"``, then the key (``foo``) must both exist - in the ``request.params`` dictionary, and the value must match the right - hand side of the expression (``123``) for the route to "match" the current - request. If this predicate returns ``False``, route matching continues. - -``header`` - This argument represents an HTTP header name or a header name/value pair. - If the argument contains a ``:`` (colon), it will be considered a - name/value pair (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``). If - the value contains a colon, the value portion should be a regular - expression. If the value does not contain a colon, the entire value will - be considered to be the header name (e.g. ``If-Modified-Since``). If the - value evaluates to a header name only without a value, the header specified - by the name must be present in the request for this predicate to be true. - If the value evaluates to a header name/value pair, the header specified by - the name must be present in the request *and* the regular expression - specified as the value must match the header value. Whether or not the - value represents a header name or a header name/value pair, the case of the - header name is not significant. If this predicate returns ``False``, route - matching continues. - -``accept`` - This value represents a match query for one or more mimetypes in the - ``Accept`` HTTP request header. If this value is specified, it must be in - one of the following forms: a mimetype match token in the form - ``text/plain``, a wildcard mimetype match token in the form ``text/*`` or a - match-all wildcard mimetype match token in the form ``*/*``. If any of the - forms matches the ``Accept`` header of the request, this predicate will be - true. If this predicate returns ``False``, route matching continues. - -``custom_predicates`` - This value should be a sequence of references to custom predicate - callables. Use custom predicates when no set of predefined predicates does - what you need. Custom predicates can be combined with predefined - predicates as necessary. Each custom predicate callable should accept two - arguments: ``info`` and ``request`` and should return either ``True`` or - ``False`` after doing arbitrary evaluation of the context resource and/or - the request. If all callables return ``True``, the associated route will - be considered viable for a given request. If any custom predicate returns - ``False``, route matching continues. See :ref:`custom_route_predicates` - for more information. - -**View-Related Arguments** - -``view`` - A Python object or a :term:`dotted Python name` to such an object that will - be used as a view callable when this route - matches. e.g. ``mypackage.views.my_view``. - -``view_context`` - A class or an :term:`interface` (or a :term:`dotted Python name` to such an - object) that the :term:`context` resource should possess for the view named - by the route to be used. If this attribute is not specified, the default - (``None``) will be used. - - If the ``view`` argument is not provided, this argument has no effect. - - This attribute can also be spelled as ``for_`` or ``view_for``. - -``view_permission`` - The permission name required to invoke the view associated with this route. - e.g. ``edit``. (see :ref:`using_security_with_urldispatch` for more - information about permissions). - - If the ``view`` attribute is not provided, this argument has no effect. - - This argument can also be spelled as ``permission``. - -``view_renderer`` - This is either a single string term (e.g. ``json``) or a string implying a - path or :term:`asset specification` (e.g. ``templates/views.pt``). If the - renderer value is a single term (does not contain a dot ``.``), the - specified term will be used to look up a renderer implementation, and that - renderer implementation will be used to construct a response from the view - return value. If the renderer term contains a dot (``.``), the specified - term will be treated as a path, and the filename extension of the last - element in the path will be used to look up the renderer implementation, - which will be passed the full path. The renderer implementation will be - used to construct a response from the view return value. See - :ref:`views_which_use_a_renderer` for more information. - - If the ``view`` argument is not provided, this argument has no effect. - - This argument can also be spelled as ``renderer``. - -``view_attr`` - The view machinery defaults to using the ``__call__`` method of the view - callable (or the function itself, if the view callable is a function) to - obtain a response dictionary. The ``attr`` value allows you to vary the - method attribute used to obtain the response. For example, if your view - was a class, and the class has a method named ``index`` and you wanted to - use this method instead of the class' ``__call__`` method to return the - response, you'd say ``attr="index"`` in the view configuration for the - view. This is most useful when the view definition is a class. - - If the ``view`` argument is not provided, this argument has no - effect. - -``use_global_views`` - When a request matches this route, and view lookup cannot find a view which - has a 'route_name' predicate argument that matches the route, try to fall - back to using a view that otherwise matches the context and request. - .. _custom_route_predicates: Custom Route Predicates ~~~~~~~~~~~~~~~~~~~~~~~ Each of the predicate callables fed to the ``custom_predicates`` argument of -:meth:`pyramid.config.Configurator.add_route` must be a callable accepting +:meth:`~pyramid.config.Configurator.add_route` must be a callable accepting two arguments. The first argument passed to a custom predicate is a dictionary conventionally named ``info``. The second argument is the current :term:`request` object. @@ -669,7 +440,7 @@ predicate function named ``num_one_two_or_three``, which ensures that the ``num`` segment is one of the values ``one``, ``two``, or ``three`` , and use the result as a custom predicate by feeding it inside a tuple to the ``custom_predicates`` argument to -:meth:`pyramid.config.Configurator.add_route`. +:meth:`~pyramid.config.Configurator.add_route`. A custom route predicate may also *modify* the ``match`` dictionary. For instance, a predicate might do some type conversion of values: @@ -823,7 +594,7 @@ The Matched Route When the URL pattern associated with a particular route configuration is matched by a request, an object named ``matched_route`` is added as an attribute of the :term:`request` object. Thus, ``request.matched_route`` -will be an object implementing the :class:`pyramid.interfaces.IRoute` +will be an object implementing the :class:`~pyramid.interfaces.IRoute` interface which matched the request. The most useful attribute of the route object is ``name``, which is the name of the route that matched. @@ -936,7 +707,7 @@ the :term:`root factory` configured at startup time (the ``root_factory`` argument to the :term:`Configurator` used to configure the application). You can override this behavior by passing in a ``factory`` argument to the -:meth:`pyramid.config.Configurator.add_route` method for a particular route. +:meth:`~pyramid.config.Configurator.add_route` method for a particular route. The ``factory`` should be a callable that accepts a :term:`request` and returns an instance of a class that will be the context resource used by the view. @@ -1001,7 +772,7 @@ Matching the Root URL It's not entirely obvious how to use a route pattern to match the root URL ("/"). To do so, give the empty string as a pattern in a call to -:meth:`pyramid.config.Configurator.add_route`: +:meth:`~pyramid.config.Configurator.add_route`: .. code-block:: python :linenos: @@ -1035,7 +806,8 @@ route patterns. For example, if you've configured a route with the ``name`` This would return something like the string ``http://example.com/1/2/3`` (at least if the current protocol and hostname implied ``http://example.com``). -See the :func:`pyramid.url.route_url` API documentation for more information. +See the :func:`~pyramid.url.route_url` API documentation for more +information. .. index:: single: redirecting to slash-appended routes @@ -1062,8 +834,10 @@ route configuration looks like so: .. code-block:: python :linenos: - config.add_route('noslash', 'no_slash', view='myproject.views.no_slash') - config.add_route('hasslash', 'has_slash/', view='myproject.views.has_slash') + config.add_route('noslash', 'no_slash', + view='myproject.views.no_slash') + config.add_route('hasslash', 'has_slash/', + view='myproject.views.has_slash') If a request enters the application with the ``PATH_INFO`` value of ``/has_slash/``, the second route will match. If a request enters the @@ -1138,16 +912,7 @@ Cleaning Up After a Request --------------------------- Sometimes it's required that some cleanup be performed at the end of a -request when a database connection is involved. When :term:`traversal` is -used, this cleanup is often done as a side effect of the traversal -:term:`root factory`. Often the root factory will insert an object into the -WSGI environment that performs some cleanup when its ``__del__`` method is -called. When URL dispatch is used, however, no special root factory is -required, so sometimes that option is not open to you. - -Instead of putting this cleanup logic in the root factory, however, you can -cause a subscriber to be fired when a new request is detected; the subscriber -can do this work. +request when a database connection is involved. For example, let's say you have a ``mypackage`` :app:`Pyramid` application package that uses SQLAlchemy, and you'd like the current SQLAlchemy database @@ -1158,37 +923,32 @@ session to be removed after each request. Put the following in the .. code-block:: python :linenos: - from mypackage.sql import DBSession - - class Cleanup: - def __init__(self, cleaner): - self.cleaner = cleaner - def __del__(self): - self.cleaner() - - def handle_teardown(event): - environ = event.request.environ - environ['mypackage.sqlcleaner'] = Cleanup(DBSession.remove) + from mypackage.models import DBSession -Then add an event subscriber in your startup configuration: + from pyramid.events import subscriber + from pyramid.events import NewRequest -.. code-block:: python - :linenos: + def cleanup_callback(request): + DBSession.remove() - config.add_subscriber('mypackage.handle_teardown', - 'pyramid.events.NewRequest') + @subscriber(NewRequest) + def add_cleanup_callback(event): + event.request.add_finished_callback(cleanup_callback) -Registering a handle_teardown subscriber will cause the DBSession to be -removed whenever the WSGI environment is destroyed (usually at the end of -every request). +Registering the ``cleanup_callback`` finished callback at the start of a +request (by causing the ``add_cleanup_callback`` to receive a +:class:`pyramid.events.NewRequest` event at the start of each request) will +cause the DBSession to be removed whenever request processing has ended. +Note that in the example above, for the :class:`pyramid.events.subscriber` +decorator to "work", the :meth:`pyramid.config.Configurator.scan` method must +be called against your ``mypackage`` package during application +initialization. -.. note:: This is only an example. In particular, it is not necessary - to cause ``DBSession.remove`` to be called as the result of an - event listener in an application generated from any - :app:`Pyramid` paster template, because these all use the - ``repoze.tm2`` middleware. The cleanup done by - ``DBSession.remove`` is unnecessary when ``repoze.tm2`` middleware - is in the WSGI pipeline. +.. note:: This is only an example. In particular, it is not necessary to + cause ``DBSession.remove`` to be called in an application generated from + any :app:`Pyramid` paster template, because these all use the + ``repoze.tm2`` middleware. The cleanup done by ``DBSession.remove`` is + unnecessary when ``repoze.tm2`` middleware is in the WSGI pipeline. .. index:: pair: URL dispatch; security @@ -1260,18 +1020,18 @@ which you started the application from. For example: See :ref:`environment_chapter` for more information about how, and where to set these values. -.. _displaying_application_routes: - .. 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`` +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. @@ -1300,6 +1060,49 @@ callable could be found. If no routes are configured within your application, nothing will be printed to the console when ``paster proutes`` is executed. +Route View Callable Registration and Lookup Details +--------------------------------------------------- + +The purpose of making it possible to specify a view callable within a route +configuration is to prevent developers from needing to deeply understand the +details of :term:`resource location` and :term:`view lookup`. When a route +names a view callable as a ``view`` argument, and a request enters the system +which matches the pattern of the route, the result is simple: the view +callable associated with the route is invoked with the request that caused +the invocation. + +For most usage, you needn't understand more than this; how it works is an +implementation detail. In the interest of completeness, however, we'll +explain how it *does* work in the this section. You can skip it if you're +uninterested. + +When a ``view`` attribute is attached to a route configuration, +:app:`Pyramid` ensures that a :term:`view configuration` is registered that +will always be found when the route pattern is matched during a request. To +do so: + +- A special route-specific :term:`interface` is created at startup time for + each route configuration declaration. + +- When a route configuration declaration mentions a ``view`` attribute, a + :term:`view configuration` is registered at startup time. This view + configuration uses the route-specific interface as a :term:`request` type. + +- At runtime, when a request causes any route to match, the :term:`request` + 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`. + References ---------- diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst index c45f053cf..0a6d9ee61 100644 --- a/docs/narr/viewconfig.rst +++ b/docs/narr/viewconfig.rst @@ -51,11 +51,9 @@ View configuration is performed in one of these 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 - per :class:`pyramid.view.view_config` and - :ref:`mapping_views_using_a_decorator_section`. + per :ref:`mapping_views_using_a_decorator_section`. - by using the :meth:`pyramid.config.Configurator.add_view` method as per - :meth:`pyramid.config.Configurator.add_view` and :ref:`mapping_views_using_imperative_config_section`. - By specifying a view within a :term:`route configuration`. View @@ -362,8 +360,7 @@ 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 :term:`ZCML` or imperative configuration for the -same purpose. +with URLs instead of using imperative configuration for the same purpose. .. warning:: @@ -372,15 +369,14 @@ same purpose. declarations. Usage of the ``view_config`` decorator is a form of :term:`declarative -configuration`, like ZCML, but in decorator form. -:class:`pyramid.view.view_config` can be used to associate :term:`view -configuration` information -- as done via the equivalent imperative code or -ZCML -- 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. - -An example of the :class:`pyramid.view.view_config` decorator might reside in +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. + +An example of the :class:`~pyramid.view.view_config` decorator might reside in a :app:`Pyramid` application module ``views.py``: .. ignore-next-block @@ -440,17 +436,17 @@ you *must* use the ``scan`` method of a Please see :ref:`decorations_and_code_scanning` for detailed information about what happens when code is scanned for configuration declarations -resulting from use of decorators like :class:`pyramid.view.view_config`. +resulting from use of decorators like :class:`~pyramid.view.view_config`. See :ref:`configuration_module` for additional API arguments to the -:meth:`pyramid.config.Configurator.scan` method. For example, the method +:meth:`~pyramid.config.Configurator.scan` method. For example, the method allows you to supply a ``package`` argument to better control exactly *which* code will be scanned. ``@view_config`` Placement ++++++++++++++++++++++++++ -A :class:`pyramid.view.view_config` decorator can be placed in various points +A :class:`~pyramid.view.view_config` decorator can be placed in various points in your application. If your view callable is a function, it may be used as a function decorator: @@ -484,7 +480,7 @@ against a class as when they are applied against a function. For example: def __call__(self): return Response('hello') -You can use the :class:`pyramid.view.view_config` decorator as a simple +You can use the :class:`~pyramid.view.view_config` decorator as a simple callable to manually decorate classes in Python 2.5 and below without the decorator syntactic sugar, if you wish: @@ -503,7 +499,7 @@ decorator syntactic sugar, if you wish: my_view = view_config()(MyView) -More than one :class:`pyramid.view.view_config` decorator can be stacked on +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 registration. For example: @@ -702,7 +698,7 @@ to a :term:`view configuration` found during view lookup will be verified. This will ensure that the currently authenticated user possesses that permission against the :term:`context` resource before the view function is actually called. Here's an example of specifying a permission in a view -configuration using :meth:`pyramid.config.Configurator.add_view`: +configuration using :meth:`~pyramid.config.Configurator.add_view`: .. code-block:: python :linenos: diff --git a/docs/narr/views.rst b/docs/narr/views.rst index 392e5ea4a..efbf7924f 100644 --- a/docs/narr/views.rst +++ b/docs/narr/views.rst @@ -230,12 +230,12 @@ implements the :term:`Response` interface is to return a def view(request): return Response('OK') -You don't need to always use :class:`pyramid.response.Response` to represent a -response. :app:`Pyramid` provides a range of different "exception" classes +You don't need to always use :class:`~pyramid.response.Response` to represent +a response. :app:`Pyramid` provides a range of different "exception" classes which can act as response objects too. For example, an instance of the class -:class:`pyramid.httpexceptions.HTTPFound` is also a valid response object (see -:ref:`http_redirect`). A view can actually return any object that has the -following attributes. +:class:`pyramid.httpexceptions.HTTPFound` is also a valid response object +(see :ref:`http_redirect`). A view can actually return any object that has +the following attributes. status The HTTP status code (including the name) for the response as a string. @@ -290,7 +290,7 @@ Unauthorized``. It is possible, however, in Python 2.5 and above, to configure an *exception view* to catch these exceptions, and return an appropriate - :class:`pyramid.response.Response`. The simplest such view could just + :class:`~pyramid.response.Response`. The simplest such view could just catch and return the original exception. See :ref:`exception_views` for more details. @@ -312,11 +312,11 @@ handled by :app:`Pyramid` itself. These are Both are exception classes which accept a single positional constructor argument: a ``message``. -If :exc:`pyramid.exceptions.NotFound` is raised within view code, the result +If :exc:`~pyramid.exceptions.NotFound` is raised within view code, the result of the :term:`Not Found View` will be returned to the user agent which performed the request. -If :exc:`pyramid.exceptions.Forbidden` is raised within view code, the result +If :exc:`~pyramid.exceptions.Forbidden` is raised within view code, the result of the :term:`Forbidden View` will be returned to the user agent which performed the request. @@ -332,8 +332,8 @@ available to the view which :app:`Pyramid` invokes as Exception Views --------------- -The machinery which allows the special :exc:`pyramid.exceptions.NotFound` and -:exc:`pyramid.exceptions.Forbidden` exceptions to be caught by specialized +The machinery which allows the special :exc:`~pyramid.exceptions.NotFound` and +:exc:`~pyramid.exceptions.Forbidden` exceptions to be caught by specialized views as described in :ref:`special_exceptions_in_callables` can also be used by application developers to convert arbitrary exceptions to responses. @@ -515,7 +515,7 @@ an error when it can't decode some high-order character encoded in another character set within form data, e.g., when ``request.params['somename']`` is accessed. -If you are using the :class:`pyramid.response.Response` class to generate a +If you are using the :class:`~pyramid.response.Response` class to generate a response, or if you use the ``render_template_*`` templating APIs, the UTF-8 charset is set automatically as the default via the ``Content-Type`` header. If you return a ``Content-Type`` header without an explicit charset, a diff --git a/docs/narr/zca.rst b/docs/narr/zca.rst index 78a7b0b75..fcab0653e 100644 --- a/docs/narr/zca.rst +++ b/docs/narr/zca.rst @@ -171,7 +171,7 @@ when a :term:`Configurator` constructor is called, or when a During a request, the application registry created by the Configurator is "made current". This means calls to -:func:`pyramid.threadlocal.get_current_registry` in the thread +:func:`~pyramid.threadlocal.get_current_registry` in the thread handling the request will return the component registry associated with the application. @@ -184,7 +184,7 @@ always return the global ZCA registry (the one in To "fix" this and make the ZCA global APIs use the "current" BFG registry, you need to call -:meth:`pyramid.config.Configurator.hook_zca` within your +:meth:`~pyramid.config.Configurator.hook_zca` within your setup code. For example: .. code-block:: python diff --git a/docs/tutorials/catalog/index.rst b/docs/tutorials/catalog/index.rst deleted file mode 100644 index e4e5bd720..000000000 --- a/docs/tutorials/catalog/index.rst +++ /dev/null @@ -1,127 +0,0 @@ -.. _catalog_tutorial: - -Using :mod:`repoze.catalog` Within :app:`Pyramid` -================================================= - -:mod:`repoze.catalog` is a ZODB-based system that can be used to index -Python objects. It also offers a query interface for retrieving -previously indexed data. Those whom are used to Zope's "ZCatalog" -implementation will feel at home using :mod:`repoze.catalog`. - -This tutorial assumes that you want a Zope-like setup. For example, -it assumes you want to use a persistent ZODB object as your -:term:`root` object, and that the :mod:`repoze.catalog` catalog will -be an attribute of this root object. It is further assumed that you -want the application to be based on :term:`traversal`. - -#. Follow the :ref:`zodb_with_zeo` tutorial to get a system set up - with ZODB and ZEO. When you are finished, come back here. - -#. Install the :mod:`repoze.catalog` software within your application's - environment: - - .. code-block:: text - - $ easy_install repoze.catalog - -#. Change your ZODB application's ``models.py`` file to look like the - below: - - .. code-block:: python - :linenos: - - from repoze.folder import Folder - from repoze.catalog.catalog import Catalog - from repoze.catalog.document import DocumentMap - from repoze.catalog.indexes.field import CatalogFieldIndex - - def get_title(object, default): - title = getattr(object, 'title', '') - if isinstance(title, basestring): - # lowercase for alphabetic sorting - title = title.lower() - return title - - class Document(Folder): - def __init__(self, title): - self.title = title - Folder.__init__(self) - - class Site(Folder): - def __init__(self): - self.catalog = Catalog() - self.catalog.document_map = DocumentMap() - self.update_indexes() - Folder.__init__(self) - - def update_indexes(self): - indexes = { - 'title': CatalogFieldIndex(get_title), - } - - catalog = self.catalog - - # add indexes - for name, index in indexes.iteritems(): - if name not in catalog: - catalog[name] = index - - # remove indexes - for name in catalog.keys(): - if name not in indexes: - del catalog[name] - - def appmaker(root): - if not 'site' in root: - root['site'] = Site() - transaction.commit() - return root['site'] - -#. We'll demonstrate how you might interact with a catalog from code - by manipulating the database directly using the ``pshell`` - command in a terminal window: - - .. code-block:: text - - [chrism@snowpro sess]$ ../bin/paster --plugin=pyramid pshell \ - development.ini myapp - Python 2.5.4 (r254:67916, Sep 4 2009, 02:12:16) - [GCC 4.2.1 (Apple Inc. build 5646)] on darwin - Type "help" for more information. "root" is the Pyramid app root object. - >>> from pyramid.traversal import resource_path - >>> from myapp.models import Document - >>> root['name'] = Document('title') - >>> doc = root['name'] - >>> docid = root.catalog.document_map.add(resource_path(doc)) - >>> root.catalog.index_doc(docid, doc) - >>> import transaction - >>> transaction.commit() - >>> root.catalog.search(title='title') - (1, IFSet([-787959756])) - -As you need them, add other indexes required by your application to -the catalog by modifying the ``update_indexes`` method of the ``Site`` -object. Whenever an index is added or removed, invoke the -``update_indexes`` method of the site (the root object) from a script -or from within a ``pshell`` session to update the set of indexes -used by your application. - -In :term:`view` code, you should be able to get a hold of he root -object via the :func:`pyramid.traversal.find_root` API. The -``catalog`` attribute of that root object will represent the catalog -previously added. - -Read the :mod:`repoze.catalog` `documentation -<http://docs.repoze.org/catalog>`_ for further information about other -types of indexes to add, using the document map, and how to issue -queries using the catalog query API. - -.. note:: - - The :mod:`repoze.folder` implementation sends events that can be - intercepted by a :term:`subscriber` when objects are added and - removed from a folder. It is often useful to hook these events for - the purpose of mutating the catalog when a new documentlike object - is added or removed. See the `repoze.folder documentation - <http://docs.repoze.org/folder>`_ for more information about the - events it sends. diff --git a/docs/tutorials/modwsgi/index.rst b/docs/tutorials/modwsgi/index.rst index c6d5d891d..5da7f32c7 100644 --- a/docs/tutorials/modwsgi/index.rst +++ b/docs/tutorials/modwsgi/index.rst @@ -102,7 +102,8 @@ 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 processes=1 \ + 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/authorization.rst b/docs/tutorials/wiki/authorization.rst index 5e45c070e..ee86eb543 100644 --- a/docs/tutorials/wiki/authorization.rst +++ b/docs/tutorials/wiki/authorization.rst @@ -137,7 +137,6 @@ referred to within the login view we just added to ``login.py``. .. literalinclude:: src/authorization/tutorial/templates/login.pt :language: xml - :tab-width: 2 Change ``view.pt`` and ``edit.pt`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -282,14 +281,12 @@ Our ``edit.pt`` template will look something like this when we're done: .. literalinclude:: src/authorization/tutorial/templates/edit.pt :linenos: :language: xml - :tab-width: 2 Our ``view.pt`` template will look something like this when we're done: .. literalinclude:: src/authorization/tutorial/templates/view.pt :linenos: :language: xml - :tab-width: 2 Revisiting the Application --------------------------- diff --git a/docs/tutorials/wiki/basiclayout.rst b/docs/tutorials/wiki/basiclayout.rst index 5c1dcb0e6..c0faf30de 100644 --- a/docs/tutorials/wiki/basiclayout.rst +++ b/docs/tutorials/wiki/basiclayout.rst @@ -187,6 +187,11 @@ The ``egg:repoze.zodbconn#closer`` middleware is in the middle of the pipeline. This is a piece of middleware which closes the ZODB connection opened by the ``PersistentApplicationFinder`` at the end of the request. +The ``egg:repoze.retry#retry`` middleware catches ``ConflictError`` +exceptions from ZODB and retries the request up to three times (ZODB is an +optimistic concurrency database that relies on application-level transaction +retries when a conflict occurs). + The ``tm`` middleware is the last piece of middleware in the pipeline. This commits a transaction near the end of the request unless there's an exception raised or the HTTP response code is an error code. The ``tm`` refers to the diff --git a/docs/tutorials/wiki/definingviews.rst b/docs/tutorials/wiki/definingviews.rst index 7ad5e57cb..31900233c 100644 --- a/docs/tutorials/wiki/definingviews.rst +++ b/docs/tutorials/wiki/definingviews.rst @@ -76,7 +76,7 @@ The ``view_page`` view function The ``view_page`` function will be configured to respond as the default view of a Page resource. We'll provide it with a ``@view_config`` decorator which -names the class ``tutorial.models.Wiki`` as its context. This means that +names the class ``tutorial.models.Page`` as its context. This means that when a Page resource is the context, and no :term:`view name` exists in the request, this view will be used. We inform :app:`Pyramid` this view will use the ``templates/view.pt`` template file as a ``renderer``. @@ -231,7 +231,6 @@ the below: .. literalinclude:: src/views/tutorial/templates/view.pt :language: xml - :tab-width: 2 .. note:: The names available for our use in a template are always those that are present in the dictionary returned by the view callable. But our @@ -258,7 +257,6 @@ below: .. literalinclude:: src/views/tutorial/templates/edit.pt :language: xml - :tab-width: 2 Static Assets ------------- diff --git a/docs/tutorials/wiki/src/authorization/development.ini b/docs/tutorials/wiki/src/authorization/development.ini index 054720aa2..1ba746d0e 100644 --- a/docs/tutorials/wiki/src/authorization/development.ini +++ b/docs/tutorials/wiki/src/authorization/development.ini @@ -12,6 +12,7 @@ zodb_uri = file://%(here)s/Data.fs?connection_cache_size=20000 pipeline = egg:WebError#evalerror egg:repoze.zodbconn#closer + egg:repoze.retry#retry tm tutorial diff --git a/docs/tutorials/wiki/src/authorization/production.ini b/docs/tutorials/wiki/src/authorization/production.ini index 458064388..5c47ade9b 100644 --- a/docs/tutorials/wiki/src/authorization/production.ini +++ b/docs/tutorials/wiki/src/authorization/production.ini @@ -30,6 +30,7 @@ commit_veto = repoze.tm:default_commit_veto pipeline = weberror egg:repoze.zodbconn#closer + egg:repoze.retry#retry tm tutorial diff --git a/docs/tutorials/wiki/src/authorization/setup.py b/docs/tutorials/wiki/src/authorization/setup.py index 38f913961..adfa70c9f 100644 --- a/docs/tutorials/wiki/src/authorization/setup.py +++ b/docs/tutorials/wiki/src/authorization/setup.py @@ -10,6 +10,7 @@ requires = [ 'pyramid', 'repoze.zodbconn', 'repoze.tm2>=1.0b1', # default_commit_veto + 'repoze.retry', 'ZODB3', 'WebError', 'docutils', diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt index 30767b28b..f9da6c414 100644 --- a/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt +++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt @@ -1,61 +1,62 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" - xmlns:tal="http://xml.zope.org/namespaces/tal"> + xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>${page.__name__} - Pyramid tutorial wiki (based on - TurboGears 20-Minute Wiki)</title> - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> - <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="${request.static_url('tutorial:static/pylons.css')}" - 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]--> + <title>${page.__name__} - Pyramid tutorial wiki (based on + TurboGears 20-Minute Wiki)</title> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> + <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="${request.static_url('tutorial:static/pylons.css')}" + 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]--> </head> <body> - <div id="wrap"> - <div id="top-small"> - <div class="top-small align-center"> - <div> - <img width="220" height="50" alt="pyramid" - src="${request.static_url('tutorial:static/pyramid-small.png')}" /> - </div> - </div> - </div> - <div id="middle"> - <div class="middle align-right"> - <div id="left" class="app-welcome align-left"> - Editing <b><span tal:replace="page.__name__">Page Name - Goes Here</span></b><br/> - You can return to the - <a href="${request.application_url}">FrontPage</a>.<br/> - </div> - <div id="right" class="app-welcome align-right"> - <span tal:condition="logged_in"> - <a href="${request.application_url}/logout">Logout</a> - </span> - </div> - </div> - </div> - <div id="bottom"> - <div class="bottom"> - <form action="${save_url}" method="post"> - <textarea name="body" tal:content="page.data" rows="10" - cols="60"/><br/> - <input type="submit" name="form.submitted" value="Save"/> - </form> - </div> - </div> - </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> - </div> + <div id="wrap"> + <div id="top-small"> + <div class="top-small align-center"> + <div> + <img width="220" height="50" alt="pyramid" + src="${request.static_url('tutorial:static/pyramid-small.png')}" /> + </div> + </div> + </div> + <div id="middle"> + <div class="middle align-right"> + <div id="left" class="app-welcome align-left"> + Editing <b><span tal:replace="page.__name__">Page Name + Goes Here</span></b><br/> + You can return to the + <a href="${request.application_url}">FrontPage</a>.<br/> + </div> + <div id="right" class="app-welcome align-right"> + <span tal:condition="logged_in"> + <a href="${request.application_url}/logout">Logout</a> + </span> + </div> + </div> + </div> + <div id="bottom"> + <div class="bottom"> + <form action="${save_url}" method="post"> + <textarea name="body" tal:content="page.data" rows="10" + cols="60"/><br/> + <input type="submit" name="form.submitted" value="Save"/> + </form> + </div> + </div> + </div> + <div id="footer"> + <div class="footer" + >© Copyright 2008-2011, Agendaless Consulting.</div> + </div> </body> </html> diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt index 09bcff65d..64e592ea9 100644 --- a/docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt +++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt @@ -1,57 +1,58 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" - xmlns:tal="http://xml.zope.org/namespaces/tal"> + xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>Login - Pyramid tutorial wiki (based on TurboGears - 20-Minute Wiki)</title> - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> - <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="${request.static_url('tutorial:static/pylons.css')}" - 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]--> + <title>Login - Pyramid tutorial wiki (based on TurboGears + 20-Minute Wiki)</title> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> + <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="${request.static_url('tutorial:static/pylons.css')}" + 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]--> </head> <body> - <div id="wrap"> - <div id="top-small"> - <div class="top-small align-center"> - <div> - <img width="220" height="50" alt="pyramid" - src="${request.static_url('tutorial:static/pyramid-small.png')}" /> - </div> - </div> - </div> - <div id="middle"> - <div class="middle align-right"> - <div id="left" class="app-welcome align-left"> - <b>Login</b><br/> - <span tal:replace="message"/> - </div> - <div id="right" class="app-welcome align-right"></div> - </div> - </div> - <div id="bottom"> - <div class="bottom"> - <form action="${url}" method="post"> - <input type="hidden" name="came_from" value="${came_from}"/> - <input type="text" name="login" value="${login}"/><br/> - <input type="password" name="password" - value="${password}"/><br/> - <input type="submit" name="form.submitted" value="Log In"/> - </form> - </div> - </div> - </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> - </div> + <div id="wrap"> + <div id="top-small"> + <div class="top-small align-center"> + <div> + <img width="220" height="50" alt="pyramid" + src="${request.static_url('tutorial:static/pyramid-small.png')}" /> + </div> + </div> + </div> + <div id="middle"> + <div class="middle align-right"> + <div id="left" class="app-welcome align-left"> + <b>Login</b><br/> + <span tal:replace="message"/> + </div> + <div id="right" class="app-welcome align-right"></div> + </div> + </div> + <div id="bottom"> + <div class="bottom"> + <form action="${url}" method="post"> + <input type="hidden" name="came_from" value="${came_from}"/> + <input type="text" name="login" value="${login}"/><br/> + <input type="password" name="password" + value="${password}"/><br/> + <input type="submit" name="form.submitted" value="Log In"/> + </form> + </div> + </div> + </div> + <div id="footer"> + <div class="footer" + >© Copyright 2008-2011, Agendaless Consulting.</div> + </div> </body> </html> diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt index 712fd0737..d98420680 100644 --- a/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt @@ -1,75 +1,75 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>The Pyramid Web Application Development Framework</title> - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> - <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="${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]--> + <title>The Pyramid Web Application Development Framework</title> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> + <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="${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]--> </head> <body> - <div id="wrap"> - <div id="top"> - <div class="top align-center"> - <div><img src="${request.static_url('tutorial:static/pyramid.png')}" width="750" height="169" alt="pyramid"/></div> - </div> - </div> - <div id="middle"> - <div class="middle align-center"> - <p class="app-welcome"> - Welcome to <span class="app-name">${project}</span>, an application generated by<br/> - the Pyramid web application development framework. - </p> - </div> - </div> - <div id="bottom"> - <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"> - <input type="text" id="q" name="q" value="" /> - <input type="submit" id="x" value="Go" /> - </form> - </div> - <div id="right" class="align-left"> - <h2>Pyramid links</h2> - <ul class="links"> - <li> - <a href="http://pylonsproject.org">Pylons Website</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> - </li> - <li> - <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> - </li> - </ul> - </div> - </div> - </div> - </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> - </div> + <div id="wrap"> + <div id="top"> + <div class="top align-center"> + <div><img src="${request.static_url('tutorial:static/pyramid.png')}" width="750" height="169" alt="pyramid"/></div> + </div> + </div> + <div id="middle"> + <div class="middle align-center"> + <p class="app-welcome"> + Welcome to <span class="app-name">${project}</span>, an application generated by<br/> + the Pyramid web application development framework. + </p> + </div> + </div> + <div id="bottom"> + <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"> + <input type="text" id="q" name="q" value="" /> + <input type="submit" id="x" value="Go" /> + </form> + </div> + <div id="right" class="align-left"> + <h2>Pyramid links</h2> + <ul class="links"> + <li> + <a href="http://pylonsproject.org">Pylons Website</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> + </li> + <li> + <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> + </li> + </ul> + </div> + </div> + </div> + </div> + <div id="footer"> + <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> + </div> </body> </html> diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt index 113144687..d207a0c23 100644 --- a/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt +++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt @@ -1,64 +1,65 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" - xmlns:tal="http://xml.zope.org/namespaces/tal"> + xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>${page.__name__} - Pyramid tutorial wiki (based on - TurboGears 20-Minute Wiki)</title> - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> - <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="${request.static_url('tutorial:static/pylons.css')}" - 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]--> + <title>${page.__name__} - Pyramid tutorial wiki (based on + TurboGears 20-Minute Wiki)</title> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> + <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="${request.static_url('tutorial:static/pylons.css')}" + 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]--> </head> <body> - <div id="wrap"> - <div id="top-small"> - <div class="top-small align-center"> - <div> - <img width="220" height="50" alt="pyramid" - src="${request.static_url('tutorial:static/pyramid-small.png')}" /> - </div> - </div> - </div> - <div id="middle"> - <div class="middle align-right"> - <div id="left" class="app-welcome align-left"> - Viewing <b><span tal:replace="page.__name__">Page Name - Goes Here</span></b><br/> - You can return to the - <a href="${request.application_url}">FrontPage</a>.<br/> - </div> - <div id="right" class="app-welcome align-right"> - <span tal:condition="logged_in"> - <a href="${request.application_url}/logout">Logout</a> - </span> - </div> - </div> - </div> - <div id="bottom"> - <div class="bottom"> - <div tal:replace="structure content"> - Page text goes here. - </div> - <p> - <a tal:attributes="href edit_url" href=""> - Edit this page - </a> - </p> - </div> - </div> - </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> - </div> + <div id="wrap"> + <div id="top-small"> + <div class="top-small align-center"> + <div> + <img width="220" height="50" alt="pyramid" + src="${request.static_url('tutorial:static/pyramid-small.png')}" /> + </div> + </div> + </div> + <div id="middle"> + <div class="middle align-right"> + <div id="left" class="app-welcome align-left"> + Viewing <b><span tal:replace="page.__name__">Page Name + Goes Here</span></b><br/> + You can return to the + <a href="${request.application_url}">FrontPage</a>.<br/> + </div> + <div id="right" class="app-welcome align-right"> + <span tal:condition="logged_in"> + <a href="${request.application_url}/logout">Logout</a> + </span> + </div> + </div> + </div> + <div id="bottom"> + <div class="bottom"> + <div tal:replace="structure content"> + Page text goes here. + </div> + <p> + <a tal:attributes="href edit_url" href=""> + Edit this page + </a> + </p> + </div> + </div> + </div> + <div id="footer"> + <div class="footer" + >© Copyright 2008-2011, Agendaless Consulting.</div> + </div> </body> </html> diff --git a/docs/tutorials/wiki/src/basiclayout/development.ini b/docs/tutorials/wiki/src/basiclayout/development.ini index 054720aa2..555010bed 100644 --- a/docs/tutorials/wiki/src/basiclayout/development.ini +++ b/docs/tutorials/wiki/src/basiclayout/development.ini @@ -12,6 +12,7 @@ zodb_uri = file://%(here)s/Data.fs?connection_cache_size=20000 pipeline = egg:WebError#evalerror egg:repoze.zodbconn#closer + egg:repoze.retry#retry tm tutorial @@ -46,6 +47,6 @@ level = NOTSET formatter = generic [formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s +format = %(asctime)s %(levelname)-5.5s [%(name)s] %(message)s # End logging configuration diff --git a/docs/tutorials/wiki/src/basiclayout/production.ini b/docs/tutorials/wiki/src/basiclayout/production.ini index 458064388..5c47ade9b 100644 --- a/docs/tutorials/wiki/src/basiclayout/production.ini +++ b/docs/tutorials/wiki/src/basiclayout/production.ini @@ -30,6 +30,7 @@ commit_veto = repoze.tm:default_commit_veto pipeline = weberror egg:repoze.zodbconn#closer + egg:repoze.retry#retry tm tutorial diff --git a/docs/tutorials/wiki/src/basiclayout/setup.py b/docs/tutorials/wiki/src/basiclayout/setup.py index cb3b92347..2d540d65b 100644 --- a/docs/tutorials/wiki/src/basiclayout/setup.py +++ b/docs/tutorials/wiki/src/basiclayout/setup.py @@ -10,6 +10,7 @@ requires = [ 'pyramid', 'repoze.zodbconn', 'repoze.tm2>=1.0b1', # default_commit_veto + 'repoze.retry', 'ZODB3', 'WebError', ] diff --git a/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt index c4dfc0707..c24daa711 100644 --- a/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt @@ -1,75 +1,75 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>The Pyramid Web Application Development Framework</title> - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> - <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="${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]--> + <title>The Pyramid Web Application Development Framework</title> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> + <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="${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]--> </head> <body> - <div id="wrap"> - <div id="top"> - <div class="top align-center"> - <div><img src="${request.static_url('tutorial:static/pyramid.png')}" width="750" height="169" alt="pyramid"/></div> - </div> - </div> - <div id="middle"> - <div class="middle align-center"> - <p class="app-welcome"> - Welcome to <span class="app-name">${project}</span>, an application generated by<br/> - the Pyramid web application development framework. - </p> - </div> - </div> - <div id="bottom"> - <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"> - <input type="text" id="q" name="q" value="" /> - <input type="submit" id="x" value="Go" /> - </form> - </div> - <div id="right" class="align-left"> - <h2>Pyramid links</h2> - <ul class="links"> - <li> - <a href="http://pylonsproject.org/">Pylons Website</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> - </li> - <li> - <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> - </li> - </ul> - </div> - </div> - </div> - </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> - </div> + <div id="wrap"> + <div id="top"> + <div class="top align-center"> + <div><img src="${request.static_url('tutorial:static/pyramid.png')}" width="750" height="169" alt="pyramid"/></div> + </div> + </div> + <div id="middle"> + <div class="middle align-center"> + <p class="app-welcome"> + Welcome to <span class="app-name">${project}</span>, an application generated by<br/> + the Pyramid web application development framework. + </p> + </div> + </div> + <div id="bottom"> + <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"> + <input type="text" id="q" name="q" value="" /> + <input type="submit" id="x" value="Go" /> + </form> + </div> + <div id="right" class="align-left"> + <h2>Pyramid links</h2> + <ul class="links"> + <li> + <a href="http://pylonsproject.org/">Pylons Website</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> + </li> + <li> + <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> + </li> + </ul> + </div> + </div> + </div> + </div> + <div id="footer"> + <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> + </div> </body> </html> diff --git a/docs/tutorials/wiki/src/models/development.ini b/docs/tutorials/wiki/src/models/development.ini index 054720aa2..1ba746d0e 100644 --- a/docs/tutorials/wiki/src/models/development.ini +++ b/docs/tutorials/wiki/src/models/development.ini @@ -12,6 +12,7 @@ zodb_uri = file://%(here)s/Data.fs?connection_cache_size=20000 pipeline = egg:WebError#evalerror egg:repoze.zodbconn#closer + egg:repoze.retry#retry tm tutorial diff --git a/docs/tutorials/wiki/src/models/production.ini b/docs/tutorials/wiki/src/models/production.ini index 458064388..5c47ade9b 100644 --- a/docs/tutorials/wiki/src/models/production.ini +++ b/docs/tutorials/wiki/src/models/production.ini @@ -30,6 +30,7 @@ commit_veto = repoze.tm:default_commit_veto pipeline = weberror egg:repoze.zodbconn#closer + egg:repoze.retry#retry tm tutorial diff --git a/docs/tutorials/wiki/src/models/setup.py b/docs/tutorials/wiki/src/models/setup.py index 3cd43d5d8..daa5e5eb1 100644 --- a/docs/tutorials/wiki/src/models/setup.py +++ b/docs/tutorials/wiki/src/models/setup.py @@ -10,8 +10,10 @@ requires = [ 'pyramid', 'repoze.zodbconn', 'repoze.tm2>=1.0b1', # default_commit_veto + 'repoze.retry', 'ZODB3', 'WebError', + 'docutils', ] setup(name='tutorial', diff --git a/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt index 712fd0737..d98420680 100644 --- a/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt @@ -1,75 +1,75 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>The Pyramid Web Application Development Framework</title> - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> - <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="${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]--> + <title>The Pyramid Web Application Development Framework</title> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> + <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="${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]--> </head> <body> - <div id="wrap"> - <div id="top"> - <div class="top align-center"> - <div><img src="${request.static_url('tutorial:static/pyramid.png')}" width="750" height="169" alt="pyramid"/></div> - </div> - </div> - <div id="middle"> - <div class="middle align-center"> - <p class="app-welcome"> - Welcome to <span class="app-name">${project}</span>, an application generated by<br/> - the Pyramid web application development framework. - </p> - </div> - </div> - <div id="bottom"> - <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"> - <input type="text" id="q" name="q" value="" /> - <input type="submit" id="x" value="Go" /> - </form> - </div> - <div id="right" class="align-left"> - <h2>Pyramid links</h2> - <ul class="links"> - <li> - <a href="http://pylonsproject.org">Pylons Website</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> - </li> - <li> - <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> - </li> - </ul> - </div> - </div> - </div> - </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> - </div> + <div id="wrap"> + <div id="top"> + <div class="top align-center"> + <div><img src="${request.static_url('tutorial:static/pyramid.png')}" width="750" height="169" alt="pyramid"/></div> + </div> + </div> + <div id="middle"> + <div class="middle align-center"> + <p class="app-welcome"> + Welcome to <span class="app-name">${project}</span>, an application generated by<br/> + the Pyramid web application development framework. + </p> + </div> + </div> + <div id="bottom"> + <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"> + <input type="text" id="q" name="q" value="" /> + <input type="submit" id="x" value="Go" /> + </form> + </div> + <div id="right" class="align-left"> + <h2>Pyramid links</h2> + <ul class="links"> + <li> + <a href="http://pylonsproject.org">Pylons Website</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> + </li> + <li> + <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> + </li> + </ul> + </div> + </div> + </div> + </div> + <div id="footer"> + <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> + </div> </body> </html> diff --git a/docs/tutorials/wiki/src/views/development.ini b/docs/tutorials/wiki/src/views/development.ini index 054720aa2..555010bed 100644 --- a/docs/tutorials/wiki/src/views/development.ini +++ b/docs/tutorials/wiki/src/views/development.ini @@ -12,6 +12,7 @@ zodb_uri = file://%(here)s/Data.fs?connection_cache_size=20000 pipeline = egg:WebError#evalerror egg:repoze.zodbconn#closer + egg:repoze.retry#retry tm tutorial @@ -46,6 +47,6 @@ level = NOTSET formatter = generic [formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s +format = %(asctime)s %(levelname)-5.5s [%(name)s] %(message)s # End logging configuration diff --git a/docs/tutorials/wiki/src/views/production.ini b/docs/tutorials/wiki/src/views/production.ini index 458064388..5c47ade9b 100644 --- a/docs/tutorials/wiki/src/views/production.ini +++ b/docs/tutorials/wiki/src/views/production.ini @@ -30,6 +30,7 @@ commit_veto = repoze.tm:default_commit_veto pipeline = weberror egg:repoze.zodbconn#closer + egg:repoze.retry#retry tm tutorial diff --git a/docs/tutorials/wiki/src/views/setup.py b/docs/tutorials/wiki/src/views/setup.py index 9538cbbff..daa5e5eb1 100644 --- a/docs/tutorials/wiki/src/views/setup.py +++ b/docs/tutorials/wiki/src/views/setup.py @@ -10,6 +10,7 @@ requires = [ 'pyramid', 'repoze.zodbconn', 'repoze.tm2>=1.0b1', # default_commit_veto + 'repoze.retry', 'ZODB3', 'WebError', 'docutils', diff --git a/docs/tutorials/wiki/src/views/tutorial/templates/edit.pt b/docs/tutorials/wiki/src/views/tutorial/templates/edit.pt index e287e174e..6dbb0edde 100644 --- a/docs/tutorials/wiki/src/views/tutorial/templates/edit.pt +++ b/docs/tutorials/wiki/src/views/tutorial/templates/edit.pt @@ -1,57 +1,58 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" - xmlns:tal="http://xml.zope.org/namespaces/tal"> + xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>${page.__name__} - Pyramid tutorial wiki (based on - TurboGears 20-Minute Wiki)</title> - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> - <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="${request.static_url('tutorial:static/pylons.css')}" - 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]--> + <title>${page.__name__} - Pyramid tutorial wiki (based on + TurboGears 20-Minute Wiki)</title> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> + <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="${request.static_url('tutorial:static/pylons.css')}" + 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]--> </head> <body> - <div id="wrap"> - <div id="top-small"> - <div class="top-small align-center"> - <div> - <img width="220" height="50" alt="pyramid" - src="${request.static_url('tutorial:static/pyramid-small.png')}" /> - </div> - </div> - </div> - <div id="middle"> - <div class="middle align-right"> - <div id="left" class="app-welcome align-left"> - Editing <b><span tal:replace="page.__name__">Page Name Goes - Here</span></b><br/> - You can return to the - <a href="${request.application_url}">FrontPage</a>.<br/> - </div> - <div id="right" class="app-welcome align-right"></div> - </div> - </div> - <div id="bottom"> - <div class="bottom"> - <form action="${save_url}" method="post"> - <textarea name="body" tal:content="page.data" rows="10" - cols="60"/><br/> - <input type="submit" name="form.submitted" value="Save"/> - </form> - </div> - </div> - </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> - </div> + <div id="wrap"> + <div id="top-small"> + <div class="top-small align-center"> + <div> + <img width="220" height="50" alt="pyramid" + src="${request.static_url('tutorial:static/pyramid-small.png')}" /> + </div> + </div> + </div> + <div id="middle"> + <div class="middle align-right"> + <div id="left" class="app-welcome align-left"> + Editing <b><span tal:replace="page.__name__">Page Name Goes + Here</span></b><br/> + You can return to the + <a href="${request.application_url}">FrontPage</a>.<br/> + </div> + <div id="right" class="app-welcome align-right"></div> + </div> + </div> + <div id="bottom"> + <div class="bottom"> + <form action="${save_url}" method="post"> + <textarea name="body" tal:content="page.data" rows="10" + cols="60"/><br/> + <input type="submit" name="form.submitted" value="Save"/> + </form> + </div> + </div> + </div> + <div id="footer"> + <div class="footer" + >© Copyright 2008-2011, Agendaless Consulting.</div> + </div> </body> </html> diff --git a/docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt index 712fd0737..d98420680 100644 --- a/docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt @@ -1,75 +1,75 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>The Pyramid Web Application Development Framework</title> - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> - <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="${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]--> + <title>The Pyramid Web Application Development Framework</title> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> + <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="${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]--> </head> <body> - <div id="wrap"> - <div id="top"> - <div class="top align-center"> - <div><img src="${request.static_url('tutorial:static/pyramid.png')}" width="750" height="169" alt="pyramid"/></div> - </div> - </div> - <div id="middle"> - <div class="middle align-center"> - <p class="app-welcome"> - Welcome to <span class="app-name">${project}</span>, an application generated by<br/> - the Pyramid web application development framework. - </p> - </div> - </div> - <div id="bottom"> - <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"> - <input type="text" id="q" name="q" value="" /> - <input type="submit" id="x" value="Go" /> - </form> - </div> - <div id="right" class="align-left"> - <h2>Pyramid links</h2> - <ul class="links"> - <li> - <a href="http://pylonsproject.org">Pylons Website</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> - </li> - <li> - <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> - </li> - </ul> - </div> - </div> - </div> - </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> - </div> + <div id="wrap"> + <div id="top"> + <div class="top align-center"> + <div><img src="${request.static_url('tutorial:static/pyramid.png')}" width="750" height="169" alt="pyramid"/></div> + </div> + </div> + <div id="middle"> + <div class="middle align-center"> + <p class="app-welcome"> + Welcome to <span class="app-name">${project}</span>, an application generated by<br/> + the Pyramid web application development framework. + </p> + </div> + </div> + <div id="bottom"> + <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"> + <input type="text" id="q" name="q" value="" /> + <input type="submit" id="x" value="Go" /> + </form> + </div> + <div id="right" class="align-left"> + <h2>Pyramid links</h2> + <ul class="links"> + <li> + <a href="http://pylonsproject.org">Pylons Website</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> + </li> + <li> + <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> + </li> + </ul> + </div> + </div> + </div> + </div> + <div id="footer"> + <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> + </div> </body> </html> diff --git a/docs/tutorials/wiki/src/views/tutorial/templates/view.pt b/docs/tutorials/wiki/src/views/tutorial/templates/view.pt index 992c5aa43..537ae3a15 100644 --- a/docs/tutorials/wiki/src/views/tutorial/templates/view.pt +++ b/docs/tutorials/wiki/src/views/tutorial/templates/view.pt @@ -1,60 +1,61 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" - xmlns:tal="http://xml.zope.org/namespaces/tal"> + xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>${page.__name__} - Pyramid tutorial wiki (based on - TurboGears 20-Minute Wiki)</title> - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> - <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="${request.static_url('tutorial:static/pylons.css')}" - 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]--> + <title>${page.__name__} - Pyramid tutorial wiki (based on + TurboGears 20-Minute Wiki)</title> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> + <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="${request.static_url('tutorial:static/pylons.css')}" + 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]--> </head> <body> - <div id="wrap"> - <div id="top-small"> - <div class="top-small align-center"> - <div> - <img width="220" height="50" alt="pyramid" - src="${request.static_url('tutorial:static/pyramid-small.png')}" /> - </div> - </div> - </div> - <div id="middle"> - <div class="middle align-right"> - <div id="left" class="app-welcome align-left"> - Viewing <b><span tal:replace="page.__name__">Page Name Goes - Here</span></b><br/> - You can return to the - <a href="${request.application_url}">FrontPage</a>.<br/> - </div> - <div id="right" class="app-welcome align-right"></div> - </div> - </div> - <div id="bottom"> - <div class="bottom"> - <div tal:replace="structure content"> - Page text goes here. - </div> - <p> - <a tal:attributes="href edit_url" href=""> - Edit this page - </a> - </p> - </div> - </div> - </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> - </div> + <div id="wrap"> + <div id="top-small"> + <div class="top-small align-center"> + <div> + <img width="220" height="50" alt="pyramid" + src="${request.static_url('tutorial:static/pyramid-small.png')}" /> + </div> + </div> + </div> + <div id="middle"> + <div class="middle align-right"> + <div id="left" class="app-welcome align-left"> + Viewing <b><span tal:replace="page.__name__">Page Name Goes + Here</span></b><br/> + You can return to the + <a href="${request.application_url}">FrontPage</a>.<br/> + </div> + <div id="right" class="app-welcome align-right"></div> + </div> + </div> + <div id="bottom"> + <div class="bottom"> + <div tal:replace="structure content"> + Page text goes here. + </div> + <p> + <a tal:attributes="href edit_url" href=""> + Edit this page + </a> + </p> + </div> + </div> + </div> + <div id="footer"> + <div class="footer" + >© Copyright 2008-2011, Agendaless Consulting.</div> + </div> </body> </html> diff --git a/docs/tutorials/wiki2/authorization.rst b/docs/tutorials/wiki2/authorization.rst index 3f1d2669a..fef74e4e2 100644 --- a/docs/tutorials/wiki2/authorization.rst +++ b/docs/tutorials/wiki2/authorization.rst @@ -203,7 +203,6 @@ referred to within the login view we just added to ``login.py``. .. literalinclude:: src/authorization/tutorial/templates/login.pt :language: xml - :tab-width: 2 Change ``view.pt`` and ``edit.pt`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -261,13 +260,11 @@ Our ``edit.pt`` template will look something like this when we're done: .. literalinclude:: src/authorization/tutorial/templates/edit.pt :language: xml - :tab-width: 2 Our ``view.pt`` template will look something like this when we're done: .. literalinclude:: src/authorization/tutorial/templates/view.pt :language: xml - :tab-width: 2 Revisiting the Application --------------------------- @@ -278,353 +275,3 @@ of hitting an edit or add page and submitting the login form with the hand corner. When we click it, we're logged out, and redirected back to the front page. -.. _wiki2_flow_of_authentication: - -Overall flow of an authentication ---------------------------------- - -Now that you have seen all the pieces of the authentication -mechanism, here are some examples that show how they all work -together. - -#. Failed login: The user requests ``/FrontPage/edit_page``. The - site presents the login form. The user enters ``editor`` as - the login, but enters an invalid password ``bad``. - The site redisplays the login form with the message "Failed - login". See :ref:`failed_login`. - -#. The user again requests ``/FrontPage/edit_page``. The site - presents the login form, and this time the user enters - login ``editor`` and password ``editor``. The site presents - the edit form with the content of ``/FrontPage``. The user - makes some changes and saves them. See :ref:`good_login`. - -#. The user again revisits ``/FrontPage/edit_page``. The site - goes immediately to the edit form without requesting - credentials. See :ref:`revisit`. - -#. The user clicks the ``Logout`` link. See :ref:`logging_out`. - -.. _failed_login: - -Failed login -~~~~~~~~~~~~ - -The process starts when the user enters URL -``http://localhost:6543/FrontPage/edit_page``. Let's assume that -this is the first request ever made to the application and the -page database is empty except for the ``Page`` instance created -for the front page by the ``initialize_sql`` function in -:file:`models.py`. - -This process involves two complete request/response cycles. - -1. From the front page, the user clicks :guilabel:`Edit page`. - The request is to ``/FrontPage/edit_page``. The view callable - is ``login.login``. The response is the ``login.pt`` template - with blank fields. - -2. The user enters invalid credentials and clicks :guilabel:`Log - in`. A ``POST`` request is sent to ``/FrontPage/edit_page``. - The view callable is again ``login.login``. The response is - the ``login.pt`` template showing the message "Failed login", - with the entry fields displaying their former values. - -Cycle 1: - -#. During URL dispatch, the route ``'/{pagename}/edit_page'`` is - considered for matching. The associated view has a - ``view_permission='edit'`` permission attached, so the - dispatch logic has to verify that the user has that permission - or the route is not considered to match. - - The context for all route matching comes from the configured - root factory, :meth:`RootFactory` in :file:`models.py`. - This class has an ``__acl__`` attribute that defines the - access control list for all routes:: - - __acl__ = [ (Allow, Everyone, 'view'), - (Allow, 'group:editors', 'edit') ] - - In practice, this means that for any route that requires the - ``edit`` permission, the user must be authenticated and - have the ``group:editors`` principal or the route is not - considered to match. - -#. To find the list of the user's principals, the authorization - first policy checks to see if the user has a - ``paste.auth.auth_tkt`` cookie. Since the user has never been - to the site, there is no such cookie, and the user is - considered to be unauthenticated. - -#. Since the user is unauthenticated, the ``groupfinder`` - function in :file:`security.py` is called with ``None`` as its - ``userid`` argument. The function returns an empty list of - principals. - -#. Because that list does not contain the ``group:editors`` - principal, the ``'/{pagename}/edit_page'`` route's ``edit`` - permission fails, and the route does not match. - -#. Because no routes match, the `forbidden view` callable is - invoked: the ``login`` function in module ``login.py``. - -#. Inside the ``login`` function, the value of ``login_url`` is - ``http://localhost:6543/login``, and the value of - ``referrer`` is ``http://localhost:6543/FrontPage/edit_page``. - - Because ``request.params`` has no key for ``'came_from'``, the - variable ``came_from`` is also set to - ``http://localhost:6543/FrontPage/edit_page``. Variables - ``message``, ``login``, and ``password`` are set to the empty - string. - - Because ``request.params`` has no key for - ``'form.submitted'``, the ``login`` function returns this - dictionary:: - - {'message': '', 'url':'http://localhost:6543/login', - 'came_from':'http://localhost:6543/FrontPage/edit_page', - 'login':'', 'password':''} - -#. This dictionary is used to render the ``login.pt`` template. - In the form, the ``action`` attribute is - ``http://localhost:6543/login``, and the value of - ``came_from`` is included in that form as a hidden field - by this line in the template:: - - <input type="hidden" name="came_from" value="${came_from}"/> - -Cycle 2: - -#. The user enters incorrect credentials and clicks the - :guilabel:`Log in` button, which does a ``POST`` request to - URL ``http://localhost:6543/login``. The name of the - :guilabel:`Log in` button in this form is ``form.submitted``. - -#. The route with pattern ``'/login'`` matches this URL, so - control is passed again to the ``login`` view callable. - -#. The ``login_url`` and ``referrer`` have the same value - this time (``http://localhost:6543/login``), so variable - ``referrer`` is set to ``'/'``. - - Since ``request.params`` does have a key ``'form.submitted'``, - the values of ``login`` and ``password`` are retrieved from - ``request.params``. - - Because the login and password do not match any of the entries - in the ``USERS`` dictionary in ``security.py``, variable - ``message`` is set to ``'Failed login'``. - - The view callable returns this dictionary:: - - {'message':'Failed login', - 'url':'http://localhost:6543/login', 'came_from':'/', - 'login':'editor', 'password':'bad'} - -#. The ``login.pt`` template is rendered using those values. - -.. _good_login: - -Successful login -~~~~~~~~~~~~~~~~ - -In this scenario, the user again requests URL -``/FrontPage/edit_page``. - -This process involves four complete request/response cycles. - -1. The user clicks :guilabel:`Edit page`. The view callable is - ``login.login``. The response is template ``login.pt``, - with all the fields blank. - -2. The user enters valid credentials and clicks :guilabel:`Log in`. - The view callable is ``login.login``. The response is a - redirect to ``/FrontPage/edit_page``. - -3. The view callable is ``views.edit_page``. The response - renders template ``edit.pt``, displaying the current page - content. - -4. The user edits the content and clicks :guilabel:`Save`. - The view callable is ``views.edit_page``. The response - is a redirect to ``/FrontPage``. - -Execution proceeds as in :ref:`failed_login`, up to the point -where the password ``editor`` is successfully matched against the -value from the ``USERS`` dictionary. - -Cycle 2: - -#. Within the ``login.login`` view callable, the value of - ``login_url`` is ``http://localhost:6543/login``, and the - value of ``referrer`` is ``'/'``, and ``came_from`` is - ``http://localhost:6543/FrontPage/edit_page`` when this block - is executed: - - .. code-block:: python - - if USERS.get(login) == password: - headers = remember(request, login) - return HTTPFound(location=came_from, headers=headers) - -#. Because the password matches this time, - :mod:`pyramid.security.remember` returns a sequence of header - tuples that will set a ``paste.auth.auth_tkt`` authentication - cookie in the user's browser for the login ``'editor'``. - -#. The ``HTTPFound`` exception returns a response that redirects - the browser to ``http://localhost:6543/FrontPage/edit_page``, - including the headers that set the authentication cookie. - -Cycle 3: - -#. Route pattern ``'/{pagename}/edit_page'`` matches this URL, - but the corresponding view is restricted by an ``'edit'`` - permission. - -#. Because the user now has an authentication cookie defining - their login name as ``'editor'``, the ``groupfinder`` function - is called with that value as its ``userid`` argument. - -#. The ``groupfinder`` function returns the list - ``['group:editors']``. This satisfies the access control - entry ``(Allow, 'group:editors', 'edit')``, which grants the - ``edit`` permission. Thus, this route matches, and control - passes to view callable ``edit_page``. - -#. Within ``edit_page``, ``name`` is set to ``'FrontPage'``, the - page name from ``request.matchdict['pagename']``, and - ``page`` is set to an instance of :class:`models.Page` - that holds the current content of ``FrontPage``. - -#. Since this request did not come from a form, - ``request.params`` does not have a key for - ``'form.submitted'``. - -#. The ``edit_page`` function calls - :meth:`pyramid.security.authenticated_userid` to find out - whether the user is authenticated. Because of the cookies - set previously, the variable ``logged_in`` is set to - the userid ``'editor'``. - -#. The ``edit_page`` function returns this dictionary:: - - {'page':page, 'logged_in':'editor', - 'save_url':'http://localhost:6543/FrontPage/edit_page'} - -#. Template :file:`edit.pt` is rendered with those values. - Among other features of this template, these lines - cause the inclusion of a :guilabel:`Logout` link:: - - <span tal:condition="logged_in"> - <a href="${request.application_url}/logout">Logout</a> - </span> - - For the example case, this link will refer to - ``http://localhost:6543/logout``. - - These lines of the template display the current page's - content in a form whose ``action`` attribute is - ``http://localhost:6543/FrontPage/edit_page``:: - - <form action="${save_url}" method="post"> - <textarea name="body" tal:content="page.data" rows="10" cols="60"/> - <input type="submit" name="form.submitted" value="Save"/> - </form> - -Cycle 4: - -#. The user edits the page content and clicks - :guilabel:`Save`. - -#. URL ``http://localhost:6543/FrontPage/edit_page`` goes through - the same routing as before, up until the line that checks - whether ``request.params`` has a key ``'form.submitted'``. - This time, within the ``edit_page`` view callable, these - lines are executed:: - - page.data = request.params['body'] - session.add(page) - return HTTPFound(location = route_url('view_page', request, - pagename=name)) - - The first two lines replace the old page content with the - contents of the ``body`` text area from the form, and then - update the page stored in the database. The third line - causes a response that redirects the browser to - ``http://localhost:6543/FrontPage``. - -.. _revisit: - -Revisiting after authentication -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In this case, the user has an authentication cookie set in their -browser that specifies their login as ``'editor'``. The -requested URL is ``http://localhost:6543/FrontPage/edit_page``. - -This process requires two request/response cycles. - -1. The user clicks :guilabel:`Edit page`. The view callable is - ``views.edit_page``. The response is ``edit.pt``, showing - the current page content. - -2. The user edits the content and clicks :guilabel:`Save`. - The view callable is ``views.edit_page``. The response is - a redirect to ``/Frontpage``. - -Cycle 1: - -#. The route with pattern ``/{pagename}/edit_page`` matches the - URL, and because of the authentication cookie, ``groupfinder`` - returns a list containing the ``group:editors`` principal, - which ``models.RootFactory.__acl__`` uses to grant the - ``edit`` permission, so this route matches and dispatches - to the view callable :meth:`views.edit_page`. - -#. In ``edit_page``, because the request did not come from a form - submission, ``request.params`` has no key for - ``'form.submitted'``. - -#. The variable ``logged_in`` is set to the login name - ``'editor'`` by calling ``authenticated_userid``, which - extracts it from the authentication cookie. - -#. The function returns this dictionary:: - - {'page':page, - 'save_url':'http://localhost:6543/FrontPage/edit_page', - 'logged_in':'editor'} - -#. Template :file:`edit.pt` is rendered with the values from - that dictionary. Because of the presence of the - ``'logged_in'`` entry, a :guilabel:`Logout` link appears. - -Cycle 2: - -#. The user edits the page content and clicks :guilabel:`Save`. - -#. The ``POST`` operation works as in :ref:`good_login`. - -.. _logging_out: - -Logging out -~~~~~~~~~~~ - -This process starts with a request URL -``http://localhost:6543/logout``. - -#. The route with pattern ``'/logout'`` matches and dispatches - to the view callable ``logout`` in :file:`login.py`. - -#. The call to :meth:`pyramid.security.forget` returns a list of - header tuples that will, when returned with the response, - cause the browser to delete the user's authentication cookie. - -#. The view callable returns an ``HTTPFound`` exception that - redirects the browser to named route ``view_wiki``, which - will translate to URL ``http://localhost:6543``. It - also passes along the headers that delete the - authentication cookie. diff --git a/docs/tutorials/wiki2/basiclayout.rst b/docs/tutorials/wiki2/basiclayout.rst index 565bd0e96..17dcfc48f 100644 --- a/docs/tutorials/wiki2/basiclayout.rst +++ b/docs/tutorials/wiki2/basiclayout.rst @@ -60,7 +60,7 @@ function: #. *Lines 13-14*. Register a :term:`route configuration` via the :meth:`pyramid.config.Configurator.add_route` method that will be - used when the URL is ``/``. Since this route has an ``pattern`` equalling + used when the URL is ``/``. Since this route has a ``pattern`` equalling ``/`` it is the "default" route. The argument named ``view`` with the value ``tutorial.views.my_view`` is the dotted name to a *function* we write (generated by the ``pyramid_routesalchemy`` template) that is given diff --git a/docs/tutorials/wiki2/definingviews.rst b/docs/tutorials/wiki2/definingviews.rst index acf539e1a..d4417ed0b 100644 --- a/docs/tutorials/wiki2/definingviews.rst +++ b/docs/tutorials/wiki2/definingviews.rst @@ -213,7 +213,6 @@ the below: .. literalinclude:: src/views/tutorial/templates/view.pt :language: xml - :tab-width: 2 .. note:: The names available for our use in a template are always those that are present in the dictionary returned by the view @@ -241,8 +240,6 @@ the below: .. literalinclude:: src/views/tutorial/templates/edit.pt :language: xml - :tab-width: 2 - Static Assets ------------- diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/templates/edit.pt b/docs/tutorials/wiki2/src/authorization/tutorial/templates/edit.pt index 27ab544b5..ca28b9fa5 100644 --- a/docs/tutorials/wiki2/src/authorization/tutorial/templates/edit.pt +++ b/docs/tutorials/wiki2/src/authorization/tutorial/templates/edit.pt @@ -1,61 +1,62 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" - xmlns:tal="http://xml.zope.org/namespaces/tal"> + xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>${page.name} - Pyramid tutorial wiki (based on - TurboGears 20-Minute Wiki)</title> - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> - <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="${request.static_url('tutorial:static/pylons.css')}" - 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]--> + <title>${page.name} - Pyramid tutorial wiki (based on + TurboGears 20-Minute Wiki)</title> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> + <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="${request.static_url('tutorial:static/pylons.css')}" + 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]--> </head> <body> - <div id="wrap"> - <div id="top-small"> - <div class="top-small align-center"> - <div> - <img width="220" height="50" alt="pyramid" - src="${request.static_url('tutorial:static/pyramid-small.png')}" /> - </div> - </div> - </div> - <div id="middle"> - <div class="middle align-right"> - <div id="left" class="app-welcome align-left"> - Editing <b><span tal:replace="page.name">Page Name - Goes Here</span></b><br/> - You can return to the - <a href="${request.application_url}">FrontPage</a>.<br/> - </div> - <div id="right" class="app-welcome align-right"> - <span tal:condition="logged_in"> - <a href="${request.application_url}/logout">Logout</a> - </span> - </div> - </div> - </div> - <div id="bottom"> - <div class="bottom"> - <form action="${save_url}" method="post"> - <textarea name="body" tal:content="page.data" rows="10" - cols="60"/><br/> - <input type="submit" name="form.submitted" value="Save"/> - </form> - </div> - </div> - </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> - </div> + <div id="wrap"> + <div id="top-small"> + <div class="top-small align-center"> + <div> + <img width="220" height="50" alt="pyramid" + src="${request.static_url('tutorial:static/pyramid-small.png')}" /> + </div> + </div> + </div> + <div id="middle"> + <div class="middle align-right"> + <div id="left" class="app-welcome align-left"> + Editing <b><span tal:replace="page.name">Page Name + Goes Here</span></b><br/> + You can return to the + <a href="${request.application_url}">FrontPage</a>.<br/> + </div> + <div id="right" class="app-welcome align-right"> + <span tal:condition="logged_in"> + <a href="${request.application_url}/logout">Logout</a> + </span> + </div> + </div> + </div> + <div id="bottom"> + <div class="bottom"> + <form action="${save_url}" method="post"> + <textarea name="body" tal:content="page.data" rows="10" + cols="60"/><br/> + <input type="submit" name="form.submitted" value="Save"/> + </form> + </div> + </div> + </div> + <div id="footer"> + <div class="footer" + >© Copyright 2008-2011, Agendaless Consulting.</div> + </div> </body> </html> diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/templates/login.pt b/docs/tutorials/wiki2/src/authorization/tutorial/templates/login.pt index 09bcff65d..64e592ea9 100644 --- a/docs/tutorials/wiki2/src/authorization/tutorial/templates/login.pt +++ b/docs/tutorials/wiki2/src/authorization/tutorial/templates/login.pt @@ -1,57 +1,58 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" - xmlns:tal="http://xml.zope.org/namespaces/tal"> + xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>Login - Pyramid tutorial wiki (based on TurboGears - 20-Minute Wiki)</title> - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> - <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="${request.static_url('tutorial:static/pylons.css')}" - 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]--> + <title>Login - Pyramid tutorial wiki (based on TurboGears + 20-Minute Wiki)</title> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> + <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="${request.static_url('tutorial:static/pylons.css')}" + 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]--> </head> <body> - <div id="wrap"> - <div id="top-small"> - <div class="top-small align-center"> - <div> - <img width="220" height="50" alt="pyramid" - src="${request.static_url('tutorial:static/pyramid-small.png')}" /> - </div> - </div> - </div> - <div id="middle"> - <div class="middle align-right"> - <div id="left" class="app-welcome align-left"> - <b>Login</b><br/> - <span tal:replace="message"/> - </div> - <div id="right" class="app-welcome align-right"></div> - </div> - </div> - <div id="bottom"> - <div class="bottom"> - <form action="${url}" method="post"> - <input type="hidden" name="came_from" value="${came_from}"/> - <input type="text" name="login" value="${login}"/><br/> - <input type="password" name="password" - value="${password}"/><br/> - <input type="submit" name="form.submitted" value="Log In"/> - </form> - </div> - </div> - </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> - </div> + <div id="wrap"> + <div id="top-small"> + <div class="top-small align-center"> + <div> + <img width="220" height="50" alt="pyramid" + src="${request.static_url('tutorial:static/pyramid-small.png')}" /> + </div> + </div> + </div> + <div id="middle"> + <div class="middle align-right"> + <div id="left" class="app-welcome align-left"> + <b>Login</b><br/> + <span tal:replace="message"/> + </div> + <div id="right" class="app-welcome align-right"></div> + </div> + </div> + <div id="bottom"> + <div class="bottom"> + <form action="${url}" method="post"> + <input type="hidden" name="came_from" value="${came_from}"/> + <input type="text" name="login" value="${login}"/><br/> + <input type="password" name="password" + value="${password}"/><br/> + <input type="submit" name="form.submitted" value="Log In"/> + </form> + </div> + </div> + </div> + <div id="footer"> + <div class="footer" + >© Copyright 2008-2011, Agendaless Consulting.</div> + </div> </body> </html> diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/authorization/tutorial/templates/mytemplate.pt index 712fd0737..d98420680 100644 --- a/docs/tutorials/wiki2/src/authorization/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki2/src/authorization/tutorial/templates/mytemplate.pt @@ -1,75 +1,75 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>The Pyramid Web Application Development Framework</title> - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> - <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="${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]--> + <title>The Pyramid Web Application Development Framework</title> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> + <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="${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]--> </head> <body> - <div id="wrap"> - <div id="top"> - <div class="top align-center"> - <div><img src="${request.static_url('tutorial:static/pyramid.png')}" width="750" height="169" alt="pyramid"/></div> - </div> - </div> - <div id="middle"> - <div class="middle align-center"> - <p class="app-welcome"> - Welcome to <span class="app-name">${project}</span>, an application generated by<br/> - the Pyramid web application development framework. - </p> - </div> - </div> - <div id="bottom"> - <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"> - <input type="text" id="q" name="q" value="" /> - <input type="submit" id="x" value="Go" /> - </form> - </div> - <div id="right" class="align-left"> - <h2>Pyramid links</h2> - <ul class="links"> - <li> - <a href="http://pylonsproject.org">Pylons Website</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> - </li> - <li> - <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> - </li> - </ul> - </div> - </div> - </div> - </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> - </div> + <div id="wrap"> + <div id="top"> + <div class="top align-center"> + <div><img src="${request.static_url('tutorial:static/pyramid.png')}" width="750" height="169" alt="pyramid"/></div> + </div> + </div> + <div id="middle"> + <div class="middle align-center"> + <p class="app-welcome"> + Welcome to <span class="app-name">${project}</span>, an application generated by<br/> + the Pyramid web application development framework. + </p> + </div> + </div> + <div id="bottom"> + <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"> + <input type="text" id="q" name="q" value="" /> + <input type="submit" id="x" value="Go" /> + </form> + </div> + <div id="right" class="align-left"> + <h2>Pyramid links</h2> + <ul class="links"> + <li> + <a href="http://pylonsproject.org">Pylons Website</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> + </li> + <li> + <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> + </li> + </ul> + </div> + </div> + </div> + </div> + <div id="footer"> + <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> + </div> </body> </html> diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/templates/view.pt b/docs/tutorials/wiki2/src/authorization/tutorial/templates/view.pt index 6f015c5dd..5a69818c1 100644 --- a/docs/tutorials/wiki2/src/authorization/tutorial/templates/view.pt +++ b/docs/tutorials/wiki2/src/authorization/tutorial/templates/view.pt @@ -1,64 +1,65 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" - xmlns:tal="http://xml.zope.org/namespaces/tal"> + xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>${page.name} - Pyramid tutorial wiki (based on - TurboGears 20-Minute Wiki)</title> - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> - <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="${request.static_url('tutorial:static/pylons.css')}" - 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]--> + <title>${page.name} - Pyramid tutorial wiki (based on + TurboGears 20-Minute Wiki)</title> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> + <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="${request.static_url('tutorial:static/pylons.css')}" + 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]--> </head> <body> - <div id="wrap"> - <div id="top-small"> - <div class="top-small align-center"> - <div> - <img width="220" height="50" alt="pyramid" - src="${request.static_url('tutorial:static/pyramid-small.png')}" /> - </div> - </div> - </div> - <div id="middle"> - <div class="middle align-right"> - <div id="left" class="app-welcome align-left"> - Viewing <b><span tal:replace="page.name">Page Name - Goes Here</span></b><br/> - You can return to the - <a href="${request.application_url}">FrontPage</a>.<br/> - </div> - <div id="right" class="app-welcome align-right"> - <span tal:condition="logged_in"> - <a href="${request.application_url}/logout">Logout</a> - </span> - </div> - </div> - </div> - <div id="bottom"> - <div class="bottom"> - <div tal:replace="structure content"> - Page text goes here. - </div> - <p> - <a tal:attributes="href edit_url" href=""> - Edit this page - </a> - </p> - </div> - </div> - </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> - </div> + <div id="wrap"> + <div id="top-small"> + <div class="top-small align-center"> + <div> + <img width="220" height="50" alt="pyramid" + src="${request.static_url('tutorial:static/pyramid-small.png')}" /> + </div> + </div> + </div> + <div id="middle"> + <div class="middle align-right"> + <div id="left" class="app-welcome align-left"> + Viewing <b><span tal:replace="page.name">Page Name + Goes Here</span></b><br/> + You can return to the + <a href="${request.application_url}">FrontPage</a>.<br/> + </div> + <div id="right" class="app-welcome align-right"> + <span tal:condition="logged_in"> + <a href="${request.application_url}/logout">Logout</a> + </span> + </div> + </div> + </div> + <div id="bottom"> + <div class="bottom"> + <div tal:replace="structure content"> + Page text goes here. + </div> + <p> + <a tal:attributes="href edit_url" href=""> + Edit this page + </a> + </p> + </div> + </div> + </div> + <div id="footer"> + <div class="footer" + >© Copyright 2008-2011, Agendaless Consulting.</div> + </div> </body> </html> diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt index 712fd0737..d98420680 100644 --- a/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt @@ -1,75 +1,75 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>The Pyramid Web Application Development Framework</title> - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> - <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="${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]--> + <title>The Pyramid Web Application Development Framework</title> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> + <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="${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]--> </head> <body> - <div id="wrap"> - <div id="top"> - <div class="top align-center"> - <div><img src="${request.static_url('tutorial:static/pyramid.png')}" width="750" height="169" alt="pyramid"/></div> - </div> - </div> - <div id="middle"> - <div class="middle align-center"> - <p class="app-welcome"> - Welcome to <span class="app-name">${project}</span>, an application generated by<br/> - the Pyramid web application development framework. - </p> - </div> - </div> - <div id="bottom"> - <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"> - <input type="text" id="q" name="q" value="" /> - <input type="submit" id="x" value="Go" /> - </form> - </div> - <div id="right" class="align-left"> - <h2>Pyramid links</h2> - <ul class="links"> - <li> - <a href="http://pylonsproject.org">Pylons Website</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> - </li> - <li> - <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> - </li> - </ul> - </div> - </div> - </div> - </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> - </div> + <div id="wrap"> + <div id="top"> + <div class="top align-center"> + <div><img src="${request.static_url('tutorial:static/pyramid.png')}" width="750" height="169" alt="pyramid"/></div> + </div> + </div> + <div id="middle"> + <div class="middle align-center"> + <p class="app-welcome"> + Welcome to <span class="app-name">${project}</span>, an application generated by<br/> + the Pyramid web application development framework. + </p> + </div> + </div> + <div id="bottom"> + <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"> + <input type="text" id="q" name="q" value="" /> + <input type="submit" id="x" value="Go" /> + </form> + </div> + <div id="right" class="align-left"> + <h2>Pyramid links</h2> + <ul class="links"> + <li> + <a href="http://pylonsproject.org">Pylons Website</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> + </li> + <li> + <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> + </li> + </ul> + </div> + </div> + </div> + </div> + <div id="footer"> + <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> + </div> </body> </html> diff --git a/docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.pt index 712fd0737..d98420680 100644 --- a/docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.pt @@ -1,75 +1,75 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>The Pyramid Web Application Development Framework</title> - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> - <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="${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]--> + <title>The Pyramid Web Application Development Framework</title> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> + <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="${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]--> </head> <body> - <div id="wrap"> - <div id="top"> - <div class="top align-center"> - <div><img src="${request.static_url('tutorial:static/pyramid.png')}" width="750" height="169" alt="pyramid"/></div> - </div> - </div> - <div id="middle"> - <div class="middle align-center"> - <p class="app-welcome"> - Welcome to <span class="app-name">${project}</span>, an application generated by<br/> - the Pyramid web application development framework. - </p> - </div> - </div> - <div id="bottom"> - <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"> - <input type="text" id="q" name="q" value="" /> - <input type="submit" id="x" value="Go" /> - </form> - </div> - <div id="right" class="align-left"> - <h2>Pyramid links</h2> - <ul class="links"> - <li> - <a href="http://pylonsproject.org">Pylons Website</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> - </li> - <li> - <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> - </li> - </ul> - </div> - </div> - </div> - </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> - </div> + <div id="wrap"> + <div id="top"> + <div class="top align-center"> + <div><img src="${request.static_url('tutorial:static/pyramid.png')}" width="750" height="169" alt="pyramid"/></div> + </div> + </div> + <div id="middle"> + <div class="middle align-center"> + <p class="app-welcome"> + Welcome to <span class="app-name">${project}</span>, an application generated by<br/> + the Pyramid web application development framework. + </p> + </div> + </div> + <div id="bottom"> + <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"> + <input type="text" id="q" name="q" value="" /> + <input type="submit" id="x" value="Go" /> + </form> + </div> + <div id="right" class="align-left"> + <h2>Pyramid links</h2> + <ul class="links"> + <li> + <a href="http://pylonsproject.org">Pylons Website</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> + </li> + <li> + <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> + </li> + </ul> + </div> + </div> + </div> + </div> + <div id="footer"> + <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> + </div> </body> </html> diff --git a/docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt b/docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt index 3a7e26732..3f2039cb6 100644 --- a/docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt +++ b/docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt @@ -1,57 +1,58 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" - xmlns:tal="http://xml.zope.org/namespaces/tal"> + xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>${page.name} - Pyramid tutorial wiki (based on - TurboGears 20-Minute Wiki)</title> - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> - <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="${request.static_url('tutorial:static/pylons.css')}" - 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]--> + <title>${page.name} - Pyramid tutorial wiki (based on + TurboGears 20-Minute Wiki)</title> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> + <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="${request.static_url('tutorial:static/pylons.css')}" + 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]--> </head> <body> - <div id="wrap"> - <div id="top-small"> - <div class="top-small align-center"> - <div> - <img width="220" height="50" alt="pyramid" - src="${request.static_url('tutorial:static/pyramid-small.png')}" /> - </div> - </div> - </div> - <div id="middle"> - <div class="middle align-right"> - <div id="left" class="app-welcome align-left"> - Editing <b><span tal:replace="page.name">Page Name Goes - Here</span></b><br/> - You can return to the - <a href="${request.application_url}">FrontPage</a>.<br/> - </div> - <div id="right" class="app-welcome align-right"></div> - </div> - </div> - <div id="bottom"> - <div class="bottom"> - <form action="${save_url}" method="post"> - <textarea name="body" tal:content="page.data" rows="10" - cols="60"/><br/> - <input type="submit" name="form.submitted" value="Save"/> - </form> - </div> - </div> - </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> - </div> + <div id="wrap"> + <div id="top-small"> + <div class="top-small align-center"> + <div> + <img width="220" height="50" alt="pyramid" + src="${request.static_url('tutorial:static/pyramid-small.png')}" /> + </div> + </div> + </div> + <div id="middle"> + <div class="middle align-right"> + <div id="left" class="app-welcome align-left"> + Editing <b><span tal:replace="page.name">Page Name Goes + Here</span></b><br/> + You can return to the + <a href="${request.application_url}">FrontPage</a>.<br/> + </div> + <div id="right" class="app-welcome align-right"></div> + </div> + </div> + <div id="bottom"> + <div class="bottom"> + <form action="${save_url}" method="post"> + <textarea name="body" tal:content="page.data" rows="10" + cols="60"/><br/> + <input type="submit" name="form.submitted" value="Save"/> + </form> + </div> + </div> + </div> + <div id="footer"> + <div class="footer" + >© Copyright 2008-2011, Agendaless Consulting.</div> + </div> </body> </html> diff --git a/docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt index 712fd0737..d98420680 100644 --- a/docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt @@ -1,75 +1,75 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>The Pyramid Web Application Development Framework</title> - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> - <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="${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]--> + <title>The Pyramid Web Application Development Framework</title> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> + <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="${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]--> </head> <body> - <div id="wrap"> - <div id="top"> - <div class="top align-center"> - <div><img src="${request.static_url('tutorial:static/pyramid.png')}" width="750" height="169" alt="pyramid"/></div> - </div> - </div> - <div id="middle"> - <div class="middle align-center"> - <p class="app-welcome"> - Welcome to <span class="app-name">${project}</span>, an application generated by<br/> - the Pyramid web application development framework. - </p> - </div> - </div> - <div id="bottom"> - <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"> - <input type="text" id="q" name="q" value="" /> - <input type="submit" id="x" value="Go" /> - </form> - </div> - <div id="right" class="align-left"> - <h2>Pyramid links</h2> - <ul class="links"> - <li> - <a href="http://pylonsproject.org">Pylons Website</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> - </li> - <li> - <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> - </li> - <li> - <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> - </li> - </ul> - </div> - </div> - </div> - </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> - </div> + <div id="wrap"> + <div id="top"> + <div class="top align-center"> + <div><img src="${request.static_url('tutorial:static/pyramid.png')}" width="750" height="169" alt="pyramid"/></div> + </div> + </div> + <div id="middle"> + <div class="middle align-center"> + <p class="app-welcome"> + Welcome to <span class="app-name">${project}</span>, an application generated by<br/> + the Pyramid web application development framework. + </p> + </div> + </div> + <div id="bottom"> + <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"> + <input type="text" id="q" name="q" value="" /> + <input type="submit" id="x" value="Go" /> + </form> + </div> + <div id="right" class="align-left"> + <h2>Pyramid links</h2> + <ul class="links"> + <li> + <a href="http://pylonsproject.org">Pylons Website</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a> + </li> + <li> + <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a> + </li> + <li> + <a href="irc://irc.freenode.net#pyramid">IRC Channel</a> + </li> + </ul> + </div> + </div> + </div> + </div> + <div id="footer"> + <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> + </div> </body> </html> diff --git a/docs/tutorials/wiki2/src/views/tutorial/templates/view.pt b/docs/tutorials/wiki2/src/views/tutorial/templates/view.pt index ba74b4352..423c1d5a1 100644 --- a/docs/tutorials/wiki2/src/views/tutorial/templates/view.pt +++ b/docs/tutorials/wiki2/src/views/tutorial/templates/view.pt @@ -1,60 +1,61 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" - xmlns:tal="http://xml.zope.org/namespaces/tal"> + xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>${page.name} - Pyramid tutorial wiki (based on - TurboGears 20-Minute Wiki)</title> - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> - <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="${request.static_url('tutorial:static/pylons.css')}" - 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]--> + <title>${page.name} - Pyramid tutorial wiki (based on + TurboGears 20-Minute Wiki)</title> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> + <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="${request.static_url('tutorial:static/pylons.css')}" + 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]--> </head> <body> - <div id="wrap"> - <div id="top-small"> - <div class="top-small align-center"> - <div> - <img width="220" height="50" alt="pyramid" - src="${request.static_url('tutorial:static/pyramid-small.png')}" /> - </div> - </div> - </div> - <div id="middle"> - <div class="middle align-right"> - <div id="left" class="app-welcome align-left"> - Viewing <b><span tal:replace="page.name">Page Name - Goes Here</span></b><br/> - You can return to the - <a href="${request.application_url}">FrontPage</a>.<br/> - </div> - <div id="right" class="app-welcome align-right"></div> - </div> - </div> - <div id="bottom"> - <div class="bottom"> - <div tal:replace="structure content"> - Page text goes here. - </div> - <p> - <a tal:attributes="href edit_url" href=""> - Edit this page - </a> - </p> - </div> - </div> - </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> - </div> + <div id="wrap"> + <div id="top-small"> + <div class="top-small align-center"> + <div> + <img width="220" height="50" alt="pyramid" + src="${request.static_url('tutorial:static/pyramid-small.png')}" /> + </div> + </div> + </div> + <div id="middle"> + <div class="middle align-right"> + <div id="left" class="app-welcome align-left"> + Viewing <b><span tal:replace="page.name">Page Name + Goes Here</span></b><br/> + You can return to the + <a href="${request.application_url}">FrontPage</a>.<br/> + </div> + <div id="right" class="app-welcome align-right"></div> + </div> + </div> + <div id="bottom"> + <div class="bottom"> + <div tal:replace="structure content"> + Page text goes here. + </div> + <p> + <a tal:attributes="href edit_url" href=""> + Edit this page + </a> + </p> + </div> + </div> + </div> + <div id="footer"> + <div class="footer" + >© Copyright 2008-2011, Agendaless Consulting.</div> + </div> </body> </html> diff --git a/docs/tutorials/zeo/index.rst b/docs/tutorials/zeo/index.rst deleted file mode 100644 index b47c6c477..000000000 --- a/docs/tutorials/zeo/index.rst +++ /dev/null @@ -1,238 +0,0 @@ -.. _zodb_with_zeo: - -Using ZODB with ZEO -=================== - -:term:`ZODB` is a Python object persistence mechanism. :term:`ZODB` -works well as a storage mechanism for :app:`Pyramid` applications, -especially in applications that use :term:`traversal`. - -:term:`ZEO` is an extension to ZODB which allows more than one process -to simultaneously communicate with a ZODB storage. Making a ZODB -database accessible to more than one process means that you can debug -your application objects at the same time that a :app:`Pyramid` -server that accesses the database is running, and will also allow your -application to run under multiprocess configurations, such as those -exposed by :term:`mod_wsgi`. - -The easiest way to get started with ZODB in a :app:`Pyramid` application is -to use the ZODB ``pyramid_zodb`` paster template. See -:ref:`additional_paster_templates` for more information about using this -template. However, the Paster template does not set up a ZEO-capable -application. This chapter shows you how to do that "from scratch". - -Installing Dependencies ------------------------ - -#. Edit your :app:`Pyramid` application's ``setup.py`` file, adding - the following packages to the ``install_requires`` of the - application: - - - ``repoze.folder`` - - - ``repoze.retry`` - - - ``repoze.tm2`` - - - ``repoze.zodbconn`` - - For example, the relevant portion of your application's - ``setup.py`` file might look like so when you're finished adding - the dependencies. - - .. code-block:: python - :linenos: - - setup( - # ... other elements left out for brevity - install_requires=[ - 'pyramid', - 'repoze.folder', - 'repoze.retry', - 'repoze.tm2', - 'repoze.zodbconn', - ], - # ... other elements left out for brevity - ) - -#. Rerun your application's ``setup.py`` file (e.g. using ``python - setup.py develop``) to get these packages installed. A number of - packages will be installed, including ``ZODB``. For the purposes - of this tutorial, we'll assume that your "application" is actually - just the result of the ``pyramid_starter`` Paster template. - -Configuration -------------- - -#. Edit your application's Paste ``development.ini`` file. - - If you already have an ``app`` section in the ``.ini`` file named - ``main``, rename this section to ``myapp`` (e.g. ``app:main`` -> - ``app:myapp``). Add a key to it named ``zodb_uri``, e.g. - - .. code-block:: ini - - [app:myapp] - use = egg:myapp#app - zodb_uri = zeo://%(here)s/zeo.sock - reload_templates = true - debug_authorization = false - debug_notfound = false - - If a ``pipeline`` named ``main`` does not already exist in the - paste ``.ini`` file , add a ``pipeline`` section named ``main``. - Put the names ``connector``, ``egg:repoze.retry#retry``, and - ``egg:repoze.tm2#tm`` to the top of the pipeline. - - .. code-block:: ini - - [pipeline:main] - pipeline = - egg:repoze.retry#retry - egg:repoze.tm2#tm - myapp - - When you're finished, your ``.ini`` file might look like so: - - .. code-block:: ini - - [DEFAULT] - debug = true - - [app:myapp] - use = egg:myapp#app - zodb_uri = zeo://%(here)s/zeo.sock - reload_templates = true - debug_authorization = false - debug_notfound = false - - [pipeline:main] - pipeline = - egg:repoze.retry#retry - egg:repoze.tm2#tm - myapp - - [server:main] - use = egg:Paste#http - host = 0.0.0.0 - port = 6543 - - See :ref:`MyProject_ini` for more information about project Paste - ``.ini`` files. - -#. Add a ``zeo.conf`` file to your package with the following - contents: - - .. code-block:: text - - %define INSTANCE . - - <zeo> - address $INSTANCE/zeo.sock - read-only false - invalidation-queue-size 100 - pid-filename $INSTANCE/zeo.pid - </zeo> - - <blobstorage 1> - <filestorage> - path $INSTANCE/myapp.db - </filestorage> - blob-dir $INSTANCE/blobs - </blobstorage> - -#. For the purposes of this tutorial we'll assume that you want your - :app:`Pyramid` application's :term:`root` object to be a - "folderish" object. To achieve this, change your application's - ``models.py`` file to look like the below: - - .. code-block:: python - - from repoze.folder import Folder - - class MyModel(Folder): - pass - - def appmaker(root): - if not 'myapp' in root: - root['myapp'] = MyModel() - transaction.commit() - return root['myapp'] - -#. Change your application's ``__init__.py`` to look something like the - below: - - .. code-block:: python - - from pyramid.config import Configurator - from repoze.zodbconn.finder import PersistentApplicationFinder - from myapp.models import appmaker - import transaction - - def app(global_config, **settings): - """ This function returns a ``pyramid`` WSGI - application. - - It is usually called by the PasteDeploy framework during - ``paster serve``""" - # paster app config callback - zodb_uri = settings['zodb_uri'] - finder = PersistentApplicationFinder(zodb_uri, appmaker) - def get_root(request): - return finder(request.environ) - config = Configurator(root_factory=get_root, settings=settings) - # .. other configuration statements .. - return config.make_wsgi_app() - -Running -------- - -#. Start the ZEO server in a terminal with the current directory set - to the package directory: - - .. code-block:: text - - ../bin/runzeo -C zeo.conf - - You should see something like this, as a result: - - .. code-block:: text - :linenos: - - [chrism@snowpro myapp]$ ../bin/runzeo -C zeo.conf - ------ - 2009-09-19T13:48:41 INFO ZEO.runzeo (9910) created PID file './zeo.pid' - # ... more output ... - 2009-09-19T13:48:41 INFO ZEO.zrpc (9910) listening on ./zeo.sock - -#. While the ZEO server is running, start the application server: - - .. code-block:: text - :linenos: - - [chrism@snowpro myapp]$ ../bin/paster serve myapp.ini - Starting server in PID 10177. - serving on 0.0.0.0:6543 view at http://127.0.0.1:6543 - -#. The root object is now a "folderish" ZODB object. Nothing else - about the application has changed. - -#. You can manipulate the database directly (even when the - application's HTTP server is running) by using the ``pshell`` - command in a third terminal window: - - .. code-block:: text - :linenos: - - [chrism@snowpro sess]$ ../bin/paster --plugin=pyramid pshell \ - myapp.ini myapp - Python 2.5.4 (r254:67916, Sep 4 2009, 02:12:16) - [GCC 4.2.1 (Apple Inc. build 5646)] on darwin - Type "help" for more information. "root" is the Pyramid app root object. - >>> root - <sess.models.MyModel object None at 0x16438f0> - >>> root.foo = 'bar' - >>> import transaction - >>> transaction.commit() - - diff --git a/docs/whatsnew-1.0.rst b/docs/whatsnew-1.0.rst index 91253b29b..4a41840eb 100644 --- a/docs/whatsnew-1.0.rst +++ b/docs/whatsnew-1.0.rst @@ -151,7 +151,7 @@ Terminology Changes - All documentation which previously referred to "model" now refers to "resource". -- The ``starter`` paster template now has a resources.py`` module instead +- The ``starter`` paster template now has a ``resources.py`` module instead of a ``models.py`` module. - Positional argument names of various APIs have been changed from @@ -561,5 +561,17 @@ Documentation Enhancements - The (weak) "Converting a CMF Application to Pyramid" tutorial has been removed from the tutorials section. It was moved to the - ``pyramid_tutorials`` Github repository. + ``pyramid_tutorials`` Github repository at + http://docs.pylonsproject.org/projects/pyramid_tutorials/dev/. + +- Moved "Using ZODB With ZEO" and "Using repoze.catalog Within Pyramid" + tutorials out of core documentation and into the Pyramid Tutorials site + (http://docs.pylonsproject.org/projects/pyramid_tutorials/dev/). + +- Removed API documentation for deprecated ``pyramid.testing`` APIs named + ``registerDummySecurityPolicy``, ``registerResources``, ``registerModels``, + ``registerEventListener``, ``registerTemplateRenderer``, + ``registerDummyRenderer``, ``registerView``, ``registerUtility``, + ``registerAdapter``, ``registerSubscriber``, ``registerRoute``, and + ``registerSettings``. |
