diff options
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 @@ -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="""\ |
