summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci-tests.yml9
-rw-r--r--CHANGES.rst302
-rw-r--r--CONTRIBUTORS.txt6
-rw-r--r--HACKING.txt14
-rw-r--r--HISTORY.rst314
-rw-r--r--README.rst8
-rw-r--r--contributing.md18
-rw-r--r--docs/conf.py3
-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/paste.rst4
-rw-r--r--docs/narr/upgrading.rst6
-rw-r--r--docs/narr/urldispatch.rst2
-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--setup.py7
-rw-r--r--src/pyramid/authentication.py22
-rw-r--r--src/pyramid/config/assets.py4
-rw-r--r--src/pyramid/csrf.py12
-rw-r--r--src/pyramid/httpexceptions.py21
-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.py16
-rw-r--r--src/pyramid/util.py14
-rw-r--r--tests/pkgs/restbugapp/views.py2
-rw-r--r--tests/test_config/test_views.py10
-rw-r--r--tox.ini32
53 files changed, 541 insertions, 494 deletions
diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml
index 625c6a60f..a47889e8c 100644
--- a/.github/workflows/ci-tests.yml
+++ b/.github/workflows/ci-tests.yml
@@ -15,11 +15,11 @@ jobs:
strategy:
matrix:
py:
- - "3.6"
- "3.7"
- "3.8"
- "3.9"
- - "pypy3"
+ - "3.10"
+ - "pypy-3.8"
os:
- "ubuntu-latest"
- "windows-latest"
@@ -33,7 +33,7 @@ jobs:
- os: "ubuntu-latest"
pytest-args: "--cov"
- os: "ubuntu-latest"
- py: "pypy3"
+ py: "pypy-3.8"
pytest-args: ""
exclude:
@@ -42,9 +42,6 @@ jobs:
architecture: x86
- os: "macos-latest"
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 }}
diff --git a/CHANGES.rst b/CHANGES.rst
index 887c8ce95..0ee6fd30d 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,308 +1,16 @@
-2.0b1 (2021-02-20)
-==================
-
-- Break potential reference cycle between ``request`` and ``context``.
- See https://github.com/Pylons/pyramid/pull/3649
-
-- Remove ``update_wrapper`` from ``pyramid.decorator.reify``.
- See https://github.com/Pylons/pyramid/pull/3657
-
-2.0b0 (2020-12-15)
-==================
-
-- Overhaul tutorials and update cookiecutter to de-emphasize ``request.user``
- in favor of ``request.identity`` for common use cases.
- See https://github.com/Pylons/pyramid/pull/3629
-
-- Improve documentation and patterns with builtin fixtures shipped in the
- cookiecutters.
- See https://github.com/Pylons/pyramid/pull/3629
-
-2.0a0 (2020-11-29)
-==================
+unreleased
+==========
Features
--------
-- Add support for Python 3.9.
- See https://github.com/Pylons/pyramid/issues/3622
-
-- The ``aslist`` method now handles non-string objects when flattening.
- See https://github.com/Pylons/pyramid/pull/3594
-
-- It is now possible to pass multiple values to the ``header`` predicate
- for route and view configuration.
- See https://github.com/Pylons/pyramid/pull/3576
-
-- Add support for Python 3.8.
- See https://github.com/Pylons/pyramid/pull/3547
-
-- New security APIs have been added to support a massive overhaul of the
- authentication and authorization system. Read
- "Upgrading Authentication/Authorization" in the "What's New in Pyramid 2.0"
- chapter of the documentation for information about using this new system.
-
- - ``pyramid.config.Configurator.set_security_policy``.
- - ``pyramid.interfaces.ISecurityPolicy``
- - ``pyramid.request.Request.identity``.
- - ``pyramid.request.Request.is_authenticated``
- - ``pyramid.authentication.SessionAuthenticationHelper``
- - ``pyramid.authorization.ACLHelper``
- - ``is_authenticated=True/False`` predicate for route and view configs
-
- See https://github.com/Pylons/pyramid/pull/3465 and
- https://github.com/Pylons/pyramid/pull/3598
-
-- Changed the default ``serializer`` on
- ``pyramid.session.SignedCookieSessionFactory`` to use
- ``pyramid.session.JSONSerializer`` instead of
- ``pyramid.session.PickleSerializer``. Read
- "Upgrading Session Serialization" in the "What's New in Pyramid 2.0" chapter
- of the documentation for more information about why this change was made.
- See https://github.com/Pylons/pyramid/pull/3413
-
-- It is now possible to control whether a route pattern contains a trailing
- slash when it is composed with a route prefix using
- ``config.include(..., route_prefix=...)`` or
- ``with config.route_prefix_context(...)``. This can be done by specifying
- an empty pattern and setting the new argument
- ``inherit_slash=True``. For example:
-
- .. code-block:: python
-
- with config.route_prefix_context('/users'):
- config.add_route('users', '', inherit_slash=True)
-
- In the example, the resulting pattern will be ``/users``. Similarly, if the
- route prefix were ``/users/`` then the final pattern would be ``/users/``.
- If the ``pattern`` was ``'/'``, then the final pattern would always be
- ``/users/``. This new setting is only available if the pattern supplied
- to ``add_route`` is the empty string (``''``).
- See https://github.com/Pylons/pyramid/pull/3420
-
-- No longer define ``pyramid.request.Request.json_body`` which is already
- provided by WebOb. This allows the attribute to now be settable.
- See https://github.com/Pylons/pyramid/pull/3447
-
-- Improve debugging info from ``pyramid.view.view_config`` decorator.
- See https://github.com/Pylons/pyramid/pull/3483
-
-- A new parameter, ``allow_no_origin``, was added to
- ``pyramid.config.Configurator.set_default_csrf_options`` as well as
- ``pyramid.csrf.check_csrf_origin``. This option controls whether a
- request is rejected if it has no ``Origin`` or ``Referer`` header -
- often the result of a user configuring their browser not to send a
- ``Referer`` header for privacy reasons even on same-domain requests.
- The default is to reject requests without a known origin. It is also
- possible to allow the special ``Origin: null`` header by adding it to the
- ``pyramid.csrf_trusted_origins`` list in the settings.
- See https://github.com/Pylons/pyramid/pull/3512
- and https://github.com/Pylons/pyramid/pull/3518
-
-- A new parameter, ``check_origin``, was added to
- ``pyramid.config.Configurator.set_default_csrf_options`` which disables
- origin checking entirely.
- See https://github.com/Pylons/pyramid/pull/3518
-
-- Added ``pyramid.interfaces.IPredicateInfo`` which defines the object passed
- to predicate factories as their second argument.
- See https://github.com/Pylons/pyramid/pull/3514
-
-- Added support for serving pre-compressed static assets by using the
- ``content_encodings`` argument of
- ``pyramid.config.Configurator.add_static_view`` and
- ``pyramid.static.static_view``.
- See https://github.com/Pylons/pyramid/pull/3537
-
-- Fix ``DeprecationWarning`` emitted by using the ``imp`` module.
- See https://github.com/Pylons/pyramid/pull/3553
-
-- Properties created via ``config.add_request_method(..., property=True)`` or
- ``request.set_property`` used to be readonly. They can now be overridden
- via ``request.foo = ...`` and until the value is deleted it will return
- the overridden value. This is most useful when mocking request properties
- in testing.
- See https://github.com/Pylons/pyramid/pull/3559
-
-- Finished callbacks are now executed as part of the ``closer`` that is
- invoked as part of ``pyramid.scripting.prepare`` and
- ``pyramid.paster.bootstrap``.
- See https://github.com/Pylons/pyramid/pull/3561
-
-- Added ``pyramid.request.RequestLocalCache`` which can be used to create
- simple objects that are shared across requests and can be used to store
- per-request data. This is useful when the source of data is external to
- the request itself. Often a reified property is used on a request via
- ``pyramid.config.Configurator.add_request_method``, or
- ``pyramid.decorator.reify``, and these work great when the data is
- generated on-demand when accessing the request property. However, often
- the case is that the data is generated when accessing some other system
- and then we want to cache the data for the duration of the request.
- See https://github.com/Pylons/pyramid/pull/3561
-
-- Exposed ``pyramid.authorization.ALL_PERMISSIONS`` and
- ``pyramid.authorization.DENY_ALL`` such that all of the ACL-related constants
- are now importable from the ``pyramid.authorization`` namespace.
- See https://github.com/Pylons/pyramid/pull/3563
-
-- ``pserve`` now outputs verbose messaging to `stderr` instead of `stdout`
- to circumvent buffering issues that exist by default on `stdout`.
- See https://github.com/Pylons/pyramid/pull/3593
-
-Deprecations
-------------
-
-- Deprecated the authentication and authorization interfaces and
- principal-based support. See "Upgrading Authentication/Authorization" in
- the "What's New in Pyramid 2.0" chapter of the documentation for information
- on equivalent APIs and notes on upgrading. The following APIs are deprecated
- as a result of this change:
-
- - ``pyramid.config.Configurator.set_authentication_policy``
- - ``pyramid.config.Configurator.set_authorization_policy``
- - ``pyramid.interfaces.IAuthenticationPolicy``
- - ``pyramid.interfaces.IAuthorizationPolicy``
- - ``pyramid.request.Request.effective_principals``
- - ``pyramid.request.Request.unauthenticated_userid``
- - ``pyramid.authentication.AuthTktAuthenticationPolicy``
- - ``pyramid.authentication.RemoteUserAuthenticationPolicy``
- - ``pyramid.authentication.RepozeWho1AuthenticationPolicy``
- - ``pyramid.authentication.SessionAuthenticationPolicy``
- - ``pyramid.authentication.BasicAuthAuthenticationPolicy``
- - ``pyramid.authorization.ACLAuthorizationPolicy``
- - The ``effective_principals`` view and route predicates.
-
- See https://github.com/Pylons/pyramid/pull/3465
-
-- Deprecated ``pyramid.security.principals_allowed_by_permission``. This
- method continues to work with the deprecated
- ``pyramid.interfaces.IAuthorizationPolicy`` interface but will not work with
- the new ``pyramid.interfaces.ISecurityPolicy``.
- See https://github.com/Pylons/pyramid/pull/3465
-
-- Deprecated several ACL-related aspects of ``pyramid.security``. Equivalent
- objects should now be imported from the ``pyramid.authorization`` namespace.
- This includes:
-
- - ``pyramid.security.Everyone``
- - ``pyramid.security.Authenticated``
- - ``pyramid.security.ALL_PERMISSIONS``
- - ``pyramid.security.DENY_ALL``
- - ``pyramid.security.ACLAllowed``
- - ``pyramid.security.ACLDenied``
-
- See https://github.com/Pylons/pyramid/pull/3563
-
-- Deprecated ``pyramid.session.PickleSerializer``.
- See https://github.com/pylons/pyramid/issues/2709,
- and https://github.com/pylons/pyramid/pull/3353,
- and https://github.com/pylons/pyramid/pull/3413
+Bug Fixes
+---------
Backward Incompatibilities
--------------------------
-- Drop support for Python 2.7, 3.4, and 3.5.
- See https://github.com/Pylons/pyramid/pull/3421,
- and https://github.com/Pylons/pyramid/pull/3547,
- and https://github.com/Pylons/pyramid/pull/3634
-
-- Removed the ``pyramid.compat`` module. Integrators should use the ``six``
- module or vendor shims they are using into their own codebases going forward.
- https://github.com/Pylons/pyramid/pull/3421
-
-- ``pcreate`` and the builtin scaffolds have been removed in favor of
- using the ``cookiecutter`` tool and the ``pyramid-cookiecutter-starter``
- cookiecutter. The script and scaffolds were deprecated in Pyramid 1.8.
- See https://github.com/Pylons/pyramid/pull/3406
-
-- Changed the default ``hashalg`` on
- ``pyramid.authentication.AuthTktCookieHelper`` to ``sha512``.
- See https://github.com/Pylons/pyramid/pull/3557
-
-- Removed ``pyramid.interfaces.ITemplateRenderer``. This interface was
- deprecated since Pyramid 1.5 and was an interface
- used by libraries like ``pyramid_mako`` and ``pyramid_chameleon`` but
- provided no functionality within Pyramid itself.
- See https://github.com/Pylons/pyramid/pull/3409
-
-- Removed ``pyramid.security.has_permission``,
- ``pyramid.security.authenticated_userid``,
- ``pyramid.security.unauthenticated_userid``, and
- ``pyramid.security.effective_principals``. These methods were deprecated
- in Pyramid 1.5 and all have equivalents available as properties on the
- request. For example, ``request.authenticated_userid``.
- See https://github.com/Pylons/pyramid/pull/3410
-
-- Removed support for supplying a media range to the ``accept`` predicate of
- both ``pyramid.config.Configurator.add_view`` and
- ``pyramid.config.Configurator.add_route``. These options were deprecated
- in Pyramid 1.10 and WebOb 1.8 because they resulted in uncontrollable
- matching that was not compliant with the RFC.
- See https://github.com/Pylons/pyramid/pull/3411
-
-- Removed ``pyramid.session.UnencryptedCookieSessionFactoryConfig``. This
- session factory was replaced with
- ``pyramid.session.SignedCookieSessionFactory`` in Pyramid 1.5 and has been
- deprecated since then.
- See https://github.com/Pylons/pyramid/pull/3412
-
-- Removed ``pyramid.session.signed_serialize``, and
- ``pyramid.session.signed_deserialize``. These methods were only used by
- the now-removed ``pyramid.session.UnencryptedCookieSessionFactoryConfig``
- and were coupled to the vulnerable pickle serialization format which could
- lead to remove code execution if the secret key is compromised.
- See https://github.com/Pylons/pyramid/pull/3412
-
-- Changed the default ``serializer`` on
- ``pyramid.session.SignedCookieSessionFactory`` to use
- ``pyramid.session.JSONSerializer`` instead of
- ``pyramid.session.PickleSerializer``. Read "Upgrading Session Serialization"
- in the "What's New in Pyramid 2.0" chapter of the documentation for more
- information about why this change was made.
- See https://github.com/Pylons/pyramid/pull/3413
-
-- ``pyramid.request.Request.invoke_exception_view`` will no longer be called
- by the default execution policy.
- See https://github.com/Pylons/pyramid/pull/3496
-
-- ``pyramid.config.Configurator.scan`` will no longer, by default, execute
- Venusian decorator callbacks registered for categories other than
- ``'pyramid'``. To find any decorator regardless of category, specify
- ``config.scan(..., categories=None)``.
- See https://github.com/Pylons/pyramid/pull/3510
-
-- The second argument to predicate factories has been changed from ``config``
- to ``info``, an instance of ``pyramid.interfaces.IPredicateInfo``. This
- limits the data available to predicates but still provides the package,
- registry, settings and dotted-name resolver which should cover most use
- cases and is largely backward compatible.
- See https://github.com/Pylons/pyramid/pull/3514
-
-- Removed the ``check_csrf`` predicate. Instead, use
- ``pyramid.config.Configurator.set_default_csrf_options`` and the
- ``require_csrf`` view option to enable automatic CSRF checking.
- See https://github.com/Pylons/pyramid/pull/3521
-
-- Update the default behavior of
- ``pyramid.authenticationAuthTktAuthenticationPolicy`` and
- ``pyramid.authentication.AuthTktCookieHelper`` to only set a single cookie
- without a domain parameter when no other domain constraints are specified.
- Prior to this change, ``wild_domain=False`` (the default) was effectively
- treated the same as ``wild_domain=True``, in which a cookie was defined
- such that browsers would use it both for the request's domain, as well as
- any subdomain. In the new behavior, cookies will only affect the current
- domain, and not subdomains, by default.
- See https://github.com/Pylons/pyramid/pull/3587
+- Pyramid is no longer tested on, nor supports Python 3.6
Documentation Changes
---------------------
-
-- Restore build of PDF on Read The Docs.
- See https://github.com/Pylons/pyramid/issues/3290
-
-- Fix docs build for Sphinx 2.0.
- See https://github.com/Pylons/pyramid/pull/3480
-
-- Significant updates to the wiki, wiki2 tutorials to demonstrate the new
- security policy usage as well as a much more production-ready test harness.
- See https://github.com/Pylons/pyramid/pull/3557
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/HISTORY.rst b/HISTORY.rst
index 8b0028065..7bda92fa4 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -1,3 +1,317 @@
+2.0 (2021-02-28)
+================
+
+- No changes from 2.0b1.
+
+2.0b1 (2021-02-20)
+==================
+
+- Break potential reference cycle between ``request`` and ``context``.
+ See https://github.com/Pylons/pyramid/pull/3649
+
+- Remove ``update_wrapper`` from ``pyramid.decorator.reify``.
+ See https://github.com/Pylons/pyramid/pull/3657
+
+2.0b0 (2020-12-15)
+==================
+
+- Overhaul tutorials and update cookiecutter to de-emphasize ``request.user``
+ in favor of ``request.identity`` for common use cases.
+ See https://github.com/Pylons/pyramid/pull/3629
+
+- Improve documentation and patterns with builtin fixtures shipped in the
+ cookiecutters.
+ See https://github.com/Pylons/pyramid/pull/3629
+
+2.0a0 (2020-11-29)
+==================
+
+Features
+--------
+
+- Add support for Python 3.9.
+ See https://github.com/Pylons/pyramid/issues/3622
+
+- The ``aslist`` method now handles non-string objects when flattening.
+ See https://github.com/Pylons/pyramid/pull/3594
+
+- It is now possible to pass multiple values to the ``header`` predicate
+ for route and view configuration.
+ See https://github.com/Pylons/pyramid/pull/3576
+
+- Add support for Python 3.8.
+ See https://github.com/Pylons/pyramid/pull/3547
+
+- New security APIs have been added to support a massive overhaul of the
+ authentication and authorization system. Read
+ "Upgrading Authentication/Authorization" in the "What's New in Pyramid 2.0"
+ chapter of the documentation for information about using this new system.
+
+ - ``pyramid.config.Configurator.set_security_policy``.
+ - ``pyramid.interfaces.ISecurityPolicy``
+ - ``pyramid.request.Request.identity``.
+ - ``pyramid.request.Request.is_authenticated``
+ - ``pyramid.authentication.SessionAuthenticationHelper``
+ - ``pyramid.authorization.ACLHelper``
+ - ``is_authenticated=True/False`` predicate for route and view configs
+
+ See https://github.com/Pylons/pyramid/pull/3465 and
+ https://github.com/Pylons/pyramid/pull/3598
+
+- Changed the default ``serializer`` on
+ ``pyramid.session.SignedCookieSessionFactory`` to use
+ ``pyramid.session.JSONSerializer`` instead of
+ ``pyramid.session.PickleSerializer``. Read
+ "Upgrading Session Serialization" in the "What's New in Pyramid 2.0" chapter
+ of the documentation for more information about why this change was made.
+ See https://github.com/Pylons/pyramid/pull/3413
+
+- It is now possible to control whether a route pattern contains a trailing
+ slash when it is composed with a route prefix using
+ ``config.include(..., route_prefix=...)`` or
+ ``with config.route_prefix_context(...)``. This can be done by specifying
+ an empty pattern and setting the new argument
+ ``inherit_slash=True``. For example:
+
+ .. code-block:: python
+
+ with config.route_prefix_context('/users'):
+ config.add_route('users', '', inherit_slash=True)
+
+ In the example, the resulting pattern will be ``/users``. Similarly, if the
+ route prefix were ``/users/`` then the final pattern would be ``/users/``.
+ If the ``pattern`` was ``'/'``, then the final pattern would always be
+ ``/users/``. This new setting is only available if the pattern supplied
+ to ``add_route`` is the empty string (``''``).
+ See https://github.com/Pylons/pyramid/pull/3420
+
+- No longer define ``pyramid.request.Request.json_body`` which is already
+ provided by WebOb. This allows the attribute to now be settable.
+ See https://github.com/Pylons/pyramid/pull/3447
+
+- Improve debugging info from ``pyramid.view.view_config`` decorator.
+ See https://github.com/Pylons/pyramid/pull/3483
+
+- A new parameter, ``allow_no_origin``, was added to
+ ``pyramid.config.Configurator.set_default_csrf_options`` as well as
+ ``pyramid.csrf.check_csrf_origin``. This option controls whether a
+ request is rejected if it has no ``Origin`` or ``Referer`` header -
+ often the result of a user configuring their browser not to send a
+ ``Referer`` header for privacy reasons even on same-domain requests.
+ The default is to reject requests without a known origin. It is also
+ possible to allow the special ``Origin: null`` header by adding it to the
+ ``pyramid.csrf_trusted_origins`` list in the settings.
+ See https://github.com/Pylons/pyramid/pull/3512
+ and https://github.com/Pylons/pyramid/pull/3518
+
+- A new parameter, ``check_origin``, was added to
+ ``pyramid.config.Configurator.set_default_csrf_options`` which disables
+ origin checking entirely.
+ See https://github.com/Pylons/pyramid/pull/3518
+
+- Added ``pyramid.interfaces.IPredicateInfo`` which defines the object passed
+ to predicate factories as their second argument.
+ See https://github.com/Pylons/pyramid/pull/3514
+
+- Added support for serving pre-compressed static assets by using the
+ ``content_encodings`` argument of
+ ``pyramid.config.Configurator.add_static_view`` and
+ ``pyramid.static.static_view``.
+ See https://github.com/Pylons/pyramid/pull/3537
+
+- Fix ``DeprecationWarning`` emitted by using the ``imp`` module.
+ See https://github.com/Pylons/pyramid/pull/3553
+
+- Properties created via ``config.add_request_method(..., property=True)`` or
+ ``request.set_property`` used to be readonly. They can now be overridden
+ via ``request.foo = ...`` and until the value is deleted it will return
+ the overridden value. This is most useful when mocking request properties
+ in testing.
+ See https://github.com/Pylons/pyramid/pull/3559
+
+- Finished callbacks are now executed as part of the ``closer`` that is
+ invoked as part of ``pyramid.scripting.prepare`` and
+ ``pyramid.paster.bootstrap``.
+ See https://github.com/Pylons/pyramid/pull/3561
+
+- Added ``pyramid.request.RequestLocalCache`` which can be used to create
+ simple objects that are shared across requests and can be used to store
+ per-request data. This is useful when the source of data is external to
+ the request itself. Often a reified property is used on a request via
+ ``pyramid.config.Configurator.add_request_method``, or
+ ``pyramid.decorator.reify``, and these work great when the data is
+ generated on-demand when accessing the request property. However, often
+ the case is that the data is generated when accessing some other system
+ and then we want to cache the data for the duration of the request.
+ See https://github.com/Pylons/pyramid/pull/3561
+
+- Exposed ``pyramid.authorization.ALL_PERMISSIONS`` and
+ ``pyramid.authorization.DENY_ALL`` such that all of the ACL-related constants
+ are now importable from the ``pyramid.authorization`` namespace.
+ See https://github.com/Pylons/pyramid/pull/3563
+
+- ``pserve`` now outputs verbose messaging to `stderr` instead of `stdout`
+ to circumvent buffering issues that exist by default on `stdout`.
+ See https://github.com/Pylons/pyramid/pull/3593
+
+Deprecations
+------------
+
+- Deprecated the authentication and authorization interfaces and
+ principal-based support. See "Upgrading Authentication/Authorization" in
+ the "What's New in Pyramid 2.0" chapter of the documentation for information
+ on equivalent APIs and notes on upgrading. The following APIs are deprecated
+ as a result of this change:
+
+ - ``pyramid.config.Configurator.set_authentication_policy``
+ - ``pyramid.config.Configurator.set_authorization_policy``
+ - ``pyramid.interfaces.IAuthenticationPolicy``
+ - ``pyramid.interfaces.IAuthorizationPolicy``
+ - ``pyramid.request.Request.effective_principals``
+ - ``pyramid.request.Request.unauthenticated_userid``
+ - ``pyramid.authentication.AuthTktAuthenticationPolicy``
+ - ``pyramid.authentication.RemoteUserAuthenticationPolicy``
+ - ``pyramid.authentication.RepozeWho1AuthenticationPolicy``
+ - ``pyramid.authentication.SessionAuthenticationPolicy``
+ - ``pyramid.authentication.BasicAuthAuthenticationPolicy``
+ - ``pyramid.authorization.ACLAuthorizationPolicy``
+ - The ``effective_principals`` view and route predicates.
+
+ See https://github.com/Pylons/pyramid/pull/3465
+
+- Deprecated ``pyramid.security.principals_allowed_by_permission``. This
+ method continues to work with the deprecated
+ ``pyramid.interfaces.IAuthorizationPolicy`` interface but will not work with
+ the new ``pyramid.interfaces.ISecurityPolicy``.
+ See https://github.com/Pylons/pyramid/pull/3465
+
+- Deprecated several ACL-related aspects of ``pyramid.security``. Equivalent
+ objects should now be imported from the ``pyramid.authorization`` namespace.
+ This includes:
+
+ - ``pyramid.security.Everyone``
+ - ``pyramid.security.Authenticated``
+ - ``pyramid.security.ALL_PERMISSIONS``
+ - ``pyramid.security.DENY_ALL``
+ - ``pyramid.security.ACLAllowed``
+ - ``pyramid.security.ACLDenied``
+
+ See https://github.com/Pylons/pyramid/pull/3563
+
+- Deprecated ``pyramid.session.PickleSerializer``.
+ See https://github.com/pylons/pyramid/issues/2709,
+ and https://github.com/pylons/pyramid/pull/3353,
+ and https://github.com/pylons/pyramid/pull/3413
+
+Backward Incompatibilities
+--------------------------
+
+- Drop support for Python 2.7, 3.4, and 3.5.
+ See https://github.com/Pylons/pyramid/pull/3421,
+ and https://github.com/Pylons/pyramid/pull/3547,
+ and https://github.com/Pylons/pyramid/pull/3634
+
+- Removed the ``pyramid.compat`` module. Integrators should use the ``six``
+ module or vendor shims they are using into their own codebases going forward.
+ https://github.com/Pylons/pyramid/pull/3421
+
+- ``pcreate`` and the builtin scaffolds have been removed in favor of
+ using the ``cookiecutter`` tool and the ``pyramid-cookiecutter-starter``
+ cookiecutter. The script and scaffolds were deprecated in Pyramid 1.8.
+ See https://github.com/Pylons/pyramid/pull/3406
+
+- Changed the default ``hashalg`` on
+ ``pyramid.authentication.AuthTktCookieHelper`` to ``sha512``.
+ See https://github.com/Pylons/pyramid/pull/3557
+
+- Removed ``pyramid.interfaces.ITemplateRenderer``. This interface was
+ deprecated since Pyramid 1.5 and was an interface
+ used by libraries like ``pyramid_mako`` and ``pyramid_chameleon`` but
+ provided no functionality within Pyramid itself.
+ See https://github.com/Pylons/pyramid/pull/3409
+
+- Removed ``pyramid.security.has_permission``,
+ ``pyramid.security.authenticated_userid``,
+ ``pyramid.security.unauthenticated_userid``, and
+ ``pyramid.security.effective_principals``. These methods were deprecated
+ in Pyramid 1.5 and all have equivalents available as properties on the
+ request. For example, ``request.authenticated_userid``.
+ See https://github.com/Pylons/pyramid/pull/3410
+
+- Removed support for supplying a media range to the ``accept`` predicate of
+ both ``pyramid.config.Configurator.add_view`` and
+ ``pyramid.config.Configurator.add_route``. These options were deprecated
+ in Pyramid 1.10 and WebOb 1.8 because they resulted in uncontrollable
+ matching that was not compliant with the RFC.
+ See https://github.com/Pylons/pyramid/pull/3411
+
+- Removed ``pyramid.session.UnencryptedCookieSessionFactoryConfig``. This
+ session factory was replaced with
+ ``pyramid.session.SignedCookieSessionFactory`` in Pyramid 1.5 and has been
+ deprecated since then.
+ See https://github.com/Pylons/pyramid/pull/3412
+
+- Removed ``pyramid.session.signed_serialize``, and
+ ``pyramid.session.signed_deserialize``. These methods were only used by
+ the now-removed ``pyramid.session.UnencryptedCookieSessionFactoryConfig``
+ and were coupled to the vulnerable pickle serialization format which could
+ lead to remove code execution if the secret key is compromised.
+ See https://github.com/Pylons/pyramid/pull/3412
+
+- Changed the default ``serializer`` on
+ ``pyramid.session.SignedCookieSessionFactory`` to use
+ ``pyramid.session.JSONSerializer`` instead of
+ ``pyramid.session.PickleSerializer``. Read "Upgrading Session Serialization"
+ in the "What's New in Pyramid 2.0" chapter of the documentation for more
+ information about why this change was made.
+ See https://github.com/Pylons/pyramid/pull/3413
+
+- ``pyramid.request.Request.invoke_exception_view`` will no longer be called
+ by the default execution policy.
+ See https://github.com/Pylons/pyramid/pull/3496
+
+- ``pyramid.config.Configurator.scan`` will no longer, by default, execute
+ Venusian decorator callbacks registered for categories other than
+ ``'pyramid'``. To find any decorator regardless of category, specify
+ ``config.scan(..., categories=None)``.
+ See https://github.com/Pylons/pyramid/pull/3510
+
+- The second argument to predicate factories has been changed from ``config``
+ to ``info``, an instance of ``pyramid.interfaces.IPredicateInfo``. This
+ limits the data available to predicates but still provides the package,
+ registry, settings and dotted-name resolver which should cover most use
+ cases and is largely backward compatible.
+ See https://github.com/Pylons/pyramid/pull/3514
+
+- Removed the ``check_csrf`` predicate. Instead, use
+ ``pyramid.config.Configurator.set_default_csrf_options`` and the
+ ``require_csrf`` view option to enable automatic CSRF checking.
+ See https://github.com/Pylons/pyramid/pull/3521
+
+- Update the default behavior of
+ ``pyramid.authenticationAuthTktAuthenticationPolicy`` and
+ ``pyramid.authentication.AuthTktCookieHelper`` to only set a single cookie
+ without a domain parameter when no other domain constraints are specified.
+ Prior to this change, ``wild_domain=False`` (the default) was effectively
+ treated the same as ``wild_domain=True``, in which a cookie was defined
+ such that browsers would use it both for the request's domain, as well as
+ any subdomain. In the new behavior, cookies will only affect the current
+ domain, and not subdomains, by default.
+ See https://github.com/Pylons/pyramid/pull/3587
+
+Documentation Changes
+---------------------
+
+- Restore build of PDF on Read The Docs.
+ See https://github.com/Pylons/pyramid/issues/3290
+
+- Fix docs build for Sphinx 2.0.
+ See https://github.com/Pylons/pyramid/pull/3480
+
+- Significant updates to the wiki, wiki2 tutorials to demonstrate the new
+ security policy usage as well as a much more production-ready test harness.
+ See https://github.com/Pylons/pyramid/pull/3557
+
1.10 (2018-10-31)
=================
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 534b399c6..75dbfb86b 100644
--- a/contributing.md
+++ b/contributing.md
@@ -6,23 +6,17 @@ 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
Git branches and their purpose and status at the time of this writing are listed below.
-* [master](https://github.com/Pylons/pyramid/) - The branch on which further
- development takes place. The default branch on GitHub.
-* [2.0-branch](https://github.com/Pylons/pyramid/tree/2.0-branch) - The branch
- classified as "alpha".
-* [1.10-branch](https://github.com/Pylons/pyramid/tree/1.10-branch) - The branch
- classified as "stable" or "latest".
-* [1.9-branch](https://github.com/Pylons/pyramid/tree/1.9-branch) - The oldest
- actively maintained and stable branch.
-
-Older branches are not actively maintained. In general, two stable branches and
-one or two development branches are actively maintained.
+* [master](https://github.com/Pylons/pyramid/) - The branch on which further development takes place. The default branch on GitHub.
+* [2.0-branch](https://github.com/Pylons/pyramid/tree/2.0-branch) - The branch classified as "stable" or "latest".
+* [1.10-branch](https://github.com/Pylons/pyramid/tree/1.10-branch) - The oldest actively maintained and stable branch.
+
+Older branches are not actively maintained. In general, two stable branches and one or two development branches are actively maintained.
## Developing
diff --git a/docs/conf.py b/docs/conf.py
index a03c61ec7..95b3193c5 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -142,6 +142,7 @@ if book:
# 'whatsnew-1.8': 'index',
# 'whatsnew-1.9': 'index',
# 'whatsnew-1.10': 'index',
+# 'whatsnew-2.0': 'index',
# 'tutorials/gae/index': 'index',
# 'api/chameleon_text': 'api',
# 'api/chameleon_zpt': 'api',
@@ -450,5 +451,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/paste.rst b/docs/narr/paste.rst
index e198176d4..d579c7625 100644
--- a/docs/narr/paste.rst
+++ b/docs/narr/paste.rst
@@ -68,8 +68,8 @@ path, which refers to a callable in our ``myproject`` package's ``__init__.py``
module.
The ``egg:`` prefix in ``egg:myproject`` indicates that this is an entry point
-*URI* specifier, where the "scheme" is "egg". An "egg" is created when you run
-``setup.py install`` or ``setup.py develop`` within your project.
+*URI* specifier, where the "scheme" is "egg".
+An "egg" is created when you install your project.
In English, this entry point can thus be referred to as a "PasteDeploy
application factory in the ``myproject`` project which has the entry point
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/narr/urldispatch.rst b/docs/narr/urldispatch.rst
index 684e64395..99d4804db 100644
--- a/docs/narr/urldispatch.rst
+++ b/docs/narr/urldispatch.rst
@@ -1109,7 +1109,7 @@ See this code:
class AnyOfPredicate:
def __init__(self, val, info):
self.segment_name = val[0]
- self.allowed = tuple(val[0:])
+ self.allowed = tuple(val[1:])
def text(self):
args = (self.segment_name,) + self.allowed
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/setup.py b/setup.py
index c3860e0e9..33ee30719 100644
--- a/setup.py
+++ b/setup.py
@@ -22,7 +22,7 @@ def readfile(name):
README = readfile('README.rst')
CHANGES = readfile('CHANGES.rst')
-VERSION = '2.0b1'
+VERSION = '2.1.dev0'
install_requires = [
'hupper >= 1.5', # ignore_files support
@@ -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/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/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/httpexceptions.py b/src/pyramid/httpexceptions.py
index 9fd5f7d55..4e2b0ee1b 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__(
@@ -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..9a7c9af0e 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
@@ -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_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/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