summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--CHANGES.rst46
-rw-r--r--CONTRIBUTORS.txt10
-rw-r--r--HACKING.txt2
-rw-r--r--RELEASING.txt10
-rw-r--r--docs/Makefile11
-rw-r--r--docs/api/httpexceptions.rst2
-rw-r--r--docs/conf.py76
-rwxr-xr-xdocs/make_book2
-rwxr-xr-xdocs/make_pdf2
-rw-r--r--docs/narr/myproject/myproject/templates/layout.jinja22
-rw-r--r--docs/narr/urldispatch.rst18
-rw-r--r--docs/quick_tour.rst1
-rw-r--r--docs/quick_tour/logging/hello_world/templates/layout.jinja22
-rw-r--r--docs/quick_tour/package/hello_world/templates/layout.jinja22
-rw-r--r--docs/quick_tour/sessions/hello_world/templates/layout.jinja22
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/templates/layout.jinja22
-rw-r--r--docs/quick_tutorial/authentication.rst4
-rw-r--r--docs/quick_tutorial/authentication/setup.py6
-rw-r--r--docs/quick_tutorial/authorization/setup.py6
-rw-r--r--docs/quick_tutorial/cookiecutters/cc_starter/templates/layout.jinja22
-rw-r--r--docs/quick_tutorial/cookiecutters/setup.py2
-rw-r--r--docs/quick_tutorial/databases/setup.py10
-rw-r--r--docs/quick_tutorial/forms.rst2
-rw-r--r--docs/quick_tutorial/forms/setup.py6
-rw-r--r--docs/quick_tutorial/json/setup.py4
-rw-r--r--docs/quick_tutorial/logging/setup.py4
-rw-r--r--docs/quick_tutorial/more_view_classes/setup.py4
-rw-r--r--docs/quick_tutorial/requirements.rst32
-rw-r--r--docs/quick_tutorial/retail_forms/setup.py6
-rw-r--r--docs/quick_tutorial/routing/setup.py4
-rw-r--r--docs/quick_tutorial/sessions/setup.py4
-rw-r--r--docs/quick_tutorial/static_assets/setup.py4
-rw-r--r--docs/quick_tutorial/templating/setup.py2
-rw-r--r--docs/quick_tutorial/tutorial_approach.rst18
-rw-r--r--docs/quick_tutorial/view_classes/setup.py4
-rw-r--r--docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt2
-rw-r--r--docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt2
-rw-r--r--docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt2
-rw-r--r--docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt2
-rw-r--r--docs/tutorials/wiki/src/installation/tutorial/templates/mytemplate.pt2
-rw-r--r--docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt2
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt2
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/templates/login.pt2
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt2
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/templates/view.pt2
-rw-r--r--docs/tutorials/wiki/src/views/tutorial/templates/edit.pt2
-rw-r--r--docs/tutorials/wiki/src/views/tutorial/templates/view.pt2
-rw-r--r--docs/tutorials/wiki2/index.rst4
-rw-r--r--docs/tutorials/wiki2/src/authentication/tutorial/templates/layout.jinja22
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/templates/layout.jinja22
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/templates/layout.jinja22
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/templates/layout.jinja22
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/templates/layout.jinja22
-rw-r--r--docs/tutorials/wiki2/src/tests/tutorial/templates/layout.jinja22
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/templates/layout.jinja22
-rw-r--r--docs/typographical-conventions.rst24
-rw-r--r--pyramid/config/__init__.py45
-rw-r--r--pyramid/config/routes.py58
-rw-r--r--pyramid/httpexceptions.py52
-rw-r--r--pyramid/scaffolds/alchemy/+package+/templates/layout.jinja2_tmpl2
-rw-r--r--pyramid/scaffolds/starter/+package+/templates/layout.jinja2_tmpl2
-rw-r--r--pyramid/scaffolds/zodb/+package+/templates/mytemplate.pt_tmpl2
-rw-r--r--pyramid/session.py31
-rw-r--r--pyramid/tests/test_httpexceptions.py11
-rw-r--r--pyramid/tests/test_session.py7
-rw-r--r--pyramid/tests/test_url.py64
-rw-r--r--setup.py41
68 files changed, 448 insertions, 249 deletions
diff --git a/.gitignore b/.gitignore
index fe132412a..942b3caba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,3 +27,5 @@ jyenv/
pypyenv/
env*/
venv/
+.cache/
+.python-version
diff --git a/CHANGES.rst b/CHANGES.rst
index 7a8fa31f2..e09c3723c 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -21,13 +21,39 @@ Features
instead of ``pyramid.util.Request``.
See https://github.com/Pylons/pyramid/pull/3129
-- In ``cherrypy_server_runner``, prefer imports from the ``cheroot`` package over the legacy
- imports from `cherrypy.wsgiserver`.
+- In ``cherrypy_server_runner``, prefer imports from the ``cheroot`` package
+ over the legacy imports from `cherrypy.wsgiserver`.
See https://github.com/Pylons/pyramid/pull/3235
+- Add a context manager ``route_prefix_context`` to the
+ ``pyramid.config.Configurator`` to allow for convenient setting of the
+ route_prefix for ``include`` and ``add_route`` calls inside the context.
+ See https://github.com/Pylons/pyramid/pull/3279
+
+- Modify the builtin session implementations to support SameSite options on
+ cookies and set the default to ``'Lax'``. This affects
+ ``pyramid.session.BaseCookieSessionFactory``,
+ ``pyramid.session.SignedCookieSessionFactory``, and
+ ``pyramid.session.UnencryptedCookieSessionFactoryConfig``.
+ See https://github.com/Pylons/pyramid/pull/3300
+
+- Added new ``pyramid.httpexceptions.HTTPPermanentRedirect``
+ exception/response object for a HTTP 308 redirect.
+ See https://github.com/Pylons/pyramid/pull/3302
+
Bug Fixes
---------
+- Set appropriate ``code`` and ``title`` attributes on the ``HTTPClientError``
+ and ``HTTPServerError`` exception classes. This prevents inadvertently
+ returning a 520 error code.
+ See https://github.com/Pylons/pyramid/pull/3280
+
+- Replace ``webob.acceptparse.MIMEAccept`` from WebOb with
+ ``webob.acceptparse.create_accept_header`` in the HTTP exception handling
+ code. The old ``MIMEAccept`` has been deprecated. The new methods follow the
+ RFC's more closely. See https://github.com/Pylons/pyramid/pull/3251
+
Deprecations
------------
@@ -39,6 +65,22 @@ Backward Incompatibilities
depending on it directly within your project.
See https://github.com/Pylons/pyramid/pull/3140
+- Remove the ``permission`` argument from
+ ``pyramid.config.Configurator.add_route``. This was an argument left over
+ from a feature removed in Pyramid 1.5 and has had no effect since then.
+ See https://github.com/Pylons/pyramid/pull/3299
+
+- Modify the builtin session implementations to set ``SameSite='Lax'`` on
+ cookies. This affects ``pyramid.session.BaseCookieSessionFactory``,
+ ``pyramid.session.SignedCookieSessionFactory``, and
+ ``pyramid.session.UnencryptedCookieSessionFactoryConfig``.
+ See https://github.com/Pylons/pyramid/pull/3300
+
Documentation Changes
---------------------
+- Bump Sphinx to >= 1.7.4 in setup.py to support ``emphasize-lines`` in PDFs
+ and to pave the way for xelatex support. See
+ https://github.com/Pylons/pyramid/pull/3271,
+ https://github.com/Pylons/pyramid/issues/667, and
+ https://github.com/Pylons/pyramid/issues/2572
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index b6dbcff2c..a56821e74 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -316,3 +316,13 @@ Contributors
- Deneys Maartens, 2017/11/03
- Heron Rossi, 2018/03/08
+
+- Hunter Senft-Grupp, 2018/05/14
+
+- Junhak Lee, 2018/05/14
+
+- Alex Gaynor, 2018/05/24
+
+- Jason Williams, 2018/06/11
+
+- Benjamin Gmurczyk, 2018/06/14
diff --git a/HACKING.txt b/HACKING.txt
index 20cff7cac..8ec44605c 100644
--- a/HACKING.txt
+++ b/HACKING.txt
@@ -242,7 +242,7 @@ or adds the feature. To build and review docs, use the following steps.
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.
diff --git a/RELEASING.txt b/RELEASING.txt
index ba978562e..bec140309 100644
--- a/RELEASING.txt
+++ b/RELEASING.txt
@@ -71,9 +71,15 @@ Prepare new release branch
- Change setup.py version to the release version number.
+- Make sure PyPI long description renders (requires ``readme_renderer``
+ installed into your Python)::
+
+ $ python setup.py check -r -s -m
+
- Create a release tag.
-- Build and publish to PyPI::
+- Make sure your Python has ``setuptools-git``, ``twine``, and ``wheel``
+ installed and release to PyPI::
$ python setup.py sdist bdist_wheel
$ twine upload dist/pyramid-X.X-*
@@ -133,6 +139,8 @@ Marketing and communications
- Edit `https://en.wikipedia.org/wiki/Pylons_project <https://en.wikipedia.org/wiki/Pylons_project>`_.
+- Edit `https://en.wikipedia.org/wiki/Comparison_of_web_frameworks <https://en.wikipedia.org/wiki/Comparison_of_web_frameworks>`_.
+
- Announce to Twitter.
```
diff --git a/docs/Makefile b/docs/Makefile
index 411ff35df..91f36aefc 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -12,7 +12,7 @@ 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 text web pickle htmlhelp latex latexpdf changes linkcheck epub doctest
+.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"
@@ -22,6 +22,7 @@ help:
@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"
@@ -30,6 +31,12 @@ help:
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
@@ -68,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
diff --git a/docs/api/httpexceptions.rst b/docs/api/httpexceptions.rst
index d4cf97f1d..e25a07cd5 100644
--- a/docs/api/httpexceptions.rst
+++ b/docs/api/httpexceptions.rst
@@ -51,6 +51,8 @@
.. autoexception:: HTTPTemporaryRedirect
+ .. autoexception:: HTTPPermanentRedirect
+
.. autoexception:: HTTPBadRequest
.. autoexception:: HTTPUnauthorized
diff --git a/docs/conf.py b/docs/conf.py
index cf92e05e8..075345d8c 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -53,7 +53,6 @@ extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.doctest',
'sphinx.ext.intersphinx',
- 'sphinx.ext.todo',
'sphinx.ext.viewcode',
'sphinxcontrib.autoprogram',
# enable pylons_sphinx_latesturl when this branch is no longer "latest"
@@ -124,9 +123,6 @@ exclude_patterns = ['_themes/README.rst', ]
# unit titles (such as .. function::).
add_module_names = False
-# Add support for todo items
-todo_include_todos = True
-
# The name of the Pygments (syntax highlighting) style to use.
#pygments_style = book and 'bw' or 'tango'
if book:
@@ -175,8 +171,6 @@ html_last_updated_fmt = '%b %d, %Y'
# Do not use smart quotes.
smartquotes = False
-# Remove next line when RTD goes to Sphinx==1.6.6
-html_use_smartypants = False
# Output file base name for HTML help builder.
htmlhelp_basename = 'pyramid'
@@ -190,7 +184,10 @@ latex_paper_size = 'letter'
# 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]).
@@ -220,6 +217,17 @@ latex_domain_indices = False
_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,
@@ -276,28 +284,22 @@ _PREAMBLE = r"""
\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
@@ -318,7 +320,6 @@ _PREAMBLE = r"""
latex_elements = {
'preamble': _PREAMBLE,
- 'wrapperclass': 'book',
'date': '',
'releasename': 'Version',
'title': r'The Pyramid Web Framework',
@@ -342,17 +343,6 @@ 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')]
@@ -360,26 +350,14 @@ 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=[]):
diff --git a/docs/make_book b/docs/make_book
index 94e249441..c3d3743ae 100755
--- a/docs/make_book
+++ b/docs/make_book
@@ -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
diff --git a/docs/make_pdf b/docs/make_pdf
index 6c9863bc9..6cf0ff726 100755
--- a/docs/make_pdf
+++ b/docs/make_pdf
@@ -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
diff --git a/docs/narr/myproject/myproject/templates/layout.jinja2 b/docs/narr/myproject/myproject/templates/layout.jinja2
index 1baca52bd..38f5ae7a8 100644
--- a/docs/narr/myproject/myproject/templates/layout.jinja2
+++ b/docs/narr/myproject/myproject/templates/layout.jinja2
@@ -16,7 +16,7 @@
<!-- Custom styles for this scaffold -->
<link href="{{request.static_url('myproject:static/theme.css')}}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst
index 9ac01e24a..00c7bd3bf 100644
--- a/docs/narr/urldispatch.rst
+++ b/docs/narr/urldispatch.rst
@@ -1045,6 +1045,24 @@ may be added in the future. For example:
config = Configurator()
config.include(users_include, route_prefix='/users')
+A convenience context manager exists to set the route prefix for any
+:meth:`pyramid.config.Configurator.add_route` or
+:meth:`pyramid.config.Configurator.include` calls within the context.
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.config import Configurator
+
+ def timing_include(config):
+ config.add_route('timing.show_times', '/times')
+
+ def main(global_config, **settings)
+ config = Configurator()
+ with config.route_prefix_context('/timing'):
+ config.include(timing_include)
+ config.add_route('timing.average', '/average')
+
.. index::
single: route predicates (custom)
diff --git a/docs/quick_tour.rst b/docs/quick_tour.rst
index c6e696ae3..97dda98c0 100644
--- a/docs/quick_tour.rst
+++ b/docs/quick_tour.rst
@@ -10,6 +10,7 @@ for those who want to evaluate Pyramid, whether you are new to Python web
frameworks, or a pro in a hurry. For more detailed treatment of each topic,
give the :ref:`quick_tutorial` a try.
+If you would prefer to cut and paste the example code in this tour you may browse the source code located in the `Pyramid repository in the directory "docs/quick_tour" <https://github.com/Pylons/pyramid/>`. If you have downloaded the source code, you will find the tour in the same location.
Installation
============
diff --git a/docs/quick_tour/logging/hello_world/templates/layout.jinja2 b/docs/quick_tour/logging/hello_world/templates/layout.jinja2
index 64142f819..45226b9e3 100644
--- a/docs/quick_tour/logging/hello_world/templates/layout.jinja2
+++ b/docs/quick_tour/logging/hello_world/templates/layout.jinja2
@@ -16,7 +16,7 @@
<!-- Custom styles for this scaffold -->
<link href="{{request.static_url('hello_world:static/theme.css')}}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/quick_tour/package/hello_world/templates/layout.jinja2 b/docs/quick_tour/package/hello_world/templates/layout.jinja2
index 64142f819..45226b9e3 100644
--- a/docs/quick_tour/package/hello_world/templates/layout.jinja2
+++ b/docs/quick_tour/package/hello_world/templates/layout.jinja2
@@ -16,7 +16,7 @@
<!-- Custom styles for this scaffold -->
<link href="{{request.static_url('hello_world:static/theme.css')}}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/quick_tour/sessions/hello_world/templates/layout.jinja2 b/docs/quick_tour/sessions/hello_world/templates/layout.jinja2
index 64142f819..45226b9e3 100644
--- a/docs/quick_tour/sessions/hello_world/templates/layout.jinja2
+++ b/docs/quick_tour/sessions/hello_world/templates/layout.jinja2
@@ -16,7 +16,7 @@
<!-- Custom styles for this scaffold -->
<link href="{{request.static_url('hello_world:static/theme.css')}}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/templates/layout.jinja2 b/docs/quick_tour/sqla_demo/sqla_demo/templates/layout.jinja2
index 904fa442f..107691acf 100644
--- a/docs/quick_tour/sqla_demo/sqla_demo/templates/layout.jinja2
+++ b/docs/quick_tour/sqla_demo/sqla_demo/templates/layout.jinja2
@@ -16,7 +16,7 @@
<!-- Custom styles for this scaffold -->
<link href="{{request.static_url('sqla_demo:static/theme.css')}}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/quick_tutorial/authentication.rst b/docs/quick_tutorial/authentication.rst
index 95acc33e4..529f51ddd 100644
--- a/docs/quick_tutorial/authentication.rst
+++ b/docs/quick_tutorial/authentication.rst
@@ -39,7 +39,7 @@ Steps
.. literalinclude:: authentication/setup.py
:language: python
- :emphasize-lines: 7
+ :emphasize-lines: 4
:linenos:
#. We can now install our project in development mode:
@@ -94,7 +94,7 @@ Steps
#. Click the "Log In" link.
-#. Submit the login form with the username ``editor`` and the password
+#. Submit the login form with the username ``editor`` and the password
``editor``.
#. Note that the "Log In" link has changed to "Logout".
diff --git a/docs/quick_tutorial/authentication/setup.py b/docs/quick_tutorial/authentication/setup.py
index 808a6f9a9..a5117af5a 100644
--- a/docs/quick_tutorial/authentication/setup.py
+++ b/docs/quick_tutorial/authentication/setup.py
@@ -1,10 +1,10 @@
from setuptools import setup
requires = [
+ 'bcrypt',
'pyramid',
- 'waitress',
'pyramid_chameleon',
- 'bcrypt'
+ 'waitress',
]
setup(name='tutorial',
@@ -13,4 +13,4 @@ setup(name='tutorial',
[paste.app_factory]
main = tutorial:main
""",
-) \ No newline at end of file
+)
diff --git a/docs/quick_tutorial/authorization/setup.py b/docs/quick_tutorial/authorization/setup.py
index 808a6f9a9..a5117af5a 100644
--- a/docs/quick_tutorial/authorization/setup.py
+++ b/docs/quick_tutorial/authorization/setup.py
@@ -1,10 +1,10 @@
from setuptools import setup
requires = [
+ 'bcrypt',
'pyramid',
- 'waitress',
'pyramid_chameleon',
- 'bcrypt'
+ 'waitress',
]
setup(name='tutorial',
@@ -13,4 +13,4 @@ setup(name='tutorial',
[paste.app_factory]
main = tutorial:main
""",
-) \ No newline at end of file
+)
diff --git a/docs/quick_tutorial/cookiecutters/cc_starter/templates/layout.jinja2 b/docs/quick_tutorial/cookiecutters/cc_starter/templates/layout.jinja2
index 13a65ff72..90d2d106a 100644
--- a/docs/quick_tutorial/cookiecutters/cc_starter/templates/layout.jinja2
+++ b/docs/quick_tutorial/cookiecutters/cc_starter/templates/layout.jinja2
@@ -16,7 +16,7 @@
<!-- Custom styles for this scaffold -->
<link href="{{request.static_url('cc_starter:static/theme.css')}}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/quick_tutorial/cookiecutters/setup.py b/docs/quick_tutorial/cookiecutters/setup.py
index e47cdf8ea..0d1b3f70e 100644
--- a/docs/quick_tutorial/cookiecutters/setup.py
+++ b/docs/quick_tutorial/cookiecutters/setup.py
@@ -10,8 +10,8 @@ with open(os.path.join(here, 'CHANGES.txt')) as f:
requires = [
'pyramid',
- 'pyramid_jinja2',
'pyramid_debugtoolbar',
+ 'pyramid_jinja2',
'waitress',
]
diff --git a/docs/quick_tutorial/databases/setup.py b/docs/quick_tutorial/databases/setup.py
index 66045fd7e..13d1d6637 100644
--- a/docs/quick_tutorial/databases/setup.py
+++ b/docs/quick_tutorial/databases/setup.py
@@ -1,13 +1,13 @@
from setuptools import setup
requires = [
+ 'deform',
'pyramid',
- 'waitress',
'pyramid_chameleon',
- 'deform',
- 'sqlalchemy',
'pyramid_tm',
- 'zope.sqlalchemy'
+ 'sqlalchemy',
+ 'waitress',
+ 'zope.sqlalchemy',
]
setup(name='tutorial',
@@ -18,4 +18,4 @@ setup(name='tutorial',
[console_scripts]
initialize_tutorial_db = tutorial.initialize_db:main
""",
-) \ No newline at end of file
+)
diff --git a/docs/quick_tutorial/forms.rst b/docs/quick_tutorial/forms.rst
index 3c865ad09..45eb05a8f 100644
--- a/docs/quick_tutorial/forms.rst
+++ b/docs/quick_tutorial/forms.rst
@@ -41,7 +41,7 @@ Steps
pulls in Colander as a dependency:
.. literalinclude:: forms/setup.py
- :emphasize-lines: 7
+ :emphasize-lines: 4
:linenos:
#. We can now install our project in development mode:
diff --git a/docs/quick_tutorial/forms/setup.py b/docs/quick_tutorial/forms/setup.py
index 5293ef7f0..968889e74 100644
--- a/docs/quick_tutorial/forms/setup.py
+++ b/docs/quick_tutorial/forms/setup.py
@@ -1,10 +1,10 @@
from setuptools import setup
requires = [
+ 'deform',
'pyramid',
- 'waitress',
'pyramid_chameleon',
- 'deform'
+ 'waitress',
]
setup(name='tutorial',
@@ -13,4 +13,4 @@ setup(name='tutorial',
[paste.app_factory]
main = tutorial:main
""",
-) \ No newline at end of file
+)
diff --git a/docs/quick_tutorial/json/setup.py b/docs/quick_tutorial/json/setup.py
index aefa352d4..744612371 100644
--- a/docs/quick_tutorial/json/setup.py
+++ b/docs/quick_tutorial/json/setup.py
@@ -2,8 +2,8 @@ from setuptools import setup
requires = [
'pyramid',
+ 'pyramid_chameleon',
'waitress',
- 'pyramid_chameleon'
]
setup(name='tutorial',
@@ -12,4 +12,4 @@ setup(name='tutorial',
[paste.app_factory]
main = tutorial:main
""",
-) \ No newline at end of file
+)
diff --git a/docs/quick_tutorial/logging/setup.py b/docs/quick_tutorial/logging/setup.py
index aefa352d4..744612371 100644
--- a/docs/quick_tutorial/logging/setup.py
+++ b/docs/quick_tutorial/logging/setup.py
@@ -2,8 +2,8 @@ from setuptools import setup
requires = [
'pyramid',
+ 'pyramid_chameleon',
'waitress',
- 'pyramid_chameleon'
]
setup(name='tutorial',
@@ -12,4 +12,4 @@ setup(name='tutorial',
[paste.app_factory]
main = tutorial:main
""",
-) \ No newline at end of file
+)
diff --git a/docs/quick_tutorial/more_view_classes/setup.py b/docs/quick_tutorial/more_view_classes/setup.py
index aefa352d4..744612371 100644
--- a/docs/quick_tutorial/more_view_classes/setup.py
+++ b/docs/quick_tutorial/more_view_classes/setup.py
@@ -2,8 +2,8 @@ from setuptools import setup
requires = [
'pyramid',
+ 'pyramid_chameleon',
'waitress',
- 'pyramid_chameleon'
]
setup(name='tutorial',
@@ -12,4 +12,4 @@ setup(name='tutorial',
[paste.app_factory]
main = tutorial:main
""",
-) \ No newline at end of file
+)
diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst
index a65cfe6d2..29f263176 100644
--- a/docs/quick_tutorial/requirements.rst
+++ b/docs/quick_tutorial/requirements.rst
@@ -79,15 +79,15 @@ will reside as we proceed through the tutorial:
.. code-block:: text
- `── ~
- `── projects
- `── quick_tutorial
- │── env
- `── step_one
- │── intro
- │ │── __init__.py
- │ `── app.py
- `── setup.py
+ ~
+ └── projects
+ └── quick_tutorial
+ ├── env
+ └── step_one
+ ├── intro
+ │ ├── __init__.py
+ │ └── app.py
+ └── setup.py
For Linux, the commands to do so are as follows:
@@ -202,17 +202,3 @@ part is pretty easy. We'll also install a WSGI server, Waitress.
Our Python virtual environment now has the Pyramid software available
as well as the ``waitress`` package.
-You can optionally install some of the extra Python packages used in this
-tutorial.
-
-.. code-block:: bash
-
- # Mac and Linux
- $ $VENV/bin/pip install webtest pytest pytest-cov deform sqlalchemy \
- pyramid_chameleon pyramid_debugtoolbar pyramid_jinja2 waitress \
- pyramid_tm zope.sqlalchemy
-
-.. code-block:: doscon
-
- # Windows
- c:\> %VENV%\Scripts\pip install webtest pytest pytest-cov deform sqlalchemy pyramid_chameleon pyramid_debugtoolbar pyramid_jinja2 waitress pyramid_tm zope.sqlalchemy
diff --git a/docs/quick_tutorial/retail_forms/setup.py b/docs/quick_tutorial/retail_forms/setup.py
index 5293ef7f0..968889e74 100644
--- a/docs/quick_tutorial/retail_forms/setup.py
+++ b/docs/quick_tutorial/retail_forms/setup.py
@@ -1,10 +1,10 @@
from setuptools import setup
requires = [
+ 'deform',
'pyramid',
- 'waitress',
'pyramid_chameleon',
- 'deform'
+ 'waitress',
]
setup(name='tutorial',
@@ -13,4 +13,4 @@ setup(name='tutorial',
[paste.app_factory]
main = tutorial:main
""",
-) \ No newline at end of file
+)
diff --git a/docs/quick_tutorial/routing/setup.py b/docs/quick_tutorial/routing/setup.py
index aefa352d4..744612371 100644
--- a/docs/quick_tutorial/routing/setup.py
+++ b/docs/quick_tutorial/routing/setup.py
@@ -2,8 +2,8 @@ from setuptools import setup
requires = [
'pyramid',
+ 'pyramid_chameleon',
'waitress',
- 'pyramid_chameleon'
]
setup(name='tutorial',
@@ -12,4 +12,4 @@ setup(name='tutorial',
[paste.app_factory]
main = tutorial:main
""",
-) \ No newline at end of file
+)
diff --git a/docs/quick_tutorial/sessions/setup.py b/docs/quick_tutorial/sessions/setup.py
index aefa352d4..744612371 100644
--- a/docs/quick_tutorial/sessions/setup.py
+++ b/docs/quick_tutorial/sessions/setup.py
@@ -2,8 +2,8 @@ from setuptools import setup
requires = [
'pyramid',
+ 'pyramid_chameleon',
'waitress',
- 'pyramid_chameleon'
]
setup(name='tutorial',
@@ -12,4 +12,4 @@ setup(name='tutorial',
[paste.app_factory]
main = tutorial:main
""",
-) \ No newline at end of file
+)
diff --git a/docs/quick_tutorial/static_assets/setup.py b/docs/quick_tutorial/static_assets/setup.py
index aefa352d4..744612371 100644
--- a/docs/quick_tutorial/static_assets/setup.py
+++ b/docs/quick_tutorial/static_assets/setup.py
@@ -2,8 +2,8 @@ from setuptools import setup
requires = [
'pyramid',
+ 'pyramid_chameleon',
'waitress',
- 'pyramid_chameleon'
]
setup(name='tutorial',
@@ -12,4 +12,4 @@ setup(name='tutorial',
[paste.app_factory]
main = tutorial:main
""",
-) \ No newline at end of file
+)
diff --git a/docs/quick_tutorial/templating/setup.py b/docs/quick_tutorial/templating/setup.py
index d1910178e..744612371 100644
--- a/docs/quick_tutorial/templating/setup.py
+++ b/docs/quick_tutorial/templating/setup.py
@@ -2,8 +2,8 @@ from setuptools import setup
requires = [
'pyramid',
- 'waitress',
'pyramid_chameleon',
+ 'waitress',
]
setup(name='tutorial',
diff --git a/docs/quick_tutorial/tutorial_approach.rst b/docs/quick_tutorial/tutorial_approach.rst
index 8da9f71b3..83b229746 100644
--- a/docs/quick_tutorial/tutorial_approach.rst
+++ b/docs/quick_tutorial/tutorial_approach.rst
@@ -15,7 +15,7 @@ This "Getting Started" tutorial is broken into independent steps, starting with
the smallest possible "single file WSGI app" example. Each of these steps
introduces a topic and a very small set of concepts via working code. The steps
each correspond to a directory in our workspace, where each step's directory is
-a Python package.
+a Python package. Source code used in this tutorial is located in the `Pyramid repository in the directory "docs/quick_tutorial" <https://github.com/Pylons/pyramid/>`_. You may ``git clone`` the repository, download, or copy-paste the source code. If you do so, then make sure you use the same branch as this documentation.
As we develop our tutorial, our directory tree will resemble the structure
below:
@@ -23,14 +23,14 @@ below:
.. code-block:: text
quick_tutorial
- │── env
- `── request_response
- `── tutorial
- │ │── __init__.py
- │ │── tests.py
- │ `── views.py
- │── development.ini
- `── setup.py
+ ├── env
+ └── request_response
+ ├── tutorial
+ │ ├── __init__.py
+ │ ├── tests.py
+ │ └── views.py
+ ├── development.ini
+ └── setup.py
Each of the directories in our ``quick_tutorial`` workspace (e.g., ``request_response``) is a *Python
project* (except as noted for the ``hello_world`` step). The ``tutorial``
diff --git a/docs/quick_tutorial/view_classes/setup.py b/docs/quick_tutorial/view_classes/setup.py
index aefa352d4..744612371 100644
--- a/docs/quick_tutorial/view_classes/setup.py
+++ b/docs/quick_tutorial/view_classes/setup.py
@@ -2,8 +2,8 @@ from setuptools import setup
requires = [
'pyramid',
+ 'pyramid_chameleon',
'waitress',
- 'pyramid_chameleon'
]
setup(name='tutorial',
@@ -12,4 +12,4 @@ setup(name='tutorial',
[paste.app_factory]
main = tutorial:main
""",
-) \ No newline at end of file
+)
diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt
index a14d1801d..3ef0c7e0e 100644
--- a/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt
+++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt
@@ -17,7 +17,7 @@
<!-- Custom styles for this scaffold -->
<link href="${request.static_url('tutorial:static/theme.css')}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt
index 23a381a37..626db6637 100644
--- a/docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt
+++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt
@@ -17,7 +17,7 @@
<!-- Custom styles for this scaffold -->
<link href="${request.static_url('tutorial:static/theme.css')}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt
index f3c987c53..5d9478fb9 100644
--- a/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt
+++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt
@@ -17,7 +17,7 @@
<!-- Custom styles for this scaffold -->
<link href="${request.static_url('tutorial:static/theme.css')}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt
index a6736560f..d63ea8c45 100644
--- a/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt
@@ -16,7 +16,7 @@
<!-- Custom styles for this scaffold -->
<link href="${request.static_url('tutorial:static/theme.css')}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/tutorials/wiki/src/installation/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/installation/tutorial/templates/mytemplate.pt
index a6736560f..d63ea8c45 100644
--- a/docs/tutorials/wiki/src/installation/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki/src/installation/tutorial/templates/mytemplate.pt
@@ -16,7 +16,7 @@
<!-- Custom styles for this scaffold -->
<link href="${request.static_url('tutorial:static/theme.css')}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt
index a6736560f..d63ea8c45 100644
--- a/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt
@@ -16,7 +16,7 @@
<!-- Custom styles for this scaffold -->
<link href="${request.static_url('tutorial:static/theme.css')}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt
index a14d1801d..3ef0c7e0e 100644
--- a/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt
+++ b/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt
@@ -17,7 +17,7 @@
<!-- Custom styles for this scaffold -->
<link href="${request.static_url('tutorial:static/theme.css')}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/login.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/login.pt
index 23a381a37..626db6637 100644
--- a/docs/tutorials/wiki/src/tests/tutorial/templates/login.pt
+++ b/docs/tutorials/wiki/src/tests/tutorial/templates/login.pt
@@ -17,7 +17,7 @@
<!-- Custom styles for this scaffold -->
<link href="${request.static_url('tutorial:static/theme.css')}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt
index 2468d3912..1d33787d9 100644
--- a/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt
@@ -16,7 +16,7 @@
<!-- Custom styles for this scaffold -->
<link href="${request.static_url('tutorial:static/theme.css')}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt
index f3c987c53..5d9478fb9 100644
--- a/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt
+++ b/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt
@@ -17,7 +17,7 @@
<!-- Custom styles for this scaffold -->
<link href="${request.static_url('tutorial:static/theme.css')}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/tutorials/wiki/src/views/tutorial/templates/edit.pt b/docs/tutorials/wiki/src/views/tutorial/templates/edit.pt
index 7549aea17..2db3ca79c 100644
--- a/docs/tutorials/wiki/src/views/tutorial/templates/edit.pt
+++ b/docs/tutorials/wiki/src/views/tutorial/templates/edit.pt
@@ -17,7 +17,7 @@
<!-- Custom styles for this scaffold -->
<link href="${request.static_url('tutorial:static/theme.css')}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/tutorials/wiki/src/views/tutorial/templates/view.pt b/docs/tutorials/wiki/src/views/tutorial/templates/view.pt
index b7a87b20a..1feeab5ef 100644
--- a/docs/tutorials/wiki/src/views/tutorial/templates/view.pt
+++ b/docs/tutorials/wiki/src/views/tutorial/templates/view.pt
@@ -17,7 +17,7 @@
<!-- Custom styles for this scaffold -->
<link href="${request.static_url('tutorial:static/theme.css')}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/tutorials/wiki2/index.rst b/docs/tutorials/wiki2/index.rst
index 740a7f014..40a194155 100644
--- a/docs/tutorials/wiki2/index.rst
+++ b/docs/tutorials/wiki2/index.rst
@@ -7,8 +7,8 @@ This tutorial introduces an :term:`SQLAlchemy` and :term:`URL dispatch`-based
:app:`Pyramid` application to a developer familiar with Python. When finished, the developer will have created a basic wiki
application with authentication and authorization.
-For cut and paste purposes, the source code for all stages of this tutorial can
-be browsed on `GitHub <https://github.com/Pylons/pyramid/>`_,
+For cut and paste purposes, the source code for all stages of this
+tutorial can be browsed on GitHub at `GitHub <https://github.com/Pylons/pyramid/>`_ for a specific branch or version under ``docs/tutorials/wiki2/src``,
which corresponds to the same location if you have Pyramid sources.
.. toctree::
diff --git a/docs/tutorials/wiki2/src/authentication/tutorial/templates/layout.jinja2 b/docs/tutorials/wiki2/src/authentication/tutorial/templates/layout.jinja2
index 9b2dc82fc..b98ccbd95 100644
--- a/docs/tutorials/wiki2/src/authentication/tutorial/templates/layout.jinja2
+++ b/docs/tutorials/wiki2/src/authentication/tutorial/templates/layout.jinja2
@@ -16,7 +16,7 @@
<!-- Custom styles for this scaffold -->
<link href="{{request.static_url('tutorial:static/theme.css')}}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/templates/layout.jinja2 b/docs/tutorials/wiki2/src/authorization/tutorial/templates/layout.jinja2
index 9b2dc82fc..b98ccbd95 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/templates/layout.jinja2
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/templates/layout.jinja2
@@ -16,7 +16,7 @@
<!-- Custom styles for this scaffold -->
<link href="{{request.static_url('tutorial:static/theme.css')}}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/layout.jinja2 b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/layout.jinja2
index 6ce99d08e..5d4313fe2 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/layout.jinja2
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/layout.jinja2
@@ -16,7 +16,7 @@
<!-- Custom styles for this scaffold -->
<link href="{{request.static_url('tutorial:static/theme.css')}}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/tutorials/wiki2/src/installation/tutorial/templates/layout.jinja2 b/docs/tutorials/wiki2/src/installation/tutorial/templates/layout.jinja2
index 6ce99d08e..5d4313fe2 100644
--- a/docs/tutorials/wiki2/src/installation/tutorial/templates/layout.jinja2
+++ b/docs/tutorials/wiki2/src/installation/tutorial/templates/layout.jinja2
@@ -16,7 +16,7 @@
<!-- Custom styles for this scaffold -->
<link href="{{request.static_url('tutorial:static/theme.css')}}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/tutorials/wiki2/src/models/tutorial/templates/layout.jinja2 b/docs/tutorials/wiki2/src/models/tutorial/templates/layout.jinja2
index 6ce99d08e..5d4313fe2 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/templates/layout.jinja2
+++ b/docs/tutorials/wiki2/src/models/tutorial/templates/layout.jinja2
@@ -16,7 +16,7 @@
<!-- Custom styles for this scaffold -->
<link href="{{request.static_url('tutorial:static/theme.css')}}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/tutorials/wiki2/src/tests/tutorial/templates/layout.jinja2 b/docs/tutorials/wiki2/src/tests/tutorial/templates/layout.jinja2
index 9b2dc82fc..b98ccbd95 100644
--- a/docs/tutorials/wiki2/src/tests/tutorial/templates/layout.jinja2
+++ b/docs/tutorials/wiki2/src/tests/tutorial/templates/layout.jinja2
@@ -16,7 +16,7 @@
<!-- Custom styles for this scaffold -->
<link href="{{request.static_url('tutorial:static/theme.css')}}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/tutorials/wiki2/src/views/tutorial/templates/layout.jinja2 b/docs/tutorials/wiki2/src/views/tutorial/templates/layout.jinja2
index 5e7dfe894..80062cbff 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/templates/layout.jinja2
+++ b/docs/tutorials/wiki2/src/views/tutorial/templates/layout.jinja2
@@ -16,7 +16,7 @@
<!-- Custom styles for this scaffold -->
<link href="{{request.static_url('tutorial:static/theme.css')}}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
diff --git a/docs/typographical-conventions.rst b/docs/typographical-conventions.rst
index f128effea..2bfe4ffa6 100644
--- a/docs/typographical-conventions.rst
+++ b/docs/typographical-conventions.rst
@@ -217,18 +217,6 @@ The version in which a feature is deprecated in a project is displayed as follow
Use the ``require_csrf`` option or read :ref:`auto_csrf_checking` instead to have :class:`pyramid.exceptions.BadCSRFToken` exceptions raised.
-.. _typographical-conventions-danger:
-
-Danger
-------
-
-Danger represents critical information related to a topic or concept, and should recommend to the user "don't do this dangerous thing".
-
-.. danger::
-
- This is danger or an error.
-
-
.. _typographical-conventions-warnings:
Warnings
@@ -265,18 +253,6 @@ See also
See :ref:`Quick Tutorial section on Requirements <qtut_requirements>`.
-.. _typographical-conventions-todo:
-
-Todo
-----
-
-Todo items designated tasks that require further work.
-
-.. todo::
-
- This is a todo item.
-
-
.. _typographical-conventions-cross-references:
Cross-references
diff --git a/pyramid/config/__init__.py b/pyramid/config/__init__.py
index a34f0b4db..886eec0df 100644
--- a/pyramid/config/__init__.py
+++ b/pyramid/config/__init__.py
@@ -790,21 +790,6 @@ class Configurator(
action_state = self.action_state
- if route_prefix is None:
- route_prefix = ''
-
- old_route_prefix = self.route_prefix
- if old_route_prefix is None:
- old_route_prefix = ''
-
- route_prefix = '%s/%s' % (
- old_route_prefix.rstrip('/'),
- route_prefix.lstrip('/')
- )
- route_prefix = route_prefix.strip('/')
- if not route_prefix:
- route_prefix = None
-
c = self.maybe_dotted(callable)
module = self.inspect.getmodule(c)
if module is c:
@@ -825,20 +810,22 @@ class Configurator(
if action_state.processSpec(spec):
- configurator = self.__class__(
- registry=self.registry,
- package=package_of(module),
- root_package=self.root_package,
- autocommit=self.autocommit,
- route_prefix=route_prefix,
- )
- configurator.basepath = os.path.dirname(sourcefile)
- configurator.includepath = self.includepath + (spec,)
- self.begin()
- try:
- c(configurator)
- finally:
- self.end()
+ with self.route_prefix_context(route_prefix):
+ configurator = self.__class__(
+ registry=self.registry,
+ package=package_of(module),
+ root_package=self.root_package,
+ autocommit=self.autocommit,
+ route_prefix=self.route_prefix,
+ )
+ configurator.basepath = os.path.dirname(sourcefile)
+ configurator.includepath = self.includepath + (spec,)
+
+ self.begin()
+ try:
+ c(configurator)
+ finally:
+ self.end()
def add_directive(self, name, directive, action_wrap=True):
"""
diff --git a/pyramid/config/routes.py b/pyramid/config/routes.py
index 203baa128..20fdb2b5d 100644
--- a/pyramid/config/routes.py
+++ b/pyramid/config/routes.py
@@ -1,3 +1,4 @@
+import contextlib
import warnings
from pyramid.compat import urlparse
@@ -23,7 +24,6 @@ class RoutesConfiguratorMixin(object):
def add_route(self,
name,
pattern=None,
- permission=None,
factory=None,
for_=None,
header=None,
@@ -198,9 +198,9 @@ class RoutesConfiguratorMixin(object):
request_param
- This value can be any string. A view declaration with this
- argument ensures that the associated route will only match
- when the request has a key in the ``request.params``
+ This value can be any string or an iterable of strings. A view
+ declaration with this argument ensures that the associated route will
+ only match when the request has a key in the ``request.params``
dictionary (an HTTP ``GET`` or ``POST`` variable) that has a
name which matches the supplied value. If the value
supplied as the argument has a ``=`` sign in it,
@@ -467,3 +467,53 @@ class RoutesConfiguratorMixin(object):
self.registry.registerUtility(mapper, IRoutesMapper)
return mapper
+ @contextlib.contextmanager
+ def route_prefix_context(self, route_prefix):
+ """ Return this configurator with the
+ :attr:`pyramid.config.Configurator.route_prefix` attribute mutated to
+ include the new ``route_prefix``.
+
+ When the context exits, the ``route_prefix`` is reset to the original.
+
+ Example Usage:
+
+ >>> config = Configurator()
+ >>> with config.route_prefix_context('foo'):
+ ... config.add_route('bar', '/bar')
+
+ Arguments
+
+ route_prefix
+
+ A string suitable to be used as a route prefix, or ``None``.
+
+ .. versionadded:: 1.10
+ """
+
+ original_route_prefix = self.route_prefix
+
+ if route_prefix is None:
+ route_prefix = ''
+
+ old_route_prefix = self.route_prefix
+ if old_route_prefix is None:
+ old_route_prefix = ''
+
+ route_prefix = '{}/{}'.format(
+ old_route_prefix.rstrip('/'),
+ route_prefix.lstrip('/'),
+ )
+
+ route_prefix = route_prefix.strip('/')
+
+ if not route_prefix:
+ route_prefix = None
+
+ self.begin()
+ try:
+ self.route_prefix = route_prefix
+ yield
+
+ finally:
+ self.route_prefix = original_route_prefix
+ self.end()
diff --git a/pyramid/httpexceptions.py b/pyramid/httpexceptions.py
index 1f3934fdc..bef8420b1 100644
--- a/pyramid/httpexceptions.py
+++ b/pyramid/httpexceptions.py
@@ -7,7 +7,7 @@ single HTTP status code. Each class is a subclass of the
:class:`~HTTPException`. Each exception class is also a :term:`response`
object.
-Each exception class has a status code according to :rfc:`2068`:
+Each exception class has a status code according to :rfc:`2068` or :rfc:`7538`:
codes with 100-300 are not really errors; 400s are client errors,
and 500s are server errors.
@@ -29,6 +29,7 @@ Exception
* 304 - HTTPNotModified
* 305 - HTTPUseProxy
* 307 - HTTPTemporaryRedirect
+ * 308 - HTTPPermanentRedirect
HTTPError
HTTPClientError
* 400 - HTTPBadRequest
@@ -121,10 +122,11 @@ passed to the exception's constructor.
The subclasses of :class:`~_HTTPMove`
(:class:`~HTTPMultipleChoices`, :class:`~HTTPMovedPermanently`,
-:class:`~HTTPFound`, :class:`~HTTPSeeOther`, :class:`~HTTPUseProxy` and
-:class:`~HTTPTemporaryRedirect`) are redirections that require a ``Location``
-field. Reflecting this, these subclasses have one additional keyword argument:
-``location``, which indicates the location to which to redirect.
+:class:`~HTTPFound`, :class:`~HTTPSeeOther`, :class:`~HTTPUseProxy`,
+:class:`~HTTPTemporaryRedirect`, and :class: `~HTTPPermanentRedirect) are
+redirections that require a ``Location`` field. Reflecting this, these
+subclasses have one additional keyword argument: ``location``,
+which indicates the location to which to redirect.
"""
import json
@@ -133,7 +135,7 @@ from string import Template
from zope.interface import implementer
from webob import html_escape as _html_escape
-from webob.acceptparse import MIMEAccept
+from webob.acceptparse import create_accept_header
from pyramid.compat import (
class_types,
@@ -250,10 +252,12 @@ ${body}''')
html_comment = ''
comment = self.comment or ''
accept_value = environ.get('HTTP_ACCEPT', '')
- accept = MIMEAccept(accept_value)
+ accept = create_accept_header(accept_value)
# Attempt to match text/html or application/json, if those don't
# match, we will fall through to defaulting to text/plain
- match = accept.best_match(['text/html', 'application/json'])
+ acceptable = accept.acceptable_offers(['text/html', 'application/json'])
+ acceptable = [offer[0] for offer in acceptable] + ['text/plain']
+ match = acceptable[0]
if match == 'text/html':
self.content_type = 'text/html'
@@ -593,6 +597,19 @@ class HTTPTemporaryRedirect(_HTTPMove):
code = 307
title = 'Temporary Redirect'
+class HTTPPermanentRedirect(_HTTPMove):
+ """
+ subclass of :class:`~_HTTPMove`
+
+ This indicates that the requested resource resides permanently
+ under a different URI and that the request method must not be
+ changed.
+
+ code: 308, title: Permanent Redirect
+ """
+ code = 308
+ title = 'Permanent Redirect'
+
############################################################
## 4xx client error
############################################################
@@ -606,7 +623,8 @@ class HTTPClientError(HTTPError):
a bug. A server-side traceback is not warranted. Unless specialized,
this is a '400 Bad Request'
"""
- pass
+ code = 400
+ title = 'Bad Request'
class HTTPBadRequest(HTTPClientError):
"""
@@ -617,8 +635,6 @@ class HTTPBadRequest(HTTPClientError):
code: 400, title: Bad Request
"""
- code = 400
- title = 'Bad Request'
explanation = ('The server could not comply with the request since '
'it is either malformed or otherwise incorrect.')
@@ -1032,11 +1048,18 @@ class HTTPServerError(HTTPError):
This is an error condition in which the server is presumed to be
in-error. Unless specialized, this is a '500 Internal Server Error'.
"""
- pass
-
-class HTTPInternalServerError(HTTPServerError):
code = 500
title = 'Internal Server Error'
+
+class HTTPInternalServerError(HTTPServerError):
+ """
+ subclass of :class:`~HTTPServerError`
+
+ This indicates that the server encountered an unexpected condition
+ which prevented it from fulfilling the request.
+
+ code: 500, title: Internal Server Error
+ """
explanation = (
'The server has either erred or is incapable of performing '
'the requested operation.')
@@ -1150,6 +1173,7 @@ for name, value in list(globals().items()):
if (
isinstance(value, class_types) and
issubclass(value, HTTPException) and
+ value not in {HTTPClientError, HTTPServerError} and
not name.startswith('_')
):
code = getattr(value, 'code', None)
diff --git a/pyramid/scaffolds/alchemy/+package+/templates/layout.jinja2_tmpl b/pyramid/scaffolds/alchemy/+package+/templates/layout.jinja2_tmpl
index d610a94dc..d6b3ca9c6 100644
--- a/pyramid/scaffolds/alchemy/+package+/templates/layout.jinja2_tmpl
+++ b/pyramid/scaffolds/alchemy/+package+/templates/layout.jinja2_tmpl
@@ -16,7 +16,7 @@
<!-- Custom styles for this scaffold -->
<link href="\{\{request.static_url('{{package}}:static/theme.css')\}\}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js" integrity="sha384-f1r2UzjsxZ9T4V1f2zBO/evUqSEOpeaUUZcMTz1Up63bl4ruYnFYeM+BxI4NhyI0" crossorigin="anonymous"></script>
diff --git a/pyramid/scaffolds/starter/+package+/templates/layout.jinja2_tmpl b/pyramid/scaffolds/starter/+package+/templates/layout.jinja2_tmpl
index 7ed979808..54baf7a2a 100644
--- a/pyramid/scaffolds/starter/+package+/templates/layout.jinja2_tmpl
+++ b/pyramid/scaffolds/starter/+package+/templates/layout.jinja2_tmpl
@@ -16,7 +16,7 @@
<!-- Custom styles for this scaffold -->
<link href="\{\{request.static_url('{{package}}:static/theme.css')\}\}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js" integrity="sha384-f1r2UzjsxZ9T4V1f2zBO/evUqSEOpeaUUZcMTz1Up63bl4ruYnFYeM+BxI4NhyI0" crossorigin="anonymous"></script>
diff --git a/pyramid/scaffolds/zodb/+package+/templates/mytemplate.pt_tmpl b/pyramid/scaffolds/zodb/+package+/templates/mytemplate.pt_tmpl
index dd93ebd2e..f66effa41 100644
--- a/pyramid/scaffolds/zodb/+package+/templates/mytemplate.pt_tmpl
+++ b/pyramid/scaffolds/zodb/+package+/templates/mytemplate.pt_tmpl
@@ -16,7 +16,7 @@
<!-- Custom styles for this scaffold -->
<link href="${request.static_url('{{package}}:static/theme.css')}" rel="stylesheet">
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
<script src="//oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js" integrity="sha384-f1r2UzjsxZ9T4V1f2zBO/evUqSEOpeaUUZcMTz1Up63bl4ruYnFYeM+BxI4NhyI0" crossorigin="anonymous"></script>
diff --git a/pyramid/session.py b/pyramid/session.py
index 4a9c8c100..d05ac66eb 100644
--- a/pyramid/session.py
+++ b/pyramid/session.py
@@ -135,6 +135,7 @@ def BaseCookieSessionFactory(
domain=None,
secure=False,
httponly=False,
+ samesite='Lax',
timeout=1200,
reissue_time=0,
set_on_exception=True,
@@ -187,6 +188,10 @@ def BaseCookieSessionFactory(
Hide the cookie from Javascript by setting the 'HttpOnly' flag of the
session cookie. Default: ``False``.
+ ``samesite``
+ The 'samesite' option of the session cookie. Set the value to ``None``
+ to turn off the samesite option. Default: ``'Lax'``.
+
``timeout``
A number of seconds of inactivity before a session times out. If
``None`` then the cookie never expires. This lifetime only applies
@@ -216,6 +221,10 @@ def BaseCookieSessionFactory(
while rendering a view. Default: ``True``.
.. versionadded: 1.5a3
+
+ .. versionchanged: 1.10
+
+ Added the ``samesite`` option and made the default ``'Lax'``.
"""
@implementer(ISession)
@@ -229,6 +238,7 @@ def BaseCookieSessionFactory(
_cookie_domain = domain
_cookie_secure = secure
_cookie_httponly = httponly
+ _cookie_samesite = samesite
_cookie_on_exception = set_on_exception
_timeout = timeout if timeout is None else int(timeout)
_reissue_time = reissue_time if reissue_time is None else int(reissue_time)
@@ -367,6 +377,7 @@ def BaseCookieSessionFactory(
domain=self._cookie_domain,
secure=self._cookie_secure,
httponly=self._cookie_httponly,
+ samesite=self._cookie_samesite,
)
return True
@@ -382,6 +393,7 @@ def UnencryptedCookieSessionFactoryConfig(
cookie_domain=None,
cookie_secure=False,
cookie_httponly=False,
+ cookie_samesite='Lax',
cookie_on_exception=True,
signed_serialize=signed_serialize,
signed_deserialize=signed_deserialize,
@@ -434,6 +446,10 @@ def UnencryptedCookieSessionFactoryConfig(
``cookie_httponly``
The 'httpOnly' flag of the session cookie.
+ ``cookie_samesite``
+ The 'samesite' option of the session cookie. Set the value to ``None``
+ to turn off the samesite option. Default: ``'Lax'``.
+
``cookie_on_exception``
If ``True``, set a session cookie even if an exception occurs
while rendering a view.
@@ -447,6 +463,10 @@ def UnencryptedCookieSessionFactoryConfig(
A callable which takes a signed and serialized data structure in bytes
and a secret and returns the original data structure if the signature
is valid. Default: ``signed_deserialize`` (using pickle).
+
+ .. versionchanged: 1.10
+
+ Added the ``samesite`` option and made the default ``'Lax'``.
"""
class SerializerWrapper(object):
@@ -469,6 +489,7 @@ def UnencryptedCookieSessionFactoryConfig(
domain=cookie_domain,
secure=cookie_secure,
httponly=cookie_httponly,
+ samesite=cookie_samesite,
timeout=timeout,
reissue_time=0, # to keep session.accessed == session.renewed
set_on_exception=cookie_on_exception,
@@ -491,6 +512,7 @@ def SignedCookieSessionFactory(
domain=None,
secure=False,
httponly=False,
+ samesite='Lax',
set_on_exception=True,
timeout=1200,
reissue_time=0,
@@ -553,6 +575,10 @@ def SignedCookieSessionFactory(
Hide the cookie from Javascript by setting the 'HttpOnly' flag of the
session cookie. Default: ``False``.
+ ``samesite``
+ The 'samesite' option of the session cookie. Set the value to ``None``
+ to turn off the samesite option. Default: ``'Lax'``.
+
``timeout``
A number of seconds of inactivity before a session times out. If
``None`` then the cookie never expires. This lifetime only applies
@@ -589,6 +615,10 @@ def SignedCookieSessionFactory(
the :class:`pyramid.session.PickleSerializer` serializer will be used.
.. versionadded: 1.5a3
+
+ .. versionchanged: 1.10
+
+ Added the ``samesite`` option and made the default ``Lax``.
"""
if serializer is None:
serializer = PickleSerializer()
@@ -608,6 +638,7 @@ def SignedCookieSessionFactory(
domain=domain,
secure=secure,
httponly=httponly,
+ samesite=samesite,
timeout=timeout,
reissue_time=reissue_time,
set_on_exception=set_on_exception,
diff --git a/pyramid/tests/test_httpexceptions.py b/pyramid/tests/test_httpexceptions.py
index e2d463008..ed6c41e0e 100644
--- a/pyramid/tests/test_httpexceptions.py
+++ b/pyramid/tests/test_httpexceptions.py
@@ -283,6 +283,17 @@ class TestHTTPException(unittest.TestCase):
if header[0] == 'Content-Type':
self.assertEqual(header[1], 'application/json')
+ def test__content_type_invalid(self):
+ cls = self._getTargetSubclass()
+ exc = cls()
+ environ = _makeEnviron()
+ environ['HTTP_ACCEPT'] = 'invalid'
+ start_response = DummyStartResponse()
+ exc(environ, start_response)
+ for header in start_response.headerlist:
+ if header[0] == 'Content-Type':
+ self.assertEqual(header[1], 'text/html; charset=UTF-8')
+
def test__default_app_iter_with_comment_ampersand(self):
cls = self._getTargetSubclass()
exc = cls(comment='comment & comment')
diff --git a/pyramid/tests/test_session.py b/pyramid/tests/test_session.py
index ade602799..e3d819944 100644
--- a/pyramid/tests/test_session.py
+++ b/pyramid/tests/test_session.py
@@ -145,13 +145,14 @@ class SharedCookieSessionTests(object):
response = Response()
self.assertEqual(session._set_cookie(response), True)
cookieval = response.headerlist[-1][1]
- val, domain, path, secure, httponly = [x.strip() for x in
- cookieval.split(';')]
+ val, domain, path, secure, httponly, samesite = [x.strip() for x in
+ cookieval.split(';')]
self.assertTrue(val.startswith('abc='))
self.assertEqual(domain, 'Domain=localhost')
self.assertEqual(path, 'Path=/foo')
self.assertEqual(secure, 'secure')
self.assertEqual(httponly, 'HttpOnly')
+ self.assertEqual(samesite, 'SameSite=Lax')
def test_flash_default(self):
request = testing.DummyRequest()
@@ -503,7 +504,7 @@ class TestUnencryptedCookieSession(SharedCookieSessionTests, unittest.TestCase):
expected_cookieval = dummy_signed_serialize(
(session.accessed, session.created, {'key': 'value'}), secret)
response = Response()
- response.set_cookie('session', expected_cookieval)
+ response.set_cookie('session', expected_cookieval, samesite='Lax')
expected_cookie = response.headerlist[-1][1]
self.assertEqual(cookie, expected_cookie)
diff --git a/pyramid/tests/test_url.py b/pyramid/tests/test_url.py
index af2e5405c..31b3dd571 100644
--- a/pyramid/tests/test_url.py
+++ b/pyramid/tests/test_url.py
@@ -1251,6 +1251,70 @@ class Test_external_static_url_integration(unittest.TestCase):
request.route_url('acme', foo='bar'),
'http://acme.org/bar')
+class Test_with_route_prefix(unittest.TestCase):
+
+ def setUp(self):
+ self.config = testing.setUp()
+
+ def tearDown(self):
+ testing.tearDown()
+
+ def _makeRequest(self, route):
+ from pyramid.request import Request
+ return Request.blank(route)
+
+ def test_old_route_is_preserved(self):
+ self.config.route_prefix = 'old_prefix'
+ with self.config.route_prefix_context('new_addon'):
+ assert 'new_addon' in self.config.route_prefix
+
+ assert 'old_prefix' == self.config.route_prefix
+
+ def test_route_prefix_none(self):
+ self.config.route_prefix = 'old_prefix'
+ with self.config.route_prefix_context(None):
+ assert 'old_prefix' == self.config.route_prefix
+
+ assert 'old_prefix' == self.config.route_prefix
+
+ def test_route_prefix_empty(self):
+ self.config.route_prefix = 'old_prefix'
+ with self.config.route_prefix_context(''):
+ assert 'old_prefix' == self.config.route_prefix
+
+ assert 'old_prefix' == self.config.route_prefix
+
+ def test_route_has_prefix(self):
+ with self.config.route_prefix_context('bar'):
+ self.config.add_route('acme', '/foo')
+ request = self._makeRequest('/')
+ self.assertEqual(
+ request.route_url('acme'),
+ 'http://localhost/bar/foo',
+ )
+
+ def test_route_does_not_have_prefix(self):
+ with self.config.route_prefix_context('bar'):
+ pass
+
+ self.config.add_route('acme', '/foo')
+ request = self._makeRequest('/')
+ self.assertEqual(
+ request.route_url('acme'),
+ 'http://localhost/foo',
+ )
+
+ def test_error_reset_prefix(self):
+ self.config.route_prefix = 'old_prefix'
+
+ try:
+ with self.config.route_prefix_context('new_prefix'):
+ raise RuntimeError
+ except RuntimeError:
+ pass
+
+ assert self.config.route_prefix == 'old_prefix'
+
class DummyContext(object):
def __init__(self, next=None):
self.next = next
diff --git a/setup.py b/setup.py
index c44117068..17a18f3b5 100644
--- a/setup.py
+++ b/setup.py
@@ -11,48 +11,49 @@
# FITNESS FOR A PARTICULAR PURPOSE
#
##############################################################################
-from setuptools import setup, find_packages
+from setuptools import find_packages, setup
+
def readfile(name):
with open(name) as f:
return f.read()
+
README = readfile('README.rst')
CHANGES = readfile('CHANGES.rst')
install_requires = [
- 'setuptools',
- 'WebOb >= 1.7.0', # Response.has_body
- 'zope.interface >= 3.8.0', # has zope.interface.registry
- 'zope.deprecation >= 3.5.0', # py3 compat
- 'venusian >= 1.0', # ``ignore``
- 'translationstring >= 0.4', # py3 compat
- 'PasteDeploy >= 1.5.0', # py3 compat
+ 'hupper',
'plaster',
'plaster_pastedeploy',
- 'hupper',
- ]
+ 'setuptools',
+ 'translationstring >= 0.4', # py3 compat
+ 'venusian >= 1.0', # ``ignore``
+ 'webob >= 1.8.2', # cookies.make_cookie allows non-bytes samesite
+ 'zope.deprecation >= 3.5.0', # py3 compat
+ 'zope.interface >= 3.8.0', # has zope.interface.registry
+]
tests_require = [
- 'WebTest >= 1.3.1', # py3 compat
- 'zope.component >= 4.0', # py3 compat
- ]
+ 'webtest >= 1.3.1', # py3 compat
+ 'zope.component >= 4.0', # py3 compat
+]
docs_extras = [
- 'Sphinx >= 1.3.5, != 1.7.3',
+ 'Sphinx >= 1.7.4',
'docutils',
- 'repoze.sphinx.autointerface',
- 'pylons_sphinx_latesturl',
'pylons-sphinx-themes',
+ 'pylons_sphinx_latesturl',
+ 'repoze.sphinx.autointerface',
'sphinxcontrib-autoprogram',
- ]
+]
testing_extras = tests_require + [
- 'nose',
'coverage',
+ 'nose',
'virtualenv', # for scaffolding tests
- ]
+]
setup(name='pyramid',
version='1.10.dev0',
@@ -88,7 +89,7 @@ setup(name='pyramid',
':python_version<"3.2"': ['repoze.lru >= 0.4'],
'testing': testing_extras,
'docs': docs_extras,
- },
+ },
tests_require=tests_require,
test_suite="pyramid.tests",
entry_points="""\