View
@@ -3,14 +3,16 @@ Hacking on Pyramid
Here are some guidelines for hacking on Pyramid.
Using a Development Checkout
----------------------------
You'll have to create a development environment to hack on Pyramid, using a
Pyramid checkout. You can either do this by hand, or if you have ``tox``
installed (it's on PyPI), you can use tox to set up a working development
installed (it's on PyPI), you can use ``tox`` to set up a working development
environment. Each installation method is described below.
By Hand
+++++++
@@ -26,180 +28,191 @@ By Hand
substituting your account username and specifying the destination as
"hack-on-pyramid".
$ cd ~
$ git clone git@github.com:USERNAME/pyramid.git hack-on-pyramid
$ cd hack-on-pyramid
# Configure remotes such that you can pull changes from the Pyramid
# repository into your local repository.
$ git remote add upstream https://github.com/Pylons/pyramid.git
# fetch and merge changes from upstream into master
$ git fetch upstream
$ git merge upstream/master
$ cd ~
$ git clone git@github.com:USERNAME/pyramid.git hack-on-pyramid
$ cd hack-on-pyramid
# Configure remotes such that you can pull changes from the Pyramid
# repository into your local repository.
$ git remote add upstream https://github.com/Pylons/pyramid.git
# fetch and merge changes from upstream into master
$ git fetch upstream
$ git merge upstream/master
Now your local repo is set up such that you will push changes to your GitHub
repo, from which you can submit a pull request.
- Create a virtualenv in which to install Pyramid:
$ cd ~/hack-on-pyramid
$ virtualenv -ppython2.7 env
- Create a virtual environment in which to install Pyramid:
Note that very old versions of virtualenv (virtualenv versions below, say,
1.10 or thereabouts) require you to pass a ``--no-site-packages`` flag to
get a completely isolated environment.
You can choose which Python version you want to use by passing a ``-p``
flag to ``virtualenv``. For example, ``virtualenv -ppython2.7``
chooses the Python 2.7 interpreter to be installed.
$ cd ~/hack-on-pyramid
$ python3 -m venv env
From here on in within these instructions, the ``~/hack-on-pyramid/env``
virtual environment you created above will be referred to as ``$VENV``.
To use the instructions in the steps that follow literally, use the
``export VENV=~/hack-on-pyramid/env`` command.
- Install ``setuptools-git`` into the virtualenv (for good measure, as we're
using git to do version control):
$ $VENV/bin/easy_install setuptools-git
- Install Pyramid from the checkout into the virtualenv using ``setup.py
dev``. ``setup.py dev`` is an alias for "setup.py develop" which also
installs testing requirements such as nose and coverage. Running
``setup.py dev`` *must* be done while the current working directory is the
``pyramid`` checkout directory:
- Install Pyramid from the checkout into the virtual environment, where the
current working directory is the ``pyramid`` checkout directory. We will
install Pyramid in editable (development) mode as well as its testing
requirements.
$ cd ~/hack-on-pyramid
$ $VENV/bin/python setup.py dev
$ cd ~/hack-on-pyramid
$ $VENV/bin/pip install -e ".[testing,docs]"
- Optionally create a new Pyramid project using ``pcreate``:
$ cd $VENV
$ bin/pcreate -s starter starter
$ cd $VENV
$ bin/pcreate -s starter starter
- ...and install the new project (also using ``setup.py develop``) into the
virtualenv:
- ...and install the new project into the virtual environment:
$ cd $VENV/starter
$ $VENV/bin/python setup.py develop
$ cd $VENV/starter
$ $VENV/bin/pip install -e .
Using Tox
+++++++++
Using ``Tox``
+++++++++++++
Alternatively, if you already have ``tox`` installed, there is an easier
way to get going.
- Create a new directory somewhere and ``cd`` to it:
$ mkdir ~/hack-on-pyramid
$ cd ~/hack-on-pyramid
$ mkdir ~/hack-on-pyramid
$ cd ~/hack-on-pyramid
- Check out a read-only copy of the Pyramid source:
$ git clone git://github.com/Pylons/pyramid.git .
$ git clone git://github.com/Pylons/pyramid.git .
Alternatively, create a writeable fork on GitHub and clone it.
(alternately, create a writeable fork on GitHub and check that out).
Since Pyramid is a framework and not an application, it can be convenient to
work against a sample application, preferably in its own virtual environment. A
quick way to achieve this is to use `tox
<http://tox.readthedocs.org/en/latest/>`_ with a custom configuration file
that is part of the checkout:
Since Pyramid is a framework and not an application, it can be
convenient to work against a sample application, preferably in its own
virtualenv. A quick way to achieve this is to (ab-)use ``tox``
(http://tox.readthedocs.org/en/latest/) with a custom configuration
file that's part of the checkout:
$ tox -c hacking-tox.ini
tox -c hacking-tox.ini
This will create a python-2.7 based virtual environment named ``env27``
(Pyramid's ``.gitconfig` ignores all top-level folders that start with ``env``
specifically in our use case), and inside that a simple pyramid application
named ``hacking`` that you can then fire up like so:
This will create a python-2.7 based virtualenv named ``env27`` (Pyramid's
``.gitconfig` ignores all top-level folders that start with ``env`` specifically
for this use case) and inside that a simple pyramid application named
``hacking`` that you can then fire up like so:
$ cd env27/hacking
$ ../bin/pip install -e ".[testing,docs]"
$ ../bin/pserve development.ini
cd env27/hacking
../bin/python setup.py develop
../bin/pserve development.ini
Adding Features
---------------
In order to add a feature to Pyramid:
- The feature must be documented in both the API and narrative
documentation (in ``docs/``).
- The feature must be documented in both the API and narrative documentation
(in ``docs/``).
- The feature must work fully on the following CPython versions: 2.6, 2.7, 3.2,
3.3, 3.4, and 3.5 on both UNIX and Windows.
- The feature must work fully on the following CPython versions: 2.7, 3.4, 3.5,
and 3.6 on both UNIX and Windows.
- The feature must work on the latest version of PyPy and PyPy3.
- The feature must work on the latest version of PyPy.
- The feature must not cause installation or runtime failure on App Engine.
If it doesn't cause installation or runtime failure, but doesn't actually
*work* on these platforms, that caveat should be spelled out in the
documentation.
- The feature must not depend on any particular persistence layer (filesystem,
SQL, etc).
- The feature must not depend on any particular persistence layer
(filesystem, SQL, etc).
- The feature must not add unnecessary dependencies (where "unnecessary" is of
course subjective, but new dependencies should be discussed).
- The feature must not add unnecessary dependencies (where
"unnecessary" is of course subjective, but new dependencies should
be discussed).
The above requirements are relaxed for scaffolding dependencies. If a scaffold
has an install-time dependency on something that doesn't work on a particular
platform, that caveat should be spelled out clearly in *its* documentation
(within its ``docs/`` directory).
The above requirements are relaxed for scaffolding dependencies. If a
scaffold has an install-time dependency on something that doesn't work on a
particular platform, that caveat should be spelled out clearly in *its*
documentation (within its ``docs/`` directory).
Coding Style
------------
- PEP8 compliance. Whitespace rules are relaxed: not necessary to put
2 newlines between classes. But 79-column lines, in particular, are
mandatory. See
http://docs.pylonsproject.org/en/latest/community/codestyle.html for more
- PEP8 compliance. Whitespace rules are relaxed: not necessary to put two
newlines between classes. But 79-column lines, in particular, are mandatory.
See https://pylonsproject.org/community-coding-style-standards.html for more
information.
- Please do not remove trailing whitespace. Configure your editor to reduce
diff noise. See https://github.com/Pylons/pyramid/issues/788 for more.
Running Tests
--------------
-------------
- To run all tests for Pyramid on a single Python version from your development
virtual environment (See *Using a Development Checkout* above), run
``nosetests``:
$ $VENV/bin/nosetests
- To run all tests for Pyramid on a single Python version, run ``nosetests``
from your development virtualenv (See *Using a Development Checkout* above).
- To run individual tests (i.e., during development), you can use ``nosetests``
syntax as follows:
- To run individual tests (i.e. during development) you can use a regular
expression with the ``-t`` parameter courtesy of the `nose-selecttests
<https://pypi.python.org/pypi/nose-selecttests/>`_ plugin that's been
installed (along with nose itself) via ``python setup.py dev``. The
easiest usage is to simply provide the verbatim name of the test you're
working on.
# run a single test
$ $VENV/bin/nosetests pyramid.tests.test_module:ClassName.test_mytestname
- To run the full set of Pyramid tests on all platforms, install ``tox``
(http://codespeak.net/~hpk/tox/) into a system Python. The ``tox`` console
script will be installed into the scripts location for that Python. While
# run all tests in a class
$ $VENV/bin/nosetests pyramid.tests.test_module:ClassName
Optionally you can install a nose plugin, `nose-selecttests
<https://pypi.org/project/nose-selecttests/>`_, and use a regular
expression with the ``-t`` parameter to run tests.
# run a single test
$ $VENV/bin/nosetests -t test_mytestname
- The ``tox.ini`` uses ``nose`` and ``coverage``. As such ``tox`` may be used
to run groups of tests or only a specific version of Python. For example, the
following command will run tests on Python 2.7 only without coverage:
$ tox -e py27
This command will run tests on the latest versions of Python 2 and 3 with
coverage totaled for both versions.
$ tox -e py2-cover,py3-cover,coverage
- To run the full set of Pyramid tests on all platforms, install `tox
<http://codespeak.net/~hpk/tox/>`_ into a system Python. The ``tox`` console
script will be installed into the scripts location for that Python. While
``cd``'ed to the Pyramid checkout root directory (it contains ``tox.ini``),
invoke the ``tox`` console script. This will read the ``tox.ini`` file and
execute the tests on multiple Python versions and platforms; while it runs,
it creates a virtualenv for each version/platform combination. For
example::
invoke the ``tox`` console script. This will read the ``tox.ini`` file and
execute the tests on multiple Python versions and platforms. While it runs,
it creates a virtual environment for each version/platform combination. For
example:
$ sudo /usr/bin/pip install tox
$ cd ~/hack-on-pyramid/
$ /usr/bin/tox
$ sudo /usr/bin/easy_install tox
$ cd ~/hack-on-pyramid/
$ /usr/bin/tox
- The tests can also be run using `pytest <http://pytest.org/>`_. This is
intended as a convenience for people who are more used to or fond of
``pytest``. Run the tests like so:
- The tests can also be run using ``pytest`` (http://pytest.org/). This is
intended as a convenience for people who are more used or fond of ``pytest``.
Run the tests like so::
$ $VENV/bin/pip install pytest
$ $VENV/bin/py.test --strict pyramid/
$ $VENV/bin/easy_install pytest
$ $VENV/bin/py.test --strict pyramid/
To run individual tests (i.e., during development), see "py.test usage -
Specifying tests / selecting tests":
http://pytest.org/latest/usage.html#specifying-tests-selecting-tests
- Functional tests related to the "scaffolds" (starter, zodb, alchemy) which
create a virtualenv, install the scaffold package and its dependencies, start
a server, and hit a URL on the server can be run like so::
create a virtual environment, install the scaffold package and its
dependencies, start a server, and hit a URL on the server, can be run like
so:
$ ./scaffoldtests.sh
$ ./scaffoldtests.sh
Alternatively:
Alternately::
$ tox -e{py27,py34,py35,pypy}-scaffolds
$ tox -e{py26,py27,py32,py33,py34,py35,pypy,pypy3}-scaffolds,
Test Coverage
-------------
@@ -208,6 +221,7 @@ Test Coverage
can test coverage via ``./coverage.sh`` (which itself just executes ``tox
-epy2-cover,py3-cover,coverage``).
Documentation Coverage and Building HTML Documentation
------------------------------------------------------
@@ -217,18 +231,18 @@ changed to reflect the bug fix, ideally in the same commit that fixes the bug
or adds the feature. To build and review docs, use the following steps.
1. In the main Pyramid checkout directory, run ``./builddocs.sh`` (which just
turns around and runs ``tox -e docs``)::
turns around and runs ``tox -e docs``):
$ ./builddocs.sh
$ ./builddocs.sh
2. Open the ``docs/_build/html/index.html`` file to see the resulting HTML
rendering.
Change Log
----------
- Feature additions and bugfixes must be added to the ``CHANGES.txt``
- Feature additions and bugfixes must be added to the ``CHANGES.rst``
file in the prevailing style. Changelog entries should be long and
descriptive, not cryptic. Other developers should be able to know
what your changelog entry means.
View

Large diffs are not rendered by default.

Oops, something went wrong.
View
@@ -0,0 +1,16 @@
graft pyramid
graft docs
prune docs/_build
include README.rst
include CHANGES.rst HISTORY.rst BFG_HISTORY.rst
include CONTRIBUTORS.txt LICENSE.txt COPYRIGHT.txt
include contributing.md RELEASING.txt
include tox.ini appveyor.yml .travis.yml rtd.txt
include HACKING.txt hacking-tox.ini
include builddocs.sh coverage.sh scaffoldtests.sh
include TODO.txt
global-exclude __pycache__ *.py[cod]
View
@@ -3,37 +3,53 @@ Pyramid
.. image:: https://travis-ci.org/Pylons/pyramid.png?branch=master
:target: https://travis-ci.org/Pylons/pyramid
:alt: master Travis CI Status
.. image:: https://readthedocs.org/projects/pyramid/badge/?version=master
:target: http://docs.pylonsproject.org/projects/pyramid/en/master/
:alt: Master Documentation Status
.. image:: https://readthedocs.org/projects/pyramid/badge/?version=latest
:target: http://docs.pylonsproject.org/projects/pyramid/en/latest/
:alt: Latest Documentation Status
:target: https://docs.pylonsproject.org/projects/pyramid/en/master
:alt: master Documentation Status
.. image:: https://img.shields.io/badge/irc-freenode-blue.svg
:target: https://webchat.freenode.net/?channels=pyramid
:alt: IRC Freenode
Pyramid is a small, fast, down-to-earth, open source Python web framework. It
makes real-world web application development and deployment more fun, more
predictable, and more productive.
`Pyramid <https://trypyramid.com/>`_ is a small, fast, down-to-earth, open
source Python web framework. It makes real-world web application development
and deployment more fun, more predictable, and more productive.
.. code-block:: python
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
Pyramid is produced by the `Pylons Project <http://pylonsproject.org/>`_.
def hello_world(request):
return Response('Hello %(name)s!' % request.matchdict)
if __name__ == '__main__':
with Configurator() as config:
config.add_route('hello', '/hello/{name}')
config.add_view(hello_world, route_name='hello')
app = config.make_wsgi_app()
server = make_server('0.0.0.0', 8080, app)
server.serve_forever()
Pyramid is a project of the `Pylons Project <https://pylonsproject.org>`_.
Support and Documentation
-------------------------
See the `Pylons Project website <http://pylonsproject.org/>`_ to view
documentation, report bugs, and obtain support.
See `Pyramid Support and Development
<https://docs.pylonsproject.org/projects/pyramid/en/latest/#support-and-development>`_
for documentation, reporting bugs, and getting support.
Developing and Contributing
---------------------------
See ``HACKING.txt`` and ``contributing.md`` for guidelines for running tests,
adding features, coding style, and updating documentation when developing in or
contributing to Pyramid.
See `HACKING.txt <https://github.com/Pylons/pyramid/blob/master/HACKING.txt>`_ and
`contributing.md <https://github.com/Pylons/pyramid/blob/master/contributing.md>`_
for guidelines on running tests, adding features, coding style, and updating
documentation when developing in or contributing to Pyramid.
License
-------
@@ -44,6 +60,6 @@ Pyramid is offered under the BSD-derived `Repoze Public License
Authors
-------
Pyramid is made available by `Agendaless Consulting <http://agendaless.com>`_
and a team of contributors.
Pyramid is made available by `Agendaless Consulting <https://agendaless.com>`_
and a team of `contributors
<https://github.com/Pylons/pyramid/graphs/contributors>`_.
View
@@ -6,12 +6,19 @@ Releasing Pyramid
- Alpha, beta, dev and similar statuses do not qualify whether a release is
major or minor. The term "pre-release" means alpha, beta, or dev.
- A release is final when it is no longer pre-release.
- A *major* release is where the first number either before or after the
first dot increases. Examples: 1.6 to 1.7a1, or 1.8 to 2.0.
- A *minor* or *bug fix* release is where the number after the second dot
increases. Example: 1.6 to 1.6.1.
Prepare new release branch
--------------------------
- Create a new release branch, incrementing the version number.
- Do any necessary branch merges (e.g., master to branch, branch to master).
- On release branch:
@@ -26,21 +33,31 @@ Releasing Pyramid
- Run tests on Windows if feasible.
- Make sure all scaffold tests pass (Py 2.7, 3.3, 3.4, 3.5, pypy, and pypy3 on
UNIX; this doesn't work on Windows):
- Make sure all scaffold tests pass (CPython 2.7, 3.4, 3.5, and 3.6, and PyPy
on UNIX; this doesn't work on Windows):
$ ./scaffoldtests.sh
- Ensure all features of the release are documented (audit CHANGES.txt or
- For each ``pyramid-cookiecutter-*``, make a new branch off "master" with the
same name to align with the new Pyramid release branch name.
- In the docs, update the ``cookiecutter`` command with the new branch name,
for example, ``cookiecutter gh:Pylons/pyramid-cookiecutter-starter --checkout
x.y-branch``. A search for ``cookiecutter gh:Pylons/pyramid-cookiecutter-``
should return all instances to be updated.
- Ensure all features of the release are documented (audit CHANGES.rst or
communicate with contributors).
- Copy relevant changes (delta bug fixes) from CHANGES.txt to
- Change CHANGES.rst heading to reflect the new version number.
- Copy relevant changes (delta bug fixes) from CHANGES.rst to
docs/whatsnew-X.X (if it's a major release). Minor releases should
include a link under "Bug Fix Releases" to the minor feature
changes in CHANGES.txt.
changes in CHANGES.rst.
- Update README.rst to use correct versions of badges and URLs according to
each branch and context, i.e., RTD "latest" == GitHub/Travis "1.x-branch".
- Update README.rst to use correct versions of badges, URLs, and ALT option
according to the new release branch name.
- Update whatsnew-X.X.rst in docs to point at change log entries for individual
releases if applicable.
@@ -52,15 +69,12 @@ Releasing Pyramid
branch, and previously released branch. Also in the previously released
branch only, uncomment the sections to enable pylons_sphinx_latesturl.
- Change setup.py version to the new version number on both master and the new
branch.
- Change setup.py version to the release version number.
- Change CHANGES.txt heading to reflect the new version number.
- Make sure PyPI long description renders (requires ``collective.dist``
- Make sure PyPI long description renders (requires ``readme_renderer``
installed into your Python)::
$ python setup.py check -r
$ python setup.py check -r -s -m
- Create a release tag.
@@ -70,47 +84,105 @@ Releasing Pyramid
$ python setup.py sdist bdist_wheel
$ twine upload dist/pyramid-X.X-*
- Edit Pylons/pylonshq/templates/home/home.mako.
- Configure RTD to publish the new release version of the docs.
Prepare master for further development (major releases only)
------------------------------------------------------------
- Checkout master.
- In CHANGES.rst, preserve headings but clear out content. Add heading
"unreleased" for the version number.
- From the release branch, forward port the changes in CHANGES.rst to
HISTORY.rst.
- In contributing.md, forward port branch descriptions from release branch.
- In docs/conf.py, add a commented line under
pylons_sphinx_latesturl_pagename_overrides for the release.
- Change setup.py version to the next version number.
- Update README.rst to use correct versions of badges, URLs, and ALT option
for "master" instead of the major release version.
- Edit Pylons/pylonshq/templates/home/inside.rst for major releases only.
- In the docs, update the ``cookiecutter`` command with ``master``,
for example, ``cookiecutter gh:Pylons/pyramid-cookiecutter-starter --checkout
master``. A search for ``cookiecutter gh:Pylons/pyramid-cookiecutter-``
should return all instances to be updated.
- Edit Pylons/trypyramid.com/src/templates/resources.html for major releases
only.
Update previous version (final releases only)
---------------------------------------------
- Edit Pylons/pylonsrtd/pylonsrtd/docs/pyramid.rst for major releases only.
- In docs/conf.py, update values under html_theme_options for in_progress and
outdated. Uncomment the sections to enable pylons_sphinx_latesturl.
- Configure RTD to point the "latest" alias to the new release version of the
docs.
Cookiecutters
-------------
- For each cookiecutter, clone the newly released branch to "latest" branch.
Marketing and communications
----------------------------
- Edit Pylons/trypyramid.com/src/templates/resources.html for major releases,
pre-releases, and once pre-releases are final.
- Edit `http://wiki.python.org/moin/WebFrameworks
<http://wiki.python.org/moin/WebFrameworks>`_.
- Publish new version of docs.
- Edit `https://en.wikipedia.org/wiki/Pylons_project <https://en.wikipedia.org/wiki/Pylons_project>`_.
- Announce to maillist.
- Edit `https://en.wikipedia.org/wiki/Comparison_of_web_frameworks <https://en.wikipedia.org/wiki/Comparison_of_web_frameworks>`_.
- Announce to Twitter.
Announcement template
----------------------
```
Pyramid 1.x released.
Pyramid 1.X.X has been released.
PyPI
https://pypi.org/project/pyramid/1.x/
=== One time only for new version, first pre-release ===
What's New
https://docs.pylonsproject.org/projects/pyramid/en/1.X-branch/whatsnew-1.X.html
=== For all subsequent pre-releases ===
Changes
https://docs.pylonsproject.org/projects/pyramid/en/1.X-branch/changes.html#version-yyyy-mm-dd
Issues
https://github.com/Pylons/pyramid/issues
```
Here are the changes:
- Announce to maillist.
```
Pyramid 1.X.X has been released.
<<changes>>
The full changelog is here:
https://docs.pylonsproject.org/projects/pyramid/en/1.X-branch/changes.html
A "What's New In Pyramid 1.X" document exists at
http://docs.pylonsproject.org/projects/pyramid/1.X/whatsnew-1.X.html .
What's New In Pyramid 1.X:
https://docs.pylonsproject.org/projects/pyramid/en/1.X-branch/whatsnew-1.X.html
You will be able to see the 1.X release documentation (across all
alphas and betas, as well as when it eventually gets to final release)
at http://docs.pylonsproject.org/projects/pyramid/1.X/ .
1.X release documentation (across all alphas and betas, as well as when it gets
to final release):
https://docs.pylonsproject.org/projects/pyramid/en/1.X-branch/
You can install it via PyPI:
easy_install Pyramid==1.X
pip install Pyramid==1.X
Enjoy, and please report any issues you find to the issue tracker at
https://github.com/Pylons/pyramid/issues
Thanks!
- C
- Pyramid core developers
```
View
@@ -114,15 +114,7 @@ Nice-to-Have
Future
------
- 1.6: turn ``pyramid.settings.Settings`` into a function that returns the
original dict (after ``__getattr__`` deprecation period, it was deprecated
in 1.2).
- 1.6: Remove IContextURL and TraversalContextURL.
- 1.8: Remove set_request_property.
- 1.8: Drop Python 3.3 support.
- 1.9: Remove set_request_property.
- 1.9: Remove extra code enabling ``pyramid.security.remember(principal=...)``
and force use of ``userid``.
View
@@ -0,0 +1,21 @@
environment:
matrix:
- PYTHON: "C:\\Python36"
TOXENV: "py36"
- PYTHON: "C:\\Python35"
TOXENV: "py35"
- PYTHON: "C:\\Python27"
TOXENV: "py27"
cache:
- '%LOCALAPPDATA%\pip\Cache'
version: '{branch}.{build}'
install:
- "%PYTHON%\\python.exe -m pip install tox"
build: off
test_script:
- "%PYTHON%\\Scripts\\tox.exe"
View
@@ -3,9 +3,9 @@ Contributing
All projects under the Pylons Projects, including this one, follow the
guidelines established at [How to
Contribute](http://www.pylonsproject.org/community/how-to-contribute) and
Contribute](https://pylonsproject.org/community-how-to-contribute.html) and
[Coding Style and
Standards](http://docs.pylonsproject.org/en/latest/community/codestyle.html).
Standards](https://pylonsproject.org/community-coding-style-standards.html).
You can contribute to this project in several ways.
@@ -25,11 +25,11 @@ Git branches and their purpose and status at the time of this writing are
listed below.
* [master](https://github.com/Pylons/pyramid/) - The branch on which further
development takes place. The default branch on GitHub.
* [1.6-branch](https://github.com/Pylons/pyramid/tree/1.6-branch) - The branch
classified as "stable" or "latest". Actively maintained.
* [1.5-branch](https://github.com/Pylons/pyramid/tree/1.5-branch) - The oldest
actively maintained and stable branch.
development takes place. The default branch on GitHub.
* [1.9-branch](https://github.com/Pylons/pyramid/tree/1.9-branch) - The branch
classified as "stable" or "latest".
* [1.8-branch](https://github.com/Pylons/pyramid/tree/1.8-branch) - The oldest
actively maintained and stable branch.
Older branches are not actively maintained. In general, two stable branches and
one or two development branches are actively maintained.
@@ -49,18 +49,22 @@ Building documentation for a Pylons Project project
improve the process for Windows users are welcome by submitting an issue or a
pull request. Windows users may find it helpful to follow the guide [Installing
Pyramid on a Windows
System](http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.html#installing-pyramid-on-a-windows-system).
System](https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.html#installing-pyramid-on-a-windows-system).
1. Fork the repo on GitHub by clicking the [Fork] button.
2. Clone your fork into a workspace on your local machine.
git clone git@github.com:<username>/pyramid.git
3. Add a git remote "upstream" for the cloned fork.
3. Change directories into the cloned repository
cd pyramid
4. Add a git remote "upstream" for the cloned fork.
git remote add upstream git@github.com:Pylons/pyramid.git
4. Set an environment variable as instructed in the
5. Create a virtual environment and set an environment variable as instructed in the
[prerequisites](https://github.com/Pylons/pyramid/blob/master/HACKING.txt#L55-L58).
# Mac and Linux
@@ -69,36 +73,34 @@ System](http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.ht
# Windows
set VENV=c:\hack-on-pyramid\env
5. Try to build the docs in your workspace.
6. Install `tox` into your virtual environment.
# Mac and Linux
$ make clean html SPHINXBUILD=$VENV/bin/sphinx-build
$ $VENV/bin/pip install tox
# Windows
c:\> make clean html SPHINXBUILD=%VENV%\bin\sphinx-build
7. Try to build the docs in your workspace.
$ $VENV/bin/tox -e docs
If successful, then you can make changes to the documentation. You can
load the built documentation in the `/_build/html/` directory in a web
browser.
When the build finishes, you'll find HTML documentation rendered in
`.tox/docs/html`. An `epub` version will be in `.tox/docs/epub`. And the
result of the tests that are run on the documentation will be in
`.tox/docs/doctest`.
6. From this point forward, follow the typical [git
8. From this point forward, follow the typical [git
workflow](https://help.github.com/articles/what-is-a-good-git-workflow/).
Start by pulling from the upstream to get the most current changes.
*Always* start by pulling from the upstream to get the most current changes.
git pull upstream master
7. Make a branch, make changes to the docs, and rebuild them as indicated in
step 5. To speed up the build process, you can omit `clean` from the above
command to rebuild only those pages that depend on the files you have
changed.
9. Make a branch, make changes to the docs, and rebuild them as indicated above.
8. Once you are satisfied with your changes and the documentation builds
successfully without errors or warnings, then git commit and push them to
your "origin" repository on GitHub.
10. Once you are satisfied with your changes and the documentation builds
successfully without errors or warnings, then git commit and push them to
your "origin" repository on GitHub.
git commit -m "commit message"
git push -u origin --all # first time only, subsequent can be just 'git push'.
9. Create a [pull request](https://help.github.com/articles/using-pull-requests/).
11. Create a [pull request](https://help.github.com/articles/using-pull-requests/).
10. Repeat the process starting from Step 6.
12. Repeat the process starting from Step 8.
View
@@ -12,20 +12,31 @@ PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html web pickle htmlhelp latex changes linkcheck
.PHONY: help clean html text web pickle htmlhelp latex latexpdf xelatexpdf changes linkcheck epub doctest
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " pickle to make pickle files (usable by e.g. sphinx-web)"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " changes to make an overview over all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " html to make standalone HTML files"
@echo " text to make text files"
@echo " pickle to make pickle files (usable by e.g. sphinx-web)"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " xelatexpdf to make LaTeX files and run them through xelatex"
@echo " changes to make an overview over all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " epub to make an epub"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
xelatexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through xelatex..."
$(MAKE) PDFLATEX=xelatex -C $(BUILDDIR)/latex all-pdf
@echo "xelatex finished; the PDF files are in $(BUILDDIR)/latex."
html:
mkdir -p $(BUILDDIR)/html $(BUILDDIR)/doctrees
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@@ -64,7 +75,7 @@ latex:
cp _static/latex-note.png $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make latexpdf' to build a PDF file from them."
@echo "Run \`make xelatexpdf' to build a PDF file from them."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@@ -90,3 +101,7 @@ epub:
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
View

Large diffs are not rendered by default.

Oops, something went wrong.
View
Binary file not shown.
View

Large diffs are not rendered by default.

Oops, something went wrong.
View
@@ -34,5 +34,10 @@ Helper Classes
.. autoclass:: AuthTktCookieHelper
:members:
.. autoclass:: HTTPBasicCredentials
:members:
Helper Functions
~~~~~~~~~~~~~~~~
.. autofunction:: extract_http_basic_credentials
View
@@ -26,6 +26,7 @@
.. automethod:: add_view
.. automethod:: add_notfound_view
.. automethod:: add_forbidden_view
.. automethod:: add_exception_view
:methodcategory:`Adding an Event Subscriber`
@@ -35,6 +36,8 @@
.. automethod:: set_authentication_policy
.. automethod:: set_authorization_policy
.. automethod:: set_default_csrf_options
.. automethod:: set_csrf_storage_policy
.. automethod:: set_default_permission
.. automethod:: add_permission
@@ -65,8 +68,10 @@
.. automethod:: add_traverser
.. automethod:: add_tween
.. automethod:: add_route_predicate
.. automethod:: add_subscriber_predicate
.. automethod:: add_view_predicate
.. automethod:: add_view_deriver
.. automethod:: set_execution_policy
.. automethod:: set_request_factory
.. automethod:: set_root_factory
.. automethod:: set_session_factory
View
@@ -0,0 +1,23 @@
.. _csrf_module:
:mod:`pyramid.csrf`
-------------------
.. automodule:: pyramid.csrf
.. autoclass:: LegacySessionCSRFStoragePolicy
:members:
.. autoclass:: SessionCSRFStoragePolicy
:members:
.. autoclass:: CookieCSRFStoragePolicy
:members:
.. autofunction:: get_csrf_token
.. autofunction:: new_csrf_token
.. autofunction:: check_csrf_origin
.. autofunction:: check_csrf_token
View
@@ -51,6 +51,8 @@
.. autoexception:: HTTPTemporaryRedirect
.. autoexception:: HTTPPermanentRedirect
.. autoexception:: HTTPBadRequest
.. autoexception:: HTTPUnauthorized
View
@@ -6,6 +6,7 @@
.. automodule:: pyramid.i18n
.. autoclass:: TranslationString
:noindex:
.. autofunction:: TranslationStringFactory
View
@@ -1,4 +1,4 @@
.. _html_api_documentation:
.. _api_documentation:
API Documentation
=================
View
@@ -44,6 +44,9 @@ Other Interfaces
.. autointerface:: IRoutePregenerator
:members:
.. autointerface:: ICSRFStoragePolicy
:members:
.. autointerface:: ISession
:members:
@@ -59,9 +62,15 @@ Other Interfaces
.. autointerface:: IRenderer
:members:
.. autointerface:: IRequestFactory
:members:
.. autointerface:: IResponseFactory
:members:
.. autointerface:: IRouter
:members:
.. autointerface:: IViewMapperFactory
:members:
View
@@ -7,8 +7,8 @@
.. autofunction:: bootstrap
.. autofunction:: get_app(config_uri, name=None, options=None)
.. autofunction:: get_app
.. autofunction:: get_appsettings(config_uri, name=None, options=None)
.. autofunction:: get_appsettings
.. autofunction:: setup_logging(config_uri, global_conf=None)
.. autofunction:: setup_logging
View
@@ -80,15 +80,23 @@ Return Values
'george', 'read')`` that means deny access. A sequence of ACEs
makes up an ACL. It is a string, and its actual value is "Deny".
.. autoclass:: Denied
:members: msg
.. automethod:: __new__
.. autoclass:: Allowed
:members: msg
.. automethod:: __new__
.. autoclass:: ACLDenied
:members:
:members: msg
.. autoclass:: ACLAllowed
:members:
.. automethod:: __new__
.. autoclass:: Denied
:members:
.. autoclass:: ACLAllowed
:members: msg
.. autoclass:: Allowed
:members:
.. automethod:: __new__
View
@@ -9,10 +9,6 @@
.. autofunction:: signed_deserialize
.. autofunction:: check_csrf_origin
.. autofunction:: check_csrf_token
.. autofunction:: SignedCookieSessionFactory
.. autofunction:: UnencryptedCookieSessionFactoryConfig
View
@@ -5,7 +5,7 @@
.. automodule:: pyramid.url
.. autofunction:: pyramid.url.resource_url(context, request, *elements, query=None, anchor=None)
.. autofunction:: resource_url
.. autofunction:: route_url
View
@@ -23,4 +23,11 @@
.. autoclass:: forbidden_view_config
:members:
.. autoclass:: exception_view_config
:members:
.. attribute:: UseSubrequest
Object passed to :meth:`pyramid.config.Configurator.add_notfound_view` as
the value to ``append_slash`` if you wish to cause a :term:`subrequest`
rather than a redirect.
View
@@ -54,7 +54,14 @@ technologies.
Book Content
============
This book is divided into three major parts:
This book is divided into four major parts:
:ref:`tutorials`
Each tutorial builds a sample application or implements a set of
concepts with a sample; it then describes the application or
concepts in terms of the sample. You should read the tutorials if
you want a guided tour of :app:`Pyramid`.
:ref:`narrative_documentation`
@@ -66,19 +73,16 @@ This book is divided into three major parts:
out-of-order, or when you need only a reminder about a particular
topic while you're developing an application.
:ref:`tutorials`
Each tutorial builds a sample application or implements a set of
concepts with a sample; it then describes the application or
concepts in terms of the sample. You should read the tutorials if
you want a guided tour of :app:`Pyramid`.
:ref:`api_documentation`
Comprehensive reference material for every public API exposed by
:app:`Pyramid`. The API documentation is organized
alphabetically by module name.
:ref:`pscripts_documentation`
``p*`` scripts included with :app:`Pyramid`.
.. index::
single: repoze.zope2
single: Zope 3
View
@@ -3,11 +3,11 @@
:app:`Pyramid` Change History
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. include:: ../CHANGES.txt
.. include:: ../CHANGES.rst
.. include:: ../HISTORY.txt
.. include:: ../HISTORY.rst
:mod:`repoze.bfg` Change History (previous name for Pyramid)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. include:: ../BFG_HISTORY.txt
.. include:: ../BFG_HISTORY.rst
View
@@ -49,36 +49,40 @@ def nothing(*arg):
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
'repoze.sphinx.autointerface',
'sphinx.ext.autodoc',
'sphinx.ext.doctest',
'repoze.sphinx.autointerface',
'sphinx.ext.viewcode',
'sphinx.ext.intersphinx',
'sphinxcontrib.programoutput',
'sphinx.ext.viewcode',
'sphinxcontrib.autoprogram',
# enable pylons_sphinx_latesturl when this branch is no longer "latest"
# 'pylons_sphinx_latesturl',
]
# Looks for objects in external projects
intersphinx_mapping = {
'colander': ('http://docs.pylonsproject.org/projects/colander/en/latest', None),
'cookbook': ('http://docs.pylonsproject.org/projects/pyramid-cookbook/en/latest/', None),
'deform': ('http://docs.pylonsproject.org/projects/deform/en/latest', None),
'jinja2': ('http://docs.pylonsproject.org/projects/pyramid-jinja2/en/latest/', None),
'pylonswebframework': ('http://docs.pylonsproject.org/projects/pylons-webframework/en/latest/', None),
'colander': ('https://docs.pylonsproject.org/projects/colander/en/latest', None),
'cookbook': ('https://docs.pylonsproject.org/projects/pyramid-cookbook/en/latest/', None),
'cookiecutter': ('https://cookiecutter.readthedocs.io/en/latest/', None),
'deform': ('https://docs.pylonsproject.org/projects/deform/en/latest', None),
'jinja2': ('https://docs.pylonsproject.org/projects/pyramid-jinja2/en/latest/', None),
'plaster': ('https://docs.pylonsproject.org/projects/plaster/en/latest/', None),
'pylonswebframework': ('https://docs.pylonsproject.org/projects/pylons-webframework/en/latest/', None),
'python': ('https://docs.python.org/3', None),
'pytest': ('http://pytest.org/latest/', None),
'pytest': ('https://docs.pytest.org/en/latest/', None),
'sphinx': ('http://www.sphinx-doc.org/en/latest', None),
'sqla': ('http://docs.sqlalchemy.org/en/latest', None),
'tm': ('http://docs.pylonsproject.org/projects/pyramid-tm/en/latest/', None),
'toolbar': ('http://docs.pylonsproject.org/projects/pyramid-debugtoolbar/en/latest', None),
'tstring': ('http://docs.pylonsproject.org/projects/translationstring/en/latest', None),
'tutorials': ('http://docs.pylonsproject.org/projects/pyramid-tutorials/en/latest/', None),
'venusian': ('http://docs.pylonsproject.org/projects/venusian/en/latest', None),
'webob': ('http://docs.webob.org/en/latest', None),
'tm': ('https://docs.pylonsproject.org/projects/pyramid-tm/en/latest/', None),
'toolbar': ('https://docs.pylonsproject.org/projects/pyramid-debugtoolbar/en/latest', None),
'tstring': ('https://docs.pylonsproject.org/projects/translationstring/en/latest', None),
'tutorials': ('https://docs.pylonsproject.org/projects/pyramid-tutorials/en/latest/', None),
'venusian': ('https://docs.pylonsproject.org/projects/venusian/en/latest', None),
'webob': ('https://docs.pylonsproject.org/projects/webob/en/latest/', None),
'webtest': ('http://webtest.pythonpaste.org/en/latest', None),
'who': ('http://repozewho.readthedocs.org/en/latest', None),
'zcml': ('http://docs.pylonsproject.org/projects/pyramid-zcml/en/latest', None),
'zcomponent': ('http://docs.zope.org/zope.component', None),
'who': ('http://repozewho.readthedocs.io/en/latest', None),
'zcml': ('https://docs.pylonsproject.org/projects/pyramid-zcml/en/latest', None),
'zcomponent': ('http://zopecomponent.readthedocs.io/en/latest/', None),
'zinterface': ('http://zopeinterface.readthedocs.io/en/latest/', None),
}
@@ -128,7 +132,7 @@ def nothing(*arg):
# -----------------------
# enable pylons_sphinx_latesturl when this branch is no longer "latest"
# pylons_sphinx_latesturl_base = (
# 'http://docs.pylonsproject.org/projects/pyramid/en/latest/')
# 'https://docs.pylonsproject.org/projects/pyramid/en/latest/')
# pylons_sphinx_latesturl_pagename_overrides = {
# # map old pagename -> new pagename
# 'whatsnew-1.0': 'index',
@@ -138,6 +142,9 @@ def nothing(*arg):
# 'whatsnew-1.4': 'index',
# 'whatsnew-1.5': 'index',
# 'whatsnew-1.6': 'index',
# 'whatsnew-1.7': 'index',
# 'whatsnew-1.8': 'index',
# 'whatsnew-1.9': 'index',
# 'tutorials/gae/index': 'index',
# 'api/chameleon_text': 'api',
# 'api/chameleon_zpt': 'api',
@@ -162,9 +169,8 @@ def nothing(*arg):
# using the given strftime format.
html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
html_use_smartypants = False # people use cutnpaste in some places
# Do not use smart quotes.
smartquotes = False
# Output file base name for HTML help builder.
htmlhelp_basename = 'pyramid'
@@ -178,7 +184,10 @@ def nothing(*arg):
# The font size ('10pt', '11pt' or '12pt').
latex_font_size = '10pt'
latex_additional_files = ['_static/latex-note.png', '_static/latex-warning.png']
latex_additional_files = [
'_static/latex-note.png',
'_static/latex-warning.png',
]
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, document class [howto/manual]).
@@ -190,10 +199,10 @@ def nothing(*arg):
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
latex_use_parts = True
latex_toplevel_sectioning = "section"
# If false, no module index is generated.
latex_use_modindex = False
latex_domain_indices = False
## Say, for a moment that you have a twoside document that needs a 3cm
## inner margin to allow for binding and at least two centimetres the
@@ -208,6 +217,17 @@ def nothing(*arg):
_PREAMBLE = r"""
\usepackage[]{geometry}
\geometry{bindingoffset=0.45in,textheight=7.25in,hdivide={0.5in,*,0.75in},vdivide={1in,7.25in,1in},papersize={7.5in,9.25in}}
%XeLaTeX packages
\usepackage{xltxtra}
\usepackage{fontspec} %Font package
\usepackage{xunicode}
%Select fonts
\setmainfont[Mapping=tex-text]{nimbusserif}
\setsansfont[Mapping=tex-text]{nimbussans}
\setmonofont{nimbusmono}
\hypersetup{
colorlinks=true,
linkcolor=black,
@@ -264,28 +284,22 @@ def nothing(*arg):
\definecolor{VerbatimColor}{rgb}{1,1,1}
\definecolor{VerbatimBorderColor}{rgb}{1,1,1}
\makeatletter
\renewcommand{\py@noticestart@warning}{\py@heavybox}
\renewcommand{\py@noticeend@warning}{\py@endheavybox}
\renewcommand{\py@noticestart@note}{\py@heavybox}
\renewcommand{\py@noticeend@note}{\py@endheavybox}
\makeatother
% icons in note and warning boxes
\usepackage{ifthen}
% Keep a copy of the original notice environment
\let\origbeginnotice\notice
\let\origendnotice\endnotice
% Redefine the notice environment so we can add our own code to it
\renewenvironment{notice}[2]{%
\origbeginnotice{#1}{}% equivalent to original \begin{notice}{#1}{#2}
% Keep a copy of the original sphinxadmonition environment
\let\origbeginadmon\sphinxadmonition
\let\origendadmon\endsphinxadmonition
% Redefine the sphinxadmonition environment so we can add our own code to it
\renewenvironment{sphinxadmonition}[2]{%
\origbeginadmon{#1}{}% equivalent to original \begin{sphinxadmonition}{#1}{#2}
% load graphics
\ifthenelse{\equal{#1}{warning}}{\includegraphics{latex-warning.png}}{}
\ifthenelse{\equal{#1}{note}}{\includegraphics{latex-note.png}}{}
% etc.
}{%
\origendnotice% equivalent to original \end{notice}
}{%
\origendadmon % equivalent to original \end{sphinxadmonition}
}
% try to prevent code-block boxes from splitting across pages
@@ -306,7 +320,6 @@ def nothing(*arg):
latex_elements = {
'preamble': _PREAMBLE,
'wrapperclass': 'book',
'date': '',
'releasename': 'Version',
'title': r'The Pyramid Web Framework',
@@ -330,44 +343,21 @@ def frontmatter(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
return [nodes.raw(
'',
r"""
\frontmatter
% prevent part/chapter/section numbering
\setcounter{secnumdepth}{-2}
% suppress headers
\pagestyle{plain}
% reset page counter
\setcounter{page}{1}
% suppress first toc pagenum
\addtocontents{toc}{\protect\thispagestyle{empty}}
""",
format='latex')]
def mainmatter(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
return [nodes.raw(
'',
r"""
\mainmatter
% allow part/chapter/section numbering
\setcounter{secnumdepth}{2}
% get headers back
\pagestyle{fancy}
\fancyhf{}
\renewcommand{\headrulewidth}{0.5pt}
\renewcommand{\footrulewidth}{0pt}
\fancyfoot[C]{\thepage}
\fancyhead[RO]{\rightmark}
\fancyhead[LE]{\leftmark}
""",
format='latex')]
def backmatter(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
return [nodes.raw('', '\\backmatter\n\\setcounter{secnumdepth}{-1}\n',
format='latex')]
return [nodes.raw(
'',
format='latex')]
def app_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
View

This file was deleted.

Oops, something went wrong.
View
@@ -1,7 +1,7 @@
Copyright, Trademarks, and Attributions
=======================================
*The Pyramid Web Framework, Version 1.1*
"The Pyramid Web Framework, Version |version|"
by Chris McDonough
@@ -18,7 +18,7 @@ First print publishing: February, 2011
All rights reserved. This material may be copied or distributed only
subject to the terms and conditions set forth in the `Creative Commons
Attribution-Noncommercial-Share Alike 3.0 United States License
<http://creativecommons.org/licenses/by-nc-sa/3.0/us/>`_. You must
<https://creativecommons.org/licenses/by-nc-sa/3.0/us/>`_. You must
give the original author credit. You may not use this work for
commercial purposes. If you alter, transform, or build upon this
work, you may distribute the resulting work only under the same or
@@ -63,7 +63,7 @@ Contributors:
GitHub.
Cover Designer:
Hugues Laflamme of `Kemeneur <http://www.kemeneur.com/>`_.
Hugues Laflamme of Kemeneur.
Used with permission:
@@ -80,8 +80,8 @@ Print Production
----------------
The print version of this book was produced using the `Sphinx
<http://sphinx.pocoo.org/>`_ documentation generation system and the
`LaTeX <http://www.latex-project.org/>`_ typesetting system.
<http://www.sphinx-doc.org/en/stable/>`_ documentation generation system and
the `LaTeX <http://www.latex-project.org/>`_ typesetting system.
Contacting The Publisher
------------------------
@@ -90,15 +90,14 @@ Please send documentation licensing inquiries, translation inquiries,
and other business communications to `Agendaless Consulting
<mailto:webmaster@agendaless.com>`_. Please send software and other
technical queries to the `Pylons-devel mailing list
<http://groups.google.com/group/pylons-devel>`_.
<https://groups.google.com/forum/#!forum/pylons-devel>`_.
HTML Version and Source Code
----------------------------
An HTML version of this book is freely available via
http://docs.pylonsproject.org/projects/pyramid/en/latest/
https://docs.pylonsproject.org/projects/pyramid/en/latest/
The source code for the examples used in this book are available
within the :app:`Pyramid` software distribution, always available
via https://github.com/Pylons/pyramid
View
@@ -131,7 +131,7 @@ obvious.
First, what's a "utility"? Well, for the purposes of this discussion, and
for the purpose of the code above, it's just not very important. If you
really want to know, you can read `this
<http://www.muthukadan.net/docs/zca.html#utility>`_. However, still, readers
<http://muthukadan.net/docs/zca.html#utility>`_. However, still, readers
of such code need to understand the concept in order to parse it. This is
problem number one.
@@ -591,7 +591,7 @@ extensibility because it must be deployed in multiple locations.
Pyramid Is Too Big
------------------
"The :app:`Pyramid` compressed tarball is larger than 2MB. It must beenormous!"
"The :app:`Pyramid` compressed tarball is larger than 2MB. It must be enormous!"
No. We just ship it with docs, test code, and scaffolding. Here's a breakdown
of what's included in subdirectories of the package tree:
@@ -608,7 +608,7 @@ pyramid/scaffolds/
133KB
pyramid/ (except for ``pyramd/tests`` and ``pyramid/scaffolds``)
pyramid/ (except for ``pyramid/tests`` and ``pyramid/scaffolds``)
812KB
@@ -665,7 +665,7 @@ desktop GUI platforms by using similar terminology, and to provide some frame
of reference for how various components in the common web framework might
hang together. But in the opinion of the author, "MVC" doesn't match the web
very well in general. Quoting from the `Model-View-Controller Wikipedia entry
<http://en.wikipedia.org/wiki/Model–view–controller>`_:
<https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller>`_:
Though MVC comes in different flavors, control flow is generally as
follows:
@@ -847,9 +847,9 @@ Challenge
+++++++++
:app:`Pyramid` performs automatic authorization checks only at :term:`view`
execution time. Zope 3 wraps context objects with a `security proxy
<http://wiki.zope.org/zope3/WhatAreSecurityProxies>`_, which causes Zope 3 also
to do security checks during attribute access. I like this, because it means:
execution time. Zope 3 wraps context objects with a security proxy, which
causes Zope 3 also to do security checks during attribute access. I like this,
because it means:
#) When I use the security proxy machinery, I can have a view that
conditionally displays certain HTML elements (like form fields) or
@@ -1006,16 +1006,18 @@ the following:
Microframeworks have smaller Hello World programs
-------------------------------------------------
Self-described "microframeworks" exist. `Bottle <http://bottle.paws.de>`_ and
`Flask <http://flask.pocoo.org/>`_ are two that are becoming popular. `Bobo
<http://bobo.digicool.com/>`_ doesn't describe itself as a microframework, but
its intended user base is much the same. Many others exist. We've even (only as
a teaching tool, not as any sort of official project) `created one using
Pyramid <http://static.repoze.org/casts/videotags.html>`_. The videos use BFG,
a precursor to Pyramid, but the resulting code is `available for Pyramid too
<https://github.com/Pylons/groundhog>`_). Microframeworks are small frameworks
with one common feature: each allows its users to create a fully functional
application that lives in a single Python file.
Self-described "microframeworks" exist. `Bottle
<http://bottlepy.org/docs/dev/index.html>`_ and `Flask
<http://flask.pocoo.org/>`_ are two that are becoming popular. `Bobo
<https://bobo.readthedocs.io/en/latest/>`_ doesn't describe itself as a
microframework, but its intended user base is much the same. Many others exist.
We've even (only as a teaching tool, not as any sort of official project)
`created one using Pyramid <http://static.repoze.org/casts/videotags.html>`_.
The videos use BFG, a precursor to Pyramid, but the resulting code is
`available for Pyramid too <https://github.com/Pylons/groundhog>`_).
Microframeworks are small frameworks with one common feature: each allows its
users to create a fully functional application that lives in a single Python
file.
Some developers and microframework authors point out that Pyramid's "hello
world" single-file program is longer (by about five lines) than the equivalent
@@ -1295,12 +1297,12 @@ Consider the following simple `Groundhog
from groundhog import Groundhog
app = Groundhog('myapp', 'seekrit')
app.route('/admin')
@app.route('/admin')
def admin():
return '<html>admin page</html>'
app.route('/:action')
def action():
@app.route('/:action')
def do_action(action):
if action == 'add':
return '<html>add</html>'
if action == 'delete':
@@ -1320,15 +1322,15 @@ order of the function definitions in the file?
from groundhog import Groundhog
app = Groundhog('myapp', 'seekrit')
app.route('/:action')
def action():
@app.route('/:action')
def do_action(action):
if action == 'add':
return '<html>add</html>'
if action == 'delete':
return '<html>delete</html>'
return app.abort(404)
app.route('/admin')
@app.route('/admin')
def admin():
return '<html>admin page</html>'
@@ -1430,9 +1432,10 @@ object which *is not logically global*:
# this is executed if the request method was GET or the
# credentials were invalid
The `Pylons 1.X <http://pylonsproject.org>`_ web framework uses a similar
strategy. It calls these things "Stacked Object Proxies", so, for purposes
of this discussion, I'll do so as well.
The `Pylons 1.X
<https://docs.pylonsproject.org/projects/pylons-webframework/en/latest/>`_
web framework uses a similar strategy. It calls these things "Stacked Object
Proxies", so, for purposes of this discussion, I'll do so as well.
Import statements in Python (``import foo``, ``from bar import baz``) are
most frequently performed to obtain a reference to an object defined globally
@@ -1526,20 +1529,20 @@ inlined comments take into account what we've discussed in the
.. code-block:: python
:linenos:
from pyramid.response import Response # explicit response, no thread local
from wsgiref.simple_server import make_server # explicitly WSGI
from wsgiref.simple_server import make_server # explicitly WSGI
from pyramid.config import Configurator # to configure app registry
from pyramid.response import Response # explicit response, no threadlocal
def hello_world(request): # accepts a request; no request thread local reqd
def hello_world(request): # accept a request; no request threadlocal reqd
# explicit response object means no response threadlocal
return Response('Hello world!')
if __name__ == '__main__':
from pyramid.config import Configurator
config = Configurator() # no global application object
config.add_view(hello_world) # explicit non-decorator registration
app = config.make_wsgi_app() # explicitly WSGI
with Configurator() as config: # no global application object
config.add_view(hello_world) # explicit non-decorator registration
app = config.make_wsgi_app() # explicitly WSGI
server = make_server('0.0.0.0', 8080, app)
server.serve_forever() # explicitly WSGI
server.serve_forever() # explicitly WSGI
Pyramid doesn't offer pluggable apps
@@ -1631,7 +1634,7 @@ Let's take this criticism point-by-point.
Too Complex
+++++++++++
If you can understand this hello world program, you can use Pyramid:
If you can understand this "hello world" program, you can use Pyramid:
.. code-block:: python
:linenos:
@@ -1644,16 +1647,17 @@ If you can understand this hello world program, you can use Pyramid:
return Response('Hello world!')
if __name__ == '__main__':
config = Configurator()
config.add_view(hello_world)
app = config.make_wsgi_app()
with Configurator() as config:
config.add_view(hello_world)
app = config.make_wsgi_app()
server = make_server('0.0.0.0', 8080, app)
server.serve_forever()
Pyramid has ~ 700 pages of documentation (printed), covering topics from the
very basic to the most advanced. *Nothing* is left undocumented, quite
Pyramid has over 1200 pages of documentation (printed), covering topics from
the very basic to the most advanced. *Nothing* is left undocumented, quite
literally. It also has an *awesome*, very helpful community. Visit the
#pyramid IRC channel on freenode.net (irc://freenode.net#pyramid) and see.
`#pyramid IRC channel on freenode.net
<https://webchat.freenode.net/?channels=pyramid>`_ and see.
Hate Zope
+++++++++
@@ -1701,5 +1705,6 @@ Other Challenges
----------------
Other challenges are encouraged to be sent to the `Pylons-devel
<http://groups.google.com/group/pylons-devel>`_ maillist. We'll try to address
them by considering a design change, or at very least via exposition here.
<https://groups.google.com/forum/#!forum/pylons-devel>`_ maillist. We'll try
to address them by considering a design change, or at very least via exposition
here.
View

Large diffs are not rendered by default.

Oops, something went wrong.
View
@@ -5,7 +5,7 @@ The Pyramid Web Framework
=========================
:app:`Pyramid` is a small, fast, down-to-earth Python web framework. It is
developed as part of the `Pylons Project <http://docs.pylonsproject.org/>`_.
developed as part of the `Pylons Project <https://pylonsproject.org>`_.
It is licensed under a `BSD-like license <http://repoze.org/license.html>`_.
Here is one of the simplest :app:`Pyramid` applications you can make:
@@ -18,7 +18,7 @@ After you install :app:`Pyramid` and run this application, when you visit
this application works.
.. _html_getting_started:
.. _getting_started:
Getting Started
===============
@@ -35,9 +35,6 @@ speed right away.
* :doc:`quick_tour` gives an overview of the major features in Pyramid,
covering a little about a lot.
* :doc:`quick_tutorial/index` is similar to the Quick Tour, but in a tutorial
format, with somewhat deeper treatment of each topic and with working code.
* Like learning by example? Visit the official :ref:`html_tutorials` as well as
the community-contributed :ref:`Pyramid Tutorials
<tutorials:pyramid-tutorials>` and :ref:`Pyramid Community Cookbook
@@ -53,32 +50,34 @@ speed right away.
Tutorials
=========
Official tutorials explaining how to use :app:`Pyramid` to build various types
of applications, and how to deploy :app:`Pyramid` applications to various
platforms.
Official tutorials provide a quick overview of :app:`Pyramid`'s features in more depth than the Quick Tour and with working code, explain how to use :app:`Pyramid` to build various types of applications, and how to deploy :app:`Pyramid` applications to various platforms.
.. toctree::
:maxdepth: 1
tutorials/wiki2/index.rst
tutorials/wiki/index.rst
tutorials/modwsgi/index.rst
quick_tutorial/index
tutorials/wiki2/index
tutorials/wiki/index
tutorials/modwsgi/index
.. _support-and-development:
Support and Development
=======================
The `Pylons Project web site <http://pylonsproject.org/>`_ is the main online
source of :app:`Pyramid` support and development information.
The `Pyramid website <https://trypyramid.com/resources.html>`_ is the main
entry point to :app:`Pyramid` web framework resources for support and
development information.
To report bugs, use the `issue tracker
<https://github.com/Pylons/pyramid/issues>`_.
If you've got questions that aren't answered by this documentation, contact the
`Pylons-discuss maillist <http://groups.google.com/group/pylons-discuss>`_ or
join the `#pyramid IRC channel <irc://irc.freenode.net/#pyramid>`_.
`Pylons-discuss maillist
<https://groups.google.com/forum/#!forum/pylons-discuss>`_ or join the
`#pyramid IRC channel
<https://webchat.freenode.net/?channels=pyramid>`_.
Browse and check out tagged and trunk versions of :app:`Pyramid` via the
`Pyramid GitHub repository <https://github.com/Pylons/pyramid/>`_. To check out
@@ -92,9 +91,7 @@ the trunk via ``git``, use either command:
# Otherwise, HTTPS will work, using your GitHub login:
git clone https://github.com/Pylons/pyramid.git
To find out how to become a contributor to :app:`Pyramid`, please see the
`contributor's section of the documentation
<http://docs.pylonsproject.org/en/latest/#contributing>`_.
To find out how to become a contributor to :app:`Pyramid`, please see `How to Contribute Source Code and Documentation <https://pylonsproject.org/community-how-to-contribute.html>`_.
.. _html_narrative_documentation:
@@ -142,6 +139,7 @@ Narrative documentation in chapter form explaining how to use :app:`Pyramid`.
narr/extending
narr/advconfig
narr/extconfig
narr/cookiecutters
narr/scaffolding
narr/upgrading
narr/threadlocals
@@ -165,7 +163,7 @@ Comprehensive reference material for every public API exposed by
``p*`` Scripts Documentation
============================
``p*`` scripts included with :app:`Pyramid`:.
``p*`` scripts included with :app:`Pyramid`.
.. toctree::
:maxdepth: 1
@@ -181,6 +179,8 @@ Change History
.. toctree::
:maxdepth: 1
whatsnew-1.9
whatsnew-1.8
whatsnew-1.7
whatsnew-1.6
whatsnew-1.5
@@ -210,13 +210,13 @@ Copyright, Trademarks, and Attributions
copyright
Typographical Conventions
=========================
Typographical Conventions and Style Guide
=========================================
.. toctree::
:maxdepth: 1
conventions
typographical-conventions
Index and Glossary
View
@@ -14,12 +14,27 @@ Front Matter
.. toctree::
:maxdepth: 1
copyright.rst
conventions.rst
authorintro.rst
copyright
typographical-conventions
authorintro
designdefense
.. mainmatter::
.. _tutorials:
Tutorials
@@@@@@@@@
.. toctree::
:maxdepth: 1
quick_tour
quick_tutorial/index
tutorials/wiki2/index
tutorials/wiki/index
tutorials/modwsgi/index
.. _narrative_documentation:
Narrative Documentation
@@ -63,36 +78,53 @@ Narrative Documentation
narr/extending
narr/advconfig
narr/extconfig
narr/cookiecutters
narr/scaffolding
narr/upgrading
narr/threadlocals
narr/zca
.. _tutorials:
Tutorials
@@@@@@@@@
API Documentation
@@@@@@@@@@@@@@@@@
.. toctree::
:maxdepth: 1
:glob:
tutorials/wiki2/index.rst
tutorials/wiki/index.rst
tutorials/modwsgi/index.rst
api/index
api/*
.. _api_documentation:
API Documentation
@@@@@@@@@@@@@@@@@
``p*`` Scripts Documentation
@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.. toctree::
:maxdepth: 1
:glob:
api/*
pscripts/index
pscripts/*
.. backmatter::
Change History
@@@@@@@@@@@@@@
.. toctree::
:maxdepth: 1
whatsnew-1.7
whatsnew-1.6
whatsnew-1.5
whatsnew-1.4
whatsnew-1.3
whatsnew-1.2
whatsnew-1.1
whatsnew-1.0
changes
Glossary and Index
@@@@@@@@@@@@@@@@@@
View
@@ -1,4 +1,4 @@
#!/bin/sh
make clean latex SPHINXBUILD=../env/bin/sphinx-build BOOK=1
make clean xelatexpdf SPHINXBUILD=../env/bin/sphinx-build BOOK=1
cd _build/latex && make all-pdf
View
@@ -1,4 +1,4 @@
#!/bin/sh
make clean latex SPHINXBUILD=../env/bin/sphinx-build
make clean xelatexpdf SPHINXBUILD=../env/bin/sphinx-build
cd _build/latex && make all-pdf
View

This file was deleted.

Oops, something went wrong.
View

This file was deleted.

Oops, something went wrong.
View

This file was deleted.

Oops, something went wrong.
View

This file was deleted.

Oops, something went wrong.
View
@@ -0,0 +1,330 @@
Advanced :app:`Pyramid` Design Features
=======================================
:app:`Pyramid` has been built from the ground up to avoid the problems that other frameworks can suffer.
You Don't Need Singletons
-------------------------
Have you ever struggled with parameterizing Django's ``settings.py`` file for multiple installations of the same Django application? Have you ever needed to monkey-patch a framework fixture to get it to behave properly for your use case? Have you ever tried to deploy your application using an asynchronous server and failed?
All these problems are symptoms of :term:`mutable` :term:`global state`, also known as :term:`import time` :term:`side effect`\ s and arise from the use of :term:`singleton` data structures.
:app:`Pyramid` is written so that you don't run into these types of problems. It is even possible to run multiple copies of the *same* :app:`Pyramid` application configured differently within a single Python process. This makes running :app:`Pyramid` in shared hosting environments a snap.
Simplify your View Code with Predicates
---------------------------------------
How many times have you found yourself beginning the logic of your view code with something like this:
.. code-block:: python
:linenos:
if request.user.is_authenticated:
# do one thing
else:
# do something else
Unlike many other systems, :app:`Pyramid` allows you to associate more than one view with a single route. For example, you can create a route with the pattern ``/items`` and when the route is matched, you can send the request to one view if the request method is GET, another view if the request method is POST, and so on.
:app:`Pyramid` uses a system of :term:`view predicate`\ s to allow this. Matching the request method is one basic thing you can do with a :term:`view predicate`. You can also associate views with other request parameters, such as elements in the query string, the Accept header, whether the request is an AJAX (XHR) request or not, and lots of other things.
For our example above, you can do this instead:
.. code-block:: python
:linenos:
@view_config(route_name="items", effective_principals=pyramid.security.Authenticated)
def auth_view(request):
# do one thing
@view_config(route_name="items")
def anon_view(request):
# do something else
This approach allows you to develop view code that is simpler, more easily understandable, and more directly testable.
.. seealso::
See also :ref:`view_configuration_parameters`.
Stop Worrying About Transactions
--------------------------------
:app:`Pyramid`\ 's :term:`cookiecutter`\ s render projects that include a *transaction management* system. When you use this system, you can stop worrying about when to commit your changes, :app:`Pyramid` handles it for you. The system will commit at the end of a request or abort if there was an exception.
Why is that a good thing? Imagine a situation where you manually commit a change to your persistence layer. It's very likely that other framework code will run *after* your changes are done. If an error happens in that other code, you can easily wind up with inconsistent data if you're not extremely careful.
Using transaction management saves you from needing to think about this. Either a request completes successfully and all changes are committed, or it does not and all changes are aborted.
:app:`Pyramid`\ 's transaction management is extendable, so you can synchronize commits between multiple databases or databases of different kinds. It also allows you to do things like conditionally send email if a transaction is committed, but otherwise keep quiet.
.. seealso::
See also :ref:`bfg_sql_wiki_tutorial` (note the lack of commit statements anywhere in application code).
Stop Worrying About Configuration
---------------------------------
When a system is small, it's reasonably easy to keep it all in your head. But as systems grow large, configuration grows more complex. Your app may grow to have hundreds or even thousands of configuration statements.
:app:`Pyramid`\ 's configuration system keeps track of each of your statements. If you accidentally add two that are identical, or :app:`Pyramid` can't make sense out of what it would mean to have both statements active at the same time, it will complain loudly at startup time.
:app:`Pyramid`\ 's configuration system is not dumb though. If you use the :meth:`~pyramid.config.Configurator.include` system, it can automatically resolve conflicts on its own. More local statements are preferred over less local ones. So you can intelligently factor large systems into smaller ones.
.. seealso::
See also :ref:`conflict_detection`.
Compose Powerful Apps From Simple Parts
----------------------------------------
Speaking of the :app:`Pyramid` structured :meth:`~pyramid.config.Configurator.include` mechanism, it allows you to compose complex applications from multiple, simple Python packages. All the configuration statements that can be performed in your main :app:`Pyramid` application can also be used in included packages. You can add views, routes, and subscribers, and even set authentication and authorization policies.
If you need, you can extend or override the configuration of an existing application by including its configuration in your own and then modifying it.
For example, if you want to reuse an existing application that already has a bunch of routes, you can just use the ``include`` statement with a ``route_prefix``. All the routes of that application will be availabe, prefixed as you requested:
.. code-block:: python
:linenos:
from pyramid.config import Configurator
if __name__ == '__main__':
config = Configurator()
config.include('pyramid_jinja2')
config.include('pyramid_exclog')
config.include('some.other.package', route_prefix='/somethingelse')
.. seealso::
See also :ref:`including_configuration` and :ref:`building_an_extensible_app`.
Authenticate Users Your Way
---------------------------
:app:`Pyramid` ships with prebuilt, well-tested authentication and authorization schemes out of the box. Using a scheme is a matter of configuration. So if you need to change approaches later, you need only update your configuration.
In addition, the system that handles authentication and authorization is flexible and pluggable. If you want to use another security add-on, or define your own, you can. And again, you need only update your application configuration to make the change.
.. seealso::
See also :ref:`enabling_authorization_policy`.
Build Trees of Resources
------------------------
:app:`Pyramid` supports :term:`traversal`, a way of mapping URLs to a concrete :term:`resource tree`. If your application naturally consists of an arbitrary heirarchy of different types of content (like a CMS or a Document Management System), traversal is for you. If you have a requirement for a highly granular security model ("Jane can edit documents in *this* folder, but not *that* one"), traversal can be a powerful approach.
.. seealso::
See also :ref:`hello_traversal_chapter` and :ref:`much_ado_about_traversal_chapter`.
Take Action on Each Request with Tweens
---------------------------------------
:app:`Pyramid` has a system for applying an arbitrary action to each request or response called a :term:`tween`. The system is similar in concept to WSGI :term:`middleware`, but can be more useful since :term:`tween`\ s run in the :app:`Pyramid` context, and have access to templates, request objects, and other niceties.
The :app:`Pyramid` debug toolbar is a :term:`tween`, as is the ``pyramid_tm`` transaction manager.
.. seealso::
See also :ref:`registering_tweens`.
Return What You Want From Your Views
------------------------------------
We have shown elsewhere (in the :doc:`introduction`) how using a :term:`renderer` allows you to return simple Python dictionaries from your view code. But some frameworks allow you to return strings or tuples from view callables. When frameworks allow for this, code looks slightly prettier because there are fewer imports and less code. For example, compare this:
.. code-block:: python
:linenos:
from pyramid.response import Response
def aview(request):
return Response("Hello world!")
To this:
.. code-block:: python
:linenos:
def aview(request):
return "Hello world!"
Nicer to look at, right?
Out of the box, :app:`Pyramid` will raise an exception if you try to run the second example above. After all, a view should return a response, and "explicit is better than implicit".
But if you're a developer who likes the aesthetics of simplicity, :app:`Pyramid` provides a way to support this sort of thing, the :term:`response adapter`\ :
.. code-block:: python
:linenos:
from pyramid.config import Configurator
from pyramid.response import Response
def string_response_adapter(s):
response = Response(s)
response.content_type = 'text/html'
return response
A new response adapter is registered in configuration:
.. code-block:: python
:linenos:
if __name__ == '__main__':
config = Configurator()
config.add_response_adapter(string_response_adapter, str)
With that, you may return strings from any of your view callables, e.g.:
.. code-block:: python
:linenos:
def helloview(request):
return "Hello world!"
def goodbyeview(request):
return "Goodbye world!"
You can even use a :term:`response adapter` to allow for custom content types and return codes:
.. code-block:: python
:linenos:
from pyramid.config import Configurator
def tuple_response_adapter(val):
status_int, content_type, body = val
response = Response(body)
response.content_type = content_type
response.status_int = status_int
return response
def string_response_adapter(body):
response = Response(body)
response.content_type = 'text/html'
response.status_int = 200
return response
if __name__ == '__main__':
config = Configurator()
config.add_response_adapter(string_response_adapter, str)
config.add_response_adapter(tuple_response_adapter, tuple)
With this, both of these views will work as expected:
.. code-block:: python
:linenos:
def aview(request):
return "Hello world!"
def anotherview(request):
return (403, 'text/plain', "Forbidden")
.. seealso::
See also :ref:`using_iresponse`.
Use Global Response Objects
---------------------------
Views have to return responses. But constructing them in view code is a chore. And perhaps registering a :term:`response adapter` as shown above is just too much work. :app:`Pyramid` provides a global response object as well. You can use it directly, if you prefer:
.. code-block:: python
:linenos:
def aview(request):
response = request.response
response.body = 'Hello world!'
response.content_type = 'text/plain'
return response
.. seealso::
See also :ref:`request_response_attr`.
Extend Configuration
--------------------
Perhaps the :app:`Pyramid` configurator's syntax feels a bit verbose to you. Or possibly you would like to add a feature to configuration without asking the core developers to change :app:`Pyramid` itself?
You can extend :app:`Pyramid`\ 's :term:`configurator` with your own directives. For example, let's say you find yourself calling :meth:`pyramid.config.Configurator.add_view` repetitively. Usually you can get rid of the boring with existing shortcuts, but let's say that this is a case where there is no such shortcut:
.. code-block:: python
:linenos:
from pyramid.config import Configurator
config = Configurator()
config.add_route('xhr_route', '/xhr/{id}')
config.add_view('my.package.GET_view', route_name='xhr_route',
xhr=True, permission='view', request_method='GET')
config.add_view('my.package.POST_view', route_name='xhr_route',
xhr=True, permission='view', request_method='POST')
config.add_view('my.package.HEAD_view', route_name='xhr_route',
xhr=True, permission='view', request_method='HEAD')
Pretty tedious right? You can add a directive to the :app:`Pyramid` :term:`configurator` to automate some of the tedium away:
.. code-block:: python
:linenos:
from pyramid.config import Configurator
def add_protected_xhr_views(config, module):
module = config.maybe_dotted(module)
for method in ('GET', 'POST', 'HEAD'):
view = getattr(module, 'xhr_%s_view' % method, None)
if view is not None:
config.add_view(view, route_name='xhr_route', xhr=True,
permission='view', request_method=method)
config = Configurator()
config.add_directive('add_protected_xhr_views', add_protected_xhr_views)
Once that's done, you can call the directive you've just added as a method of the :term:`configurator` object:
.. code-block:: python
:linenos:
config.add_route('xhr_route', '/xhr/{id}')
config.add_protected_xhr_views('my.package')
Much better!
You can share your configuration code with others, too. Add your code to a Python package. Put the call to :meth:`~pyramid.config.Configurator.add_directive` in a function. When other programmers install your package, they'll be able to use your configuration by passing your function to a call to :meth:`~pyramid.config.Configurator.include`.
.. seealso::
See also :ref:`add_directive`.
Introspect Your Application
---------------------------
If you're building a large, pluggable system, it's useful to be able to get a list of what has been plugged in *at application runtime*. For example, you might want to show users a set of tabs at the top of the screen based on a list of the views they registered.
:app:`Pyramid` provides an :term:`introspector` for just this purpose.
Here's an example of using :app:`Pyramid`\ 's :term:`introspector` from within a view:
.. code-block:: python
:linenos:
from pyramid.view import view_config
from pyramid.response import Response
@view_config(route_name='bar')
def show_current_route_pattern(request):
introspector = request.registry.introspector
route_name = request.matched_route.name
route_intr = introspector.get('routes', route_name)
return Response(str(route_intr['pattern']))
.. seealso::
See also :ref:`using_introspection`.
View
@@ -28,7 +28,7 @@ asset:
The use of assets is quite common in most web development projects. For
example, when you create a :app:`Pyramid` application using one of the
available scaffolds, as described in :ref:`creating_a_project`, the directory
available :term:`cookiecutter`\ s, as described in :ref:`creating_a_project`, the directory
representing the application contains a Python :term:`package`. Within that
Python package, there are directories full of files which are static assets.
For example, there's a ``static`` directory which contains ``.css``, ``.js``,
View
@@ -649,15 +649,20 @@ using the :func:`pyramid.paster.bootstrap` command in the body of your script.
.. versionadded:: 1.1
:func:`pyramid.paster.bootstrap`
.. versionchanged:: 1.8
Added the ability for ``bootstrap`` to cleanup automatically via the
``with`` statement.
In the simplest case, :func:`pyramid.paster.bootstrap` can be used with a
single argument, which accepts the :term:`PasteDeploy` ``.ini`` file
representing your Pyramid application's configuration as a single argument:
.. code-block:: python
from pyramid.paster import bootstrap
env = bootstrap('/path/to/my/development.ini')
print(env['request'].route_url('home'))
with bootstrap('/path/to/my/development.ini') as env:
print(env['request'].route_url('home'))
:func:`pyramid.paster.bootstrap` returns a dictionary containing
framework-related information. This dictionary will always contain a
@@ -723,8 +728,9 @@ load instead of ``main``:
.. code-block:: python
from pyramid.paster import bootstrap
env = bootstrap('/path/to/my/development.ini#another')
print(env['request'].route_url('home'))
with bootstrap('/path/to/my/development.ini#another') as env:
print(env['request'].route_url('home'))
The above example specifies the ``another`` ``app``, ``pipeline``, or
``composite`` section of your PasteDeploy configuration file. The ``app``
@@ -761,9 +767,9 @@ desired request and passing it into :func:`~pyramid.paster.bootstrap`:
from pyramid.request import Request
request = Request.blank('/', base_url='https://example.com/prefix')
env = bootstrap('/path/to/my/development.ini#another', request=request)
print(env['request'].application_url)
# will print 'https://example.com/prefix'
with bootstrap('/path/to/my/development.ini#another', request=request) as env:
print(env['request'].application_url)
# will print 'https://example.com/prefix'
Now you can readily use Pyramid's APIs for generating URLs:
@@ -776,7 +782,9 @@ Now you can readily use Pyramid's APIs for generating URLs:
Cleanup
~~~~~~~
When your scripting logic finishes, it's good manners to call the ``closer``
If you're using the ``with``-statement variant then there's nothing to
worry about. However if you're using the returned environment directly then
when your scripting logic finishes, it's good manners to call the ``closer``
callback:
.. code-block:: python
@@ -831,7 +839,7 @@ In general, you can make your script into a console script by doing the
following:
- Use an existing distribution (such as one you've already created via
``pcreate``) or create a new distribution that possesses at least one package
``cookiecutter``) or create a new distribution that possesses at least one package
or module. It should, within any module within the distribution, house a
callable (usually a function) that takes no arguments and which runs any of
the code you wish to run.
@@ -891,15 +899,12 @@ contains the following code:
omit = options.omit
if omit is None:
omit = []
env = bootstrap(config_uri)
settings, closer = env['registry'].settings, env['closer']
try:
with bootstrap(config_uri) as env:
settings = env['registry'].settings
for k, v in settings.items():
if any([k.startswith(x) for x in omit]):
continue
print('%-40s %-20s' % (k, v))
finally:
closer()
This script uses the Python ``optparse`` module to allow us to make sense out
of extra arguments passed to the script. It uses the
View
@@ -47,14 +47,14 @@ configured imperatively:
return Response('Hello world!')
if __name__ == '__main__':
config = Configurator()
config.add_view(hello_world)
app = config.make_wsgi_app()
with Configurator() as config:
config.add_view(hello_world)
app = config.make_wsgi_app()
server = make_server('0.0.0.0', 8080, app)
server.serve_forever()
We won't talk much about what this application does yet. Just note that the
"configuration' statements take place underneath the ``if __name__ ==
configuration statements take place underneath the ``if __name__ ==
'__main__':`` stanza in the form of method calls on a :term:`Configurator`
object (e.g., ``config.add_view(...)``). These statements take place one after
the other, and are executed in order, so the full power of Python, including
@@ -116,9 +116,9 @@ and its subpackages. For example:
return Response('Hello')
if __name__ == '__main__':
config = Configurator()
config.scan()
app = config.make_wsgi_app()
with Configurator() as config:
config.scan()
app = config.make_wsgi_app()
server = make_server('0.0.0.0', 8080, app)
server.serve_forever()
View
@@ -0,0 +1,22 @@
.. _cookiecutters:
Pyramid cookiecutters
=====================
.. versionadded:: 1.8
A :term:`cookiecutter` is a command-line utility that creates projects from :ref:`cookiecutters <cookiecutter:readme>` (project templates), e.g., creating a Python package project from a Python package project template.
Pyramid cookiecutters have replaced the now deprecated Pyramid scaffolds, and should be used going forward. Pyramid cookiecutters released under the Pylons Project include:
* `pyramid-cookiecutter-alchemy <https://github.com/Pylons/pyramid-cookiecutter-alchemy>`_
* `pyramid-cookiecutter-starter <https://github.com/Pylons/pyramid-cookiecutter-starter>`_
* `pyramid-cookiecutter-zodb <https://github.com/Pylons/pyramid-cookiecutter-zodb>`_
.. seealso::
See also `Cookiecutter Installation <https://cookiecutter.readthedocs.io/en/latest/installation.html>`_ and `Cookiecutter Features <https://cookiecutter.readthedocs.io/en/latest/readme.html#features>`_. Development of cookiecutters is documented under `Learn the Basics of Cookiecutter by Creating a Cookiecutter <https://cookiecutter.readthedocs.io/en/latest/first_steps.html>`_.
.. seealso::
See also :term:`scaffold`.
View
@@ -260,7 +260,9 @@ Pre-defined Phases
- :meth:`pyramid.config.Configurator.add_subscriber_predicate`
- :meth:`pyramid.config.Configurator.add_view_predicate`
- :meth:`pyramid.config.Configurator.add_view_deriver`
- :meth:`pyramid.config.Configurator.override_asset`
- :meth:`pyramid.config.Configurator.set_authorization_policy`
- :meth:`pyramid.config.Configurator.set_default_csrf_options`
- :meth:`pyramid.config.Configurator.set_default_permission`
- :meth:`pyramid.config.Configurator.set_view_mapper`
View
@@ -190,7 +190,7 @@ The general pattern for extending an existing application looks something like
this:
- Create a new Python package. The easiest way to do this is to create a new
:app:`Pyramid` application using the scaffold mechanism. See
:app:`Pyramid` application using a :term:`cookiecutter`. See
:ref:`creating_a_project` for more information.
- In the new package, create Python files containing views and other overridden
View
@@ -27,15 +27,15 @@ installed, an HTTP server is started on TCP port 8080.
On UNIX:
.. code-block:: text
.. code-block:: bash
$ $VENV/bin/python helloworld.py
On Windows:
.. code-block:: text
.. code-block:: doscon
C:\> %VENV%\Scripts\python.exe helloworld.py
c:\> %VENV%\Scripts\python helloworld.py
This command will not return and nothing will be printed to the console. When
port 8080 is visited by a browser on the URL ``/hello/world``, the server will
@@ -60,7 +60,7 @@ Imports
The above ``helloworld.py`` script uses the following set of import statements:
.. literalinclude:: helloworld.py
:linenos:
:lineno-match:
:lines: 1-3
The script imports the :class:`~pyramid.config.Configurator` class from the
@@ -83,7 +83,7 @@ The above script, beneath its set of imports, defines a function named
``hello_world``.
.. literalinclude:: helloworld.py
:linenos:
:lineno-match:
:pyobject: hello_world
The function accepts a single argument (``request``) and it returns an instance
@@ -125,7 +125,7 @@ imports and function definitions, placed within the confines of an ``if``
statement:
.. literalinclude:: helloworld.py
:linenos:
:lineno-match:
:lines: 9-15
Let's break this down piece by piece.
@@ -134,7 +134,7 @@ Configurator Construction
~~~~~~~~~~~~~~~~~~~~~~~~~
.. literalinclude:: helloworld.py
:linenos:
:lineno-match:
:lines: 9-10
The ``if __name__ == '__main__':`` line in the code sample above represents a
@@ -153,8 +153,8 @@ code within the ``if`` statement to execute if this module is imported from
another; the code within the ``if`` block should only be run during a direct
script execution.
The ``config = Configurator()`` line above creates an instance of the
:class:`~pyramid.config.Configurator` class. The resulting ``config`` object
The ``with Configurator() as config:`` line above creates an instance of the
:class:`~pyramid.config.Configurator` class using a :term:`context manager`. The resulting ``config`` object
represents an API which the script uses to configure this particular
:app:`Pyramid` application. Methods called on the Configurator will cause
registrations to be made in an :term:`application registry` associated with the
@@ -166,7 +166,7 @@ Adding Configuration
~~~~~~~~~~~~~~~~~~~~
.. literalinclude:: helloworld.py
:linenos:
:lineno-match:
:lines: 11-12
The first line above calls the :meth:`pyramid.config.Configurator.add_route`
@@ -185,7 +185,7 @@ WSGI Application Creation
~~~~~~~~~~~~~~~~~~~~~~~~~
.. literalinclude:: helloworld.py
:linenos:
:lineno-match:
:lines: 13
After configuring views and ending configuration, the script creates a WSGI
@@ -197,7 +197,7 @@ method returns a :term:`WSGI` application object that can be used by any WSGI
server to present an application to a requestor. :term:`WSGI` is a protocol
that allows servers to talk to Python applications. We don't discuss
:term:`WSGI` in any depth within this book, but you can learn more about it by
visiting `wsgi.org <http://wsgi.org>`_.
reading its `documentation <https://wsgi.readthedocs.io/en/latest/>`_.
The :app:`Pyramid` application object, in particular, is an instance of a class
representing a :app:`Pyramid` :term:`router`. It has a reference to the
@@ -212,7 +212,7 @@ WSGI Application Serving
~~~~~~~~~~~~~~~~~~~~~~~~
.. literalinclude:: helloworld.py
:linenos:
:lineno-match:
:lines: 14-15
Finally, we actually serve the application to requestors by starting up a WSGI
View
@@ -7,10 +7,9 @@ def hello_world(request):
return Response('Hello %(name)s!' % request.matchdict)
if __name__ == '__main__':
config = Configurator()
config.add_route('hello', '/hello/{name}')
config.add_view(hello_world, route_name='hello')
app = config.make_wsgi_app()
with Configurator() as config:
config.add_route('hello', '/hello/{name}')
config.add_view(hello_world, route_name='hello')
app = config.make_wsgi_app()
server = make_server('0.0.0.0', 8080, app)
server.serve_forever()
Oops, something went wrong.