diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b3a22fcc2a..a5b65930821 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,7 @@ jobs: - name: Install Python uses: actions/setup-python@v4 with: - python-version: '3.8' + python-version: '3.11' - name: Cache the .tox dir uses: actions/cache@v3 with: @@ -47,7 +47,7 @@ jobs: - name: Install Python uses: actions/setup-python@v4 with: - python-version: '3.8' + python-version: '3.11' - name: Cache the .tox dir uses: actions/cache@v3 with: @@ -82,7 +82,7 @@ jobs: - name: Install Python uses: actions/setup-python@v4 with: - python-version: '3.8' + python-version: '3.11' - name: Cache the .tox dir uses: actions/cache@v3 with: @@ -109,7 +109,7 @@ jobs: - name: Install Python uses: actions/setup-python@v4 with: - python-version: '3.8' + python-version: '3.11' - name: Cache the .tox dir uses: actions/cache@v3 with: @@ -152,7 +152,7 @@ jobs: - name: Install Python uses: actions/setup-python@v4 with: - python-version: '3.8' + python-version: '3.11' - name: Cache the .tox dir uses: actions/cache@v3 with: diff --git a/.python-version b/.python-version index 89a1ad7ad3c..d4b278f0a7d 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.8.12 +3.11.7 diff --git a/Dockerfile b/Dockerfile index 213910faf00..8ff374cd2f7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,7 @@ COPY h/static ./h/static RUN yarn build # Stage 2: Build the rest of the app using the build output from Stage 1. -FROM python:3.8.12-alpine3.13 +FROM python:3.11.7-alpine3.19 LABEL maintainer="Hypothes.is Project and contributors" # Install system build and runtime dependencies. diff --git a/h/accounts/schemas.py b/h/accounts/schemas.py index 5d75d3fb11e..81d74aa6d44 100644 --- a/h/accounts/schemas.py +++ b/h/accounts/schemas.py @@ -4,7 +4,7 @@ import colander import deform -from jinja2 import Markup +from markupsafe import Markup from h import i18n, models from h.models.user import ( diff --git a/h/form.py b/h/form.py index 6b47aa7fdb1..016f3d448ac 100644 --- a/h/form.py +++ b/h/form.py @@ -5,8 +5,8 @@ form templates in preference to the defaults. """ import deform -import jinja2 import pyramid_jinja2 +from markupsafe import Markup from pyramid import httpexceptions from pyramid.path import AssetResolver @@ -45,7 +45,7 @@ def __call__(self, template_name, **kwargs): context = self._system.copy() context.update(kwargs) - return jinja2.Markup(template.render(context)) + return Markup(template.render(context)) def create_environment(base): diff --git a/h/presenters/annotation_html.py b/h/presenters/annotation_html.py index 9bd38c286e8..0309fa9f5a5 100644 --- a/h/presenters/annotation_html.py +++ b/h/presenters/annotation_html.py @@ -1,5 +1,5 @@ -import jinja2 from dateutil import parser +from markupsafe import Markup, escape from h.presenters.document_html import DocumentHTMLPresenter @@ -16,7 +16,7 @@ def __init__(self, annotation): @property def uri(self): - return jinja2.escape(self.annotation.target_uri) + return escape(self.annotation.target_uri) @property def text_rendered(self): @@ -28,15 +28,15 @@ def text_rendered(self): care of all necessary escaping. """ if self.annotation.text_rendered: - return jinja2.Markup(self.annotation.text_rendered) - return jinja2.Markup("") + return Markup(self.annotation.text_rendered) + return Markup("") @property def quote(self): """Get the text in the document which this annotation refers to.""" selection = self._get_selection() if selection: - return jinja2.escape(selection) + return escape(selection) return "" @@ -55,12 +55,12 @@ def description(self): selection = self._get_selection() if selection: - selection = jinja2.escape(selection) + selection = escape(selection) description += f"<blockquote>{selection}</blockquote>" text = self.annotation.text if text: - text = jinja2.escape(text) + text = escape(text) description += f"{text}" return description @@ -74,7 +74,7 @@ def created_day_string(self): date. """ - created_string = jinja2.escape(self.annotation.created) + created_string = escape(self.annotation.created) return parser.parse(created_string).strftime("%Y-%m-%d") @property diff --git a/h/presenters/document_html.py b/h/presenters/document_html.py index f6864d27805..fd8f1ec0074 100644 --- a/h/presenters/document_html.py +++ b/h/presenters/document_html.py @@ -1,6 +1,6 @@ from urllib.parse import unquote, urlparse -import jinja2 +import markupsafe class DocumentHTMLPresenter: @@ -24,7 +24,7 @@ def filename(self): """ if self.uri.lower().startswith("file:///"): - return jinja2.escape(self.uri.split("/")[-1]) + return markupsafe.escape(self.uri.split("/")[-1]) return "" @property @@ -44,7 +44,7 @@ def href(self): """ if self.document.web_uri: - return jinja2.escape(self.document.web_uri) + return markupsafe.escape(self.document.web_uri) return "" @property @@ -64,14 +64,14 @@ def hostname_or_filename(self): object so that it doesn't get double-escaped. """ if self.filename: - return jinja2.escape(unquote(self.filename)) + return markupsafe.escape(unquote(self.filename)) hostname = urlparse(self.uri).hostname # urlparse()'s .hostname is sometimes None. hostname = hostname or "" - return jinja2.escape(hostname) + return markupsafe.escape(hostname) @property def link(self): @@ -129,7 +129,7 @@ def link_text(self): Markup object so it doesn't get double-escaped. """ - title = jinja2.escape(self.title) + title = markupsafe.escape(self.title) # Sometimes self.title is the annotated document's URI (if the document # has no title). In those cases we want to remove the http(s):// from @@ -160,17 +160,17 @@ def title(self): # Convert non-string titles into strings. # We're assuming that title cannot be a byte string. title = str(title) - return jinja2.escape(title) + return markupsafe.escape(title) if self.filename: - return jinja2.escape(unquote(self.filename)) + return markupsafe.escape(unquote(self.filename)) - return jinja2.escape(unquote(self.uri)) + return markupsafe.escape(unquote(self.uri)) @property def uri(self): if self.document.document_uris: - return jinja2.escape(self.document.document_uris[0].uri) + return markupsafe.escape(self.document.document_uris[0].uri) return "" @property @@ -205,7 +205,7 @@ def truncate(content, length=55): if len(content) <= length: return content - return content[:length] + jinja2.Markup("…") + return content[:length] + markupsafe.Markup("…") host_or_filename = truncate(host_or_filename) link_text = truncate(link_text) @@ -220,10 +220,10 @@ def truncate(content, length=55): link += "
{host_or_filename}" link = link.format( - href=jinja2.escape(href), - title=jinja2.escape(title), - link_text=jinja2.escape(link_text), - host_or_filename=jinja2.escape(host_or_filename), + href=markupsafe.escape(href), + title=markupsafe.escape(title), + link_text=markupsafe.escape(link_text), + host_or_filename=markupsafe.escape(host_or_filename), ) - return jinja2.Markup(link) + return markupsafe.Markup(link) diff --git a/h/views/accounts.py b/h/views/accounts.py index 5d3abfbf1e2..b368c3c5463 100644 --- a/h/views/accounts.py +++ b/h/views/accounts.py @@ -4,7 +4,7 @@ import colander import deform -import jinja2 +from markupsafe import Markup from pyramid import httpexceptions, security from pyramid.exceptions import BadCSRFToken from pyramid.view import view_config, view_defaults @@ -285,7 +285,7 @@ def _reset_password(self, user, password): svc.update_password(user, password) self.request.session.flash( - jinja2.Markup( + Markup( _( "Your password has been reset. You can now log in with " "your new password." @@ -321,7 +321,7 @@ def get_when_not_logged_in(self): activation = models.Activation.get_by_code(self.request.db, code) if activation is None: self.request.session.flash( - jinja2.Markup( + Markup( _( "We didn't recognize that activation link. " "Have you already activated your account? " @@ -340,7 +340,7 @@ def get_when_not_logged_in(self): user.activate() self.request.session.flash( - jinja2.Markup( + Markup( _( "Your account has been activated! " "You can now log in using the password you provided." @@ -369,14 +369,12 @@ def get_when_logged_in(self): # The user is already logged in to the account (so the account # must already be activated). self.request.session.flash( - jinja2.Markup( - _("Your account has been activated and you're logged in.") - ), + Markup(_("Your account has been activated and you're logged in.")), "success", ) else: self.request.session.flash( - jinja2.Markup( + Markup( _( "You're already logged in to a different account. " 'Log out and open the activation link ' diff --git a/h/views/activity.py b/h/views/activity.py index 0041bd5d5e8..6ad5e426f6d 100644 --- a/h/views/activity.py +++ b/h/views/activity.py @@ -2,7 +2,7 @@ from urllib.parse import urlparse -from jinja2 import Markup +from markupsafe import Markup from pyramid import httpexceptions from pyramid.view import view_config, view_defaults diff --git a/h/views/admin/groups.py b/h/views/admin/groups.py index e1a0c18b32e..f8719d94339 100644 --- a/h/views/admin/groups.py +++ b/h/views/admin/groups.py @@ -1,4 +1,4 @@ -from jinja2 import Markup +from markupsafe import Markup from pyramid.httpexceptions import HTTPFound from pyramid.view import view_config, view_defaults diff --git a/h/views/admin/organizations.py b/h/views/admin/organizations.py index 8217e1098fa..07c292e6496 100644 --- a/h/views/admin/organizations.py +++ b/h/views/admin/organizations.py @@ -1,4 +1,4 @@ -from jinja2 import Markup +from markupsafe import Markup from pyramid.httpexceptions import HTTPFound from pyramid.view import view_config, view_defaults from sqlalchemy import func diff --git a/h/views/admin/users.py b/h/views/admin/users.py index 91fe83d956e..08ddd8eb161 100644 --- a/h/views/admin/users.py +++ b/h/views/admin/users.py @@ -1,4 +1,4 @@ -import jinja2 +from markupsafe import Markup from pyramid import httpexceptions from pyramid.view import view_config @@ -70,7 +70,7 @@ def users_activate(request): request.session.flash( # pylint:disable=consider-using-f-string - jinja2.Markup(_("User {name} has been activated!".format(name=user.username))), + Markup(_("User {name} has been activated!".format(name=user.username))), "success", ) @@ -145,7 +145,7 @@ def users_delete(request): @view_config(context=UserNotFoundError) def user_not_found(exc, request): # pragma: no cover - request.session.flash(jinja2.Markup(_(exc.message)), "error") + request.session.flash(Markup(_(exc.message)), "error") return httpexceptions.HTTPFound(location=request.route_path("admin.users")) diff --git a/requirements/checkdocs.txt b/requirements/checkdocs.txt index 304230e460f..fc07073a116 100644 --- a/requirements/checkdocs.txt +++ b/requirements/checkdocs.txt @@ -1,10 +1,10 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile requirements/checkdocs.in # -alabaster==0.7.13 +alabaster==0.7.16 # via sphinx babel==2.14.0 # via sphinx @@ -27,15 +27,12 @@ idna==3.6 imagesize==1.4.1 # via sphinx importlib-metadata==7.0.1 - # via - # build - # pip-sync-faster - # sphinx + # via pip-sync-faster jinja2==3.1.3 # via sphinx livereload==2.6.3 # via sphinx-autobuild -markupsafe==2.0.1 +markupsafe==2.1.3 # via jinja2 packaging==23.2 # via @@ -51,43 +48,41 @@ pygments==2.17.2 # via sphinx pyproject-hooks==1.0.0 # via build -pytz==2023.3.post1 - # via babel requests==2.31.0 # via sphinx six==1.16.0 # via livereload snowballstemmer==2.2.0 # via sphinx -sphinx==7.1.2 +sphinx==7.2.6 # via # -r requirements/checkdocs.in # sphinx-autobuild # sphinx-rtd-theme + # sphinxcontrib-applehelp + # sphinxcontrib-devhelp + # sphinxcontrib-htmlhelp # sphinxcontrib-jquery + # sphinxcontrib-qthelp + # sphinxcontrib-serializinghtml sphinx-autobuild==2021.3.14 # via -r requirements/checkdocs.in sphinx-rtd-theme==2.0.0 # via -r requirements/checkdocs.in -sphinxcontrib-applehelp==1.0.4 +sphinxcontrib-applehelp==1.0.7 # via sphinx -sphinxcontrib-devhelp==1.0.2 +sphinxcontrib-devhelp==1.0.5 # via sphinx -sphinxcontrib-htmlhelp==2.0.1 +sphinxcontrib-htmlhelp==2.0.4 # via sphinx sphinxcontrib-jquery==4.1 # via sphinx-rtd-theme sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.3 +sphinxcontrib-qthelp==1.0.6 # via sphinx -sphinxcontrib-serializinghtml==1.1.5 +sphinxcontrib-serializinghtml==1.1.9 # via sphinx -tomli==2.0.1 - # via - # build - # pip-tools - # pyproject-hooks tornado==6.4 # via livereload urllib3==2.1.0 diff --git a/requirements/checkformatting.txt b/requirements/checkformatting.txt index 1b0f87bcd29..ccfac48215b 100644 --- a/requirements/checkformatting.txt +++ b/requirements/checkformatting.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile requirements/checkformatting.in @@ -13,9 +13,7 @@ click==8.1.7 # black # pip-tools importlib-metadata==7.0.1 - # via - # build - # pip-sync-faster + # via pip-sync-faster isort==5.13.2 # via -r requirements/checkformatting.in mypy-extensions==1.0.0 @@ -36,14 +34,6 @@ platformdirs==4.1.0 # via black pyproject-hooks==1.0.0 # via build -tomli==2.0.1 - # via - # black - # build - # pip-tools - # pyproject-hooks -typing-extensions==4.9.0 - # via black wheel==0.42.0 # via pip-tools zipp==3.17.0 diff --git a/requirements/coverage.txt b/requirements/coverage.txt index 50eb288ed34..ad907c2bd0c 100644 --- a/requirements/coverage.txt +++ b/requirements/coverage.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile requirements/coverage.in @@ -11,9 +11,7 @@ click==8.1.7 coverage==7.4.0 # via -r requirements/coverage.in importlib-metadata==7.0.1 - # via - # build - # pip-sync-faster + # via pip-sync-faster packaging==23.2 # via build pip-sync-faster==0.0.3 @@ -24,11 +22,6 @@ pip-tools==7.3.0 # pip-sync-faster pyproject-hooks==1.0.0 # via build -tomli==2.0.1 - # via - # build - # pip-tools - # pyproject-hooks wheel==0.42.0 # via pip-tools zipp==3.17.0 diff --git a/requirements/dev.txt b/requirements/dev.txt index 6acd6be9c2e..417b966d188 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile requirements/dev.in @@ -17,14 +17,6 @@ attrs==23.2.0 # -r requirements/prod.txt # jsonschema # referencing -backcall==0.2.0 - # via ipython -backports-zoneinfo[tzdata]==0.2.1 - # via - # -r requirements/prod.txt - # backports-zoneinfo - # celery - # kombu bcrypt==4.1.2 # via -r requirements/prod.txt billiard==4.2.0 @@ -125,26 +117,18 @@ hupper==1.12 importlib-metadata==7.0.1 # via # -r requirements/prod.txt - # alembic - # build - # chameleon # data-tasks # h-api # h-assets - # markdown # pip-sync-faster importlib-resources==6.1.1 # via # -r requirements/prod.txt - # alembic - # chameleon # data-tasks # h-api - # jsonschema - # jsonschema-specifications ipdb==0.13.13 # via -r requirements/dev.in -ipython==8.12.3 +ipython==8.20.0 # via # ipdb # pyramid-ipython @@ -157,7 +141,7 @@ itsdangerous==2.1.2 # via -r requirements/prod.txt jedi==0.19.1 # via ipython -jinja2==2.11.3 +jinja2==3.1.3 # via # -r requirements/prod.txt # data-tasks @@ -180,7 +164,7 @@ mako==1.3.0 # alembic markdown==3.5.2 # via -r requirements/prod.txt -markupsafe==1.1.1 +markupsafe==2.1.3 # via # -r requirements/prod.txt # jinja2 @@ -212,18 +196,12 @@ peppercorn==0.6 # deform pexpect==4.9.0 # via ipython -pickleshare==0.7.5 - # via ipython pip-sync-faster==0.0.3 # via -r requirements/dev.in pip-tools==7.3.0 # via # -r requirements/dev.in # pip-sync-faster -pkgutil-resolve-name==1.3.10 - # via - # -r requirements/prod.txt - # jsonschema plaster==1.1.2 # via # -r requirements/prod.txt @@ -366,12 +344,6 @@ text-unidecode==1.3 # via # -r requirements/prod.txt # python-slugify -tomli==2.0.1 - # via - # build - # ipdb - # pip-tools - # pyproject-hooks traitlets==5.14.1 # via # ipython @@ -393,13 +365,9 @@ typing-extensions==4.9.0 # via # -r requirements/prod.txt # alembic - # faker - # ipython - # kombu tzdata==2023.4 # via # -r requirements/prod.txt - # backports-zoneinfo # celery urllib3==2.1.0 # via @@ -442,7 +410,6 @@ zipp==3.17.0 # via # -r requirements/prod.txt # importlib-metadata - # importlib-resources zope-deprecation==5.0 # via # -r requirements/prod.txt diff --git a/requirements/docs.txt b/requirements/docs.txt index 41a52a99123..b55bde8e118 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -1,10 +1,10 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile requirements/docs.in # -alabaster==0.7.13 +alabaster==0.7.16 # via sphinx babel==2.14.0 # via sphinx @@ -27,15 +27,12 @@ idna==3.6 imagesize==1.4.1 # via sphinx importlib-metadata==7.0.1 - # via - # build - # pip-sync-faster - # sphinx + # via pip-sync-faster jinja2==3.1.3 # via sphinx livereload==2.6.3 # via sphinx-autobuild -markupsafe==2.0.1 +markupsafe==2.1.3 # via jinja2 packaging==23.2 # via @@ -51,43 +48,41 @@ pygments==2.17.2 # via sphinx pyproject-hooks==1.0.0 # via build -pytz==2023.3.post1 - # via babel requests==2.31.0 # via sphinx six==1.16.0 # via livereload snowballstemmer==2.2.0 # via sphinx -sphinx==7.1.2 +sphinx==7.2.6 # via # -r requirements/docs.in # sphinx-autobuild # sphinx-rtd-theme + # sphinxcontrib-applehelp + # sphinxcontrib-devhelp + # sphinxcontrib-htmlhelp # sphinxcontrib-jquery + # sphinxcontrib-qthelp + # sphinxcontrib-serializinghtml sphinx-autobuild==2021.3.14 # via -r requirements/docs.in sphinx-rtd-theme==2.0.0 # via -r requirements/docs.in -sphinxcontrib-applehelp==1.0.4 +sphinxcontrib-applehelp==1.0.7 # via sphinx -sphinxcontrib-devhelp==1.0.2 +sphinxcontrib-devhelp==1.0.5 # via sphinx -sphinxcontrib-htmlhelp==2.0.1 +sphinxcontrib-htmlhelp==2.0.4 # via sphinx sphinxcontrib-jquery==4.1 # via sphinx-rtd-theme sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.3 +sphinxcontrib-qthelp==1.0.6 # via sphinx -sphinxcontrib-serializinghtml==1.1.5 +sphinxcontrib-serializinghtml==1.1.9 # via sphinx -tomli==2.0.1 - # via - # build - # pip-tools - # pyproject-hooks tornado==6.4 # via livereload urllib3==2.1.0 diff --git a/requirements/format.txt b/requirements/format.txt index f6bbd202a65..0cc48a38c28 100644 --- a/requirements/format.txt +++ b/requirements/format.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile requirements/format.in @@ -13,9 +13,7 @@ click==8.1.7 # black # pip-tools importlib-metadata==7.0.1 - # via - # build - # pip-sync-faster + # via pip-sync-faster isort==5.13.2 # via -r requirements/format.in mypy-extensions==1.0.0 @@ -36,14 +34,6 @@ platformdirs==4.1.0 # via black pyproject-hooks==1.0.0 # via build -tomli==2.0.1 - # via - # black - # build - # pip-tools - # pyproject-hooks -typing-extensions==4.9.0 - # via black wheel==0.42.0 # via pip-tools zipp==3.17.0 diff --git a/requirements/functests.txt b/requirements/functests.txt index 50bff1ce6c2..c424b36ffbb 100644 --- a/requirements/functests.txt +++ b/requirements/functests.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile requirements/functests.in @@ -15,12 +15,6 @@ attrs==23.2.0 # -r requirements/prod.txt # jsonschema # referencing -backports-zoneinfo[tzdata]==0.2.1 - # via - # -r requirements/prod.txt - # backports-zoneinfo - # celery - # kombu bcrypt==4.1.2 # via -r requirements/prod.txt beautifulsoup4==4.12.2 @@ -89,8 +83,6 @@ elasticsearch==6.8.2 # elasticsearch-dsl elasticsearch-dsl==6.4.0 # via -r requirements/prod.txt -exceptiongroup==1.2.0 - # via pytest factory-boy==3.3.0 # via -r requirements/functests.in faker==22.2.0 @@ -119,23 +111,15 @@ hupper==1.12 importlib-metadata==7.0.1 # via # -r requirements/prod.txt - # alembic - # build - # chameleon # data-tasks # h-api # h-assets - # markdown # pip-sync-faster importlib-resources==6.1.1 # via # -r requirements/prod.txt - # alembic - # chameleon # data-tasks # h-api - # jsonschema - # jsonschema-specifications iniconfig==2.0.0 # via pytest iso8601==2.1.0 @@ -145,7 +129,7 @@ iso8601==2.1.0 # deform itsdangerous==2.1.2 # via -r requirements/prod.txt -jinja2==2.11.3 +jinja2==3.1.3 # via # -r requirements/prod.txt # data-tasks @@ -168,7 +152,7 @@ mako==1.3.0 # alembic markdown==3.5.2 # via -r requirements/prod.txt -markupsafe==1.1.1 +markupsafe==2.1.3 # via # -r requirements/prod.txt # jinja2 @@ -201,10 +185,6 @@ pip-tools==7.3.0 # via # -r requirements/functests.in # pip-sync-faster -pkgutil-resolve-name==1.3.10 - # via - # -r requirements/prod.txt - # jsonschema plaster==1.1.2 # via # -r requirements/prod.txt @@ -344,12 +324,6 @@ text-unidecode==1.3 # via # -r requirements/prod.txt # python-slugify -tomli==2.0.1 - # via - # build - # pip-tools - # pyproject-hooks - # pytest transaction==4.0 # via # -r requirements/prod.txt @@ -367,12 +341,9 @@ typing-extensions==4.9.0 # via # -r requirements/prod.txt # alembic - # faker - # kombu tzdata==2023.4 # via # -r requirements/prod.txt - # backports-zoneinfo # celery urllib3==2.1.0 # via @@ -420,7 +391,6 @@ zipp==3.17.0 # via # -r requirements/prod.txt # importlib-metadata - # importlib-resources zope-deprecation==5.0 # via # -r requirements/prod.txt diff --git a/requirements/lint.txt b/requirements/lint.txt index 0c61729e859..ca3b66b2143 100644 --- a/requirements/lint.txt +++ b/requirements/lint.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile requirements/lint.in @@ -22,13 +22,6 @@ attrs==23.2.0 # hypothesis # jsonschema # referencing -backports-zoneinfo[tzdata]==0.2.1 - # via - # -r requirements/functests.txt - # -r requirements/tests.txt - # backports-zoneinfo - # celery - # kombu bcrypt==4.1.2 # via # -r requirements/functests.txt @@ -133,12 +126,6 @@ elasticsearch-dsl==6.4.0 # via # -r requirements/functests.txt # -r requirements/tests.txt -exceptiongroup==1.2.0 - # via - # -r requirements/functests.txt - # -r requirements/tests.txt - # hypothesis - # pytest execnet==2.0.2 # via # -r requirements/tests.txt @@ -195,24 +182,16 @@ importlib-metadata==7.0.1 # via # -r requirements/functests.txt # -r requirements/tests.txt - # alembic - # build - # chameleon # data-tasks # h-api # h-assets - # markdown # pip-sync-faster importlib-resources==6.1.1 # via # -r requirements/functests.txt # -r requirements/tests.txt - # alembic - # chameleon # data-tasks # h-api - # jsonschema - # jsonschema-specifications iniconfig==2.0.0 # via # -r requirements/functests.txt @@ -230,7 +209,7 @@ itsdangerous==2.1.2 # via # -r requirements/functests.txt # -r requirements/tests.txt -jinja2==2.11.3 +jinja2==3.1.3 # via # -r requirements/functests.txt # -r requirements/tests.txt @@ -260,7 +239,7 @@ markdown==3.5.2 # via # -r requirements/functests.txt # -r requirements/tests.txt -markupsafe==1.1.1 +markupsafe==2.1.3 # via # -r requirements/functests.txt # -r requirements/tests.txt @@ -310,11 +289,6 @@ pip-tools==7.3.0 # -r requirements/lint.in # -r requirements/tests.txt # pip-sync-faster -pkgutil-resolve-name==1.3.10 - # via - # -r requirements/functests.txt - # -r requirements/tests.txt - # jsonschema plaster==1.1.2 # via # -r requirements/functests.txt @@ -539,16 +513,6 @@ text-unidecode==1.3 # -r requirements/functests.txt # -r requirements/tests.txt # python-slugify -tomli==2.0.1 - # via - # -r requirements/functests.txt - # -r requirements/tests.txt - # build - # coverage - # pip-tools - # pylint - # pyproject-hooks - # pytest tomlkit==0.12.3 # via pylint transaction==4.0 @@ -571,15 +535,10 @@ typing-extensions==4.9.0 # -r requirements/functests.txt # -r requirements/tests.txt # alembic - # astroid - # faker - # kombu - # pylint tzdata==2023.4 # via # -r requirements/functests.txt # -r requirements/tests.txt - # backports-zoneinfo # celery urllib3==2.1.0 # via @@ -644,7 +603,6 @@ zipp==3.17.0 # -r requirements/functests.txt # -r requirements/tests.txt # importlib-metadata - # importlib-resources zope-deprecation==5.0 # via # -r requirements/functests.txt diff --git a/requirements/prod.in b/requirements/prod.in index 1854bfb1c3e..4b48841caee 100644 --- a/requirements/prod.in +++ b/requirements/prod.in @@ -37,8 +37,8 @@ pycryptodomex pyparsing >= 2.1.5 pyramid pyramid-exclog -markupsafe==1.1.1 -jinja2 < 3 +markupsafe +jinja2 pyramid-jinja2 pyramid-services pyramid-mailer diff --git a/requirements/prod.txt b/requirements/prod.txt index fa34fbfa523..cb4832354bc 100644 --- a/requirements/prod.txt +++ b/requirements/prod.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile requirements/prod.in @@ -12,10 +12,6 @@ attrs==23.2.0 # via # jsonschema # referencing -backports-zoneinfo[tzdata]==0.2.1 - # via - # celery - # kombu bcrypt==4.1.2 # via -r requirements/prod.in billiard==4.2.0 @@ -83,28 +79,21 @@ hupper==1.12 # via pyramid importlib-metadata==7.0.1 # via - # alembic - # chameleon # data-tasks # h-api # h-assets - # markdown importlib-resources==6.1.1 # via # -r requirements/prod.in - # alembic - # chameleon # data-tasks # h-api - # jsonschema - # jsonschema-specifications iso8601==2.1.0 # via # colander # deform itsdangerous==2.1.2 # via -r requirements/prod.in -jinja2==2.11.3 +jinja2==3.1.3 # via # -r requirements/prod.in # data-tasks @@ -123,7 +112,7 @@ mako==1.3.0 # via alembic markdown==3.5.2 # via -r requirements/prod.in -markupsafe==1.1.1 +markupsafe==2.1.3 # via # -r requirements/prod.in # jinja2 @@ -144,8 +133,6 @@ pastedeploy==3.1.0 # via plaster-pastedeploy peppercorn==0.6 # via deform -pkgutil-resolve-name==1.3.10 - # via jsonschema plaster==1.1.2 # via # plaster-pastedeploy @@ -264,13 +251,9 @@ translationstring==1.4 # deform # pyramid typing-extensions==4.9.0 - # via - # alembic - # kombu + # via alembic tzdata==2023.4 - # via - # backports-zoneinfo - # celery + # via celery urllib3==2.1.0 # via # elasticsearch @@ -297,9 +280,7 @@ ws4py==0.5.1 wsaccel==0.6.6 # via -r requirements/prod.in zipp==3.17.0 - # via - # importlib-metadata - # importlib-resources + # via importlib-metadata zope-deprecation==5.0 # via # deform diff --git a/requirements/tests.txt b/requirements/tests.txt index 38f81fe8a6e..d91646f1ece 100644 --- a/requirements/tests.txt +++ b/requirements/tests.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile requirements/tests.in @@ -16,12 +16,6 @@ attrs==23.2.0 # hypothesis # jsonschema # referencing -backports-zoneinfo[tzdata]==0.2.1 - # via - # -r requirements/prod.txt - # backports-zoneinfo - # celery - # kombu bcrypt==4.1.2 # via -r requirements/prod.txt billiard==4.2.0 @@ -92,10 +86,6 @@ elasticsearch==6.8.2 # elasticsearch-dsl elasticsearch-dsl==6.4.0 # via -r requirements/prod.txt -exceptiongroup==1.2.0 - # via - # hypothesis - # pytest execnet==2.0.2 # via pytest-xdist factory-boy==3.3.0 @@ -130,23 +120,15 @@ hypothesis==6.92.9 importlib-metadata==7.0.1 # via # -r requirements/prod.txt - # alembic - # build - # chameleon # data-tasks # h-api # h-assets - # markdown # pip-sync-faster importlib-resources==6.1.1 # via # -r requirements/prod.txt - # alembic - # chameleon # data-tasks # h-api - # jsonschema - # jsonschema-specifications iniconfig==2.0.0 # via pytest iso8601==2.1.0 @@ -156,7 +138,7 @@ iso8601==2.1.0 # deform itsdangerous==2.1.2 # via -r requirements/prod.txt -jinja2==2.11.3 +jinja2==3.1.3 # via # -r requirements/prod.txt # data-tasks @@ -179,7 +161,7 @@ mako==1.3.0 # alembic markdown==3.5.2 # via -r requirements/prod.txt -markupsafe==1.1.1 +markupsafe==2.1.3 # via # -r requirements/prod.txt # jinja2 @@ -212,10 +194,6 @@ pip-tools==7.3.0 # via # -r requirements/tests.in # pip-sync-faster -pkgutil-resolve-name==1.3.10 - # via - # -r requirements/prod.txt - # jsonschema plaster==1.1.2 # via # -r requirements/prod.txt @@ -361,13 +339,6 @@ text-unidecode==1.3 # via # -r requirements/prod.txt # python-slugify -tomli==2.0.1 - # via - # build - # coverage - # pip-tools - # pyproject-hooks - # pytest transaction==4.0 # via # -r requirements/prod.txt @@ -385,12 +356,9 @@ typing-extensions==4.9.0 # via # -r requirements/prod.txt # alembic - # faker - # kombu tzdata==2023.4 # via # -r requirements/prod.txt - # backports-zoneinfo # celery urllib3==2.1.0 # via @@ -433,7 +401,6 @@ zipp==3.17.0 # via # -r requirements/prod.txt # importlib-metadata - # importlib-resources zope-deprecation==5.0 # via # -r requirements/prod.txt diff --git a/tests/unit/h/models/group_test.py b/tests/unit/h/models/group_test.py index 3709722a6a6..4f79aba4ceb 100644 --- a/tests/unit/h/models/group_test.py +++ b/tests/unit/h/models/group_test.py @@ -156,7 +156,7 @@ def test_type_raises_for_unknown_type_of_group(factories): def test_you_cannot_set_type(factories): group = factories.Group() - with pytest.raises(AttributeError, match="can't set attribute"): + with pytest.raises(AttributeError, match="object has no setter"): group.type = "open" diff --git a/tests/unit/h/models/subscriptions_test.py b/tests/unit/h/models/subscriptions_test.py index a6194d8ef45..17b82893a23 100644 --- a/tests/unit/h/models/subscriptions_test.py +++ b/tests/unit/h/models/subscriptions_test.py @@ -9,5 +9,5 @@ def test___repr__(self): assert ( repr(subscription) - == "" + == "" ) diff --git a/tests/unit/h/presenters/annotation_html_test.py b/tests/unit/h/presenters/annotation_html_test.py index d3abbe45ae3..e31e7a2ad52 100644 --- a/tests/unit/h/presenters/annotation_html_test.py +++ b/tests/unit/h/presenters/annotation_html_test.py @@ -1,7 +1,7 @@ import datetime import pytest -from jinja2 import Markup +from markupsafe import Markup from h.presenters.annotation_html import AnnotationHTMLPresenter diff --git a/tests/unit/h/presenters/document_html_test.py b/tests/unit/h/presenters/document_html_test.py index 38fbafc97ee..d107546155d 100644 --- a/tests/unit/h/presenters/document_html_test.py +++ b/tests/unit/h/presenters/document_html_test.py @@ -1,7 +1,7 @@ from unittest import mock -import jinja2 import pytest +from markupsafe import Markup, escape from h.presenters.document_html import DocumentHTMLPresenter @@ -26,7 +26,7 @@ def test_filename_returns_Markup(self): document_uris=[mock.Mock(uri="file:///home/seanh/MyFile.pdf")] ) - assert isinstance(presenter.filename, jinja2.Markup) + assert isinstance(presenter.filename, Markup) def test_filename_with_FILE_uri(self): presenter = self.presenter( @@ -65,7 +65,7 @@ def test_href_returns_empty_string_for_document_with_no_web_uri(self): def test_href_returns_Markup(self): web_uri = "http://www.example.com/example.html" - assert isinstance(self.presenter(web_uri=web_uri).href, jinja2.Markup) + assert isinstance(self.presenter(web_uri=web_uri).href, Markup) link_text_fixtures = pytest.mark.usefixtures("title") @@ -105,12 +105,12 @@ def test_link_text_with_https_title(self, title): @link_text_fixtures def test_link_text_returns_Markup_if_title_returns_Markup(self, title): for title_ in ( - jinja2.Markup("Example Document"), - jinja2.Markup("http://www.example.com/example.html"), - jinja2.Markup("https://www.example.com/example.html"), + Markup("Example Document"), + Markup("http://www.example.com/example.html"), + Markup("https://www.example.com/example.html"), ): title.return_value = title_ - assert isinstance(self.presenter().link_text, jinja2.Markup) + assert isinstance(self.presenter().link_text, Markup) hostname_or_filename_fixtures = pytest.mark.usefixtures("uri", "filename") @@ -122,9 +122,9 @@ def test_hostname_or_filename_returns_filename_for_files(self, filename): @hostname_or_filename_fixtures def test_hostname_or_filename_returns_Markup_if_filename_does(self, filename): - filename.return_value = jinja2.Markup("MyFile.pdf") + filename.return_value = Markup("MyFile.pdf") - assert isinstance(self.presenter().hostname_or_filename, jinja2.Markup) + assert isinstance(self.presenter().hostname_or_filename, Markup) @hostname_or_filename_fixtures def test_hostname_or_filename_unquotes_filenames(self, filename): @@ -142,9 +142,9 @@ def test_hostname_or_filename_returns_hostname_for_non_files(self, uri, filename @hostname_or_filename_fixtures def test_hostname_or_filename_returns_Markup_when_uri_does(self, uri, filename): filename.return_value = "" - uri.return_value = jinja2.Markup("http://www.example.com/example.html") + uri.return_value = Markup("http://www.example.com/example.html") - assert isinstance(self.presenter().hostname_or_filename, jinja2.Markup) + assert isinstance(self.presenter().hostname_or_filename, Markup) @hostname_or_filename_fixtures def test_hostname_or_filename_with_empty_string_for_uri(self, uri, filename): @@ -178,10 +178,10 @@ def test_title_escapes_html_in_document_titles(self): title = self.presenter(title=spam_link).title - assert jinja2.escape(spam_link) in title + assert escape(spam_link) in title for char in ["<", ">", '"', "'"]: assert char not in title - assert isinstance(title, jinja2.Markup) + assert isinstance(title, Markup) @title_fixtures def test_title_with_file_uri(self, filename): @@ -193,9 +193,9 @@ def test_title_with_file_uri(self, filename): @title_fixtures def test_title_returns_Markup_when_filename_returns_Markup(self, filename): - filename.return_value = jinja2.Markup("MyFile.pdf") + filename.return_value = Markup("MyFile.pdf") - assert isinstance(self.presenter(title=None).title, jinja2.Markup) + assert isinstance(self.presenter(title=None).title, Markup) @title_fixtures def test_title_unquotes_uris(self, uri, filename): @@ -207,9 +207,9 @@ def test_title_unquotes_uris(self, uri, filename): @title_fixtures def test_title_returns_Markup_when_uri_returns_Markup(self, uri, filename): filename.return_value = "" # This is not a file:// URI. - uri.return_value = jinja2.Markup("http://example.com/example.html") + uri.return_value = Markup("http://example.com/example.html") - assert isinstance(self.presenter(title=None).title, jinja2.Markup) + assert isinstance(self.presenter(title=None).title, Markup) @title_fixtures def test_title_when_document_has_None_for_title(self, uri, filename): diff --git a/tox.ini b/tox.ini index e427f8070c2..17eb5a55872 100644 --- a/tox.ini +++ b/tox.ini @@ -52,6 +52,11 @@ filterwarnings = # See https://github.com/pytest-dev/pytest-xdist/issues/840. ignore:^The --rsyncdir command line argument and rsyncdirs config variable are deprecated\.:DeprecationWarning + # https://github.com/webpy/webpy/issues/732 + ignore:^'cgi' is deprecated and slated for removal in Python 3.13:DeprecationWarning:webob + + # https://foss.heptapod.net/python-libs/passlib/-/issues/148 + ignore:^'crypt' is deprecated and slated for removal in Python 3.13:DeprecationWarning:passlib [testenv] skip_install = true sitepackages = {env:SITE_PACKAGES:false}