diff options
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> @@ -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' @@ -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 |
