diff options
| author | Chris McDonough <chrism@plope.com> | 2013-04-03 17:37:21 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2013-04-03 17:37:21 -0400 |
| commit | d64fa6136d0dec6717b273362de548d8f3bf47e8 (patch) | |
| tree | 23c77ac62ab9d6c93131874f835ae3166d4af53b | |
| parent | 2ca9bde9d2862655ddee276cd14a375e6a5adec6 (diff) | |
| parent | 84e455cf7c8d9cbfe6658548a61af2ecbbc1749e (diff) | |
| download | pyramid-d64fa6136d0dec6717b273362de548d8f3bf47e8.tar.gz pyramid-d64fa6136d0dec6717b273362de548d8f3bf47e8.tar.bz2 pyramid-d64fa6136d0dec6717b273362de548d8f3bf47e8.zip | |
Merge branch 'master' of github.com:Pylons/pyramid
78 files changed, 514 insertions, 422 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 6ff54884a..08e498b7a 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -21,6 +21,14 @@ Features define how to properly handle IPv6. See https://github.com/Pylons/pyramid/issues/831. +- Make it possible to use variable arguments via + ``pyramid.paster.get_appsettings``. This also allowed the generated + ``initialize_db`` script from the ``alchemy`` scaffold to grow support + for options in the form ``a=1 b=2`` so you can fill in + values in a parameterized ``.ini`` file, e.g. + ``initialize_myapp_db etc/development.ini a=1 b=2``. + See https://github.com/Pylons/pyramid/pull/911 + Bug Fixes --------- @@ -70,6 +78,15 @@ Bug Fixes methods. Now the views are found and no predicate mismatch is raised. +- Spaces and dots may now be in mako renderer template paths. This was + broken when support for the new makodef syntax was added in 1.4a1. + See https://github.com/Pylons/pyramid/issues/950 + +- ``pyramid.debug_authorization=true`` will now correctly print out + ``Allowed`` for views registered with ``NO_PERMISSION_REQUIRED`` instead + of invoking the ``permits`` method of the authorization policy. + See https://github.com/Pylons/pyramid/issues/954 + 1.4 (2012-12-18) ================ diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 02fb81528..97eb54f7b 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -194,3 +194,7 @@ Contributors - John Anderson, 2012/11/14 - Bert JW Regeer, 2013/02/01 + +- Georges Dubus, 2013/03/21 + +- Jason McKellar, 2013/03/28 diff --git a/docs/api/paster.rst b/docs/api/paster.rst index bde128e05..edc3738fc 100644 --- a/docs/api/paster.rst +++ b/docs/api/paster.rst @@ -9,6 +9,6 @@ .. autofunction:: get_app(config_uri, name=None, options=None) - .. autofunction:: get_appsettings(config_uri, name=None) + .. autofunction:: get_appsettings(config_uri, name=None, options=None) .. autofunction:: setup_logging(config_uri) diff --git a/docs/conf.py b/docs/conf.py index 8d22d4d42..1ddcae08e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -55,14 +55,21 @@ extensions = [ # Looks for objects in external projects intersphinx_mapping = { - 'who': ('http://docs.repoze.org/who/2.0', None), - 'python': ('http://docs.python.org', None), - 'python3': ('http://docs.python.org/3', None), - 'tstring': + 'zcomponent': ('http://docs.zope.org/zope.component', None), + 'webtest': ('http://webtest.pythonpaste.org/en/latest', None), + 'webob': ('http://docs.webob.org/en/latest', None), + 'sqla': ('http://docs.sqlalchemy.org/en/latest', None), + 'who': ('http://docs.repoze.org/who/latest', None), + 'python': ('http://docs.python.org', None), + 'python3': ('http://docs.python.org/3', None), + 'tstring': ('http://docs.pylonsproject.org/projects/translationstring/en/latest', None), - 'venusian': + 'venusian': ('http://docs.pylonsproject.org/projects/venusian/en/latest', None), + 'toolbar': + ('http://docs.pylonsproject.org/projects/pyramid_debugtoolbar/en/latest', + None), } # Add any paths that contain templates here, relative to this directory. diff --git a/docs/conventions.rst b/docs/conventions.rst index 4cffd1084..21b506623 100644 --- a/docs/conventions.rst +++ b/docs/conventions.rst @@ -91,3 +91,24 @@ discussed on a page, is rendered like so: Sidebar information. +When multiple objects are imported from the same package, +the following convention is used: + + .. code-block:: python + + from foo import ( + bar, + baz, + ) + +It may look unusual, but it has advantages: + +* It allows one to swap out the higher-level package ``foo`` for something + else that provides the similar API. An example would be swapping out + one Database for another (e.g. graduating from SQLite to PostgreSQL). + +* Looks more neat in cases where a large number of objects get imported from + that package. + +* Adding/removing imported objects from the package is quicker and results + in simpler diffs. diff --git a/docs/designdefense.rst b/docs/designdefense.rst index 749c9b099..7bc37ac06 100644 --- a/docs/designdefense.rst +++ b/docs/designdefense.rst @@ -120,7 +120,6 @@ that uses the ZCA global API is somewhat high. Consider a ZCA neophyte reading the code that performs a typical "unnamed utility" lookup using the :func:`zope.component.getUtility` global API: -.. ignore-next-block .. code-block:: python :linenos: @@ -190,7 +189,6 @@ special-purpose API functions that *do* use ZCA APIs. Take for example the present in the current request or ``None`` if no userid is present in the current request. The application developer calls it like so: -.. ignore-next-block .. code-block:: python :linenos: @@ -500,7 +498,6 @@ which match information in an associated "urlconf" such as Zope, likewise allows you to add arbitrary keyword and positional arguments to any method of a resource object found via traversal: -.. ignore-next-block .. code-block:: python :linenos: diff --git a/docs/glossary.rst b/docs/glossary.rst index 40c15efdc..241f951d6 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -314,7 +314,7 @@ Glossary pipeline The :term:`PasteDeploy` term for a single configuration of a WSGI - server, a WSGI application, with a set of middleware in-between. + server, a WSGI application, with a set of :term:`middleware` in-between. Zope `The Z Object Publishing Framework <http://zope.org>`_, a @@ -334,12 +334,6 @@ Glossary `Zope Object Database <http://zodb.org>`_, a persistent Python object store. - ZEO - `Zope Enterprise Objects - <http://www.zope.org/Documentation/Books/ZopeBook/2_6Edition/ZEO.stx>`_ - allows multiple simultaneous processes to access a single - :term:`ZODB` database. - WebOb `WebOb <http://webob.org>`_ is a WSGI request/response library created by Ian Bicking. @@ -907,9 +901,9 @@ Glossary The scaffold has been retired but the demo plays a similar role. Pyramid Cookbook - An additional documentation resource for Pyramid which presents topical, - practical usages of Pyramid available via - http://docs.pylonsproject.org/ . + Additional documentation for Pyramid which presents topical, + practical uses of Pyramid: + http://docs.pylonsproject.org/projects/pyramid_cookbook/en/latest. distutils The standard system for packaging and distributing Python packages. See @@ -932,18 +926,18 @@ Glossary provide, for example, Pyramid-specific view timing support, bookkeeping code that examines exceptions before they are returned to the upstream WSGI application, or a variety of other features. Tweens behave a bit - like :term:`WSGI` 'middleware' but they have the benefit of running in a + like :term:`WSGI` :term:`middleware` but they have the benefit of running in a context in which they have access to the Pyramid :term:`application registry` as well as the Pyramid rendering machinery. See :ref:`registering_tweens`. pyramid_debugtoolbar - A Pyramid add on which displays a helpful debug toolbar "on top of" HTML + A Pyramid add-on which displays a helpful debug toolbar "on top of" HTML pages rendered by your application, displaying request, routing, and database information. :mod:`pyramid_debugtoolbar` is configured into the ``development.ini`` of all applications which use a Pyramid :term:`scaffold`. For more information, see - http://docs.pylonsproject.org/projects/pyramid_debugtoolbar/dev/ . + http://docs.pylonsproject.org/projects/pyramid_debugtoolbar/en/latest/. scaffold A project template that generates some of the major parts of a Pyramid diff --git a/docs/narr/assets.rst b/docs/narr/assets.rst index deaf0ce08..09a2b83f2 100644 --- a/docs/narr/assets.rst +++ b/docs/narr/assets.rst @@ -50,7 +50,6 @@ application might address the asset using the :term:`asset specification` ``myapp:templates/some_template.pt`` using that API within a ``views.py`` file inside a ``myapp`` package: -.. ignore-next-block .. code-block:: python :linenos: @@ -120,7 +119,7 @@ from the ``/var/www/static`` directory of the computer which runs the # config is an instance of pyramid.config.Configurator config.add_static_view(name='static', path='/var/www/static') -The ``name`` prepresents a URL *prefix*. In order for files that live in the +The ``name`` represents a URL *prefix*. In order for files that live in the ``path`` directory to be served, a URL that requests one of them must begin with that prefix. In the example above, ``name`` is ``static``, and ``path`` is ``/var/www/static``. In English, this means that you wish to serve the @@ -331,7 +330,6 @@ root that exists at the end of your routing table, create an instance of the :class:`~pyramid.static.static_view` class inside a ``static.py`` file in your application root as below. -.. ignore-next-block .. code-block:: python :linenos: @@ -458,7 +456,6 @@ The ``override_asset`` API An individual call to :meth:`~pyramid.config.Configurator.override_asset` can override a single asset. For example: -.. ignore-next-block .. code-block:: python :linenos: @@ -473,7 +470,6 @@ colon separator in a specification separates the *package name* from the are not specified, the override attempts to resolve every lookup into a package from the directory of another package. For example: -.. ignore-next-block .. code-block:: python :linenos: @@ -482,7 +478,6 @@ package from the directory of another package. For example: Individual subdirectories within a package can also be overridden: -.. ignore-next-block .. code-block:: python :linenos: @@ -511,7 +506,6 @@ construction file resides (or the ``package`` argument to the :class:`~pyramid.config.Configurator` class construction). For example: -.. ignore-next-block .. code-block:: python :linenos: diff --git a/docs/narr/commandline.rst b/docs/narr/commandline.rst index 07c892439..e1347f3ca 100644 --- a/docs/narr/commandline.rst +++ b/docs/narr/commandline.rst @@ -172,8 +172,8 @@ name ``main`` as a section name: The WSGI application that is loaded will be available in the shell as the ``app`` global. Also, if the application that is loaded is the :app:`Pyramid` -app with no surrounding middleware, the ``root`` object returned by the -default :term:`root factory`, ``registry``, and ``request`` will be +app with no surrounding :term:`middleware`, the ``root`` object returned by +the default :term:`root factory`, ``registry``, and ``request`` will be available. You can also simply rely on the ``main`` default section name by omitting any @@ -572,8 +572,8 @@ configuration implied by the ``[pipeline:main]`` section of your configuration file by default. Specifying ``/path/to/my/development.ini`` is logically equivalent to specifying ``/path/to/my/development.ini#main``. In this case, we'll be using a configuration that includes an ``app`` object -which is wrapped in the Paste "translogger" middleware (which logs requests -to the console). +which is wrapped in the Paste "translogger" :term:`middleware` (which logs +requests to the console). You can also specify a particular *section* of the PasteDeploy ``.ini`` file to load instead of ``main``: diff --git a/docs/narr/configuration.rst b/docs/narr/configuration.rst index 6f82baf32..f7a69d613 100644 --- a/docs/narr/configuration.rst +++ b/docs/narr/configuration.rst @@ -140,7 +140,6 @@ In the example above, the scanner translates the arguments to :class:`~pyramid.view.view_config` into a call to the :meth:`pyramid.config.Configurator.add_view` method, effectively: -.. ignore-next-block .. code-block:: python config.add_view(hello) diff --git a/docs/narr/extending.rst b/docs/narr/extending.rst index beece7640..a60a49fea 100644 --- a/docs/narr/extending.rst +++ b/docs/narr/extending.rst @@ -50,7 +50,7 @@ layers are apt to provide the necessary "opinions" (such as mandating a storage layer, a templating system, and a structured, well-documented pattern of registering that certain URLs map to certain bits of code) which makes the concept of a "pluggable application" possible. "Pluggable applications", -thus, should not plug in to Pyramid itself but should instead plug into a +thus, should not plug into Pyramid itself but should instead plug into a system written atop Pyramid. Although it does not provide for "pluggable applications", Pyramid *does* @@ -209,7 +209,7 @@ like this: - Wire the new views and assets created in the new package up using imperative registrations within the ``main`` function of the - ``__init__.py`` file of the new application. These wiring should happen + ``__init__.py`` file of the new application. This wiring should happen *after* including the configuration functions of the old application. These registrations will extend or override any registrations performed by the original application. See :ref:`overriding_views`, diff --git a/docs/narr/firstapp.rst b/docs/narr/firstapp.rst index 6d3786d8e..e73ef66ac 100644 --- a/docs/narr/firstapp.rst +++ b/docs/narr/firstapp.rst @@ -166,7 +166,6 @@ the application. Adding Configuration ~~~~~~~~~~~~~~~~~~~~ -.. ignore-next-block .. literalinclude:: helloworld.py :linenos: :lines: 11-12 @@ -186,7 +185,6 @@ The second line registers the ``hello_world`` function as a WSGI Application Creation ~~~~~~~~~~~~~~~~~~~~~~~~~ -.. ignore-next-block .. literalinclude:: helloworld.py :linenos: :lines: 13 @@ -215,7 +213,6 @@ to its ``add_view`` and ``add_route`` methods. WSGI Application Serving ~~~~~~~~~~~~~~~~~~~~~~~~ -.. ignore-next-block .. literalinclude:: helloworld.py :linenos: :lines: 14-15 diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index 330eb0cd3..a3de23baa 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -109,9 +109,8 @@ callable: instance of the :exc:`~pyramid.httpexceptions.HTTPNotFound` exception that caused the Not Found View to be called. The value of ``request.exception.message`` will be a value explaining why the Not Found - error was raised. This message will be different when the - ``pyramid.debug_notfound`` environment setting is true than it is when it - is false. + error was raised. This message has different values depending whether the + ``pyramid.debug_notfound`` environment setting is true or false. .. note:: @@ -208,9 +207,9 @@ Here's some sample code that implements a minimal forbidden view: that caused the forbidden view to be called. The value of ``request.exception.message`` will be a value explaining why the forbidden was raised and ``request.exception.result`` will be extended information - about the forbidden exception. These messages will be different when the - ``pyramid.debug_authorization`` environment setting is true than it is when - it is false. + about the forbidden exception. These messages have different values + depending whether the ``pyramid.debug_authorization`` environment setting + is true or false. .. index:: single: request factory @@ -694,7 +693,7 @@ represents the type of interface that must be possessed by the resource for this resource url factory to be found. If the ``resource_iface`` argument is omitted, this resource url adapter will be used for *all* resources. -The API that must be implemented by your a class that provides +The API that must be implemented by a class that provides :class:`~pyramid.interfaces.IResourceURL` is as follows: .. code-block:: python @@ -1036,7 +1035,7 @@ upstream WSGI component that uses :app:`Pyramid` as its "app". This is a feature that may be used by Pyramid framework extensions, to provide, for example, Pyramid-specific view timing support bookkeeping code that examines exceptions before they are returned to the upstream WSGI application. Tweens -behave a bit like :term:`WSGI` middleware but they have the benefit of +behave a bit like :term:`WSGI` :term:`middleware` but they have the benefit of running in a context in which they have access to the Pyramid :term:`application registry` as well as the Pyramid rendering machinery. @@ -1110,8 +1109,8 @@ Once you've created a tween factory, you can register it into the implicit tween chain using the :meth:`pyramid.config.Configurator.add_tween` method using its :term:`dotted Python name`. -Here's an example of registering the a tween factory as an "implicit" -tween in a Pyramid application: +Here's an example of registering a tween factory as an "implicit" tween in a +Pyramid application: .. code-block:: python :linenos: @@ -1447,7 +1446,7 @@ view/route predicate: subscriber predicates will assume a certain event type. Here's an example of a subscriber predicate that can be used in conjunction -with a subscriber that subscribes to the :class:`pyramid.events.NewReqest` +with a subscriber that subscribes to the :class:`pyramid.events.NewRequest` event type. .. code-block:: python diff --git a/docs/narr/install.rst b/docs/narr/install.rst index 9bc62dc62..8fc63f3a4 100644 --- a/docs/narr/install.rst +++ b/docs/narr/install.rst @@ -19,13 +19,32 @@ run :app:`Pyramid`. run under any version of Python before 2.6. :app:`Pyramid` is known to run on all popular UNIX-like systems such as -Linux, MacOS X, and FreeBSD as well as on Windows platforms. It is also -known to run on :term:`PyPy` (1.9+). +Linux, Mac OS X, and FreeBSD as well as on Windows platforms. It is +also known to run on :term:`PyPy` (1.9+). :app:`Pyramid` installation does not require the compilation of any C code, so you need only a Python interpreter that meets the requirements mentioned. +For Mac OS X Users +~~~~~~~~~~~~~~~~~~ + +From `Python.org <http://python.org/download/mac/>`_: + + Python comes pre-installed on Mac OS X, but due to Apple's release + cycle, it's often one or even two years old. The overwhelming + recommendation of the "MacPython" community is to upgrade your + Python by downloading and installing a newer version from + `the Python standard release page <http://python.org/download/releases/>`_. + +It is recommended to download one of the *installer* versions, unless you prefer to install your Python through a packgage manager (e.g., macports or homebrew) or to build your Python from source. + +Unless you have a need for a specific earlier version, it is recommended +to install the latest 2.x or 3.x version of Python. + +If you use an installer for your Python, then you can skip to the +section :ref:`installing_unix`. + If You Don't Yet Have A Python Interpreter (UNIX) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -322,8 +341,8 @@ for both versions are included below. Windows Using Python 2 ~~~~~~~~~~~~~~~~~~~~~~ -#. Install, or find `Python 2.7 - <http://www.python.org/download/releases/2.7.3/>`_ for your system. +#. Install the most recent `Python 2.7.x version + <http://www.python.org/download/>`_ for your system. #. Install the `Python for Windows extensions <http://sourceforge.net/projects/pywin32/files/>`_. Make sure to @@ -371,36 +390,47 @@ Windows Using Python 2 Windows Using Python 3 ~~~~~~~~~~~~~~~~~~~~~~ -#. Install, or find `Python 3.2 - <http://www.python.org/download/releases/3.2.3/>`_ for your system. +#. Install, or find the latest version of `Python 3.x + <http://www.python.org/download/>`_ for your system and which is + supported by Pyramid. #. Install the `Python for Windows extensions <http://sourceforge.net/projects/pywin32/files/>`_. Make sure to - pick the right download for Python 3.2 and install it using the + pick the right download for Python 3.x and install it using the same Python installation from the previous step. #. Install latest :term:`distribute` distribution into the Python you obtained/installed/found in the step above: download `distribute_setup.py <http://python-distribute.org/distribute_setup.py>`_ and run it using the - ``python`` interpreter of your Python 3.2 installation using a command + ``python`` interpreter of your Python 3.x installation using a command prompt: .. code-block:: text + # modify the command according to the python version, e.g.: + # for Python 3.2.x: c:\> c:\Python32\python distribute_setup.py + # for Python 3.3.x: + c:\> c:\Python33\python distribute_setup.py #. Install :term:`virtualenv`: .. code-block:: text + # for Python 3.2.x: c:\> c:\Python32\Scripts\easy_install virtualenv + # for Python 3.3.x: + c:\> c:\Python33\Scripts\easy_install virtualenv #. Make a :term:`virtualenv` workspace: .. code-block:: text c:\> set VENV=c:\env + # for Python 3.2.x: c:\> c:\Python32\Scripts\virtualenv --no-site-packages %VENV% + # for Python 3.3.x: + c:\> c:\Python33\Scripts\virtualenv --no-site-packages %VENV% You can either follow the use of the environment variable, ``%VENV%``, or replace it with the root directory of the :term:`virtualenv`. diff --git a/docs/narr/introduction.rst b/docs/narr/introduction.rst index f9c25c69c..48164d323 100644 --- a/docs/narr/introduction.rst +++ b/docs/narr/introduction.rst @@ -600,10 +600,10 @@ Examples: :ref:`hello_traversal_chapter` and Tweens ~~~~~~ -Pyramid has a sort of internal WSGI-middleware-ish pipeline that can be -hooked by arbitrary add-ons named "tweens". The debug toolbar is a "tween", -and the ``pyramid_tm`` transaction manager is also. Tweens are more useful -than WSGI middleware in some circumstances because they run in the context of +Pyramid has a sort of internal WSGI-middleware-ish pipeline that can be hooked +by arbitrary add-ons named "tweens". The debug toolbar is a "tween", and the +``pyramid_tm`` transaction manager is also. Tweens are more useful than WSGI +:term:`middleware` in some circumstances because they run in the context of Pyramid itself, meaning you have access to templates and other renderers, a "real" request object, and other niceties. diff --git a/docs/narr/logging.rst b/docs/narr/logging.rst index 3b903be4d..b3bfb8a1e 100644 --- a/docs/narr/logging.rst +++ b/docs/narr/logging.rst @@ -298,14 +298,14 @@ Request Logging with Paste's TransLogger ---------------------------------------- Paste provides the `TransLogger -<http://pythonpaste.org/modules/translogger.html>`_ middleware for logging -requests using the `Apache Combined Log Format +<http://pythonpaste.org/modules/translogger.html>`_ :term:`middleware` for +logging requests using the `Apache Combined Log Format <http://httpd.apache.org/docs/2.2/logs.html#combined>`_. TransLogger combined with a FileHandler can be used to create an ``access.log`` file similar to Apache's. -Like any standard middleware with a Paste entry point, TransLogger can be -configured to wrap your application using ``.ini`` file syntax. First, +Like any standard :term:`middleware` with a Paste entry point, TransLogger can +be configured to wrap your application using ``.ini`` file syntax. First, rename your Pyramid ``.ini`` file's ``[app:main]`` section to ``[app:mypyramidapp]``, then add a ``[filter:translogger]`` section, then use a ``[pipeline:main]`` section file to form a WSGI pipeline with both the diff --git a/docs/narr/muchadoabouttraversal.rst b/docs/narr/muchadoabouttraversal.rst index 40d498391..483b1bb16 100644 --- a/docs/narr/muchadoabouttraversal.rst +++ b/docs/narr/muchadoabouttraversal.rst @@ -168,18 +168,12 @@ hood, when ``adict`` is a dictionary-like object, Python translates ``adict['a']`` to ``adict.__getitem__('a')``. Try doing this in a Python interpreter prompt if you don't believe us: -.. code-block:: text - :linenos: - - Python 2.4.6 (#2, Apr 29 2010, 00:31:48) - [GCC 4.4.3] on linux2 - Type "help", "copyright", "credits" or "license" for more information. - >>> adict = {} - >>> adict['a'] = 1 - >>> adict['a'] - 1 - >>> adict.__getitem__('a') - 1 +>>> adict = {} +>>> adict['a'] = 1 +>>> adict['a'] +1 +>>> adict.__getitem__('a') +1 The dictionary-like root object stores the ids of all of its subresources as diff --git a/docs/narr/project.rst b/docs/narr/project.rst index a168c24eb..9d69a65a5 100644 --- a/docs/narr/project.rst +++ b/docs/narr/project.rst @@ -416,7 +416,7 @@ If you don't see the debug toolbar image on the right hand top of the page, it means you're browsing from a system that does not have debugging access. By default, for security reasons, only a browser originating from ``localhost`` (``127.0.0.1``) can see the debug toolbar. To allow your -browser on a remote system to access the server, add the a line within the +browser on a remote system to access the server, add a line within the ``[app:main]`` section of the ``development.ini`` file in the form ``debugtoolbar.hosts = X.X.X.X``. For example, if your Pyramid application is running on a remote system, and you're browsing from a host with the IP diff --git a/docs/narr/renderers.rst b/docs/narr/renderers.rst index 08ebd881e..b4eb95186 100644 --- a/docs/narr/renderers.rst +++ b/docs/narr/renderers.rst @@ -362,7 +362,7 @@ For example (Javascript): jqhxr = $.getJSON(api_url); The string ``callback=?`` above in the ``url`` param to the JQuery -``getAjax`` function indicates to jQuery that the query should be made as +``getJSON`` function indicates to jQuery that the query should be made as a JSONP request; the ``callback`` parameter will be automatically filled in for you and used. @@ -720,7 +720,7 @@ factory, which expects to be passed a filesystem path: Adding the above code to your application startup will allow you to use the ``my.package.MyJinja2Renderer`` renderer factory implementation in view -configurations by referring to any ``renderer`` which *ends in* ``.jinja`` in +configurations by referring to any ``renderer`` which *ends in* ``.jinja2`` in the ``renderer`` attribute of a :term:`view configuration`: .. code-block:: python diff --git a/docs/narr/router.rst b/docs/narr/router.rst index b78362066..ac3deefdc 100644 --- a/docs/narr/router.rst +++ b/docs/narr/router.rst @@ -46,7 +46,7 @@ request enters a :app:`Pyramid` application through to the point that :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 used to generate the + associated ``factory`` argument, this factory is used to generate the root object, otherwise a default :term:`root factory` is used. #. If a route match was *not* found, and a ``root_factory`` argument was diff --git a/docs/narr/security.rst b/docs/narr/security.rst index 203aa2404..e91e8c542 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -85,7 +85,6 @@ during application setup to specify the authentication policy. For example: -.. ignore-next-block .. code-block:: python :linenos: @@ -151,7 +150,6 @@ API: The equivalent view registration including the ``add`` permission name may be performed via the ``@view_config`` decorator: -.. ignore-next-block .. code-block:: python :linenos: diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index fa4affd8a..c4f4b5f07 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -252,25 +252,19 @@ that were added to the flash queue, and empties the queue. .. method:: pop_flash(queue='') -.. code-block:: python - :linenos: - - >>> request.session.flash('info message') - >>> request.session.pop_flash() - ['info message'] +>>> request.session.flash('info message') +>>> request.session.pop_flash() +['info message'] Calling ``session.pop_flash()`` again like above without a corresponding call to ``session.flash()`` will return an empty list, because the queue has already been popped. -.. code-block:: python - :linenos: - - >>> request.session.flash('info message') - >>> request.session.pop_flash() - ['info message'] - >>> request.session.pop_flash() - [] +>>> request.session.flash('info message') +>>> request.session.pop_flash() +['info message'] +>>> request.session.pop_flash() +[] .. index:: single: session.peek_flash @@ -285,18 +279,15 @@ popped from flash storage. .. method:: peek_flash(queue='') -.. code-block:: python - :linenos: - - >>> request.session.flash('info message') - >>> request.session.peek_flash() - ['info message'] - >>> request.session.peek_flash() - ['info message'] - >>> request.session.pop_flash() - ['info message'] - >>> request.session.peek_flash() - [] +>>> request.session.flash('info message') +>>> request.session.peek_flash() +['info message'] +>>> request.session.peek_flash() +['info message'] +>>> request.session.pop_flash() +['info message'] +>>> request.session.peek_flash() +[] .. index:: single: preventing cross-site request forgery attacks diff --git a/docs/narr/startup.rst b/docs/narr/startup.rst index 3a9225032..1affa1758 100644 --- a/docs/narr/startup.rst +++ b/docs/narr/startup.rst @@ -8,12 +8,12 @@ you'll see something much like this show up on the console: .. code-block:: text - $ pserve myproject/MyProject.ini + $ pserve development.ini Starting server in PID 16601. serving on 0.0.0.0:6543 view at http://127.0.0.1:6543 This chapter explains what happens between the time you press the "Return" -key on your keyboard after typing ``pserve myproject/MyProject.ini`` +key on your keyboard after typing ``pserve development.ini`` and the time the line ``serving on 0.0.0.0:6543 ...`` is output to your console. diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst index 033f045a6..93ce747ee 100644 --- a/docs/narr/subrequest.rst +++ b/docs/narr/subrequest.rst @@ -155,7 +155,7 @@ In the example above, the call to exception. This is because it's using the default value for ``use_tweens``, which is ``False``. You can pass ``use_tweens=True`` instead to ensure that it will convert an exception to a Response if an :term:`exception view` is -configured instead of raising the exception. This because exception views +configured instead of raising the exception. This is because exception views are called by the exception view :term:`tween` as described in :ref:`exception_views` when any view raises an exception. @@ -250,7 +250,7 @@ It's a poor idea to use the original ``request`` object as an argument to :meth:`~pyramid.request.Request.invoke_subrequest`. You should construct a new request instead as demonstrated in the above example, using :meth:`pyramid.request.Request.blank`. Once you've constructed a request -object, you'll need to massage the it to match the view callable you'd like +object, you'll need to massage it to match the view callable you'd like to be executed during the subrequest. This can be done by adjusting the subrequest's URL, its headers, its request method, and other attributes. The documentation for :class:`pyramid.request.Request` exposes the methods you diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst index 1f1c07027..d4cf20b93 100644 --- a/docs/narr/templates.rst +++ b/docs/narr/templates.rst @@ -150,7 +150,6 @@ string, then return that string as the body of a :app:`Pyramid` For example, here's an example of using "raw" `Mako <http://www.makotemplates.org/>`_ from within a :app:`Pyramid` :term:`view`: -.. ignore-next-block .. code-block:: python :linenos: diff --git a/docs/narr/testing.rst b/docs/narr/testing.rst index 0801a8eae..bfb1287d9 100644 --- a/docs/narr/testing.rst +++ b/docs/narr/testing.rst @@ -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.threadlocal.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: @@ -231,7 +231,7 @@ application registry is not created and populated (e.g. by initializing the configurator with an authorization policy), like when you invoke application code via a unit test, :app:`Pyramid` API functions will tend to either fail or return default results. So how do you test the branch of the code in this -view function that raises :exc:`HTTPForbidden`? +view function that raises :exc:`~pyramid.httpexceptions.HTTPForbidden`? The testing API provided by :app:`Pyramid` allows you to simulate various application registry registrations for use under a unit testing framework @@ -272,7 +272,7 @@ without needing to invoke the actual application configuration implied by its self.assertEqual(response, {'greeting':'hello'}) In the above example, we create a ``MyTest`` test case that inherits from -:mod:`unittest.TestCase`. If it's in our :app:`Pyramid` application, it will +:class:`unittest.TestCase`. If it's in our :app:`Pyramid` application, it will 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 @@ -287,8 +287,9 @@ 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 -access. We check that the view function raises a :exc:`HTTPForbidden` error. +:meth:`~pyramid.config.Configurator.testing_securitypolicy`, which denies +access. We check that the view function raises a +:exc:`~pyramid.httpexceptions.HTTPForbidden` error. The second test method, named ``test_view_fn_allowed`` tests the alternate case, where the authentication policy allows access. Notice that we pass @@ -425,4 +426,4 @@ invoke the root URL. We then assert that the returned HTML has the string ``Pyramid`` in it. See the :term:`WebTest` documentation for further information about the -methods available to a :class:`webtest.TestApp` instance. +methods available to a :class:`webtest.app.TestApp` instance. diff --git a/docs/narr/traversal.rst b/docs/narr/traversal.rst index 1234620c2..2eb6ece13 100644 --- a/docs/narr/traversal.rst +++ b/docs/narr/traversal.rst @@ -22,10 +22,13 @@ resource found as the result of a traversal becomes the subsystem is used to find some view code willing to "publish" this resource by generating a :term:`response`. -Using :term:`Traversal` to map a URL to code is optional. It is often -less easy to understand than :term:`URL dispatch`, so if you're a rank -beginner, it probably makes sense to use URL dispatch to map URLs to -code instead of traversal. In that case, you can skip this chapter. +.. note:: + + Using :term:`Traversal` to map a URL to code is optional. If you're creating + your first Pyramid application it probably makes more sense to use :term:`URL + dispatch` to map URLs to code instead of traversal, as new Pyramid developers + tend to find URL dispatch slightly easier to understand. If you use URL + dispatch, you needn't read this chapter. .. index:: single: traversal details @@ -356,13 +359,13 @@ when this request comes in that we're traversing the following resource tree: Here's what happens: -- :mod:`traversal` traverses the root, and attempts to find "foo", which it +- :term:`traversal` traverses the root, and attempts to find "foo", which it finds. -- :mod:`traversal` traverses "foo", and attempts to find "bar", which it +- :term:`traversal` traverses "foo", and attempts to find "bar", which it finds. -- :mod:`traversal` traverses "bar", and attempts to find "baz", which it does +- :term:`traversal` traverses "bar", and attempts to find "baz", which it does not find (the "bar" resource raises a :exc:`KeyError` when asked for "baz"). @@ -407,16 +410,16 @@ However, for this tree: The user asks for ``http://example.com/foo/bar/baz/biz/buz.txt`` -- :mod:`traversal` traverses "foo", and attempts to find "bar", which it +- :term:`traversal` traverses "foo", and attempts to find "bar", which it finds. -- :mod:`traversal` traverses "bar", and attempts to find "baz", which it +- :term:`traversal` traverses "bar", and attempts to find "baz", which it finds. -- :mod:`traversal` traverses "baz", and attempts to find "biz", which it +- :term:`traversal` traverses "baz", and attempts to find "biz", which it finds. -- :mod:`traversal` traverses "biz", and attempts to find "buz.txt" which it +- :term:`traversal` traverses "biz", and attempts to find "buz.txt" which it does not find. The fact that it does not find a resource related to "buz.txt" at this point diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst index 181b07259..18cb3e4db 100644 --- a/docs/narr/urldispatch.rst +++ b/docs/narr/urldispatch.rst @@ -16,12 +16,13 @@ receives the :term:`request` and returns a :term:`response` object. High-Level Operational Overview ------------------------------- -If route configuration is present in an application, the :app:`Pyramid` +If any route configuration is present in an application, the :app:`Pyramid` :term:`Router` checks every incoming request against an ordered set of URL matching patterns present in a *route map*. If any route pattern matches the information in the :term:`request`, -:app:`Pyramid` will invoke :term:`view lookup` to find a matching view. +:app:`Pyramid` will invoke the :term:`view lookup` process to find a +matching view. If no route pattern in the route map matches the information in the :term:`request` provided in your application, :app:`Pyramid` will fail over @@ -54,7 +55,6 @@ The :meth:`pyramid.config.Configurator.add_route` method adds a single :term:`route configuration` to the :term:`application registry`. Here's an example: -.. ignore-next-block .. code-block:: python # "config" below is presumed to be an instance of the @@ -81,7 +81,7 @@ this is a portion of your project's ``__init__.py``: Note that we don't call :meth:`~pyramid.config.Configurator.add_view` in this setup code. However, the above :term:`scan` execution -``config.scan('mypackage')`` will pick up all :term:`configuration +``config.scan('mypackage')`` will pick up each :term:`configuration decoration`, including any objects decorated with the :class:`pyramid.view.view_config` decorator in the ``mypackage`` Python package. For example, if you have a ``views.py`` in your package, a scan will @@ -1263,7 +1263,7 @@ 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 +explain how it *does* work in this section. You can skip it if you're uninterested. When a view is associated with a route configuration, :app:`Pyramid` ensures diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst index d3221db3c..6f0001f61 100644 --- a/docs/narr/viewconfig.rst +++ b/docs/narr/viewconfig.rst @@ -62,9 +62,9 @@ particular view callable. :term:`View predicate` attributes are an important part of view configuration that enables the :term:`view lookup` subsystem to find and invoke the -appropriate view. The greater number of predicate attributes possessed by a +appropriate view. The greater the number of predicate attributes possessed by a view's configuration, the more specific the circumstances need to be before -the registered view callable will be invoked. The fewer number of predicates +the registered view callable will be invoked. The fewer the number of predicates which are supplied to a particular view configuration, the more likely it is that the associated view callable will be invoked. A view with five predicates will always be found and evaluated before a view with two, for @@ -313,9 +313,9 @@ configured view. This argument ensures that the view will only be called when the :term:`request` has key/value pairs in its :term:`matchdict` that equal - those supplied in the predicate. e.g. ``match_param="action=edit" would + those supplied in the predicate. e.g. ``match_param="action=edit"`` would require the ``action`` parameter in the :term:`matchdict` match the right - hande side of the expression (``edit``) for the view to "match" the current + hand side of the expression (``edit``) for the view to "match" the current request. If the ``match_param`` is a dict, every key/value pair must match for the @@ -488,7 +488,6 @@ acts as a :app:`Pyramid` view callable. Here's an example of the :class:`~pyramid.view.view_config` decorator that lives within a :app:`Pyramid` application module ``views.py``: -.. ignore-next-block .. code-block:: python :linenos: @@ -503,7 +502,6 @@ lives within a :app:`Pyramid` application module ``views.py``: Using this decorator as above replaces the need to add this imperative configuration stanza: -.. ignore-next-block .. code-block:: python :linenos: diff --git a/docs/narr/views.rst b/docs/narr/views.rst index 5a7be15b0..b2dd549ce 100644 --- a/docs/narr/views.rst +++ b/docs/narr/views.rst @@ -39,7 +39,7 @@ object. A request object represents a :term:`WSGI` environment provided to object contains everything your application needs to know about the specific HTTP request being made. -A view callable's ultimate responsibility is to create a :mod:`Pyramid` +A view callable's ultimate responsibility is to create a :app:`Pyramid` :term:`Response` object. This can be done by creating a :term:`Response` object in the view callable code and returning it directly or by raising special kinds of exceptions from within the body of a view callable. diff --git a/docs/narr/webob.rst b/docs/narr/webob.rst index 44940f9e6..02c03c8db 100644 --- a/docs/narr/webob.rst +++ b/docs/narr/webob.rst @@ -326,7 +326,6 @@ package that uses SQLAlchemy, and you'd like the current SQLAlchemy database session to be removed after each request. Put the following in the ``mypackage.__init__`` module: -.. ignore-next-block .. code-block:: python :linenos: @@ -355,7 +354,7 @@ initialization. cause ``DBSession.remove`` to be called in an application generated from any :app:`Pyramid` scaffold, because these all use the ``pyramid_tm`` package. The cleanup done by ``DBSession.remove`` is unnecessary when - ``pyramid_tm`` middleware is configured into the application. + ``pyramid_tm`` :term:`middleware` is configured into the application. More Details ++++++++++++ @@ -491,7 +490,6 @@ reason for the error. For instance, :class:`pyramid.Response`, so you can manipulate the instances in the same way. A typical example is: -.. ignore-next-block .. code-block:: python :linenos: diff --git a/docs/narr/zca.rst b/docs/narr/zca.rst index f7707ea29..b0e9b1709 100644 --- a/docs/narr/zca.rst +++ b/docs/narr/zca.rst @@ -21,7 +21,6 @@ application can be opaque. For example, here is a typical "unnamed utility" lookup using the :func:`zope.component.getUtility` global API as it might appear in a traditional Zope application: -.. ignore-next-block .. code-block:: python :linenos: @@ -45,7 +44,7 @@ framework implementation detail. However, developers who are already used to writing :term:`Zope` applications often still wish to use the ZCA while building a -:app:`Pyramid` application; :mod:`pyramid` makes this possible. +:app:`Pyramid` application; :app:`Pyramid` makes this possible. .. index:: single: get_current_registry @@ -84,7 +83,7 @@ While this services a reasonable goal, it causes some issues when trying to use patterns which you might use to build a typical :term:`Zope` application to build a :app:`Pyramid` application. Without special help, ZCA "global" APIs such as -``zope.component.getUtility`` and ``zope.component.getSiteManager`` +:func:`zope.component.getUtility` and :func:`zope.component.getSiteManager` will use the ZCA "global" registry. Therefore, these APIs will appear to fail when used in a :app:`Pyramid` application, because they'll be consulting the ZCA global registry rather than the @@ -105,8 +104,8 @@ Disusing the Global ZCA API +++++++++++++++++++++++++++ ZCA "global" API functions such as ``zope.component.getSiteManager``, -``zope.component.getUtility``, ``zope.component.getAdapter``, and -``zope.component.getMultiAdapter`` aren't strictly necessary. Every +``zope.component.getUtility``, :func:`zope.component.getAdapter`, and +:func:`zope.component.getMultiAdapter` aren't strictly necessary. Every component registry has a method API that offers the same functionality; it can be used instead. For example, presuming the ``registry`` value below is a Zope Component Architecture component @@ -114,7 +113,6 @@ registry, the following bit of code is equivalent to ``zope.component.getUtility(IFoo)``: .. code-block:: python - :linenos: registry.getUtility(IFoo) @@ -152,7 +150,6 @@ Consider the following bit of idiomatic :app:`Pyramid` startup code: .. code-block:: python :linenos: - from zope.component import getGlobalSiteManager from pyramid.config import Configurator def app(global_settings, **settings): @@ -189,7 +186,6 @@ For example: .. code-block:: python :linenos: - from zope.component import getGlobalSiteManager from pyramid.config import Configurator def app(global_settings, **settings): diff --git a/docs/tutorials/wiki/basiclayout.rst b/docs/tutorials/wiki/basiclayout.rst index f9d4775ad..25ac9aabd 100644 --- a/docs/tutorials/wiki/basiclayout.rst +++ b/docs/tutorials/wiki/basiclayout.rst @@ -36,7 +36,7 @@ point happens to be the ``main`` function within the file named #. *Line 15*. Register a "static view" which answers requests whose URL path start with ``/static`` using the - :meth:`pyramid.config.Configurator.add_static_view method`. This + :meth:`pyramid.config.Configurator.add_static_view` method. This statement registers a view that will serve up static assets, such as CSS and image files, for us, in this case, at ``http://localhost:6543/static/`` and below. The first argument is the diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt index 0d0738f7f..c3a0acf6b 100644 --- a/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt +++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt @@ -54,9 +54,5 @@ </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 2c7235761..3612dccde 100644 --- a/docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt +++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt @@ -50,9 +50,5 @@ </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 84824f605..e8672104d 100644 --- a/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt @@ -69,8 +69,5 @@ </div> </div> </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2012, 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 9dd6540cf..90e20764d 100644 --- a/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt +++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt @@ -57,9 +57,5 @@ </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/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt index 84824f605..e8672104d 100644 --- a/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt @@ -69,8 +69,5 @@ </div> </div> </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2012, Agendaless Consulting.</div> - </div> </body> </html> diff --git a/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt index 84824f605..e8672104d 100644 --- a/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt @@ -69,8 +69,5 @@ </div> </div> </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2012, Agendaless Consulting.</div> - </div> </body> </html> diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt index 0d0738f7f..c3a0acf6b 100644 --- a/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt +++ b/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt @@ -54,9 +54,5 @@ </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/tests/tutorial/templates/login.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/login.pt index 2c7235761..3612dccde 100644 --- a/docs/tutorials/wiki/src/tests/tutorial/templates/login.pt +++ b/docs/tutorials/wiki/src/tests/tutorial/templates/login.pt @@ -50,9 +50,5 @@ </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/tests/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt index 84824f605..e8672104d 100644 --- a/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt @@ -69,8 +69,5 @@ </div> </div> </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2012, Agendaless Consulting.</div> - </div> </body> </html> diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt index 9dd6540cf..90e20764d 100644 --- a/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt +++ b/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt @@ -57,9 +57,5 @@ </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 5ede26920..01c301e74 100644 --- a/docs/tutorials/wiki2/authorization.rst +++ b/docs/tutorials/wiki2/authorization.rst @@ -381,21 +381,21 @@ We can finally examine our application in a browser (See :ref:`wiki2-start-the-application`). Launch a browser and visit each of the following URLs, check that the result is as expected: -- ``http://localhost:6543/`` invokes the +- http://localhost:6543/ invokes the ``view_wiki`` view. This always redirects to the ``view_page`` view of the FrontPage page object. It is executable by any user. -- ``http://localhost:6543/FrontPage`` invokes +- http://localhost:6543/FrontPage invokes the ``view_page`` view of the FrontPage page object. -- ``http://localhost:6543/FrontPage/edit_page`` +- http://localhost:6543/FrontPage/edit_page invokes the edit view for the FrontPage object. It is executable by only the ``editor`` user. If a different user (or the anonymous user) invokes it, a login form will be displayed. Supplying the credentials with the username ``editor``, password ``editor`` will display the edit page form. -- ``http://localhost:6543/add_page/SomePageName`` +- http://localhost:6543/add_page/SomePageName invokes the add view for a page. It is executable by only the ``editor`` user. If a different user (or the anonymous user) invokes it, a login form will be displayed. Supplying the diff --git a/docs/tutorials/wiki2/basiclayout.rst b/docs/tutorials/wiki2/basiclayout.rst index 86fe97956..0193afab4 100644 --- a/docs/tutorials/wiki2/basiclayout.rst +++ b/docs/tutorials/wiki2/basiclayout.rst @@ -43,9 +43,9 @@ above is executed. It accepts some settings and returns a :term:`WSGI` application. (See :ref:`startup_chapter` for more about ``pserve``.) The main function first creates a :term:`SQLAlchemy` database engine using -``engine_from_config`` from the ``sqlalchemy.`` prefixed settings in the -``development.ini`` file's ``[app:main]`` section. This will be a URI -(something like ``sqlite://``): +:func:`sqlalchemy.engine_from_config` from the ``sqlalchemy.`` prefixed +settings in the ``development.ini`` file's ``[app:main]`` section. +This will be a URI (something like ``sqlite://``): .. literalinclude:: src/basiclayout/tutorial/__init__.py :lines: 13 @@ -132,11 +132,10 @@ Finally, ``main`` is finished configuring things, so it uses the View Declarations via ``views.py`` ---------------------------------- -Mapping a :term:`route` to code that will be executed when a match for -the route's pattern occurs is done by registering a :term:`view -configuration`. Our application uses the -:meth:`pyramid.view.view_config` decorator to map view callables to -each route, thereby mapping URL patterns to code. +The main function of a web framework is mapping each URL pattern to code (a +:term:`view callable`) that is executed when the requested URL matches the +corresponding :term:`route`. Our application uses the +:meth:`pyramid.view.view_config` decorator to perform this mapping. Open ``tutorial/tutorial/views.py``. It should already contain the following: @@ -228,11 +227,10 @@ To give a simple example of a model class, we define one named ``MyModel``: Our example model has an ``__init__`` method that takes two arguments (``name``, and ``value``). It stores these values as ``self.name`` and -``self.value`` -within the ``__init__`` function itself. The ``MyModel`` class also has a -``__tablename__`` attribute. This informs SQLAlchemy which table to use to -store the data representing instances of this class. - -That's about all there is to it to models, views, and initialization code in -our stock application. +``self.value`` on the instance created by the ``__init__`` function itself. +The ``MyModel`` class also has a ``__tablename__`` attribute. This informs +SQLAlchemy which table to use to store the data representing instances of this +class. +That's about all there is to it regarding models, views, and initialization +code in our stock application. diff --git a/docs/tutorials/wiki2/definingmodels.rst b/docs/tutorials/wiki2/definingmodels.rst index bd1cb00d7..60427a911 100644 --- a/docs/tutorials/wiki2/definingmodels.rst +++ b/docs/tutorials/wiki2/definingmodels.rst @@ -34,7 +34,7 @@ sample and we're not going to use it. Then, we added a ``Page`` class. Because this is a SQLAlchemy application, this class inherits from an instance of -:class:`sqlalchemy.ext.declarative.declarative_base`. +:func:`sqlalchemy.ext.declarative.declarative_base`. .. literalinclude:: src/models/tutorial/models.py :pyobject: Page @@ -45,9 +45,10 @@ As you can see, our ``Page`` class has a class level attribute ``__tablename__`` which equals the string ``'pages'``. This means that SQLAlchemy will store our wiki data in a SQL table named ``pages``. Our ``Page`` class will also have class-level attributes named ``id``, ``name`` and -``data`` (all instances of :class:`sqlalchemy.Column`). These will map to -columns in the ``pages`` table. The ``id`` attribute will be the primary key -in the table. The ``name`` attribute will be a text attribute, each value of +``data`` (all instances of :class:`sqlalchemy.schema.Column`). +These will map to columns in the ``pages`` table. +The ``id`` attribute will be the primary key in the table. +The ``name`` attribute will be a text attribute, each value of which needs to be unique within the column. The ``data`` attribute is a text attribute that will hold the body of each page. @@ -77,8 +78,6 @@ following: Installing the Project and re-initializing the Database ------------------------------------------------------- -Redo the steps in :ref:`installing_project_in_dev_mode`. - Because our model has changed, in order to reinitialize the database, we need to rerun the ``initialize_tutorial_db`` command to pick up the changes you've made to both the models.py file and to the initializedb.py file. diff --git a/docs/tutorials/wiki2/definingviews.rst b/docs/tutorials/wiki2/definingviews.rst index f2ac2f85f..a1e2313f3 100644 --- a/docs/tutorials/wiki2/definingviews.rst +++ b/docs/tutorials/wiki2/definingviews.rst @@ -6,16 +6,13 @@ A :term:`view callable` in a :app:`Pyramid` application is typically a simple Python function that accepts a single parameter named :term:`request`. A view callable is assumed to return a :term:`response` object. -The request object passed to every view that is called as the result of a -route match has an attribute named ``matchdict`` that contains the elements -placed into the URL by the ``pattern`` of a ``route`` statement. For -instance, if a call to :meth:`pyramid.config.Configurator.add_route` in -``__init__.py`` had the pattern ``{one}/{two}``, and the URL at -``http://example.com/foo/bar`` was invoked, matching this pattern, the -``matchdict`` dictionary attached to the request passed to the view would -have a ``'one'`` key with the value ``'foo'`` and a ``'two'`` key with the -value ``'bar'``. - +The request object has a dictionary as an attribute named ``matchdict``. A +``matchdict`` maps the placeholders in the matching URL ``pattern`` to the +substrings of the path in the :term:`request` URL. For instance, if a call to +:meth:`pyramid.config.Configurator.add_route` has the pattern ``/{one}/{two}``, +and a user visits ``http://example.com/foo/bar``, our pattern would be matched +against ``/foo/bar`` and the ``matchdict`` would look like: ``{'one':'foo', +'two':'bar'}`` Declaring Dependencies in Our ``setup.py`` File =============================================== @@ -148,14 +145,13 @@ As a result, the ``content`` variable is now a fully formed bit of HTML containing various view and add links for WikiWords based on the content of our current page object. -We then generate an edit URL (because it's easier to do here than in the -template), and we return a dictionary with a number of arguments. The fact -that ``view_page()`` returns a dictionary (as opposed to a :term:`response` -object) is a cue to :app:`Pyramid` that it should try to use a :term:`renderer` -associated with the view configuration to render a template. In our case, -the template which will be rendered will be the ``templates/view.pt`` -template, as indicated in the ``@view_config`` decorator that is applied to -``view_page()``. +We then generate an edit URL because it's easier to do here than in the +template, and we return a dictionary with a number of arguments. The fact that +``view_page()`` returns a dictionary (as opposed to a :term:`response` object) +is a cue to :app:`Pyramid` that it should try to use a :term:`renderer` +associated with the view configuration to render a response. In our case, the +renderer used will be the ``templates/view.pt`` template, as indicated in the +``@view_config`` decorator that is applied to ``view_page()``. The ``add_page`` view function ------------------------------ @@ -350,20 +346,20 @@ We can finally examine our application in a browser (See :ref:`wiki2-start-the-application`). Launch a browser and visit each of the following URLs, check that the result is as expected: -- ``http://localhost:6543`` in a browser invokes the +- http://localhost:6543 in a browser invokes the ``view_wiki`` view. This always redirects to the ``view_page`` view of the FrontPage page object. -- ``http://localhost:6543/FrontPage`` in a browser invokes +- http://localhost:6543/FrontPage in a browser invokes the ``view_page`` view of the front page object. -- ``http://localhost:6543/FrontPage/edit_page`` in a browser +- http://localhost:6543/FrontPage/edit_page in a browser invokes the edit view for the front page object. -- ``http://localhost:6543/add_page/SomePageName`` in a +- http://localhost:6543/add_page/SomePageName in a browser invokes the add view for a page. -- To generate an error, visit ``http://localhost:6543/foobars/edit_page`` which +- To generate an error, visit http://localhost:6543/foobars/edit_page which will generate a ``NoResultFound: No row was found for one()`` error. You'll see an interactive traceback facility provided by :term:`pyramid_debugtoolbar`. diff --git a/docs/tutorials/wiki2/design.rst b/docs/tutorials/wiki2/design.rst index c56d7fecf..df2c83398 100644 --- a/docs/tutorials/wiki2/design.rst +++ b/docs/tutorials/wiki2/design.rst @@ -100,7 +100,7 @@ listed in the following table: | | with existing | | | | | | content. | | | | | | | | | | -| | If the form was | | | | +| | If the form is | | | | | | submitted, redirect | | | | | | to /PageName | | | | +----------------------+-----------------------+-------------+------------+------------+ @@ -110,15 +110,15 @@ listed in the following table: | | the edit form | | | | | | without content. | | | | | | | | | | -| | If the form was | | | | +| | If the form is | | | | | | submitted, | | | | | | redirect to | | | | | | /PageName | | | | +----------------------+-----------------------+-------------+------------+------------+ | /login | Display login form, | login | login.pt | | -| | Forbidden [3]_ | | | | +| | Forbidden [3]_ | | | | | | | | | | -| | If the form was | | | | +| | If the form is | | | | | | submitted, | | | | | | authenticate. | | | | | | | | | | diff --git a/docs/tutorials/wiki2/installation.rst b/docs/tutorials/wiki2/installation.rst index 8c4149bfc..17788cdde 100644 --- a/docs/tutorials/wiki2/installation.rst +++ b/docs/tutorials/wiki2/installation.rst @@ -5,65 +5,139 @@ Installation Before You Begin ================ -Installation Requirements -------------------------- - -Follow the steps in :ref:`installing_chapter`, but name the virtualenv -directory ``pyramidtut``. Following these steps will ensure you have met the -following requirements: +This tutorial assumes that you have already followed the steps in +:ref:`installing_chapter`, thereby satisfying the following +requirements. * Python interpreter is installed on your operating system * :term:`setuptools` or :term:`distribute` is installed * :term:`virtualenv` is installed -* a virtual Python environment named ``pyramidtut`` has been created -* Pyramid is installed -UNIX Requirements ------------------ +Create and Use a Virtual Python Environment +------------------------------------------- + +Next let's create a `virtualenv` workspace for our project. We will +use the `VENV` environment variable instead of absolute path of the +virtual environment. + +On UNIX +^^^^^^^ -#. Install SQLite3 and its development packages if you don't already - have them installed. Usually this is via your system's package - manager. On a Debian system, this would be: +.. code-block:: text + + $ export VENV=~/pyramidtut + $ virtualenv --no-site-packages $VENV + New python executable in /home/foo/env/bin/python + Installing setuptools.............done. - .. code-block:: text +On Windows +^^^^^^^^^^ - $ sudo apt-get install libsqlite3-dev +Set the `VENV` environment variable. -#. Switch to the ``pyramidtut`` directory: +.. code-block:: text + + c:\> set VENV=c:\pyramidtut + +Versions of Python use different paths, so you will need to adjust the +path to the command for your Python version. + +Python 2.7: + +.. code-block:: text - .. code-block:: text + c:\> c:\Python27\Scripts\virtualenv --no-site-packages %VENV% - $ cd pyramidtut +Python 3.2: -Windows Requirements --------------------- +.. code-block:: text + + c:\> c:\Python32\Scripts\virtualenv --no-site-packages %VENV% + +Install Pyramid Into the Virtual Python Environment +--------------------------------------------------- + +On UNIX +^^^^^^^ + +.. code-block:: text + + $ $VENV/bin/easy_install pyramid + +On Windows +^^^^^^^^^^ + +.. code-block:: text -#. Switch to the ``pyramidtut`` directory: + c:\env> %VENV%\Scripts\easy_install pyramid - .. code-block:: text +Install SQLite3 and Its Development Packages +-------------------------------------------- - c:\> cd pyramidtut +If you used a package manager to install your Python or if you compiled +your Python from source, then you must install SQLite3 and its +development packages. If you downloaded your Python as an installer +from python.org, then you already have it installed and can proceed to +the next section :ref:`sql_making_a_project`.. + +If you need to install the SQLite3 packages, then, for example, using +the Debian system and apt-get, the command would be the following: + +.. code-block:: text + + $ sudo apt-get install libsqlite3-dev + +Change Directory to Your Virtual Python Environment +--------------------------------------------------- + +Change directory to the ``pyramidtut`` directory. + +On UNIX +^^^^^^^ + +.. code-block:: text + + $ cd pyramidtut + +On Windows +^^^^^^^^^^ + +.. code-block:: text + + c:\> cd pyramidtut .. _sql_making_a_project: Making a Project ================ -Your next step is to create a project. For this tutorial, we will use the -:term:`scaffold` named ``alchemy``, which generates an application -that uses :term:`SQLAlchemy` and :term:`URL dispatch`. :app:`Pyramid` -supplies a variety of scaffolds to generate sample projects. +Your next step is to create a project. For this tutorial we will use +the :term:`scaffold` named ``alchemy`` which generates an application +that uses :term:`SQLAlchemy` and :term:`URL dispatch`. + +:app:`Pyramid` supplies a variety of scaffolds to generate sample +projects. We will use `pcreate`—a script that comes with Pyramid to +quickly and easily generate scaffolds usually with a single command—to +create the scaffold for our project. + +By passing in `alchemy` into the `pcreate` command, the script creates +the files needed to use SQLAlchemy. By passing in our application name +`tutorial`, the script inserts that application name into all the +required files. For example, `pcreate` creates the +``initialize_tutorial_db`` in the ``pyramidtut/bin`` directory. The below instructions assume your current working directory is the "virtualenv" named "pyramidtut". -On UNIX: +On UNIX +------- .. code-block:: text $ $VENV/bin/pcreate -s alchemy tutorial -On Windows: +On Windows +---------- .. code-block:: text @@ -75,18 +149,10 @@ On Windows: startup problems, try putting both the virtualenv and the project into directories that do not contain spaces in their paths. -`pcreate` is a script that comes with Pyramid that helps by creating and organizing files -needed as part of a Pyramid project. By passing in `alchemy`, we are asking the script to -create the files needed to use SQLAlchemy. By passing in our app name `tutorial`, the script -places that application name in all the different files required. For example, the ``initialize_tutorial_db`` -that is in the ``pyramidtut/bin`` directory was created by `pcreate`. - - - .. _installing_project_in_dev_mode: -Installing the Project in "Development Mode" -============================================ +Installing the Project in Development Mode +========================================== In order to do development on the project easily, you must "register" the project as a development egg in your workspace using the @@ -94,22 +160,25 @@ the project as a development egg in your workspace using the directory you created in :ref:`sql_making_a_project`, and run the ``setup.py develop`` command using the virtualenv Python interpreter. -On UNIX: +On UNIX +------- .. code-block:: text $ cd tutorial $ $VENV/bin/python setup.py develop -On Windows: +On Windows +---------- .. code-block:: text c:\pyramidtut> cd tutorial c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py develop -Success executing this command will end with a line to the console something -like:: +The console will show `setup.py` checking for packages and installing +missing packages. Success executing this command will show a line like +the following:: Finished processing dependencies for tutorial==0.0 @@ -121,13 +190,15 @@ Running the Tests After you've installed the project in development mode, you may run the tests for the project. -On UNIX: +On UNIX +------- .. code-block:: text $ $VENV/bin/python setup.py test -q -On Windows: +On Windows +---------- .. code-block:: text @@ -153,13 +224,15 @@ tests. To get this functionality working, we'll need to install the ``nose`` and ``coverage`` packages into our ``virtualenv``: -On UNIX: +On UNIX +------- .. code-block:: text $ $VENV/bin/easy_install nose coverage -On Windows: +On Windows +---------- .. code-block:: text @@ -168,13 +241,15 @@ On Windows: Once ``nose`` and ``coverage`` are installed, we can actually run the coverage tests. -On UNIX: +On UNIX +------- .. code-block:: text $ $VENV/bin/nosetests --cover-package=tutorial --cover-erase --with-coverage -On Windows: +On Windows +---------- .. code-block:: text @@ -212,13 +287,15 @@ script` to initialize our database. Type the following command, make sure you are still in the ``tutorial`` directory (the directory with a ``development.ini`` in it): -On UNIX: +On UNIX +------- .. code-block:: text $ $VENV/bin/initialize_tutorial_db development.ini -On Windows: +On Windows +---------- .. code-block:: text @@ -260,13 +337,15 @@ Starting the Application Start the application. -On UNIX: +On UNIX +------- .. code-block:: text $ $VENV/bin/pserve development.ini --reload -On Windows: +On Windows +---------- .. code-block:: text @@ -308,4 +387,3 @@ the following assumptions: mechanism to map URLs to code (:term:`traversal`). However, for the purposes of this tutorial, we'll only be using url dispatch and SQLAlchemy. - diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt index 15ea6614f..ee9fdb7fa 100644 --- a/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt @@ -69,8 +69,5 @@ </div> </div> </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2012, 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 fbfa9870b..ee9fdb7fa 100644 --- a/docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.pt @@ -69,8 +69,5 @@ </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/tests/tutorial/templates/edit.pt b/docs/tutorials/wiki2/src/tests/tutorial/templates/edit.pt index ca28b9fa5..2004273fe 100644 --- a/docs/tutorials/wiki2/src/tests/tutorial/templates/edit.pt +++ b/docs/tutorials/wiki2/src/tests/tutorial/templates/edit.pt @@ -54,9 +54,5 @@ </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/tests/tutorial/templates/login.pt b/docs/tutorials/wiki2/src/tests/tutorial/templates/login.pt index 64e592ea9..5f8e9b98c 100644 --- a/docs/tutorials/wiki2/src/tests/tutorial/templates/login.pt +++ b/docs/tutorials/wiki2/src/tests/tutorial/templates/login.pt @@ -50,9 +50,5 @@ </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/tests/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/tests/tutorial/templates/mytemplate.pt index 14b88d16a..9c077568d 100644 --- a/docs/tutorials/wiki2/src/tests/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki2/src/tests/tutorial/templates/mytemplate.pt @@ -69,8 +69,5 @@ </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/tests/tutorial/templates/view.pt b/docs/tutorials/wiki2/src/tests/tutorial/templates/view.pt index 5a69818c1..19c50fb36 100644 --- a/docs/tutorials/wiki2/src/tests/tutorial/templates/view.pt +++ b/docs/tutorials/wiki2/src/tests/tutorial/templates/view.pt @@ -57,9 +57,5 @@ </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 3f2039cb6..5f962bbf5 100644 --- a/docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt +++ b/docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt @@ -50,9 +50,5 @@ </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 fbfa9870b..ee9fdb7fa 100644 --- a/docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt @@ -69,8 +69,5 @@ </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 423c1d5a1..78c0d2d4c 100644 --- a/docs/tutorials/wiki2/src/views/tutorial/templates/view.pt +++ b/docs/tutorials/wiki2/src/views/tutorial/templates/view.pt @@ -53,9 +53,5 @@ </div> </div> </div> - <div id="footer"> - <div class="footer" - >© Copyright 2008-2011, Agendaless Consulting.</div> - </div> </body> </html> diff --git a/docs/whatsnew-1.1.rst b/docs/whatsnew-1.1.rst index f33fc94ba..5cba8dd3e 100644 --- a/docs/whatsnew-1.1.rst +++ b/docs/whatsnew-1.1.rst @@ -43,7 +43,7 @@ The major feature additions in Pyramid 1.1 are: The object passed to a view callable as ``request`` is an instance of :class:`pyramid.request.Request`. ``request.response`` is an instance of - the class :class:`pyramid.request.Response`. View callables that are + the class :class:`pyramid.response.Response`. View callables that are configured with a :term:`renderer` will return this response object to the Pyramid router. Therefore, code in a renderer-using view callable can set response attributes such as ``request.response.content_type`` (before they @@ -95,7 +95,7 @@ Default HTTP Exception View is passed for this value, an exception view for HTTP exceptions will not be registered. Passing ``None`` returns the behavior of raising an HTTP exception to that of Pyramid 1.0 (the exception will propagate to - middleware and to the WSGI server). + :term:`middleware` and to the WSGI server). ``http_cache`` ~~~~~~~~~~~~~~ @@ -289,7 +289,7 @@ Minor Feature Additions when you want the static view to behave like the older deprecated version. - A new api function :func:`pyramid.scripting.prepare` has been added. It is - a lower-level analogue of :func:`pyramid.paster.boostrap` that accepts a + a lower-level analogue of :func:`pyramid.paster.bootstrap` that accepts a request and a registry instead of a config file argument, and is used for the same purpose: @@ -313,7 +313,7 @@ Minor Feature Additions - New API attribute :attr:`pyramid.config.global_registries` is an iterable object that contains references to every Pyramid registry loaded into the - current process via :meth:`pyramid.config.Configurator.make_app`. It also + current process via :meth:`pyramid.config.Configurator.make_wsgi_app`. It also has a ``last`` attribute containing the last registry loaded. This is used by the scripting machinery, and is available for introspection. diff --git a/docs/whatsnew-1.2.rst b/docs/whatsnew-1.2.rst index ea56cf52d..a9fc38908 100644 --- a/docs/whatsnew-1.2.rst +++ b/docs/whatsnew-1.2.rst @@ -31,11 +31,11 @@ Tweens ~~~~~~ A :term:`tween` is used to wrap the Pyramid router's primary request handling -function. This is a feature that can be used by Pyramid framework -extensions, to provide, for example, view timing support and can provide a -convenient place to hang bookkeeping code. Tweens are is a little like -:term:`WSGI` middleware, but have access to Pyramid functionality such as -renderers and a full-featured request object. +function. This is a feature that can be used by Pyramid framework extensions, +to provide, for example, view timing support and can provide a convenient +place to hang bookkeeping code. Tweens are a little like :term:`WSGI` +:term:`middleware`, but have access to Pyramid functionality such as renderers +and a full-featured request object. To support this feature, a new configurator directive exists named :meth:`pyramid.config.Configurator.add_tween`. This directive adds a @@ -51,7 +51,7 @@ Scaffolding Changes ~~~~~~~~~~~~~~~~~~~ - All scaffolds now use the ``pyramid_tm`` package rather than the - ``repoze.tm2`` middleware to manage transaction management. + ``repoze.tm2`` :term:`middleware` to manage transaction management. - The ZODB scaffold now uses the ``pyramid_zodbconn`` package rather than the ``repoze.zodbconn`` package to provide ZODB integration. @@ -59,9 +59,9 @@ Scaffolding Changes - All scaffolds now use the ``pyramid_debugtoolbar`` package rather than the ``WebError`` package to provide interactive debugging features. -- Projects created via a scaffold no longer depend on the ``WebError`` - package at all; configuration in the ``production.ini`` file which used to - require its ``error_catcher`` middleware has been removed. Configuring +- Projects created via a scaffold no longer depend on the ``WebError`` package + at all; configuration in the ``production.ini`` file which used to require + its ``error_catcher`` :term:`middleware` has been removed. Configuring error catching / email sending is now the domain of the ``pyramid_exclog`` package (see http://docs.pylonsproject.org/projects/pyramid_exclog/dev/). @@ -160,7 +160,7 @@ Minor Feature Additions a value of ``edit``. - Support an ``onerror`` keyword argument to - :meth:`pyramid.config.Configurator.scan``. This argument is passed to + :meth:`pyramid.config.Configurator.scan`. This argument is passed to :meth:`venusian.Scanner.scan` to influence error behavior when an exception is raised during scanning. diff --git a/docs/whatsnew-1.3.rst b/docs/whatsnew-1.3.rst index ef0256383..2606c3df3 100644 --- a/docs/whatsnew-1.3.rst +++ b/docs/whatsnew-1.3.rst @@ -210,13 +210,13 @@ Not Found and Forbidden View Helpers Not Found helpers: - New API: :meth:`pyramid.config.Configurator.add_notfound_view`. This is a - wrapper for :meth:`pyramid.Config.configurator.add_view` which provides + wrapper for :meth:`pyramid.config.Configurator.add_view` which provides support for an "append_slash" feature as well as doing the right thing when it comes to permissions (a Not Found View should always be public). It should be preferred over calling ``add_view`` directly with ``context=HTTPNotFound`` as was previously recommended. -- New API: :class:`pyramid.view.notfound_view_config``. This is a decorator +- New API: :class:`pyramid.view.notfound_view_config`. This is a decorator constructor like :class:`pyramid.view.view_config` that calls :meth:`pyramid.config.Configurator.add_notfound_view` when scanned. It should be preferred over using ``pyramid.view.view_config`` with @@ -225,7 +225,7 @@ Not Found helpers: Forbidden helpers: - New API: :meth:`pyramid.config.Configurator.add_forbidden_view`. This is a - wrapper for :meth:`pyramid.Config.configurator.add_view` which does the + wrapper for :meth:`pyramid.config.Configurator.add_view` which does the right thing about permissions. It should be preferred over calling ``add_view`` directly with ``context=HTTPForbidden`` as was previously recommended. @@ -267,7 +267,7 @@ Minor Feature Additions - We allow extra keyword arguments to be passed to the :meth:`pyramid.config.Configurator.action` method. -- Responses generated by Pyramid's :class:`pyramid.views.static_view` now use +- Responses generated by Pyramid's :class:`pyramid.static.static_view` now use a ``wsgi.file_wrapper`` (see http://www.python.org/dev/peps/pep-0333/#optional-platform-specific-file-handling) when one is provided by the web server. @@ -389,8 +389,8 @@ Backwards Incompatibilities and upgrade Pyramid itself "in-place"; it may simply break instead (particularly if you use ZCML's ``includeOverrides`` directive). -- String values passed to :meth:`Pyramid.request.Request.route_url` or - :meth:`Pyramid.request.Request.route_path` that are meant to replace +- String values passed to :meth:`pyramid.request.Request.route_url` or + :meth:`pyramid.request.Request.route_path` that are meant to replace "remainder" matches will now be URL-quoted except for embedded slashes. For example:: diff --git a/docs/whatsnew-1.4.rst b/docs/whatsnew-1.4.rst index f725615f3..505b9d798 100644 --- a/docs/whatsnew-1.4.rst +++ b/docs/whatsnew-1.4.rst @@ -184,11 +184,12 @@ Minor Feature Additions returns the policy object it creates. - The DummySecurityPolicy created by - :meth:`pyramid.config.testing_securitypolicy` now sets a ``forgotten`` value - on the policy (the value ``True``) when its ``forget`` method is called. + :meth:`pyramid.config.Configurator.testing_securitypolicy` now sets a + ``forgotten`` value on the policy (the value ``True``) when its ``forget`` + method is called. - The DummySecurityPolicy created by - :meth:`pyramid.config.testing_securitypolicy` now sets a + :meth:`pyramid.config.Configurator.testing_securitypolicy` now sets a ``remembered`` value on the policy, which is the value of the ``principal`` argument it's called with when its ``remember`` method is called. @@ -301,7 +302,7 @@ Backwards Incompatibilities :meth:`pyramid.config.Configurator.testing_add_subscriber` instead. * ``registerTemplateRenderer`` (aka ``registerDummyRenderer``), use - :meth:`pyramid.config.Configurator.testing_add_template` instead. + :meth:`pyramid.config.Configurator.testing_add_renderer` instead. * ``registerView``, use :meth:`pyramid.config.Configurator.add_view` instead. diff --git a/pyramid/config/__init__.py b/pyramid/config/__init__.py index e1320a55f..4f7899b54 100644 --- a/pyramid/config/__init__.py +++ b/pyramid/config/__init__.py @@ -864,14 +864,14 @@ class Configurator( This pushes a dictionary containing the :term:`application registry` implied by ``registry`` attribute of this configurator and the :term:`request` implied by the - ``request`` argument on to the :term:`thread local` stack + ``request`` argument onto the :term:`thread local` stack consulted by various :mod:`pyramid.threadlocal` API functions.""" self.manager.push({'registry':self.registry, 'request':request}) def end(self): """ Indicate that application or test configuration has ended. - This pops the last value pushed on to the :term:`thread local` + This pops the last value pushed onto the :term:`thread local` stack (usually by the ``begin`` method) and returns that value. """ @@ -963,7 +963,7 @@ class Configurator( # registry configured. global_registries.add(self.registry) - # Push the registry on to the stack in case any code that depends on + # Push the registry onto the stack in case any code that depends on # the registry threadlocal APIs used in listeners subscribed to the # IApplicationCreated event. self.manager.push({'registry':self.registry, 'request':None}) diff --git a/pyramid/config/views.py b/pyramid/config/views.py index 1c7620e67..707c84043 100644 --- a/pyramid/config/views.py +++ b/pyramid/config/views.py @@ -257,7 +257,9 @@ class ViewDeriver(object): view_name = getattr(request, 'view_name', None) if self.authn_policy and self.authz_policy: - if permission is None: + if permission is NO_PERMISSION_REQUIRED: + msg = 'Allowed (NO_PERMISSION_REQUIRED)' + elif permission is None: msg = 'Allowed (no permission registered)' else: principals = self.authn_policy.effective_principals( diff --git a/pyramid/decorator.py b/pyramid/decorator.py index 82d2b1280..e5f2996dc 100644 --- a/pyramid/decorator.py +++ b/pyramid/decorator.py @@ -15,16 +15,14 @@ class reify(object): And usage of Foo: - .. code-block:: text - - >>> f = Foo() - >>> v = f.jammy - 'jammy called' - >>> print v - 1 - >>> f.jammy - 1 - >>> # jammy func not called the second time; it replaced itself with 1 + >>> f = Foo() + >>> v = f.jammy + 'jammy called' + >>> print v + 1 + >>> f.jammy + 1 + >>> # jammy func not called the second time; it replaced itself with 1 """ def __init__(self, wrapped): self.wrapped = wrapped diff --git a/pyramid/mako_templating.py b/pyramid/mako_templating.py index f2627c1fc..061bcb717 100644 --- a/pyramid/mako_templating.py +++ b/pyramid/mako_templating.py @@ -82,7 +82,6 @@ class PkgResourceTemplateLookup(TemplateLookup): "Can not locate template for uri %r" % uri) return TemplateLookup.get_template(self, uri) - registry_lock = threading.Lock() class MakoRendererFactoryHelper(object): @@ -90,14 +89,11 @@ class MakoRendererFactoryHelper(object): self.settings_prefix = settings_prefix def __call__(self, info): - p = re.compile( - r'(?P<asset>[\w_.:/-]+)' - r'(?:\#(?P<defname>[\w_]+))?' - r'(\.(?P<ext>.*))' - ) - asset, defname, ext = p.match(info.name).group( - 'asset', 'defname', 'ext' - ) + defname = None + asset, ext = info.name.rsplit('.', 1) + if '#' in asset: + asset, defname = asset.rsplit('#', 1) + path = '%s.%s' % (asset, ext) registry = info.registry settings = info.settings diff --git a/pyramid/paster.py b/pyramid/paster.py index ce07d1fe0..967543849 100644 --- a/pyramid/paster.py +++ b/pyramid/paster.py @@ -23,26 +23,34 @@ def get_app(config_uri, name=None, options=None, loadapp=loadapp): path, section = _getpathsec(config_uri, name) config_name = 'config:%s' % path here_dir = os.getcwd() - if options: - kw = {'global_conf': options} - else: - kw = {} - app = loadapp(config_name, name=section, relative_to=here_dir, **kw) + app = loadapp( + config_name, + name=section, + relative_to=here_dir, + global_conf=options) return app -def get_appsettings(config_uri, name=None, appconfig=appconfig): +def get_appsettings(config_uri, name=None, options=None, appconfig=appconfig): """ Return a dictionary representing the key/value pairs in an ``app`` section within the file represented by ``config_uri``. + ``options``, if passed, should be a dictionary used as variable assignments + like ``{'http_port': 8080}``. This is useful if e.g. ``%(http_port)s`` is + used in the config file. + If the ``name`` is None, this will attempt to parse the name from the ``config_uri`` string expecting the format ``inifile#name``. If no name is found, the name will default to "main".""" path, section = _getpathsec(config_uri, name) config_name = 'config:%s' % path here_dir = os.getcwd() - return appconfig(config_name, name=section, relative_to=here_dir) + return appconfig( + config_name, + name=section, + relative_to=here_dir, + global_conf=options) def setup_logging(config_uri, fileConfig=fileConfig, configparser=configparser): diff --git a/pyramid/scaffolds/alchemy/+package+/scripts/initializedb.py b/pyramid/scaffolds/alchemy/+package+/scripts/initializedb.py index 66feb3008..7dfdece15 100644 --- a/pyramid/scaffolds/alchemy/+package+/scripts/initializedb.py +++ b/pyramid/scaffolds/alchemy/+package+/scripts/initializedb.py @@ -9,6 +9,8 @@ from pyramid.paster import ( setup_logging, ) +from pyramid.scripts.common import parse_vars + from ..models import ( DBSession, MyModel, @@ -18,17 +20,18 @@ from ..models import ( def usage(argv): cmd = os.path.basename(argv[0]) - print('usage: %s <config_uri>\n' + print('usage: %s <config_uri> [var=value]\n' '(example: "%s development.ini")' % (cmd, cmd)) sys.exit(1) def main(argv=sys.argv): - if len(argv) != 2: + if len(argv) < 2: usage(argv) config_uri = argv[1] + options = parse_vars(argv[2:]) setup_logging(config_uri) - settings = get_appsettings(config_uri) + settings = get_appsettings(config_uri, options=options) engine = engine_from_config(settings, 'sqlalchemy.') DBSession.configure(bind=engine) Base.metadata.create_all(engine) diff --git a/pyramid/scaffolds/alchemy/+package+/templates/mytemplate.pt_tmpl b/pyramid/scaffolds/alchemy/+package+/templates/mytemplate.pt_tmpl index 99606fe0e..99b3fe31c 100644 --- a/pyramid/scaffolds/alchemy/+package+/templates/mytemplate.pt_tmpl +++ b/pyramid/scaffolds/alchemy/+package+/templates/mytemplate.pt_tmpl @@ -69,8 +69,5 @@ </div> </div> </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2012, Agendaless Consulting.</div> - </div> </body> </html> diff --git a/pyramid/scaffolds/starter/+package+/templates/mytemplate.pt_tmpl b/pyramid/scaffolds/starter/+package+/templates/mytemplate.pt_tmpl index 4a71dd992..34706ec2f 100644 --- a/pyramid/scaffolds/starter/+package+/templates/mytemplate.pt_tmpl +++ b/pyramid/scaffolds/starter/+package+/templates/mytemplate.pt_tmpl @@ -69,8 +69,5 @@ </div> </div> </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2012, Agendaless Consulting.</div> - </div> </body> </html> diff --git a/pyramid/scaffolds/zodb/+package+/templates/mytemplate.pt b/pyramid/scaffolds/zodb/+package+/templates/mytemplate.pt index 5391509fe..200dac6d0 100644 --- a/pyramid/scaffolds/zodb/+package+/templates/mytemplate.pt +++ b/pyramid/scaffolds/zodb/+package+/templates/mytemplate.pt @@ -69,8 +69,5 @@ </div> </div> </div> - <div id="footer"> - <div class="footer">© Copyright 2008-2012, Agendaless Consulting.</div> - </div> </body> </html> diff --git a/pyramid/tests/fixtures/dummy.ini b/pyramid/tests/fixtures/dummy.ini new file mode 100644 index 000000000..bc2281168 --- /dev/null +++ b/pyramid/tests/fixtures/dummy.ini @@ -0,0 +1,4 @@ +[app:myapp] +use = call:pyramid.tests.test_paster:make_dummyapp + +foo = %(bar)s diff --git a/pyramid/tests/fixtures/hello .world.mako b/pyramid/tests/fixtures/hello .world.mako new file mode 100644 index 000000000..7a06eed97 --- /dev/null +++ b/pyramid/tests/fixtures/hello .world.mako @@ -0,0 +1,3 @@ +## -*- coding: utf-8 -*- +<%!from pyramid.compat import text_%><% a, b = 'foo', text_('föö', 'utf-8') %> +Hello ${text_('föö', 'utf-8')}
\ No newline at end of file diff --git a/pyramid/tests/test_config/test_views.py b/pyramid/tests/test_config/test_views.py index 5388001f6..94bc497ba 100644 --- a/pyramid/tests/test_config/test_views.py +++ b/pyramid/tests/test_config/test_views.py @@ -2791,7 +2791,8 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(len(logger.messages), 1) self.assertEqual(logger.messages[0], "debug_authorization of url url (view name " - "'view_name' against context None): False") + "'view_name' against context None): " + "Allowed (NO_PERMISSION_REQUIRED)") def test_secured_view_authn_policy_no_authz_policy(self): response = DummyResponse() diff --git a/pyramid/tests/test_mako_templating.py b/pyramid/tests/test_mako_templating.py index 37264aa48..50ef360d9 100644 --- a/pyramid/tests/test_mako_templating.py +++ b/pyramid/tests/test_mako_templating.py @@ -270,6 +270,34 @@ class Test_renderer_factory(Base, unittest.TestCase): self.assertEqual(renderer.lookup, lookup) self.assertEqual(renderer.path, 'helloworld.mak') + def test_space_dot_name(self): + from pyramid.mako_templating import renderer_factory + + info = DummyRendererInfo({ + 'name':'hello .world.mako', + 'package':None, + 'registry':self.config.registry, + 'settings':{}, + }) + + result = renderer_factory(info) + self.assertEqual(result.path, 'hello .world.mako') + self.assertTrue(result.defname is None) + + def test_space_dot_name_def(self): + from pyramid.mako_templating import renderer_factory + + info = DummyRendererInfo({ + 'name':'hello .world#comp.mako', + 'package':None, + 'registry':self.config.registry, + 'settings':{}, + }) + + result = renderer_factory(info) + self.assertEqual(result.path, 'hello .world.mako') + self.assertEqual(result.defname, 'comp') + class MakoRendererFactoryHelperTests(Base, unittest.TestCase): def _getTargetClass(self): from pyramid.mako_templating import MakoRendererFactoryHelper diff --git a/pyramid/tests/test_paster.py b/pyramid/tests/test_paster.py index b72e0e6b6..5e341172c 100644 --- a/pyramid/tests/test_paster.py +++ b/pyramid/tests/test_paster.py @@ -1,12 +1,12 @@ import os import unittest +here = os.path.dirname(__file__) + class Test_get_app(unittest.TestCase): - def _callFUT(self, config_file, section_name, options=None, loadapp=None): + def _callFUT(self, config_file, section_name, **kw): from pyramid.paster import get_app - return get_app( - config_file, section_name, options=options, loadapp=loadapp - ) + return get_app(config_file, section_name, **kw) def test_it(self): app = DummyApp() @@ -55,15 +55,23 @@ class Test_get_app(unittest.TestCase): self.assertEqual(loadapp.kw, {'global_conf':options}) self.assertEqual(result, app) + def test_it_with_dummyapp_requiring_options(self): + options = {'bar': 'baz'} + app = self._callFUT( + os.path.join(here, 'fixtures', 'dummy.ini'), + 'myapp', options=options) + self.assertEqual(app.settings['foo'], 'baz') + class Test_get_appsettings(unittest.TestCase): - def _callFUT(self, config_file, section_name, appconfig): + def _callFUT(self, config_file, section_name, **kw): from pyramid.paster import get_appsettings - return get_appsettings(config_file, section_name, appconfig) + return get_appsettings(config_file, section_name, **kw) def test_it(self): values = {'a':1} appconfig = DummyLoadWSGI(values) - result = self._callFUT('/foo/bar/myapp.ini', 'myapp', appconfig) + result = self._callFUT('/foo/bar/myapp.ini', 'myapp', + appconfig=appconfig) self.assertEqual(appconfig.config_name, 'config:/foo/bar/myapp.ini') self.assertEqual(appconfig.section_name, 'myapp') self.assertEqual(appconfig.relative_to, os.getcwd()) @@ -72,7 +80,8 @@ class Test_get_appsettings(unittest.TestCase): def test_it_with_hash(self): values = {'a':1} appconfig = DummyLoadWSGI(values) - result = self._callFUT('/foo/bar/myapp.ini#myapp', None, appconfig) + result = self._callFUT('/foo/bar/myapp.ini#myapp', None, + appconfig=appconfig) self.assertEqual(appconfig.config_name, 'config:/foo/bar/myapp.ini') self.assertEqual(appconfig.section_name, 'myapp') self.assertEqual(appconfig.relative_to, os.getcwd()) @@ -81,12 +90,20 @@ class Test_get_appsettings(unittest.TestCase): def test_it_with_hash_and_name_override(self): values = {'a':1} appconfig = DummyLoadWSGI(values) - result = self._callFUT('/foo/bar/myapp.ini#myapp', 'yourapp', appconfig) + result = self._callFUT('/foo/bar/myapp.ini#myapp', 'yourapp', + appconfig=appconfig) self.assertEqual(appconfig.config_name, 'config:/foo/bar/myapp.ini') self.assertEqual(appconfig.section_name, 'yourapp') self.assertEqual(appconfig.relative_to, os.getcwd()) self.assertEqual(result, values) + def test_it_with_dummyapp_requiring_options(self): + options = {'bar': 'baz'} + result = self._callFUT( + os.path.join(here, 'fixtures', 'dummy.ini'), + 'myapp', options=options) + self.assertEqual(result['foo'], 'baz') + class Test_setup_logging(unittest.TestCase): def _callFUT(self, config_file): from pyramid.paster import setup_logging @@ -165,6 +182,12 @@ class DummyApp: def __init__(self): self.registry = dummy_registry +def make_dummyapp(global_conf, **settings): + app = DummyApp() + app.settings = settings + app.global_conf = global_conf + return app + class DummyRequest: application_url = 'http://example.com:5432' script_name = '' @@ -181,6 +204,3 @@ class DummyConfigParser(object): class DummyConfigParserModule(object): ConfigParser = DummyConfigParser - - - diff --git a/pyramid/util.py b/pyramid/util.py index 56049af87..02bd7ba2a 100644 --- a/pyramid/util.py +++ b/pyramid/util.py @@ -234,18 +234,15 @@ def object_description(object): """ Produce a human-consumable text description of ``object``, usually involving a Python dotted name. For example: - .. code-block:: python - - >>> object_description(None) - u'None' - >>> from xml.dom import minidom - >>> object_description(minidom) - u'module xml.dom.minidom' - >>> object_description(minidom.Attr) - u'class xml.dom.minidom.Attr' - >>> object_description(minidom.Attr.appendChild) - u'method appendChild of class xml.dom.minidom.Attr' - >>> + >>> object_description(None) + u'None' + >>> from xml.dom import minidom + >>> object_description(minidom) + u'module xml.dom.minidom' + >>> object_description(minidom.Attr) + u'class xml.dom.minidom.Attr' + >>> object_description(minidom.Attr.appendChild) + u'method appendChild of class xml.dom.minidom.Attr' If this method cannot identify the type of the object, a generic description ala ``object <object.__name__>`` will be returned. @@ -1,6 +1,6 @@ ############################################################################## # -# Copyright (c) 2008-2011 Agendaless Consulting and Contributors. +# Copyright (c) 2008-2013 Agendaless Consulting and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the BSD-like license at |
