summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci-tests.yml31
-rw-r--r--CHANGES.rst2
-rw-r--r--CONTRIBUTORS.txt6
-rw-r--r--HACKING.txt14
-rw-r--r--README.rst8
-rw-r--r--contributing.md2
-rw-r--r--docs/conf.py15
-rw-r--r--docs/designdefense.rst4
-rw-r--r--docs/index.rst2
-rw-r--r--docs/narr/install.rst7
-rw-r--r--docs/narr/introduction.rst2
-rw-r--r--docs/narr/myproject/myproject/templates/layout.jinja22
-rw-r--r--docs/narr/upgrading.rst6
-rw-r--r--docs/quick_tour/logging/hello_world/templates/layout.jinja22
-rw-r--r--docs/quick_tour/package/hello_world/templates/layout.jinja22
-rw-r--r--docs/quick_tour/sessions/hello_world/templates/layout.jinja22
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/templates/layout.jinja22
-rw-r--r--docs/quick_tutorial/cookiecutters/cc_starter/templates/layout.jinja22
-rw-r--r--docs/quick_tutorial/requirements.rst2
-rw-r--r--docs/tutorials/wiki/src/authorization/tutorial/templates/layout.pt2
-rw-r--r--docs/tutorials/wiki/src/basiclayout/tutorial/templates/layout.pt2
-rw-r--r--docs/tutorials/wiki/src/installation/tutorial/templates/layout.pt2
-rw-r--r--docs/tutorials/wiki/src/models/tutorial/templates/layout.pt2
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/templates/layout.pt2
-rw-r--r--docs/tutorials/wiki/src/views/tutorial/templates/layout.pt2
-rw-r--r--docs/tutorials/wiki2/src/authentication/tutorial/templates/layout.jinja22
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/templates/layout.jinja22
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/templates/layout.jinja22
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/templates/layout.jinja22
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/templates/layout.jinja22
-rw-r--r--docs/tutorials/wiki2/src/tests/tutorial/templates/layout.jinja22
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/templates/layout.jinja22
-rw-r--r--pyproject.toml2
-rw-r--r--setup.cfg7
-rw-r--r--setup.py5
-rw-r--r--src/pyramid/authentication.py22
-rw-r--r--src/pyramid/config/__init__.py2
-rw-r--r--src/pyramid/config/actions.py11
-rw-r--r--src/pyramid/config/assets.py4
-rw-r--r--src/pyramid/config/routes.py2
-rw-r--r--src/pyramid/config/views.py8
-rw-r--r--src/pyramid/csrf.py12
-rw-r--r--src/pyramid/decorator.py1
-rw-r--r--src/pyramid/httpexceptions.py31
-rw-r--r--src/pyramid/i18n.py4
-rw-r--r--src/pyramid/interfaces.py124
-rw-r--r--src/pyramid/path.py6
-rw-r--r--src/pyramid/registry.py2
-rw-r--r--src/pyramid/scripts/pserve.py2
-rw-r--r--src/pyramid/security.py8
-rw-r--r--src/pyramid/session.py2
-rw-r--r--src/pyramid/static.py6
-rw-r--r--src/pyramid/testing.py18
-rw-r--r--src/pyramid/util.py14
-rw-r--r--tests/pkgs/restbugapp/views.py2
-rw-r--r--tests/test_config/test_init.py4
-rw-r--r--tests/test_config/test_views.py10
-rw-r--r--tests/test_router.py2
-rw-r--r--tox.ini32
59 files changed, 244 insertions, 238 deletions
diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml
index 625c6a60f..605ebdae0 100644
--- a/.github/workflows/ci-tests.yml
+++ b/.github/workflows/ci-tests.yml
@@ -15,36 +15,33 @@ jobs:
strategy:
matrix:
py:
- - "3.6"
- "3.7"
- "3.8"
- "3.9"
- - "pypy3"
+ - "3.10"
+ - "pypy-3.8"
os:
- - "ubuntu-latest"
- - "windows-latest"
- - "macos-latest"
+ - "ubuntu-20.04"
+ - "windows-2022"
+ - "macos-11"
architecture:
- x64
- x86
include:
- # Only run coverage on ubuntu-latest, except on pypy3
- - os: "ubuntu-latest"
+ # Only run coverage on ubuntu-20.04, except on pypy3
+ - os: "ubuntu-20.04"
pytest-args: "--cov"
- - os: "ubuntu-latest"
- py: "pypy3"
+ - os: "ubuntu-20.04"
+ py: "pypy-3.8"
pytest-args: ""
exclude:
# Linux and macOS don't have x86 python
- - os: "ubuntu-latest"
+ - os: "ubuntu-20.04"
architecture: x86
- - os: "macos-latest"
+ - os: "macos-11"
architecture: x86
- # PyPy3 on Windows doesn't seem to work
- - os: "windows-latest"
- py: "pypy3"
name: "Python: ${{ matrix.py }}-${{ matrix.architecture }} on ${{ matrix.os }}"
runs-on: ${{ matrix.os }}
@@ -59,7 +56,7 @@ jobs:
- name: Running tox
run: tox -e py -- ${{ matrix.pytest-args }}
coverage:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-20.04
name: Validate coverage
steps:
- uses: actions/checkout@v2
@@ -71,7 +68,7 @@ jobs:
- run: pip install tox
- run: tox -e py38-cover,coverage
docs:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-20.04
name: Build the documentation
steps:
- uses: actions/checkout@v2
@@ -83,7 +80,7 @@ jobs:
- run: pip install tox
- run: tox -e docs
lint:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-20.04
name: Lint the package
steps:
- uses: actions/checkout@v2
diff --git a/CHANGES.rst b/CHANGES.rst
index 4bb847a25..0ee6fd30d 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -10,5 +10,7 @@ Bug Fixes
Backward Incompatibilities
--------------------------
+- Pyramid is no longer tested on, nor supports Python 3.6
+
Documentation Changes
---------------------
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index d527b1a04..edce6e9c7 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -353,4 +353,8 @@ Contributors
- Sergey Maranchuk, 2020/04/18
-- Thibault Ravera, 2020/06/03 \ No newline at end of file
+- Thibault Ravera, 2020/06/03
+
+- Jens Troeger, 2021/04/08
+
+- Karthikeyan Singaravelan, 2021/08/24
diff --git a/HACKING.txt b/HACKING.txt
index b9cdcc940..9cc2e8edb 100644
--- a/HACKING.txt
+++ b/HACKING.txt
@@ -50,7 +50,7 @@ In order to add a feature to Pyramid:
- The feature must be documented in both the API and narrative documentation
(in `docs/`).
-- The feature must work fully on the following CPython versions: 3.6, 3.7, 3.8, and 3.9 on both UNIX and Windows.
+- The feature must work fully on the following CPython versions: 3.7, 3.8, 3.9, and 3.10 on both UNIX and Windows.
- The feature must work on the latest version of PyPy3.
@@ -69,6 +69,12 @@ Coding Style
$ $TOX -e format
+- Pyramid uses flake8 (https://pypi.org/project/flake8/) to enforce PEP8 style guidelines.
+ To run flake8, as well as running checks for Black and isort:
+
+ $ $TOX -e lint
+
+Black, isort, and flake8 versions are pinned for stability and reproducibility.
Running Tests
-------------
@@ -80,9 +86,9 @@ Running Tests
$ $TOX -e py
- To run `tox` for Python 3.9 explicitly, you may use:
+ To run `tox` for Python 3.10 explicitly, you may use:
- $ $TOX -e py39
+ $ $TOX -e py310
- To run individual tests (i.e., during development), you can use `pytest`
syntax as follows, where `$VENV` is an environment variable set to the path
@@ -103,7 +109,7 @@ Test Coverage
-------------
- The codebase *must* have 100% test statement coverage after each commit. You
- can test coverage via `tox -e py39`.
+ can test coverage via `tox -e py310`.
Documentation Coverage and Building HTML Documentation
diff --git a/README.rst b/README.rst
index 82f171f89..027a4e236 100644
--- a/README.rst
+++ b/README.rst
@@ -3,15 +3,15 @@ Pyramid
.. image:: https://github.com/Pylons/Pyramid/workflows/Build%20and%20test/badge.svg?branch=master
:target: https://github.com/Pylons/Pyramid/actions?query=workflow%3A%22Build+and+test%22
- :alt: master Travis CI Status
+ :alt: master CI Status
.. image:: https://readthedocs.org/projects/pyramid/badge/?version=master
:target: https://docs.pylonsproject.org/projects/pyramid/en/master
:alt: master Documentation Status
-.. image:: https://img.shields.io/badge/irc-freenode-blue.svg
- :target: https://webchat.freenode.net/?channels=pyramid
- :alt: IRC Freenode
+.. image:: https://img.shields.io/badge/IRC-Libera.Chat-blue.svg
+ :target: https://web.libera.chat/#pyramid
+ :alt: IRC Libera.Chat
`Pyramid <https://trypyramid.com/>`_ is a small, fast, down-to-earth, open
source Python web framework. It makes real-world web application development
diff --git a/contributing.md b/contributing.md
index ffe050035..75dbfb86b 100644
--- a/contributing.md
+++ b/contributing.md
@@ -6,7 +6,7 @@ You can contribute to this project in several ways.
* [File an Issue on GitHub](https://github.com/Pylons/pyramid/issues)
* Fork this project and create a branch with your suggested change. When ready, submit a pull request for consideration. [GitHub Flow](https://guides.github.com/introduction/flow/index.html) describes the workflow process and why it's a good practice. When submitting a pull request, sign [CONTRIBUTORS.txt](https://github.com/Pylons/pyramid/blob/master/CONTRIBUTORS.txt) if you have not yet done so.
-* Join the [IRC channel #pyramid on irc.freenode.net](https://webchat.freenode.net/?channels=pyramid).
+* Join the [IRC channel #pyramid on irc.libera.chat](https://web.libera.chat/#pyramid).
## Git Branches
diff --git a/docs/conf.py b/docs/conf.py
index 0e2c6b2cd..8e1550798 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -14,7 +14,6 @@
import sys
import os
import datetime
-import inspect
import warnings
warnings.simplefilter('ignore', DeprecationWarning)
@@ -385,20 +384,8 @@ def setup(app):
app.add_directive('frontmatter', FrontMatter)
app.add_directive('mainmatter', MainMatter)
app.add_directive('backmatter', BackMatter)
- app.connect('autodoc-process-signature', resig)
-def resig(app, what, name, obj, options, signature, return_annotation):
- """ Allow for preservation of ``@action_method`` decorated methods
- in configurator """
- docobj = getattr(obj, '__docobj__', None)
- if docobj is not None:
- argspec = inspect.getargspec(docobj)
- if argspec[0] and argspec[0][0] in ('cls', 'self'):
- del argspec[0][0]
- signature = inspect.formatargspec(*argspec)
- return signature, return_annotation
-
# turn off all line numbers in latex formatting
## from pygments.formatters import LatexFormatter
@@ -452,5 +439,5 @@ epub_tocdepth = 3
linkcheck_ignore = [
r'http://localhost:\d+',
r'http://localhost',
- r'https://webchat.freenode.net/#pyramid', # JavaScript "anchor"
+ r'https://web.libera.chat/#pyramid', # JavaScript "anchor"
]
diff --git a/docs/designdefense.rst b/docs/designdefense.rst
index 0fa609aa1..6cd5f0047 100644
--- a/docs/designdefense.rst
+++ b/docs/designdefense.rst
@@ -1656,8 +1656,8 @@ If you can understand this "hello world" program, you can use Pyramid:
Pyramid has over 1200 pages of documentation (printed), covering topics from
the very basic to the most advanced. *Nothing* is left undocumented, quite
literally. It also has an *awesome*, very helpful community. Visit the
-`#pyramid IRC channel on freenode.net
-<https://webchat.freenode.net/#pyramid>`_ and see.
+`#pyramid IRC channel on Libera.Chat
+<https://web.libera.chat/#pyramid>`_ and see.
Hate Zope
+++++++++
diff --git a/docs/index.rst b/docs/index.rst
index c1f6db81a..b5542213a 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -77,7 +77,7 @@ If you've got questions that aren't answered by this documentation, contact the
`Pylons-discuss maillist
<https://groups.google.com/forum/#!forum/pylons-discuss>`_ or join the
`#pyramid IRC channel
-<https://webchat.freenode.net/#pyramid>`_.
+<https://web.libera.chat/#pyramid>`_.
Browse and check out tagged and trunk versions of :app:`Pyramid` via the
`Pyramid GitHub repository <https://github.com/Pylons/pyramid/>`_. To check out
diff --git a/docs/narr/install.rst b/docs/narr/install.rst
index 1801f3c9a..882b40d10 100644
--- a/docs/narr/install.rst
+++ b/docs/narr/install.rst
@@ -5,7 +5,7 @@ Installing :app:`Pyramid`
.. note::
- This installation guide emphasizes the use of Python 3.6 and greater for
+ This installation guide emphasizes the use of Python 3.7 and greater for
simplicity.
@@ -15,13 +15,14 @@ Installing :app:`Pyramid`
Before You Install Pyramid
--------------------------
-Install Python version 3.6 or greater for your operating system, and satisfy
+Install Python version 3.7 or greater for your operating system, and satisfy
the :ref:`requirements-for-installing-packages`, as described in
the following sections.
.. sidebar:: Python Versions
- As of this writing, :app:`Pyramid` is tested against Python 3.6, 3.7, 3.8, and 3.9 and PyPy3.
+ As of this writing, :app:`Pyramid` is tested against Python 3.7, 3.8, 3.9,
+ and 3.10 and PyPy (matches CPython version 3.8).
:app:`Pyramid` is known to run on all popular Unix-like systems such as Linux,
macOS, and FreeBSD, as well as on Windows platforms. It is also known to
diff --git a/docs/narr/introduction.rst b/docs/narr/introduction.rst
index f62e28905..eddb02b21 100644
--- a/docs/narr/introduction.rst
+++ b/docs/narr/introduction.rst
@@ -70,7 +70,7 @@ You can get help quickly with :app:`Pyramid`. It's our goal that no :app:`Pyrami
.. seealso::
- See also our `#pyramid IRC channel <https://webchat.freenode.net/#pyramid>`_, our `pylons-discuss mailing list <https://groups.google.com/forum/#!forum/pylons-discuss>`_, and :ref:`support-and-development`.
+ See also our `#pyramid IRC channel <https://web.libera.chat/#pyramid>`_, our `pylons-discuss mailing list <https://groups.google.com/forum/#!forum/pylons-discuss>`_, and :ref:`support-and-development`.
.. _what_makes_pyramid_unique:
diff --git a/docs/narr/myproject/myproject/templates/layout.jinja2 b/docs/narr/myproject/myproject/templates/layout.jinja2
index 38f5ae7a8..fc5c05941 100644
--- a/docs/narr/myproject/myproject/templates/layout.jinja2
+++ b/docs/narr/myproject/myproject/templates/layout.jinja2
@@ -41,7 +41,7 @@
<div class="links">
<ul>
<li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
- <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=pyramid">IRC Channel</a></li>
+ <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://web.libera.chat/#pyramid">IRC Channel</a></li>
<li><i class="glyphicon glyphicon-home icon-muted"></i><a href="https://pylonsproject.org">Pylons Project</a></li>
</ul>
</div>
diff --git a/docs/narr/upgrading.rst b/docs/narr/upgrading.rst
index d6882809a..020f2ed37 100644
--- a/docs/narr/upgrading.rst
+++ b/docs/narr/upgrading.rst
@@ -86,10 +86,10 @@ At the time of a Pyramid version release, each supports all versions of Python
through the end of their lifespans. The end-of-life for a given version of
Python is when security updates are no longer released.
-- `Python 3.6 Lifespan <https://devguide.python.org/#status-of-python-branches>`_ 2021-12-23.
- `Python 3.7 Lifespan <https://devguide.python.org/#status-of-python-branches>`_ 2023-06-27.
-- `Python 3.8 Lifespan <https://devguide.python.org/#status-of-python-branches>`_ 2024-10-??.
-- `Python 3.9 Lifespan <https://devguide.python.org/#status-of-python-branches>`_ TBD.
+- `Python 3.8 Lifespan <https://devguide.python.org/#status-of-python-branches>`_ 2024-10.
+- `Python 3.9 Lifespan <https://devguide.python.org/#status-of-python-branches>`_ 2025-10.
+- `Python 3.10 Lifespan <https://devguide.python.org/#status-of-python-branches>`_ 2026-10.
To determine the Python support for a specific release of Pyramid, view its
``tox.ini`` file at the root of the repository's version.
diff --git a/docs/quick_tour/logging/hello_world/templates/layout.jinja2 b/docs/quick_tour/logging/hello_world/templates/layout.jinja2
index 45226b9e3..fd5bf0100 100644
--- a/docs/quick_tour/logging/hello_world/templates/layout.jinja2
+++ b/docs/quick_tour/logging/hello_world/templates/layout.jinja2
@@ -41,7 +41,7 @@
<div class="links">
<ul>
<li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
- <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=pyramid">IRC Channel</a></li>
+ <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://web.libera.chat/#pyramid">IRC Channel</a></li>
<li><i class="glyphicon glyphicon-home icon-muted"></i><a href="https://pylonsproject.org">Pylons Project</a></li>
</ul>
</div>
diff --git a/docs/quick_tour/package/hello_world/templates/layout.jinja2 b/docs/quick_tour/package/hello_world/templates/layout.jinja2
index 45226b9e3..fd5bf0100 100644
--- a/docs/quick_tour/package/hello_world/templates/layout.jinja2
+++ b/docs/quick_tour/package/hello_world/templates/layout.jinja2
@@ -41,7 +41,7 @@
<div class="links">
<ul>
<li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
- <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=pyramid">IRC Channel</a></li>
+ <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://web.libera.chat/#pyramid">IRC Channel</a></li>
<li><i class="glyphicon glyphicon-home icon-muted"></i><a href="https://pylonsproject.org">Pylons Project</a></li>
</ul>
</div>
diff --git a/docs/quick_tour/sessions/hello_world/templates/layout.jinja2 b/docs/quick_tour/sessions/hello_world/templates/layout.jinja2
index 45226b9e3..fd5bf0100 100644
--- a/docs/quick_tour/sessions/hello_world/templates/layout.jinja2
+++ b/docs/quick_tour/sessions/hello_world/templates/layout.jinja2
@@ -41,7 +41,7 @@
<div class="links">
<ul>
<li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
- <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=pyramid">IRC Channel</a></li>
+ <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://web.libera.chat/#pyramid">IRC Channel</a></li>
<li><i class="glyphicon glyphicon-home icon-muted"></i><a href="https://pylonsproject.org">Pylons Project</a></li>
</ul>
</div>
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 82017688a..e2bdcd7ea 100644
--- a/docs/quick_tour/sqla_demo/sqla_demo/templates/layout.jinja2
+++ b/docs/quick_tour/sqla_demo/sqla_demo/templates/layout.jinja2
@@ -41,7 +41,7 @@
<div class="links">
<ul>
<li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
- <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=pyramid">IRC Channel</a></li>
+ <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://web.libera.chat/#pyramid">IRC Channel</a></li>
<li><i class="glyphicon glyphicon-home icon-muted"></i><a href="https://pylonsproject.org">Pylons Project</a></li>
</ul>
</div>
diff --git a/docs/quick_tutorial/cookiecutters/cc_starter/templates/layout.jinja2 b/docs/quick_tutorial/cookiecutters/cc_starter/templates/layout.jinja2
index 90d2d106a..4fb4cf174 100644
--- a/docs/quick_tutorial/cookiecutters/cc_starter/templates/layout.jinja2
+++ b/docs/quick_tutorial/cookiecutters/cc_starter/templates/layout.jinja2
@@ -41,7 +41,7 @@
<div class="links">
<ul>
<li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
- <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=pyramid">IRC Channel</a></li>
+ <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://web.libera.chat/#pyramid">IRC Channel</a></li>
<li><i class="glyphicon glyphicon-home icon-muted"></i><a href="https://pylonsproject.org">Pylons Project</a></li>
</ul>
</div>
diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst
index 901f6134d..5f5c0b10b 100644
--- a/docs/quick_tutorial/requirements.rst
+++ b/docs/quick_tutorial/requirements.rst
@@ -19,7 +19,7 @@ virtual environment.)
This *Quick Tutorial* is based on:
-* **Python 3.8**. Pyramid fully supports Python 3.6+.
+* **Python 3.8**. Pyramid fully supports Python 3.7+.
This tutorial uses **Python 3.8**.
* **venv**. We believe in virtual environments.
diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/layout.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/layout.pt
index 61042da24..369b2be1a 100644
--- a/docs/tutorials/wiki/src/authorization/tutorial/templates/layout.pt
+++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/layout.pt
@@ -52,7 +52,7 @@
<div class="links">
<ul>
<li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
- <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=pyramid">IRC Channel</a></li>
+ <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://web.libera.chat/#pyramid">IRC Channel</a></li>
<li><i class="glyphicon glyphicon-home icon-muted"></i><a href="https://pylonsproject.org">Pylons Project</a></li>
</ul>
</div>
diff --git a/docs/tutorials/wiki/src/basiclayout/tutorial/templates/layout.pt b/docs/tutorials/wiki/src/basiclayout/tutorial/templates/layout.pt
index 9ca01382b..2e65a93c4 100644
--- a/docs/tutorials/wiki/src/basiclayout/tutorial/templates/layout.pt
+++ b/docs/tutorials/wiki/src/basiclayout/tutorial/templates/layout.pt
@@ -39,7 +39,7 @@
<div class="links">
<ul>
<li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
- <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=pyramid">IRC Channel</a></li>
+ <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://web.libera.chat/#pyramid">IRC Channel</a></li>
<li><i class="glyphicon glyphicon-home icon-muted"></i><a href="https://pylonsproject.org">Pylons Project</a></li>
</ul>
</div>
diff --git a/docs/tutorials/wiki/src/installation/tutorial/templates/layout.pt b/docs/tutorials/wiki/src/installation/tutorial/templates/layout.pt
index 9ca01382b..2e65a93c4 100644
--- a/docs/tutorials/wiki/src/installation/tutorial/templates/layout.pt
+++ b/docs/tutorials/wiki/src/installation/tutorial/templates/layout.pt
@@ -39,7 +39,7 @@
<div class="links">
<ul>
<li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
- <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=pyramid">IRC Channel</a></li>
+ <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://web.libera.chat/#pyramid">IRC Channel</a></li>
<li><i class="glyphicon glyphicon-home icon-muted"></i><a href="https://pylonsproject.org">Pylons Project</a></li>
</ul>
</div>
diff --git a/docs/tutorials/wiki/src/models/tutorial/templates/layout.pt b/docs/tutorials/wiki/src/models/tutorial/templates/layout.pt
index 9ca01382b..2e65a93c4 100644
--- a/docs/tutorials/wiki/src/models/tutorial/templates/layout.pt
+++ b/docs/tutorials/wiki/src/models/tutorial/templates/layout.pt
@@ -39,7 +39,7 @@
<div class="links">
<ul>
<li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
- <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=pyramid">IRC Channel</a></li>
+ <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://web.libera.chat/#pyramid">IRC Channel</a></li>
<li><i class="glyphicon glyphicon-home icon-muted"></i><a href="https://pylonsproject.org">Pylons Project</a></li>
</ul>
</div>
diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/layout.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/layout.pt
index 61042da24..369b2be1a 100644
--- a/docs/tutorials/wiki/src/tests/tutorial/templates/layout.pt
+++ b/docs/tutorials/wiki/src/tests/tutorial/templates/layout.pt
@@ -52,7 +52,7 @@
<div class="links">
<ul>
<li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
- <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=pyramid">IRC Channel</a></li>
+ <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://web.libera.chat/#pyramid">IRC Channel</a></li>
<li><i class="glyphicon glyphicon-home icon-muted"></i><a href="https://pylonsproject.org">Pylons Project</a></li>
</ul>
</div>
diff --git a/docs/tutorials/wiki/src/views/tutorial/templates/layout.pt b/docs/tutorials/wiki/src/views/tutorial/templates/layout.pt
index 1e8b808d4..62d5f28aa 100644
--- a/docs/tutorials/wiki/src/views/tutorial/templates/layout.pt
+++ b/docs/tutorials/wiki/src/views/tutorial/templates/layout.pt
@@ -44,7 +44,7 @@
<div class="links">
<ul>
<li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
- <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=pyramid">IRC Channel</a></li>
+ <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://web.libera.chat/#pyramid">IRC Channel</a></li>
<li><i class="glyphicon glyphicon-home icon-muted"></i><a href="https://pylonsproject.org">Pylons Project</a></li>
</ul>
</div>
diff --git a/docs/tutorials/wiki2/src/authentication/tutorial/templates/layout.jinja2 b/docs/tutorials/wiki2/src/authentication/tutorial/templates/layout.jinja2
index 55f4a85dc..361d8f1cf 100644
--- a/docs/tutorials/wiki2/src/authentication/tutorial/templates/layout.jinja2
+++ b/docs/tutorials/wiki2/src/authentication/tutorial/templates/layout.jinja2
@@ -52,7 +52,7 @@
<div class="links">
<ul>
<li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
- <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=pyramid">IRC Channel</a></li>
+ <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://web.libera.chat/#pyramid">IRC Channel</a></li>
<li><i class="glyphicon glyphicon-home icon-muted"></i><a href="https://pylonsproject.org">Pylons Project</a></li>
</ul>
</div>
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/templates/layout.jinja2 b/docs/tutorials/wiki2/src/authorization/tutorial/templates/layout.jinja2
index 55f4a85dc..361d8f1cf 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/templates/layout.jinja2
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/templates/layout.jinja2
@@ -52,7 +52,7 @@
<div class="links">
<ul>
<li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
- <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=pyramid">IRC Channel</a></li>
+ <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://web.libera.chat/#pyramid">IRC Channel</a></li>
<li><i class="glyphicon glyphicon-home icon-muted"></i><a href="https://pylonsproject.org">Pylons Project</a></li>
</ul>
</div>
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/layout.jinja2 b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/layout.jinja2
index f5a086f0e..a8cefba34 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/layout.jinja2
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/layout.jinja2
@@ -41,7 +41,7 @@
<div class="links">
<ul>
<li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
- <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=pyramid">IRC Channel</a></li>
+ <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://web.libera.chat/#pyramid">IRC Channel</a></li>
<li><i class="glyphicon glyphicon-home icon-muted"></i><a href="https://pylonsproject.org">Pylons Project</a></li>
</ul>
</div>
diff --git a/docs/tutorials/wiki2/src/installation/tutorial/templates/layout.jinja2 b/docs/tutorials/wiki2/src/installation/tutorial/templates/layout.jinja2
index f5a086f0e..a8cefba34 100644
--- a/docs/tutorials/wiki2/src/installation/tutorial/templates/layout.jinja2
+++ b/docs/tutorials/wiki2/src/installation/tutorial/templates/layout.jinja2
@@ -41,7 +41,7 @@
<div class="links">
<ul>
<li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
- <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=pyramid">IRC Channel</a></li>
+ <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://web.libera.chat/#pyramid">IRC Channel</a></li>
<li><i class="glyphicon glyphicon-home icon-muted"></i><a href="https://pylonsproject.org">Pylons Project</a></li>
</ul>
</div>
diff --git a/docs/tutorials/wiki2/src/models/tutorial/templates/layout.jinja2 b/docs/tutorials/wiki2/src/models/tutorial/templates/layout.jinja2
index f5a086f0e..a8cefba34 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/templates/layout.jinja2
+++ b/docs/tutorials/wiki2/src/models/tutorial/templates/layout.jinja2
@@ -41,7 +41,7 @@
<div class="links">
<ul>
<li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
- <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=pyramid">IRC Channel</a></li>
+ <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://web.libera.chat/#pyramid">IRC Channel</a></li>
<li><i class="glyphicon glyphicon-home icon-muted"></i><a href="https://pylonsproject.org">Pylons Project</a></li>
</ul>
</div>
diff --git a/docs/tutorials/wiki2/src/tests/tutorial/templates/layout.jinja2 b/docs/tutorials/wiki2/src/tests/tutorial/templates/layout.jinja2
index 55f4a85dc..361d8f1cf 100644
--- a/docs/tutorials/wiki2/src/tests/tutorial/templates/layout.jinja2
+++ b/docs/tutorials/wiki2/src/tests/tutorial/templates/layout.jinja2
@@ -52,7 +52,7 @@
<div class="links">
<ul>
<li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
- <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=pyramid">IRC Channel</a></li>
+ <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://web.libera.chat/#pyramid">IRC Channel</a></li>
<li><i class="glyphicon glyphicon-home icon-muted"></i><a href="https://pylonsproject.org">Pylons Project</a></li>
</ul>
</div>
diff --git a/docs/tutorials/wiki2/src/views/tutorial/templates/layout.jinja2 b/docs/tutorials/wiki2/src/views/tutorial/templates/layout.jinja2
index 17e8f7688..54c6e5fe7 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/templates/layout.jinja2
+++ b/docs/tutorials/wiki2/src/views/tutorial/templates/layout.jinja2
@@ -41,7 +41,7 @@
<div class="links">
<ul>
<li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
- <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=pyramid">IRC Channel</a></li>
+ <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://web.libera.chat/#pyramid">IRC Channel</a></li>
<li><i class="glyphicon glyphicon-home icon-muted"></i><a href="https://pylonsproject.org">Pylons Project</a></li>
</ul>
</div>
diff --git a/pyproject.toml b/pyproject.toml
index eddde46d9..9069096f7 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
[tool.black]
line-length = 79
skip-string-normalization = true
-py36 = false
+target-version = ['py37', 'py38', 'py39', 'py310']
exclude = '''
/(
\.git
diff --git a/setup.cfg b/setup.cfg
index a9e760853..55fa7e8b3 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,10 +1,3 @@
-[easy_install]
-zip_ok = false
-
-[aliases]
-dev = develop easy_install pyramid[testing]
-docs = develop easy_install pyramid[docs]
-
[metadata]
license_file = LICENSE.txt
diff --git a/setup.py b/setup.py
index aae4e80e9..17434313e 100644
--- a/setup.py
+++ b/setup.py
@@ -68,15 +68,16 @@ setup(
version=VERSION,
description='The Pyramid Web Framework, a Pylons project',
long_description=README + '\n\n' + CHANGES,
+ long_description_content_type='text/x-rst',
classifiers=[
"Development Status :: 6 - Mature",
"Intended Audience :: Developers",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
- "Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Framework :: Pyramid",
@@ -98,7 +99,7 @@ setup(
package_dir={'': 'src'},
include_package_data=True,
zip_safe=False,
- python_requires='>=3.6',
+ python_requires='>=3.7',
install_requires=install_requires,
extras_require={'testing': testing_extras, 'docs': docs_extras},
tests_require=tests_require,
diff --git a/src/pyramid/authentication.py b/src/pyramid/authentication.py
index 8faf84d68..9120ad03b 100644
--- a/src/pyramid/authentication.py
+++ b/src/pyramid/authentication.py
@@ -24,7 +24,7 @@ VALID_TOKEN = re.compile(r"^[A-Za-z][A-Za-z0-9+_-]*$")
class CallbackAuthenticationPolicy:
- """ Abstract class """
+ """Abstract class"""
debug = False
callback = None
@@ -265,7 +265,7 @@ class RepozeWho1AuthenticationPolicy(CallbackAuthenticationPolicy):
return userid
def unauthenticated_userid(self, request):
- """ Return the ``repoze.who.userid`` key from the detected identity."""
+ """Return the ``repoze.who.userid`` key from the detected identity."""
identity = self._get_identity(request)
if identity is None:
return None
@@ -411,7 +411,7 @@ class RemoteUserAuthenticationPolicy(CallbackAuthenticationPolicy):
self.debug = debug
def unauthenticated_userid(self, request):
- """ The ``REMOTE_USER`` value found within the ``environ``."""
+ """The ``REMOTE_USER`` value found within the ``environ``."""
return request.environ.get(self.environ_key)
def remember(self, request, userid, **kw):
@@ -631,7 +631,7 @@ class AuthTktAuthenticationPolicy(CallbackAuthenticationPolicy):
self.debug = debug
def unauthenticated_userid(self, request):
- """ The userid key within the auth_tkt cookie."""
+ """The userid key within the auth_tkt cookie."""
result = self.cookie.identify(request)
if result:
return result['userid']
@@ -647,7 +647,7 @@ class AuthTktAuthenticationPolicy(CallbackAuthenticationPolicy):
return self.cookie.remember(request, userid, **kw)
def forget(self, request):
- """ A list of headers which will delete appropriate cookies."""
+ """A list of headers which will delete appropriate cookies."""
return self.cookie.forget(request)
@@ -1235,11 +1235,11 @@ class SessionAuthenticationPolicy(CallbackAuthenticationPolicy):
self.helper = SessionAuthenticationHelper(prefix)
def remember(self, request, userid, **kw):
- """ Store a userid in the session."""
+ """Store a userid in the session."""
return self.helper.remember(request, userid, **kw)
def forget(self, request):
- """ Remove the stored userid from the session."""
+ """Remove the stored userid from the session."""
return self.helper.forget(request)
def unauthenticated_userid(self, request):
@@ -1263,18 +1263,18 @@ class SessionAuthenticationHelper:
self.userid_key = prefix + 'userid'
def remember(self, request, userid, **kw):
- """ Store a userid in the session."""
+ """Store a userid in the session."""
request.session[self.userid_key] = userid
return []
def forget(self, request, **kw):
- """ Remove the stored userid from the session."""
+ """Remove the stored userid from the session."""
if self.userid_key in request.session:
del request.session[self.userid_key]
return []
def authenticated_userid(self, request):
- """ Return the stored userid."""
+ """Return the stored userid."""
return request.session.get(self.userid_key)
@@ -1332,7 +1332,7 @@ class BasicAuthAuthenticationPolicy(CallbackAuthenticationPolicy):
self.debug = debug
def unauthenticated_userid(self, request):
- """ The userid parsed from the ``Authorization`` request header."""
+ """The userid parsed from the ``Authorization`` request header."""
credentials = extract_http_basic_credentials(request)
if credentials:
return credentials.username
diff --git a/src/pyramid/config/__init__.py b/src/pyramid/config/__init__.py
index fa90f2dd2..c500c53f6 100644
--- a/src/pyramid/config/__init__.py
+++ b/src/pyramid/config/__init__.py
@@ -805,7 +805,7 @@ class Configurator(
categories=('pyramid',),
onerror=None,
ignore=None,
- **kw
+ **kw,
):
"""Scan a Python package and any of its subpackages for objects
marked with :term:`configuration decoration` such as
diff --git a/src/pyramid/config/actions.py b/src/pyramid/config/actions.py
index e13358ce9..d80f840ac 100644
--- a/src/pyramid/config/actions.py
+++ b/src/pyramid/config/actions.py
@@ -35,7 +35,7 @@ class ActionConfiguratorMixin:
kw=None,
order=0,
introspectables=(),
- **extra
+ **extra,
):
"""Register an action which will be executed when
:meth:`pyramid.config.Configurator.commit` is called (or executed
@@ -185,7 +185,7 @@ class ActionState:
includepath=(),
info=None,
introspectables=(),
- **extra
+ **extra,
):
"""Add an action with the given discriminator, callable, and
arguments"""
@@ -557,13 +557,6 @@ def action_method(wrapped):
if info is None:
try:
f = traceback.extract_stack(limit=4)
-
- # Work around a Python 3.5 issue whereby it would insert an
- # extra stack frame. This should no longer be necessary in
- # Python 3.5.1
- last_frame = ActionInfo(*f[-1])
- if last_frame.function == 'extract_stack': # pragma: no cover
- f.pop()
info = ActionInfo(*f[-backframes])
except Exception: # pragma: no cover
info = ActionInfo(None, 0, '', '')
diff --git a/src/pyramid/config/assets.py b/src/pyramid/config/assets.py
index 0dd7cf2c2..d62b04e57 100644
--- a/src/pyramid/config/assets.py
+++ b/src/pyramid/config/assets.py
@@ -34,7 +34,7 @@ class OverrideProvider(pkg_resources.DefaultProvider):
)
def get_resource_stream(self, manager, resource_name):
- """ Return a readable file-like object for resource_name."""
+ """Return a readable file-like object for resource_name."""
overrides = self._get_overrides()
if overrides is not None:
stream = overrides.get_stream(resource_name)
@@ -45,7 +45,7 @@ class OverrideProvider(pkg_resources.DefaultProvider):
)
def get_resource_string(self, manager, resource_name):
- """ Return a string containing the contents of resource_name."""
+ """Return a string containing the contents of resource_name."""
overrides = self._get_overrides()
if overrides is not None:
string = overrides.get_string(resource_name)
diff --git a/src/pyramid/config/routes.py b/src/pyramid/config/routes.py
index 4ebae89cc..59bc368fe 100644
--- a/src/pyramid/config/routes.py
+++ b/src/pyramid/config/routes.py
@@ -38,7 +38,7 @@ class RoutesConfiguratorMixin:
pregenerator=None,
static=False,
inherit_slash=None,
- **predicates
+ **predicates,
):
"""Add a :term:`route configuration` to the current configuration
state. Arguments to ``add_route`` are divided into *predicate*
diff --git a/src/pyramid/config/views.py b/src/pyramid/config/views.py
index 0d0002f83..e75fdd1ef 100644
--- a/src/pyramid/config/views.py
+++ b/src/pyramid/config/views.py
@@ -264,7 +264,7 @@ class ViewsConfiguratorMixin:
match_param=None,
require_csrf=None,
exception_only=False,
- **view_options
+ **view_options,
):
"""Add a :term:`view configuration` to the current
configuration state. Arguments to ``add_view`` are broken
@@ -1611,7 +1611,7 @@ class ViewsConfiguratorMixin:
decorator=None,
mapper=None,
match_param=None,
- **view_options
+ **view_options,
):
"""Add a forbidden view to the current configuration state. The
view will be called when Pyramid or application code raises a
@@ -1712,7 +1712,7 @@ class ViewsConfiguratorMixin:
mapper=None,
match_param=None,
append_slash=False,
- **view_options
+ **view_options,
):
"""Add a default :term:`Not Found View` to the current configuration
state. The view will be called when Pyramid or application code raises
@@ -1850,7 +1850,7 @@ class ViewsConfiguratorMixin:
view=None,
context=None,
# force all other arguments to be specified as key=value
- **view_options
+ **view_options,
):
"""Add an :term:`exception view` for the specified ``exception`` to
the current configuration state. The view will be called when Pyramid
diff --git a/src/pyramid/csrf.py b/src/pyramid/csrf.py
index 7f4f72f44..0ade5f2d6 100644
--- a/src/pyramid/csrf.py
+++ b/src/pyramid/csrf.py
@@ -32,7 +32,7 @@ class LegacySessionCSRFStoragePolicy:
"""
def new_csrf_token(self, request):
- """ Sets a new CSRF token into the session and returns it. """
+ """Sets a new CSRF token into the session and returns it."""
return request.session.new_csrf_token()
def get_csrf_token(self, request):
@@ -41,7 +41,7 @@ class LegacySessionCSRFStoragePolicy:
return request.session.get_csrf_token()
def check_csrf_token(self, request, supplied_token):
- """ Returns ``True`` if the ``supplied_token`` is valid."""
+ """Returns ``True`` if the ``supplied_token`` is valid."""
expected_token = self.get_csrf_token(request)
return not strings_differ(
bytes_(expected_token), bytes_(supplied_token)
@@ -70,7 +70,7 @@ class SessionCSRFStoragePolicy:
self.key = key
def new_csrf_token(self, request):
- """ Sets a new CSRF token into the session and returns it. """
+ """Sets a new CSRF token into the session and returns it."""
token = self._token_factory()
request.session[self.key] = token
return token
@@ -84,7 +84,7 @@ class SessionCSRFStoragePolicy:
return token
def check_csrf_token(self, request, supplied_token):
- """ Returns ``True`` if the ``supplied_token`` is valid."""
+ """Returns ``True`` if the ``supplied_token`` is valid."""
expected_token = self.get_csrf_token(request)
return not strings_differ(
bytes_(expected_token), bytes_(supplied_token)
@@ -134,7 +134,7 @@ class CookieCSRFStoragePolicy:
self.cookie_name = cookie_name
def new_csrf_token(self, request):
- """ Sets a new CSRF token into the request and returns it. """
+ """Sets a new CSRF token into the request and returns it."""
token = self._token_factory()
request.cookies[self.cookie_name] = token
@@ -154,7 +154,7 @@ class CookieCSRFStoragePolicy:
return token
def check_csrf_token(self, request, supplied_token):
- """ Returns ``True`` if the ``supplied_token`` is valid."""
+ """Returns ``True`` if the ``supplied_token`` is valid."""
expected_token = self.get_csrf_token(request)
return not strings_differ(
bytes_(expected_token), bytes_(supplied_token)
diff --git a/src/pyramid/decorator.py b/src/pyramid/decorator.py
index 3215b1b38..9b8d10618 100644
--- a/src/pyramid/decorator.py
+++ b/src/pyramid/decorator.py
@@ -32,6 +32,7 @@ class reify:
def __init__(self, wrapped):
self.wrapped = wrapped
+ self.__name__ = wrapped.__name__
self.__doc__ = wrapped.__doc__
def __get__(self, inst, objtype=None):
diff --git a/src/pyramid/httpexceptions.py b/src/pyramid/httpexceptions.py
index 9fd5f7d55..06894f9b4 100644
--- a/src/pyramid/httpexceptions.py
+++ b/src/pyramid/httpexceptions.py
@@ -50,6 +50,7 @@ Exception
* 415 - HTTPUnsupportedMediaType
* 416 - HTTPRequestRangeNotSatisfiable
* 417 - HTTPExpectationFailed
+ * 418 - HTTPImATeapot
* 422 - HTTPUnprocessableEntity
* 423 - HTTPLocked
* 424 - HTTPFailedDependency
@@ -214,7 +215,7 @@ ${body}'''
</html>'''
)
- # Set this to True for responses that should have no request body
+ # Set this to True for responses that should have no response body
empty_body = False
def __init__(
@@ -224,7 +225,7 @@ ${body}'''
comment=None,
body_template=None,
json_formatter=None,
- **kw
+ **kw,
):
status = '%s %s' % (self.code, self.title)
Response.__init__(self, status=status, **kw)
@@ -528,7 +529,7 @@ ${html_comment}'''
headers=None,
comment=None,
body_template=None,
- **kw
+ **kw,
):
if location is None:
raise ValueError("HTTP redirects need a location to redirect to.")
@@ -538,7 +539,7 @@ ${html_comment}'''
comment=comment,
body_template=body_template,
location=location,
- **kw
+ **kw,
)
@@ -786,7 +787,7 @@ class HTTPForbidden(HTTPClientError):
comment=None,
body_template=None,
result=None,
- **kw
+ **kw,
):
HTTPClientError.__init__(
self,
@@ -794,7 +795,7 @@ class HTTPForbidden(HTTPClientError):
headers=headers,
comment=comment,
body_template=body_template,
- **kw
+ **kw,
)
self.result = result
@@ -1045,6 +1046,24 @@ class HTTPExpectationFailed(HTTPClientError):
explanation = 'Expectation failed.'
+class HTTPImATeapot(HTTPClientError):
+ """
+ subclass of :class:`~HTTPClientError`
+
+ This indicates that the server refuses to brew coffee because
+ it is, in fact and permanently, a teapot. The resulting entity
+ body may be short and stout.
+
+ See RFC2324 and RFC7168 for more information.
+
+ code: 418, title: I'm a teapot
+ """
+
+ code = 418
+ title = "I'm a teapot"
+ explanation = "Refusing to brew coffee because I'm a teapot."
+
+
class HTTPUnprocessableEntity(HTTPClientError):
"""
subclass of :class:`~HTTPClientError`
diff --git a/src/pyramid/i18n.py b/src/pyramid/i18n.py
index 793b25015..7c9ef3b4b 100644
--- a/src/pyramid/i18n.py
+++ b/src/pyramid/i18n.py
@@ -221,7 +221,7 @@ def get_localizer(request):
class Translations(gettext.GNUTranslations):
- """An extended translation catalog class (ripped off from Babel) """
+ """An extended translation catalog class (ripped off from Babel)"""
DEFAULT_DOMAIN = 'messages'
@@ -369,7 +369,7 @@ class Translations(gettext.GNUTranslations):
class LocalizerRequestMixin:
@reify
def localizer(self):
- """ Convenience property to return a localizer """
+ """Convenience property to return a localizer"""
registry = self.registry
current_locale_name = self.locale_name
diff --git a/src/pyramid/interfaces.py b/src/pyramid/interfaces.py
index 6704f7c7c..6221cc21e 100644
--- a/src/pyramid/interfaces.py
+++ b/src/pyramid/interfaces.py
@@ -79,9 +79,7 @@ class IResponse(Interface):
:class:`pyramid.response.Response` and the HTTP exception classes in
:mod:`pyramid.httpexceptions`."""
- RequestClass = Attribute(
- """ Alias for :class:`pyramid.request.Request` """
- )
+ RequestClass = Attribute("""Alias for :class:`pyramid.request.Request`""")
def __call__(environ, start_response):
""":term:`WSGI` call interface, should call the start_response
@@ -138,8 +136,8 @@ class IResponse(Interface):
)
cache_expires = Attribute(
- """ Get/set the Cache-Control and Expires headers. This sets the
- response to expire in the number of seconds passed when set. """
+ """Get/set the Cache-Control and Expires headers. This sets the
+ response to expire in the number of seconds passed when set."""
)
charset = Attribute("""Get/set the charset (in the Content-Type)""")
@@ -174,7 +172,7 @@ class IResponse(Interface):
content_length = Attribute(
"""Gets and sets and deletes the Content-Length header. For more
information on Content-Length see RFC 2616 section 14.17.
- Converts using int. """
+ Converts using int."""
)
content_location = Attribute(
@@ -207,7 +205,7 @@ class IResponse(Interface):
)
def copy():
- """ Makes a copy of the response and returns the copy. """
+ """Makes a copy of the response and returns the copy."""
date = Attribute(
"""Gets and sets and deletes the Date header. For more information on
@@ -229,19 +227,19 @@ class IResponse(Interface):
)
etag = Attribute(
- """ Gets and sets and deletes the ETag header. For more information
+ """Gets and sets and deletes the ETag header. For more information
on ETag see RFC 2616 section 14.19. Converts using Entity tag."""
)
expires = Attribute(
- """ Gets and sets and deletes the Expires header. For more
+ """Gets and sets and deletes the Expires header. For more
information on Expires see RFC 2616 section 14.21. Converts using
HTTP date."""
)
- headerlist = Attribute(""" The list of response headers. """)
+ headerlist = Attribute("""The list of response headers.""")
- headers = Attribute(""" The headers in a dictionary-like object """)
+ headers = Attribute("""The headers in a dictionary-like object""")
is_authenticated = Attribute(
"""A boolean indicating whether the request has an authenticated
@@ -253,13 +251,13 @@ class IResponse(Interface):
)
last_modified = Attribute(
- """ Gets and sets and deletes the Last-Modified header. For more
+ """Gets and sets and deletes the Last-Modified header. For more
information on Last-Modified see RFC 2616 section 14.29. Converts
using HTTP date."""
)
location = Attribute(
- """ Gets and sets and deletes the Location header. For more
+ """Gets and sets and deletes the Location header. For more
information on Location see RFC 2616 section 14.30."""
)
@@ -275,23 +273,23 @@ class IResponse(Interface):
in-place."""
pragma = Attribute(
- """ Gets and sets and deletes the Pragma header. For more information
- on Pragma see RFC 2616 section 14.32. """
+ """Gets and sets and deletes the Pragma header. For more information
+ on Pragma see RFC 2616 section 14.32."""
)
request = Attribute(
- """ Return the request associated with this response if any. """
+ """Return the request associated with this response if any."""
)
retry_after = Attribute(
- """ Gets and sets and deletes the Retry-After header. For more
+ """Gets and sets and deletes the Retry-After header. For more
information on Retry-After see RFC 2616 section 14.37. Converts
using HTTP date or delta seconds."""
)
server = Attribute(
- """ Gets and sets and deletes the Server header. For more information
- on Server see RFC216 section 14.38. """
+ """Gets and sets and deletes the Server header. For more information
+ on Server see RFC216 section 14.38."""
)
def set_cookie(
@@ -306,14 +304,14 @@ class IResponse(Interface):
expires=None,
overwrite=False,
):
- """ Set (add) a cookie for the response """
+ """Set (add) a cookie for the response"""
- status = Attribute(""" The status string. """)
+ status = Attribute("""The status string.""")
- status_int = Attribute(""" The status as an integer """)
+ status_int = Attribute("""The status as an integer""")
unicode_body = Attribute(
- """ Get/set the unicode value of the body (using the charset of
+ """Get/set the unicode value of the body (using the charset of
the Content-Type)"""
)
@@ -327,14 +325,14 @@ class IResponse(Interface):
)
www_authenticate = Attribute(
- """ Gets and sets and deletes the WWW-Authenticate header. For more
+ """Gets and sets and deletes the WWW-Authenticate header. For more
information on WWW-Authenticate see RFC 2616 section 14.47. Converts
- using 'parse_auth' and 'serialize_auth'. """
+ using 'parse_auth' and 'serialize_auth'."""
)
class IException(Interface): # not an API
- """ An interface representing a generic exception """
+ """An interface representing a generic exception"""
class IExceptionResponse(IException, IResponse):
@@ -347,17 +345,17 @@ class IExceptionResponse(IException, IResponse):
:class:`pyramid.httpexceptions.HTTPForbidden`)."""
def prepare(environ):
- """ Prepares the response for being called as a WSGI application """
+ """Prepares the response for being called as a WSGI application"""
class IDict(Interface):
# Documentation-only interface
def __contains__(k):
- """ Return ``True`` if key ``k`` exists in the dictionary."""
+ """Return ``True`` if key ``k`` exists in the dictionary."""
def __setitem__(k, value):
- """ Set a key/value pair into the dictionary"""
+ """Set a key/value pair into the dictionary"""
def __delitem__(k):
"""Delete an item from the dictionary which is passed to the
@@ -368,20 +366,20 @@ class IDict(Interface):
KeyError if the key doesn't exist"""
def __iter__():
- """ Return an iterator over the keys of this dictionary """
+ """Return an iterator over the keys of this dictionary"""
def get(k, default=None):
"""Return the value for key ``k`` from the renderer dictionary, or
the default if no such value exists."""
def items():
- """ Return a list of [(k,v)] pairs from the dictionary """
+ """Return a list of [(k,v)] pairs from the dictionary"""
def keys():
- """ Return a list of keys from the dictionary """
+ """Return a list of keys from the dictionary"""
def values():
- """ Return a list of values from the dictionary """
+ """Return a list of values from the dictionary"""
def pop(k, default=None):
"""Pop the key k from the dictionary and return its value. If k
@@ -400,10 +398,10 @@ class IDict(Interface):
the dictionary, return the default"""
def update(d):
- """ Update the renderer dictionary with another dictionary ``d``."""
+ """Update the renderer dictionary with another dictionary ``d``."""
def clear():
- """ Clear all values from the dictionary """
+ """Clear all values from the dictionary"""
class IBeforeRender(IDict):
@@ -453,7 +451,7 @@ class IRendererInfo(Interface):
)
def clone():
- """ Return a shallow copy that does not share any mutable state."""
+ """Return a shallow copy that does not share any mutable state."""
class IRendererFactory(Interface):
@@ -633,7 +631,7 @@ class IMultiDict(IDict): # docs-only interface
"""
def add(key, value):
- """ Add the key and value, not overwriting any previous value. """
+ """Add the key and value, not overwriting any previous value."""
def dict_of_lists():
"""
@@ -666,7 +664,7 @@ class IMultiDict(IDict): # docs-only interface
class IRequest(Interface):
- """ Request type interface attached to all request objects """
+ """Request type interface attached to all request objects"""
class ITweens(Interface):
@@ -710,20 +708,20 @@ class IAcceptOrder(Interface):
class IStaticURLInfo(Interface):
- """ A policy for generating URLs to static assets """
+ """A policy for generating URLs to static assets"""
def add(config, name, spec, **extra):
- """ Add a new static info registration """
+ """Add a new static info registration"""
def generate(path, request, **kw):
- """ Generate a URL for the given path """
+ """Generate a URL for the given path"""
def add_cache_buster(config, spec, cache_buster):
- """ Add a new cache buster to a particular set of assets """
+ """Add a new cache buster to a particular set of assets"""
class IResponseFactory(Interface):
- """ A utility which generates a response """
+ """A utility which generates a response"""
def __call__(request):
"""Return a response object implementing IResponse,
@@ -732,10 +730,10 @@ class IResponseFactory(Interface):
class IRequestFactory(Interface):
- """ A utility which generates a request """
+ """A utility which generates a request"""
def __call__(environ):
- """ Return an instance of ``pyramid.request.Request``"""
+ """Return an instance of ``pyramid.request.Request``"""
def blank(path):
"""Return an empty request object (see
@@ -743,23 +741,23 @@ class IRequestFactory(Interface):
class IViewClassifier(Interface):
- """ *Internal only* marker interface for views."""
+ """*Internal only* marker interface for views."""
class IExceptionViewClassifier(Interface):
- """ *Internal only* marker interface for exception views."""
+ """*Internal only* marker interface for exception views."""
class IView(Interface):
def __call__(context, request):
- """ Must return an object that implements IResponse. """
+ """Must return an object that implements IResponse."""
class ISecuredView(IView):
- """ *Internal only* interface. Not an API. """
+ """*Internal only* interface. Not an API."""
def __call_permissive__(context, request):
- """ Guaranteed-permissive version of __call__ """
+ """Guaranteed-permissive version of __call__"""
def __permitted__(context, request):
"""Return True if view execution will be permitted using the
@@ -772,17 +770,17 @@ class IMultiView(ISecuredView):
zero or more predicates. Not an API."""
def add(view, predicates, order, accept=None, phash=None):
- """ Add a view to the multiview. """
+ """Add a view to the multiview."""
class IRootFactory(Interface):
def __call__(request):
- """ Return a root object based on the request """
+ """Return a root object based on the request"""
class IDefaultRootFactory(Interface):
def __call__(request):
- """ Return the *default* root object for an application """
+ """Return the *default* root object for an application"""
class ITraverser(Interface):
@@ -915,7 +913,7 @@ class ILocation(Interface):
class IDebugLogger(Interface):
- """ Interface representing a PEP 282 logger """
+ """Interface representing a PEP 282 logger"""
ILogger = IDebugLogger # b/c
@@ -988,14 +986,14 @@ class IRoute(Interface):
class IRoutesMapper(Interface):
- """ Interface representing a Routes ``Mapper`` object """
+ """Interface representing a Routes ``Mapper`` object"""
def get_routes():
"""Return a sequence of Route objects registered in the mapper.
Static routes will not be returned in this sequence."""
def has_routes():
- """ Returns ``True`` if any route has been registered. """
+ """Returns ``True`` if any route has been registered."""
def get_route(name):
"""Returns an ``IRoute`` object if a route with the name ``name``
@@ -1009,7 +1007,7 @@ class IRoutesMapper(Interface):
pregenerator=None,
static=True,
):
- """ Add a new route. """
+ """Add a new route."""
def generate(name, kw):
"""Generate a URL using the route named ``name`` with the
@@ -1080,7 +1078,7 @@ class IPEP302Loader(Interface):
class IPackageOverrides(IPEP302Loader):
- """ Utility for pkg_resources overrides """
+ """Utility for pkg_resources overrides"""
# VH_ROOT_KEY is an interface; its imported from other packages (e.g.
@@ -1089,12 +1087,12 @@ VH_ROOT_KEY = 'HTTP_X_VHM_ROOT'
class ILocalizer(Interface):
- """ Localizer for a specific language """
+ """Localizer for a specific language"""
class ILocaleNegotiator(Interface):
def __call__(request):
- """ Return a locale name """
+ """Return a locale name"""
class ITranslationDirectories(Interface):
@@ -1131,7 +1129,7 @@ class ISessionFactory(Interface):
returns an ISession object"""
def __call__(request):
- """ Return an ISession object """
+ """Return an ISession object"""
class ISession(IDict):
@@ -1457,7 +1455,7 @@ class IJSONAdapter(Interface):
class IPredicateList(Interface):
- """ Interface representing a predicate list """
+ """Interface representing a predicate list"""
class IPredicateInfo(Interface):
@@ -1589,7 +1587,7 @@ class IViewDeriverInfo(Interface):
class IViewDerivers(Interface):
- """ Interface for view derivers list """
+ """Interface for view derivers list"""
class ICacheBuster(Interface):
diff --git a/src/pyramid/path.py b/src/pyramid/path.py
index 3c0c1a682..3db4bf0ff 100644
--- a/src/pyramid/path.py
+++ b/src/pyramid/path.py
@@ -45,7 +45,7 @@ def package_name(pkg_or_module):
def package_of(pkg_or_module):
- """ Return the package of a module or return the package itself """
+ """Return the package of a module or return the package itself"""
pkg_name = package_name(pkg_or_module)
__import__(pkg_name)
return sys.modules[pkg_name]
@@ -334,7 +334,7 @@ class DottedNameResolver(Resolver):
return self._zope_dottedname_style(dotted, package)
def _pkg_resources_style(self, value, package):
- """ package.module:attr style """
+ """package.module:attr style"""
if value.startswith(('.', ':')):
if not package:
raise ValueError(
@@ -354,7 +354,7 @@ class DottedNameResolver(Resolver):
return ep.load(False) # pragma: NO COVER
def _zope_dottedname_style(self, value, package):
- """ package.module.attr style """
+ """package.module.attr style"""
module = getattr(package, '__name__', None) # package may be None
if not module:
module = None
diff --git a/src/pyramid/registry.py b/src/pyramid/registry.py
index 66519398c..2d790015a 100644
--- a/src/pyramid/registry.py
+++ b/src/pyramid/registry.py
@@ -295,7 +295,7 @@ def undefer(v):
class predvalseq(tuple):
- """ A subtype of tuple used to represent a sequence of predicate values """
+ """A subtype of tuple used to represent a sequence of predicate values"""
global_registry = Registry('global')
diff --git a/src/pyramid/scripts/pserve.py b/src/pyramid/scripts/pserve.py
index 6906a0410..1bcf6c543 100644
--- a/src/pyramid/scripts/pserve.py
+++ b/src/pyramid/scripts/pserve.py
@@ -231,7 +231,7 @@ class PServeCommand:
webbrowser.open(url)
t = threading.Thread(target=open_browser)
- t.setDaemon(True)
+ t.daemon = True
t.start()
if self.args.reload and not hupper.is_active():
diff --git a/src/pyramid/security.py b/src/pyramid/security.py
index a0ab39701..e1de9d9a6 100644
--- a/src/pyramid/security.py
+++ b/src/pyramid/security.py
@@ -171,7 +171,7 @@ class PermitsResult(int):
@property
def msg(self):
- """ A string indicating why the result was generated."""
+ """A string indicating why the result was generated."""
return self.s % self.args
def __str__(self):
@@ -212,7 +212,7 @@ class Allowed(PermitsResult):
class SecurityAPIMixin:
- """ Mixin for Request class providing auth-related properties. """
+ """Mixin for Request class providing auth-related properties."""
@property
def identity(self):
@@ -278,7 +278,7 @@ class SecurityAPIMixin:
class AuthenticationAPIMixin:
- """ Mixin for Request class providing compatibility properties. """
+ """Mixin for Request class providing compatibility properties."""
@property
def unauthenticated_userid(self):
@@ -396,7 +396,7 @@ Deny = 'Deny'
class AllPermissionsList:
- """ Stand in 'permission list' to represent all permissions """
+ """Stand in 'permission list' to represent all permissions"""
def __iter__(self):
return iter(())
diff --git a/src/pyramid/session.py b/src/pyramid/session.py
index 032d58a8b..431fdd5ec 100644
--- a/src/pyramid/session.py
+++ b/src/pyramid/session.py
@@ -189,7 +189,7 @@ def BaseCookieSessionFactory(
@implementer(ISession)
class CookieSession(dict):
- """ Dictionary-like session object """
+ """Dictionary-like session object"""
# configuration parameters
_cookie_name = cookie_name
diff --git a/src/pyramid/static.py b/src/pyramid/static.py
index 8b19c7b16..5363c1671 100644
--- a/src/pyramid/static.py
+++ b/src/pyramid/static.py
@@ -171,7 +171,7 @@ class static_view:
return name
def get_possible_files(self, resource_name):
- """ Return a sorted list of ``(size, encoding, path)`` entries."""
+ """Return a sorted list of ``(size, encoding, path)`` entries."""
result = self.filemap.get(resource_name)
if result is not None:
return result
@@ -206,7 +206,7 @@ class static_view:
return result
def find_best_match(self, request, files):
- """ Return ``(path | None, encoding)``."""
+ """Return ``(path | None, encoding)``."""
# if the client did not specify encodings then assume only the
# identity is acceptable
if not request.accept_encoding:
@@ -408,7 +408,7 @@ class ManifestCacheBuster:
@property
def manifest(self):
- """ The current manifest dictionary."""
+ """The current manifest dictionary."""
if self.reload:
if not self.exists(self.manifest_path):
return {}
diff --git a/src/pyramid/testing.py b/src/pyramid/testing.py
index 621a69d4b..1fba3ff31 100644
--- a/src/pyramid/testing.py
+++ b/src/pyramid/testing.py
@@ -31,7 +31,7 @@ class DummyRootFactory:
class DummySecurityPolicy:
- """ A standin for a :term:`security policy`."""
+ """A standin for a :term:`security policy`."""
def __init__(
self,
@@ -105,7 +105,7 @@ class DummyTemplateRenderer:
return self.string_response
def __getattr__(self, k):
- """ Backwards compatibility """
+ """Backwards compatibility"""
val = self._received.get(k, _marker)
if val is _marker:
val = self._implementation._received.get(k, _marker)
@@ -140,7 +140,7 @@ class DummyTemplateRenderer:
class DummyResource:
- """ A dummy :app:`Pyramid` :term:`resource` object."""
+ """A dummy :app:`Pyramid` :term:`resource` object."""
def __init__(
self, __name__=None, __parent__=None, __provides__=None, **kw
@@ -179,7 +179,7 @@ class DummyResource:
self.subs[name] = val
def __getitem__(self, name):
- """ Return a named subobject (see ``__setitem__``)"""
+ """Return a named subobject (see ``__setitem__``)"""
ob = self.subs[name]
return ob
@@ -190,15 +190,15 @@ class DummyResource:
return self.subs.get(name, default)
def values(self):
- """ Return the values set by __setitem__ """
+ """Return the values set by __setitem__"""
return self.subs.values()
def items(self):
- """ Return the items set by __setitem__ """
+ """Return the items set by __setitem__"""
return self.subs.items()
def keys(self):
- """ Return the keys set by __setitem__ """
+ """Return the keys set by __setitem__"""
return self.subs.keys()
__iter__ = keys
@@ -327,7 +327,7 @@ class DummyRequest(
cookies=None,
post=None,
accept=None,
- **kw
+ **kw,
):
if environ is None:
environ = {}
@@ -545,7 +545,7 @@ def tearDown(unhook_zca=True):
def cleanUp(*arg, **kw):
- """ An alias for :func:`pyramid.testing.setUp`. """
+ """An alias for :func:`pyramid.testing.setUp`."""
package = kw.get('package', None)
if package is None:
package = caller_package()
diff --git a/src/pyramid/util.py b/src/pyramid/util.py
index f8d082348..191768eb3 100644
--- a/src/pyramid/util.py
+++ b/src/pyramid/util.py
@@ -182,7 +182,7 @@ class InstancePropertyHelper:
self.properties[name] = fn
def apply(self, target):
- """ Apply all configured properties to the ``target`` instance."""
+ """Apply all configured properties to the ``target`` instance."""
if self.properties:
self.apply_properties(target, self.properties)
@@ -275,7 +275,7 @@ class WeakOrderedSet:
self._order = []
def add(self, item):
- """ Add an item to the set."""
+ """Add an item to the set."""
oid = id(item)
if oid in self._items:
self._order.remove(oid)
@@ -286,17 +286,17 @@ class WeakOrderedSet:
self._order.append(oid)
def _remove_by_id(self, oid):
- """ Remove an item from the set."""
+ """Remove an item from the set."""
if oid in self._items:
del self._items[oid]
self._order.remove(oid)
def remove(self, item):
- """ Remove an item from the set."""
+ """Remove an item from the set."""
self._remove_by_id(id(item))
def empty(self):
- """ Clear all objects from the set."""
+ """Clear all objects from the set."""
self._items = {}
self._order = []
@@ -445,7 +445,7 @@ class TopologicalSorter:
return self.name2val.values()
def remove(self, name):
- """ Remove a node from the sort input """
+ """Remove a node from the sort input"""
self.names.remove(name)
del self.name2val[name]
after = self.name2after.pop(name, [])
@@ -499,7 +499,7 @@ class TopologicalSorter:
self.req_before.add(name)
def sorted(self):
- """ Returns the sort input values in topologically sorted order"""
+ """Returns the sort input values in topologically sorted order"""
order = [(self.first, self.last)]
roots = []
graph = {}
diff --git a/tests/pkgs/restbugapp/views.py b/tests/pkgs/restbugapp/views.py
index 6930d3668..d7e253ac2 100644
--- a/tests/pkgs/restbugapp/views.py
+++ b/tests/pkgs/restbugapp/views.py
@@ -8,7 +8,7 @@ class BaseRESTView:
class PetRESTView(BaseRESTView):
- """ REST Controller to control action of an avatar """
+ """REST Controller to control action of an avatar"""
def __init__(self, context, request):
super().__init__(context, request)
diff --git a/tests/test_config/test_init.py b/tests/test_config/test_init.py
index 0a9e2988c..4ecd081e0 100644
--- a/tests/test_config/test_init.py
+++ b/tests/test_config/test_init.py
@@ -1349,7 +1349,7 @@ class TestConfigurator__add_predicate(unittest.TestCase):
kw=None,
order=0,
introspectables=(),
- **extra
+ **extra,
):
self.assertEqual(len(introspectables), 1)
self.assertEqual(introspectables[0]['name'], 'testing')
@@ -1368,7 +1368,7 @@ class TestConfigurator__add_predicate(unittest.TestCase):
kw=None,
order=0,
introspectables=(),
- **extra
+ **extra,
):
self.assertEqual(len(introspectables), 1)
self.assertEqual(introspectables[0]['name'], 'testing')
diff --git a/tests/test_config/test_views.py b/tests/test_config/test_views.py
index fcccbfba3..72f8f0145 100644
--- a/tests/test_config/test_views.py
+++ b/tests/test_config/test_views.py
@@ -248,7 +248,7 @@ class TestViewsConfigurationMixin(unittest.TestCase):
from pyramid.renderers import null_renderer
def view(request):
- """ ABC """
+ """ABC"""
return 'OK'
def view_wrapper(fn):
@@ -271,7 +271,7 @@ class TestViewsConfigurationMixin(unittest.TestCase):
from pyramid.renderers import null_renderer
def view(request):
- """ ABC """
+ """ABC"""
return 'OK'
def view_wrapper1(fn):
@@ -306,7 +306,7 @@ class TestViewsConfigurationMixin(unittest.TestCase):
response = Response('OK')
def view(request):
- """ ABC """
+ """ABC"""
return response
config = self._makeOne(autocommit=True)
@@ -3790,7 +3790,7 @@ class Test_preserve_view_attrs(unittest.TestCase):
def test_it_different(self):
class DummyView1:
- """ 1 """
+ """1"""
__name__ = '1'
__module__ = '1'
@@ -3808,7 +3808,7 @@ class Test_preserve_view_attrs(unittest.TestCase):
""" """
class DummyView2:
- """ 2 """
+ """2"""
__name__ = '2'
__module__ = '2'
diff --git a/tests/test_router.py b/tests/test_router.py
index 857e8aea5..f136e5ab3 100644
--- a/tests/test_router.py
+++ b/tests/test_router.py
@@ -56,7 +56,7 @@ class TestRouter(unittest.TestCase):
virtual_root=None,
virtual_root_path=None,
raise_error=None,
- **kw
+ **kw,
):
from pyramid.interfaces import ITraverser
diff --git a/tox.ini b/tox.ini
index f90bd9166..0f166e6aa 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,7 +1,7 @@
[tox]
envlist =
lint,
- py36,py37,py38,py39,pypy3,
+ py37,py38,py39,py310,pypy3,
py38-cover,coverage,
docs
@@ -28,9 +28,9 @@ commands =
python setup.py check -r -s -m
check-manifest
deps =
- flake8
- black
- isort
+ flake8~=4.0.1
+ black~=22.1.0
+ isort~=5.10
readme_renderer
check-manifest
@@ -66,19 +66,23 @@ commands =
isort src/pyramid tests setup.py
black src/pyramid tests setup.py
deps =
- black
- isort
+ black~=22.1.0
+ isort~=5.10
[testenv:build]
skip_install = true
commands =
# clean up build/ and dist/ folders
- python -c 'import shutil; shutil.rmtree("dist", ignore_errors=True)'
- python setup.py clean --all
- # build sdist
- python setup.py sdist --dist-dir {toxinidir}/dist
- # build wheel from sdist
- pip wheel -v --no-deps --no-index --no-build-isolation --wheel-dir {toxinidir}/dist --find-links {toxinidir}/dist pyramid
+ python -c 'import shutil; shutil.rmtree("build", ignore_errors=True)'
+ # Make sure we aren't forgetting anything
+ check-manifest
+ # build sdist/wheel
+ python -m build .
+ # Verify all is well
+ twine check dist/*
+
deps =
- setuptools
- wheel
+ build
+ check-manifest
+ readme_renderer
+ twine