Skip to content

Commit

Permalink
Update to Python 3.11.x
Browse files Browse the repository at this point in the history
- Fix for PyPOM being incompatible with Python 3.10+
- Update the docs to reference the newer Python
- Run pyupgrade
  • Loading branch information
robhudson committed Mar 8, 2024
1 parent 3937f5c commit 354e07b
Show file tree
Hide file tree
Showing 13 changed files with 46 additions and 50 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/pull_request_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: "3.9" # matches current Python in production
python-version: "3.11" # matches current Python in production
- name: "Run Python tests (on Docker)"
run: |
make clean test-image
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
########
# Python dependencies builder
#
FROM python:3.9-slim-bullseye AS python-builder
FROM python:3.11-slim-bookworm AS python-builder

WORKDIR /app
ENV LANG=C.UTF-8
Expand Down Expand Up @@ -52,7 +52,7 @@ RUN npm run build
########
# django app container
#
FROM python:3.9-slim-bullseye AS app-base
FROM python:3.11-slim-bookworm AS app-base

# Extra python env
ENV PYTHONDONTWRITEBYTECODE=1
Expand Down
2 changes: 1 addition & 1 deletion bedrock/base/tests/test_macros.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def inner_html(el):
def test_sub_nav_markup(test_input, expected):
mock_request = {"request": {"path": "/current"}}
# need to import with context for the request key to pass along the path value
markup = render("{% from 'macros.html' import sub_nav with context %}" + "{{{{ sub_nav({0}) }}}}".format(test_input), mock_request)
markup = render("{% from 'macros.html' import sub_nav with context %}" + f"{{{{ sub_nav({test_input}) }}}}", mock_request)
doc = pq(markup)

nav_title = doc(".c-sub-navigation-title")
Expand Down
21 changes: 9 additions & 12 deletions bedrock/contentful/management/commands/update_contentful.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import json
from hashlib import sha256
from typing import Dict, Tuple, Union

from django.conf import settings
from django.core.management.base import BaseCommand
Expand Down Expand Up @@ -34,7 +33,7 @@
from bedrock.utils.management.decorators import alert_sentry_on_exception


def data_hash(data: Dict) -> str:
def data_hash(data: dict) -> str:
str_data = json.dumps(data, sort_keys=True)
return sha256(str_data.encode("utf8")).hexdigest()

Expand Down Expand Up @@ -84,7 +83,7 @@ def handle(self, *args, **options):
# This will always get shown, even if --quiet is passed
print("Contentful credentials not configured")

def refresh(self) -> Tuple[bool, int, int, int, int]:
def refresh(self) -> tuple[bool, int, int, int, int]:
update_ran = False

added_count = -1
Expand All @@ -100,7 +99,7 @@ def refresh(self) -> Tuple[bool, int, int, int, int]:

return update_ran, added_count, updated_count, deleted_count, errors_count

def _get_message_action(self, msg: str) -> Union[str, None]:
def _get_message_action(self, msg: str) -> str | None:
# Format for these messages is:
# ContentManagement.Entry.publish,<currently_irrelevant_string>,<currently_irrelevant_string>
try:
Expand Down Expand Up @@ -384,16 +383,14 @@ def _check_localisation_complete(self) -> None:
self.log(f"These fields were missing localised content: {_missing_fields}")

self.log(
(
"Localisation completeness checked:"
f"\nFully localised: {localisation_complete_count} of {viable_for_localisation_count} candidates."
f"\nNot configured for localisation: {localisation_not_configured_count}."
f"\nTotal entries checked: {seen_count}."
"\n====================================\n"
)
"Localisation completeness checked:"
f"\nFully localised: {localisation_complete_count} of {viable_for_localisation_count} candidates."
f"\nNot configured for localisation: {localisation_not_configured_count}."
f"\nTotal entries checked: {seen_count}."
"\n====================================\n"
)

def _refresh_from_contentful(self) -> Tuple[int, int, int, int]:
def _refresh_from_contentful(self) -> tuple[int, int, int, int]:
self.log("Pulling from Contentful")
updated_count = 0
added_count = 0
Expand Down
7 changes: 3 additions & 4 deletions bedrock/contentful/tests/test_contentful_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

from typing import List, Tuple
from unittest import mock

from django.conf import settings
Expand Down Expand Up @@ -171,7 +170,7 @@ def test_update_contentful__purge_queue(command_instance):
assert mock_queue.purge.call_count == 1


def _build_mock_messages(actions: List) -> List[List]:
def _build_mock_messages(actions: list) -> list[list]:
messages = []
for i, action in enumerate(actions):
msg = mock.Mock(name=f"msg-{i}-{action}")
Expand All @@ -186,7 +185,7 @@ def _build_mock_messages(actions: List) -> List[List]:
return batched_messages


def _establish_mock_queue(batched_messages: List[List]) -> Tuple[mock.Mock, mock.Mock]:
def _establish_mock_queue(batched_messages: list[list]) -> tuple[mock.Mock, mock.Mock]:
mock_queue = mock.Mock(name="mock_queue")

def _receive_messages(*args, **kwargs):
Expand Down Expand Up @@ -479,7 +478,7 @@ def test_update_contentful__refresh(
assert retval == expected


def _build_mock_entries(mock_entry_data: List[dict]) -> List[mock.Mock]:
def _build_mock_entries(mock_entry_data: list[dict]) -> list[mock.Mock]:
output = []
for datum_dict in mock_entry_data:
mock_entry = mock.Mock()
Expand Down
3 changes: 1 addition & 2 deletions bedrock/contentful/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

from collections import defaultdict
from typing import List

from django.conf import settings

Expand All @@ -15,7 +14,7 @@ def locales_with_available_content(
content_type: str,
classification: str,
default_locale: str = "en-US",
) -> List[str]:
) -> list[str]:
"""
Returns a list of locale names for which we have 'enough' content in that
locale to merit showing a listing page.
Expand Down
2 changes: 1 addition & 1 deletion bedrock/firefox/tests/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ def test_send_to_device_form(test_input, expected):
request = RequestFactory().get("/firefox/browsers/mobile/")
request.locale = locale
markup = render(
"{{{{ send_to_device({0}) }}}}".format(test_input),
f"{{{{ send_to_device({test_input}) }}}}",
{"request": request, "fluent_l10n": fluent_l10n([locale, "en"], settings.FLUENT_DEFAULT_FILES)},
)
doc = pq(markup)
Expand Down
4 changes: 2 additions & 2 deletions bedrock/mozorg/tests/test_helper_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,7 @@ def _render(self, product, campaign, locale):
req = self.rf.get("/")
req.locale = locale
return render(
"{{{{ app_store_url('{0}', '{1}') }}}}".format(product, campaign),
f"{{{{ app_store_url('{product}', '{campaign}') }}}}",
{"request": req},
)

Expand Down Expand Up @@ -849,7 +849,7 @@ def _render(self, product, campaign, locale):
req = self.rf.get("/")
req.locale = locale
return render(
"{{{{ play_store_url('{0}', '{1}') }}}}".format(product, campaign),
f"{{{{ play_store_url('{product}', '{campaign}') }}}}",
{"request": req},
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def add_or_update_advisory(data, html):
:return: SecurityAdvisory
"""
mfsa_id = data.pop("mfsa_id")
year, order = [int(x) for x in mfsa_id.split("-")]
year, order = (int(x) for x in mfsa_id.split("-"))
kwargs = {
"id": mfsa_id,
"title": data.pop("title"),
Expand Down
28 changes: 11 additions & 17 deletions docs/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ Local Installation
These instructions assume you have Python, pip, and NodeJS installed. If you don't have `pip` installed
(you probably do) you can install it with the instructions in `the pip docs <https://pip.pypa.io/en/stable/installing/>`_.

Bedrock currently uses Python 3.9.10. The recommended way to install and use that version is
Bedrock currently uses Python 3.11.x. The recommended way to install and use that version is
with `pyenv <https://github.com/pyenv/pyenv>`_ and to create a virtualenv using
`pyenv-virtualenv <https://github.com/pyenv/pyenv-virtualenv>`_ that will isolate Bedrock's
dependencies from other things installed on the system.
Expand All @@ -121,7 +121,7 @@ The following assumes you are on MacOS, using ``zsh`` as your shell and `Homebre
as your package manager. If you are not, there are installation instructions for a variety of
platforms and shells in the READMEs for the two pyenv projects.

**Install Python 3.9.10 with pyenv**
**Install Python 3.11.x with pyenv**

1. Install ``pyenv`` itself ::

Expand All @@ -140,31 +140,25 @@ using ``zsh``, the ``pyenv`` docs have other routes ::

$ zsh -l

4. Install the latest Python 3.9.x (eg 3.9.10), then test it's there::
4. Install the latest Python 3.11.x (e.g. 3.11.8), then test it's there::

$ pyenv install 3.9.10
$ pyenv install 3.11.8

If you'd like to make Python 3.9.10 your default globally, you can do so with::
If you'd like to make Python 3.11 your default globally, you can do so with::

$ pyenv global 3.9.10
$ pyenv global 3.11.8

If you only want to make Python 3.9.10 available in the current shell, while you set up the
If you only want to make Python 3.11 available in the current shell, while you set up the
Python virtualenv (below), you can do so with::

$ pyenv shell 3.9.10
$ pyenv shell 3.11.8

5. Verify that you have the correct version of Python installed::

$ python --version
Python 3.9.10
Python 3.11.8


.. note ::
At the time of writing, Python 3.9.10 was the 3.9 release that worked with least complication
across the core team's local-development platforms, incl both Intel and Apple Silicon Macs.
It's also the version of 3.9 in the ``slim-bullseye`` image used for the Dockerized version.
**Install a plugin to manage virtualenvs via pyenv and create a virtualenv for Bedrock's dependencies**

1. Install ``pyenv-virtualenv`` ::
Expand All @@ -184,7 +178,7 @@ pyenv-virtualenv installed::

4. Make a virtualenv we can use - in this example we'll call it ``bedrock`` but use whatever you want ::

$ pyenv virtualenv 3.9.10 bedrock
$ pyenv virtualenv 3.11.8 bedrock

**Use the virtualenv**

Expand All @@ -209,7 +203,7 @@ deactivate it when you exit the directory, you can do so with::

If you are on OSX and some of the compiled dependencies fails to compile, try explicitly setting
the arch flags and try again. The following are relevant to Intel Macs only. If you're on Apple
Silicon, 3.9.10 should 'just work':
Silicon, 3.11.8 should 'just work':

.. code-block:: bash
Expand Down
10 changes: 5 additions & 5 deletions lib/l10n_utils/tests/test_templatetags.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import os
import re
from typing import List, MutableSet
from collections.abc import MutableSet
from unittest.mock import patch

import pytest
Expand Down Expand Up @@ -78,11 +78,11 @@ def test_ftl_bleach_allowlists_are_comprehensive():
tags_found = set()
attrs_found = set()

def _clean_tag_matches(tag_matches: List) -> MutableSet:
return set([x.replace("<", "") for x in tag_matches])
def _clean_tag_matches(tag_matches: list) -> MutableSet:
return {x.replace("<", "") for x in tag_matches}

def _clean_attr_matches(attr_matches: List) -> MutableSet:
return set([x.replace("=", "").strip() for x in attr_matches if "?" not in x])
def _clean_attr_matches(attr_matches: list) -> MutableSet:
return {x.replace("=", "").strip() for x in attr_matches if "?" not in x}

for starting_dir in [
"l10n/",
Expand Down
9 changes: 8 additions & 1 deletion tests/pages/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

from pypom.view import WebView
# Fix for pypom being incompatible with Python 3.10+ due to
# "Moved Collections Abstract Base Classes to the collections.abc module."
import collections

collections.Iterable = collections.abc.Iterable

# The above is set before importing ``WebView`` to avoid ``AttributeError``.
from pypom.view import WebView # noqa: E402


def scroll_element_into_view(self, strategy, locator, x=0, y=0):
Expand Down
2 changes: 1 addition & 1 deletion tests/pages/pocket/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class BasePage(Page):
_platform_nav_locator = (By.CSS_SELECTOR, ".pocket-header.platform")

def __init__(self, selenium, pocket_base_url, locale="en", **url_kwargs):
super(BasePage, self).__init__(selenium, pocket_base_url, locale=locale, **url_kwargs)
super().__init__(selenium, pocket_base_url, locale=locale, **url_kwargs)

def wait_for_page_to_load(self):
self.wait.until(lambda s: self.seed_url in s.current_url)
Expand Down

0 comments on commit 354e07b

Please sign in to comment.