summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.rst10
-rw-r--r--CONTRIBUTORS.txt4
-rw-r--r--docs/Makefile11
-rw-r--r--docs/conf.py74
-rwxr-xr-xdocs/make_book2
-rwxr-xr-xdocs/make_pdf2
-rw-r--r--docs/narr/urldispatch.rst18
-rw-r--r--docs/quick_tutorial/authentication/setup.py1
-rw-r--r--docs/quick_tutorial/authorization/setup.py1
-rw-r--r--docs/quick_tutorial/json/setup.py1
-rw-r--r--docs/quick_tutorial/logging/setup.py1
-rw-r--r--docs/quick_tutorial/more_view_classes/setup.py1
-rw-r--r--docs/quick_tutorial/requirements.rst32
-rw-r--r--docs/quick_tutorial/retail_forms/setup.py1
-rw-r--r--docs/quick_tutorial/routing/setup.py1
-rw-r--r--docs/quick_tutorial/sessions/setup.py1
-rw-r--r--docs/quick_tutorial/static_assets/setup.py1
-rw-r--r--docs/quick_tutorial/templating/setup.py1
-rw-r--r--docs/quick_tutorial/tutorial_approach.rst16
-rw-r--r--docs/quick_tutorial/view_classes/setup.py1
-rw-r--r--docs/typographical-conventions.rst24
-rw-r--r--pyramid/config/__init__.py45
-rw-r--r--pyramid/config/routes.py51
-rw-r--r--pyramid/httpexceptions.py19
-rw-r--r--pyramid/tests/test_url.py64
25 files changed, 231 insertions, 152 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index 4cb8ba44b..d24fb24e8 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -25,9 +25,19 @@ Features
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
+
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
+
Deprecations
------------
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index b6dbcff2c..60e4e5732 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -316,3 +316,7 @@ Contributors
- Deneys Maartens, 2017/11/03
- Heron Rossi, 2018/03/08
+
+- Hunter Senft-Grupp, 2018/05/14
+
+- Junhak Lee, 2018/05/14 \ No newline at end of file
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/conf.py b/docs/conf.py
index cf92e05e8..80585b336 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:
@@ -190,7 +186,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 +219,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 +286,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 +322,6 @@ _PREAMBLE = r"""
latex_elements = {
'preamble': _PREAMBLE,
- 'wrapperclass': 'book',
'date': '',
'releasename': 'Version',
'title': r'The Pyramid Web Framework',
@@ -342,17 +345,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 +352,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/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_tutorial/authentication/setup.py b/docs/quick_tutorial/authentication/setup.py
index e89b4e241..a5117af5a 100644
--- a/docs/quick_tutorial/authentication/setup.py
+++ b/docs/quick_tutorial/authentication/setup.py
@@ -5,7 +5,6 @@ requires = [
'pyramid',
'pyramid_chameleon',
'waitress',
-
]
setup(name='tutorial',
diff --git a/docs/quick_tutorial/authorization/setup.py b/docs/quick_tutorial/authorization/setup.py
index e89b4e241..a5117af5a 100644
--- a/docs/quick_tutorial/authorization/setup.py
+++ b/docs/quick_tutorial/authorization/setup.py
@@ -5,7 +5,6 @@ requires = [
'pyramid',
'pyramid_chameleon',
'waitress',
-
]
setup(name='tutorial',
diff --git a/docs/quick_tutorial/json/setup.py b/docs/quick_tutorial/json/setup.py
index 1699d9b1e..744612371 100644
--- a/docs/quick_tutorial/json/setup.py
+++ b/docs/quick_tutorial/json/setup.py
@@ -4,7 +4,6 @@ requires = [
'pyramid',
'pyramid_chameleon',
'waitress',
-
]
setup(name='tutorial',
diff --git a/docs/quick_tutorial/logging/setup.py b/docs/quick_tutorial/logging/setup.py
index 1699d9b1e..744612371 100644
--- a/docs/quick_tutorial/logging/setup.py
+++ b/docs/quick_tutorial/logging/setup.py
@@ -4,7 +4,6 @@ requires = [
'pyramid',
'pyramid_chameleon',
'waitress',
-
]
setup(name='tutorial',
diff --git a/docs/quick_tutorial/more_view_classes/setup.py b/docs/quick_tutorial/more_view_classes/setup.py
index 1699d9b1e..744612371 100644
--- a/docs/quick_tutorial/more_view_classes/setup.py
+++ b/docs/quick_tutorial/more_view_classes/setup.py
@@ -4,7 +4,6 @@ requires = [
'pyramid',
'pyramid_chameleon',
'waitress',
-
]
setup(name='tutorial',
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 f64049792..968889e74 100644
--- a/docs/quick_tutorial/retail_forms/setup.py
+++ b/docs/quick_tutorial/retail_forms/setup.py
@@ -5,7 +5,6 @@ requires = [
'pyramid',
'pyramid_chameleon',
'waitress',
-
]
setup(name='tutorial',
diff --git a/docs/quick_tutorial/routing/setup.py b/docs/quick_tutorial/routing/setup.py
index 1699d9b1e..744612371 100644
--- a/docs/quick_tutorial/routing/setup.py
+++ b/docs/quick_tutorial/routing/setup.py
@@ -4,7 +4,6 @@ requires = [
'pyramid',
'pyramid_chameleon',
'waitress',
-
]
setup(name='tutorial',
diff --git a/docs/quick_tutorial/sessions/setup.py b/docs/quick_tutorial/sessions/setup.py
index 1699d9b1e..744612371 100644
--- a/docs/quick_tutorial/sessions/setup.py
+++ b/docs/quick_tutorial/sessions/setup.py
@@ -4,7 +4,6 @@ requires = [
'pyramid',
'pyramid_chameleon',
'waitress',
-
]
setup(name='tutorial',
diff --git a/docs/quick_tutorial/static_assets/setup.py b/docs/quick_tutorial/static_assets/setup.py
index 1699d9b1e..744612371 100644
--- a/docs/quick_tutorial/static_assets/setup.py
+++ b/docs/quick_tutorial/static_assets/setup.py
@@ -4,7 +4,6 @@ requires = [
'pyramid',
'pyramid_chameleon',
'waitress',
-
]
setup(name='tutorial',
diff --git a/docs/quick_tutorial/templating/setup.py b/docs/quick_tutorial/templating/setup.py
index 1699d9b1e..744612371 100644
--- a/docs/quick_tutorial/templating/setup.py
+++ b/docs/quick_tutorial/templating/setup.py
@@ -4,7 +4,6 @@ requires = [
'pyramid',
'pyramid_chameleon',
'waitress',
-
]
setup(name='tutorial',
diff --git a/docs/quick_tutorial/tutorial_approach.rst b/docs/quick_tutorial/tutorial_approach.rst
index 7d87b6a49..83b229746 100644
--- a/docs/quick_tutorial/tutorial_approach.rst
+++ b/docs/quick_tutorial/tutorial_approach.rst
@@ -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 1699d9b1e..744612371 100644
--- a/docs/quick_tutorial/view_classes/setup.py
+++ b/docs/quick_tutorial/view_classes/setup.py
@@ -4,7 +4,6 @@ requires = [
'pyramid',
'pyramid_chameleon',
'waitress',
-
]
setup(name='tutorial',
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..598af300f 100644
--- a/pyramid/config/routes.py
+++ b/pyramid/config/routes.py
@@ -1,3 +1,4 @@
+import contextlib
import warnings
from pyramid.compat import urlparse
@@ -467,3 +468,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..734080434 100644
--- a/pyramid/httpexceptions.py
+++ b/pyramid/httpexceptions.py
@@ -606,7 +606,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 +618,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 +1031,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 +1156,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/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