diff --git a/bedrock/base/cache.py b/bedrock/base/cache.py index e966eb0d652..90612cf5f48 100644 --- a/bedrock/base/cache.py +++ b/bedrock/base/cache.py @@ -49,7 +49,7 @@ def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None): def incr(self, key, delta=1, version=None): value = self.get(key, version=version) if value is None: - raise ValueError("Key '%s' not found" % key) + raise ValueError(f"Key '{key}' not found") new_value = value + delta key = self.make_key(key, version=version) with self._lock: diff --git a/bedrock/base/log_settings.py b/bedrock/base/log_settings.py index 638d5fe34d2..5e1452498f5 100644 --- a/bedrock/base/log_settings.py +++ b/bedrock/base/log_settings.py @@ -38,7 +38,7 @@ def emit(self, record): "prod": { "()": commonware.log.Formatter, "datefmt": "%H:%M:%s", - "format": "%s %s: [%%(REMOTE_ADDR)s] %s" % (hostname, settings.SYSLOG_TAG, base_fmt), + "format": f"{hostname} {settings.SYSLOG_TAG}: [%(REMOTE_ADDR)s] {base_fmt}", }, "cef": { "()": cef.SysLogFormatter, diff --git a/bedrock/base/management/commands/update_www_config.py b/bedrock/base/management/commands/update_www_config.py index 601b965a52c..c2852204172 100644 --- a/bedrock/base/management/commands/update_www_config.py +++ b/bedrock/base/management/commands/update_www_config.py @@ -16,7 +16,7 @@ def get_config_file_name(app_name=None): app_name = app_name or settings.APP_NAME or "bedrock-dev" - return os.path.join(settings.WWW_CONFIG_PATH, "waffle_configs", "%s.env" % app_name) + return os.path.join(settings.WWW_CONFIG_PATH, "waffle_configs", f"{app_name}.env") def get_config_values(): @@ -61,7 +61,7 @@ def handle(self, *args, **options): count = refresh_db_values() if count: - self.output("%s configs successfully loaded" % count) + self.output(f"{count} configs successfully loaded") else: self.output("No configs found. Please try again later.") diff --git a/bedrock/base/middleware.py b/bedrock/base/middleware.py index 9505b683b17..571dcc5b57f 100644 --- a/bedrock/base/middleware.py +++ b/bedrock/base/middleware.py @@ -105,7 +105,7 @@ def process_request(self, request): response = HttpResponse(status=401, content="

Unauthorized. This site is in private demo mode.

") realm = settings.APP_NAME or "bedrock-demo" - response["WWW-Authenticate"] = 'Basic realm="{}"'.format(realm) + response["WWW-Authenticate"] = f'Basic realm="{realm}"' return response diff --git a/bedrock/base/migrations/0001_initial.py b/bedrock/base/migrations/0001_initial.py index a23dfe70d05..83a3cec85d6 100644 --- a/bedrock/base/migrations/0001_initial.py +++ b/bedrock/base/migrations/0001_initial.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - # This Source Code Form is subject to the terms of the Mozilla Public # 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/. diff --git a/bedrock/base/models.py b/bedrock/base/models.py index 64796c0e818..706cb59b1aa 100644 --- a/bedrock/base/models.py +++ b/bedrock/base/models.py @@ -13,7 +13,7 @@ class Meta: app_label = "base" def __str__(self): - return "%s=%s" % (self.name, self.value) + return f"{self.name}={self.value}" def get_config_dict(): diff --git a/bedrock/base/templatetags/helpers.py b/bedrock/base/templatetags/helpers.py index cec3ac3836c..ad3c8470314 100644 --- a/bedrock/base/templatetags/helpers.py +++ b/bedrock/base/templatetags/helpers.py @@ -124,7 +124,7 @@ def js_bundle(name): Bundles are defined in the "media/static-bundles.json" file. """ - path = "js/{}.js".format(name) + path = f"js/{name}.js" path = staticfiles_storage.url(path) return jinja2.Markup(JS_TEMPLATE % path) @@ -135,7 +135,7 @@ def css_bundle(name): Bundles are defined in the "media/static-bundles.json" file. """ - path = "css/{}.css".format(name) + path = f"css/{name}.css" path = staticfiles_storage.url(path) return jinja2.Markup(CSS_TEMPLATE % path) diff --git a/bedrock/base/tests/test_helpers.py b/bedrock/base/tests/test_helpers.py index 25cda0e1761..ee6fa8d407a 100644 --- a/bedrock/base/tests/test_helpers.py +++ b/bedrock/base/tests/test_helpers.py @@ -2,10 +2,11 @@ # 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 unittest.mock import patch + from django.test import TestCase, override_settings from django_jinja.backend import Jinja2 -from mock import patch from bedrock.base.templatetags import helpers diff --git a/bedrock/base/tests/test_simple_dict_cache.py b/bedrock/base/tests/test_simple_dict_cache.py index 148fc7484ad..17a1da240b3 100644 --- a/bedrock/base/tests/test_simple_dict_cache.py +++ b/bedrock/base/tests/test_simple_dict_cache.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - # This Source Code Form is subject to the terms of the Mozilla Public # 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/. @@ -33,7 +31,7 @@ def custom_key_func(key, key_prefix, version): _caches_setting_base = { "default": {}, - "prefix": {"KEY_PREFIX": "cacheprefix{}".format(os.getpid())}, + "prefix": {"KEY_PREFIX": f"cacheprefix{os.getpid()}"}, "v2": {"VERSION": 2}, "custom_key": {"KEY_FUNCTION": custom_key_func}, "custom_key2": {"KEY_FUNCTION": "bedrock.base.tests.test_simple_dict_cache.custom_key_func"}, @@ -49,7 +47,7 @@ def caches_setting_for_tests(base=None, **params): # This results in the following search order: # params -> _caches_setting_base -> base base = base or {} - setting = dict((k, base.copy()) for k in _caches_setting_base.keys()) + setting = {k: base.copy() for k in _caches_setting_base.keys()} for key, cache_params in setting.items(): cache_params.update(_caches_setting_base[key]) cache_params.update(params) @@ -324,11 +322,11 @@ def _perform_cull_test(self, cull_cache, initial_count, final_count): # Create initial cache key entries. This will overflow the cache, # causing a cull. for i in range(1, initial_count): - cull_cache.set("cull%d" % i, "value", 1000) + cull_cache.set(f"cull{i}", "value", 1000) count = 0 # Count how many keys are left in the cache. for i in range(1, initial_count): - if "cull%d" % i in cull_cache: # noqa + if f"cull{i}" in cull_cache: # noqa count = count + 1 self.assertEqual(count, final_count) diff --git a/bedrock/base/tests/test_urlresolvers.py b/bedrock/base/tests/test_urlresolvers.py index 8b1a759b1fc..385ae6f1c08 100644 --- a/bedrock/base/tests/test_urlresolvers.py +++ b/bedrock/base/tests/test_urlresolvers.py @@ -1,15 +1,15 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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 unittest.mock import Mock, patch + from django.test import TestCase from django.test.client import RequestFactory from django.test.utils import override_settings from django.urls import re_path import pytest -from mock import Mock, patch from bedrock.base.urlresolvers import Prefixer, find_supported, reverse, split_path @@ -47,7 +47,7 @@ class TestReverse(TestCase): def test_unicode_url(self, get_url_prefix): # If the prefixer returns a unicode URL it should be escaped and cast # as a str object. - get_url_prefix.return_value = FakePrefixer(lambda p: "/Françoi%s" % p) + get_url_prefix.return_value = FakePrefixer(lambda p: f"/Françoi{p}") result = reverse("test.view") # Ensure that UTF-8 characters are escaped properly. diff --git a/bedrock/base/tests/test_waffle.py b/bedrock/base/tests/test_waffle.py index 32491ab082b..8556368f72b 100644 --- a/bedrock/base/tests/test_waffle.py +++ b/bedrock/base/tests/test_waffle.py @@ -2,9 +2,9 @@ # 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 django.conf import settings +from unittest.mock import patch -from mock import patch +from django.conf import settings from bedrock.base import waffle diff --git a/bedrock/base/tests/test_waffle_config.py b/bedrock/base/tests/test_waffle_config.py index 9cbeb4bab55..6b5931b4f4d 100644 --- a/bedrock/base/tests/test_waffle_config.py +++ b/bedrock/base/tests/test_waffle_config.py @@ -2,8 +2,9 @@ # 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 unittest.mock import patch + from everett.manager import ConfigManager, ConfigurationMissingError -from mock import patch from bedrock.base import waffle_config from bedrock.mozorg.tests import TestCase diff --git a/bedrock/base/views.py b/bedrock/base/views.py index e939acc200f..304a14e92fb 100644 --- a/bedrock/base/views.py +++ b/bedrock/base/views.py @@ -52,10 +52,7 @@ def get_template_names(self): GIT_SHA = getenv("GIT_SHA") BUCKET_NAME = getenv("AWS_DB_S3_BUCKET", "bedrock-db-dev") REGION_NAME = os.getenv("AWS_DB_REGION", "us-west-2") -S3_BASE_URL = "https://s3-{}.amazonaws.com/{}".format( - REGION_NAME, - BUCKET_NAME, -) +S3_BASE_URL = f"https://s3-{REGION_NAME}.amazonaws.com/{BUCKET_NAME}" def get_l10n_repo_info(): @@ -84,9 +81,9 @@ def get_extra_server_info(): "git_sha": GIT_SHA, } try: - with open(DB_INFO_FILE, "r") as fp: + with open(DB_INFO_FILE) as fp: db_info = json.load(fp) - except (IOError, ValueError): + except (OSError, ValueError): pass else: last_updated_timestamp = datetime.fromtimestamp(db_info["updated"]) @@ -94,7 +91,7 @@ def get_extra_server_info(): db_info["last_update"] = timeago.format(last_updated_timestamp) db_info["file_url"] = get_db_file_url(db_info["file_name"]) for key, value in db_info.items(): - server_info["db_%s" % key] = value + server_info[f"db_{key}"] = value return server_info diff --git a/bedrock/careers/feeds.py b/bedrock/careers/feeds.py index 716ff4e4e0c..02bf402a5cb 100644 --- a/bedrock/careers/feeds.py +++ b/bedrock/careers/feeds.py @@ -16,9 +16,8 @@ class LatestPositionsFeed(Feed): title = "Current Mozilla job openings" description = "The current list of job openings, available internships and contract opportunities at Mozilla." feed_copyright = ( - "Portions of this content are ©1998–%s by individual " - "mozilla.org contributors. Content available under a " - "Creative Commons license." % date.today().year + f"Portions of this content are ©1998–{date.today().year} by individual " + "mozilla.org contributors. Content available under a Creative Commons license." ) def link(self): diff --git a/bedrock/careers/forms.py b/bedrock/careers/forms.py index 30b691ce861..ff865aad331 100644 --- a/bedrock/careers/forms.py +++ b/bedrock/careers/forms.py @@ -13,7 +13,7 @@ class PositionFilterForm(forms.Form): location = forms.ChoiceField(widget=forms.Select(attrs={"autocomplete": "off"})) def __init__(self, *args, **kwargs): - super(PositionFilterForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # Populate position type choices dynamically. locations = Position.locations() diff --git a/bedrock/careers/models.py b/bedrock/careers/models.py index 9df90a0b400..3f17f8a4352 100644 --- a/bedrock/careers/models.py +++ b/bedrock/careers/models.py @@ -29,7 +29,7 @@ class Meta: ) def __str__(self): - return "{}@{}".format(self.job_id, self.source) + return f"{self.job_id}@{self.source}" @property def location_list(self): @@ -45,7 +45,7 @@ def position_types(cls): @classmethod def locations(cls): return sorted( - set(location.strip() for location in chain(*[locations.split(",") for locations in cls.objects.values_list("location", flat=True)])) + {location.strip() for location in chain(*[locations.split(",") for locations in cls.objects.values_list("location", flat=True)])} ) @classmethod diff --git a/bedrock/careers/tests/__init__.py b/bedrock/careers/tests/__init__.py index f401b3b2ce6..2ca4bd618b0 100644 --- a/bedrock/careers/tests/__init__.py +++ b/bedrock/careers/tests/__init__.py @@ -26,5 +26,5 @@ class Meta: @factory.lazy_attribute def apply_url(self): if self.source == "gh": - url = "https://boards.greenhouse.io/{}/jobs/{}".format(settings.GREENHOUSE_BOARD, self.job_id) + url = f"https://boards.greenhouse.io/{settings.GREENHOUSE_BOARD}/jobs/{self.job_id}" return url.format(self.job_id) diff --git a/bedrock/contentcards/management/commands/update_content_cards.py b/bedrock/contentcards/management/commands/update_content_cards.py index 05ac8345c83..120e3946a18 100644 --- a/bedrock/contentcards/management/commands/update_content_cards.py +++ b/bedrock/contentcards/management/commands/update_content_cards.py @@ -32,7 +32,7 @@ def handle(self, *args, **options): self.output("Loading content cards into database") count = ContentCard.objects.refresh() - self.output("%s content cards successfully loaded" % count) + self.output(f"{count} content cards successfully loaded") repo.set_db_latest() diff --git a/bedrock/contentcards/migrations/0001_initial.py b/bedrock/contentcards/migrations/0001_initial.py index 97aa1a15f71..3d4c58aac2f 100644 --- a/bedrock/contentcards/migrations/0001_initial.py +++ b/bedrock/contentcards/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. diff --git a/bedrock/contentcards/models.py b/bedrock/contentcards/models.py index 0198d8d77fd..36e59c3d169 100644 --- a/bedrock/contentcards/models.py +++ b/bedrock/contentcards/models.py @@ -24,7 +24,7 @@ def get_page_content_cards(page_name, locale): def get_data_from_file_path(file_path): card_name, locale = file_path.stem.split(".") page_name = file_path.parts[-2] - page_id = "{}-{}-{}".format(page_name, locale, card_name) + page_id = f"{page_name}-{locale}-{card_name}" return { "locale": locale, "card_name": card_name, @@ -35,7 +35,7 @@ def get_data_from_file_path(file_path): class ContentCardManager(models.Manager): def get_card(self, page_name, name, locale="en-US"): - card_id = "{}-{}-{}".format(page_name, locale, name) + card_id = f"{page_name}-{locale}-{name}" return self.get(id=card_id) def get_page_cards(self, page_name, locale="en-US"): @@ -82,7 +82,7 @@ class Meta: ordering = ("id",) def __str__(self): - return "{} ({})".format(self.card_name, self.locale) + return f"{self.card_name} ({self.locale})" @property def html(self): @@ -94,24 +94,24 @@ def card_data(self): data = {} data.update(self.data) if "image" in data: - data["image_url"] = "%scontentcards/img/%s" % (settings.CONTENT_CARDS_URL, data["image"]) + data["image_url"] = f"{settings.CONTENT_CARDS_URL}contentcards/img/{data['image']}" del data["image"] if "highres_image" in data: - data["highres_image_url"] = "%scontentcards/img/%s" % (settings.CONTENT_CARDS_URL, data["highres_image"]) + data["highres_image_url"] = f"{settings.CONTENT_CARDS_URL}contentcards/img/{data['highres_image']}" del data["highres_image"] if "ga_title" not in data: data["ga_title"] = data["title"] if "media_icon" in data: - data["media_icon"] = "mzp-has-%s" % data["media_icon"] + data["media_icon"] = f"mzp-has-{data['media_icon']}" if "aspect_ratio" in data: - data["aspect_ratio"] = "mzp-has-aspect-%s" % data["aspect_ratio"] + data["aspect_ratio"] = f"mzp-has-aspect-{data['aspect_ratio']}" if "size" in data: - data["class"] = "mzp-c-card-%s" % data["size"] + data["class"] = f"mzp-c-card-{data['size']}" del data["size"] if "link_url" in data and not URL_RE.match(data["link_url"]): diff --git a/bedrock/contentcards/tests/test_models.py b/bedrock/contentcards/tests/test_models.py index 507fe83badf..5218eeace98 100644 --- a/bedrock/contentcards/tests/test_models.py +++ b/bedrock/contentcards/tests/test_models.py @@ -78,7 +78,7 @@ def test_card_data(self): def test_get_page_cards(self): cards = models.ContentCard.objects.get_page_cards("home") - self.assertTrue(all(name in cards for name in ["card_%d" % i for i in range(1, 6)])) + self.assertTrue(all(name in cards for name in [f"card_{i}" for i in range(1, 6)])) self.assertDictEqual( cards["card_2"], { diff --git a/bedrock/contentful/api.py b/bedrock/contentful/api.py index 7885bdcdad7..b8bbc78a226 100644 --- a/bedrock/contentful/api.py +++ b/bedrock/contentful/api.py @@ -294,7 +294,7 @@ def render(self, node): cta_text = _make_plain_text(node) data_cta = f' data-cta-type="link" data-cta-text="{cta_text}"' - return '{4}'.format(urlunparse(url), ref, data_cta, rel, self._render_content(node)) + return f'{self._render_content(node)}' def _render_list(tag, content): diff --git a/bedrock/contentful/management/commands/update_contentful.py b/bedrock/contentful/management/commands/update_contentful.py index 225939601a8..6bb9511c645 100644 --- a/bedrock/contentful/management/commands/update_contentful.py +++ b/bedrock/contentful/management/commands/update_contentful.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. diff --git a/bedrock/contentful/tests/test_contentful_commands.py b/bedrock/contentful/tests/test_contentful_commands.py index 360dbe0584b..dae287d0dc4 100644 --- a/bedrock/contentful/tests/test_contentful_commands.py +++ b/bedrock/contentful/tests/test_contentful_commands.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. diff --git a/bedrock/exp/tests/test_views.py b/bedrock/exp/tests/test_views.py index 172f4339988..2b6ad0b07be 100644 --- a/bedrock/exp/tests/test_views.py +++ b/bedrock/exp/tests/test_views.py @@ -1,13 +1,12 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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 unittest.mock import ANY, patch + from django.test import override_settings from django.test.client import RequestFactory -from mock import ANY, patch - from bedrock.exp import views from bedrock.mozorg.tests import TestCase diff --git a/bedrock/externalfiles/__init__.py b/bedrock/externalfiles/__init__.py index 68566f211a5..8978667cf3b 100644 --- a/bedrock/externalfiles/__init__.py +++ b/bedrock/externalfiles/__init__.py @@ -20,12 +20,12 @@ def __init__(self, file_id): try: fileinfo = settings.EXTERNAL_FILES[file_id] except KeyError: - raise ValueError("No external file with the {0} ID.".format(file_id)) + raise ValueError(f"No external file with the {file_id} ID.") self._cache = caches["externalfiles"] self.file_id = file_id self.name = fileinfo["name"] - self.cache_key = "externalfile:{}".format(self.file_id) + self.cache_key = f"externalfile:{self.file_id}" self.file_path = os.path.join(settings.EXTERNAL_FILES_PATH, self.name) @property @@ -78,7 +78,7 @@ def validate_file(self): content = fp.read() if not content: - raise ValueError("%s is empty" % self.name) + raise ValueError(f"{self.name} is empty") return self.validate_content(content) @@ -91,7 +91,7 @@ def readlines(self): def update(self): from bedrock.externalfiles.models import ExternalFile as EFModel - log.info("Updating {0}.".format(self.name)) + log.info(f"Updating {self.name}.") content = self.validate_file() fo = self.file_object if fo: @@ -100,7 +100,7 @@ def update(self): else: EFModel.objects.create(name=self.file_id, content=content) - log.info("Successfully updated {0}.".format(self.name)) + log.info(f"Successfully updated {self.name}.") return True def clear_cache(self): diff --git a/bedrock/externalfiles/migrations/0001_initial.py b/bedrock/externalfiles/migrations/0001_initial.py index 1cfb394dc1f..579fa174871 100644 --- a/bedrock/externalfiles/migrations/0001_initial.py +++ b/bedrock/externalfiles/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. diff --git a/bedrock/externalfiles/tests/test_base.py b/bedrock/externalfiles/tests/test_base.py index 5a714bcf257..3b00b60c962 100644 --- a/bedrock/externalfiles/tests/test_base.py +++ b/bedrock/externalfiles/tests/test_base.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. @@ -16,7 +15,7 @@ class TestExternalFile(TestCase): @classmethod def setUpClass(cls): - super(TestExternalFile, cls).setUpClass() + super().setUpClass() timezone.activate(utc) def setUp(self): diff --git a/bedrock/firefox/firefox_details.py b/bedrock/firefox/firefox_details.py index dfbcac6e50e..4e0d4eacf09 100644 --- a/bedrock/firefox/firefox_details.py +++ b/bedrock/firefox/firefox_details.py @@ -73,7 +73,7 @@ class FirefoxDesktop(_ProductDetails): } def __init__(self, **kwargs): - super(FirefoxDesktop, self).__init__(**kwargs) + super().__init__(**kwargs) def platforms(self, channel="release", classified=False): """ @@ -258,8 +258,8 @@ def get_download_url( # Bug 1345467 - Only allow specifically configured funnelcake builds if funnelcake_id: - fc_platforms = config("FUNNELCAKE_%s_PLATFORMS" % funnelcake_id, default="", parser=ListOf(str)) - fc_locales = config("FUNNELCAKE_%s_LOCALES" % funnelcake_id, default="", parser=ListOf(str)) + fc_platforms = config(f"FUNNELCAKE_{funnelcake_id}_PLATFORMS", default="", parser=ListOf(str)) + fc_locales = config(f"FUNNELCAKE_{funnelcake_id}_LOCALES", default="", parser=ListOf(str)) include_funnelcake_param = platform in fc_platforms and _locale in fc_locales # Check if direct download link has been requested @@ -269,15 +269,15 @@ def get_download_url( transition_url = self.download_base_url_transition if funnelcake_id: # include funnelcake in scene 2 URL - transition_url += "?f=%s" % funnelcake_id + transition_url += f"?f={funnelcake_id}" if locale_in_transition: - transition_url = "/%s%s" % (locale, transition_url) + transition_url = f"/{locale}{transition_url}" return transition_url # otherwise build a full download URL - prod_name = "firefox" if channel == "release" else "firefox-%s" % channel + prod_name = "firefox" if channel == "release" else f"firefox-{channel}" suffix = "latest-ssl" if is_msi: suffix = "msi-" + suffix @@ -291,7 +291,7 @@ def get_download_url( # Use the stub installer for approved platforms # append funnelcake id to version if we have one if include_funnelcake_param: - suffix = "stub-f%s" % funnelcake_id + suffix = f"stub-f{funnelcake_id}" else: suffix = "stub" elif channel == "nightly" and locale != "en-US": @@ -301,7 +301,7 @@ def get_download_url( if is_msi: suffix = "msi-" + suffix - product = "%s-%s" % (prod_name, suffix) + product = f"{prod_name}-{suffix}" return "?".join( [ diff --git a/bedrock/firefox/migrations/0001_initial.py b/bedrock/firefox/migrations/0001_initial.py index e61170fdb17..4f3bd3b1cae 100644 --- a/bedrock/firefox/migrations/0001_initial.py +++ b/bedrock/firefox/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. diff --git a/bedrock/firefox/migrations/0002_delete_firefoxosfeedlink.py b/bedrock/firefox/migrations/0002_delete_firefoxosfeedlink.py index 6929e0fc1a8..50e8b74947d 100644 --- a/bedrock/firefox/migrations/0002_delete_firefoxosfeedlink.py +++ b/bedrock/firefox/migrations/0002_delete_firefoxosfeedlink.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. diff --git a/bedrock/firefox/templatetags/helpers.py b/bedrock/firefox/templatetags/helpers.py index d554d73bf91..d679c147744 100644 --- a/bedrock/firefox/templatetags/helpers.py +++ b/bedrock/firefox/templatetags/helpers.py @@ -150,7 +150,7 @@ def download_firefox( alt_channel = "" if channel == "release" else channel locale = locale or get_locale(ctx["request"]) funnelcake_id = ctx.get("funnelcake_id", False) - dom_id = dom_id or "download-button-%s-%s" % ("desktop" if platform == "all" else platform, channel) + dom_id = dom_id or f"download-button-{'desktop' if platform == 'all' else platform}-{channel}" # Gather data about the build for each platform builds = [] @@ -174,7 +174,7 @@ def download_firefox( data = { "locale_name": locale_name, "version": version, - "product": "firefox-%s" % platform, + "product": f"firefox-{platform}", "builds": builds, "id": dom_id, "channel": alt_channel, @@ -216,10 +216,10 @@ def download_firefox_thanks(ctx, dom_id=None, locale=None, alt_copy=None, button # if there's a funnelcake param in the page URL e.g. ?f=123 if funnelcake_id: # include param in transitional URL e.g. /firefox/download/thanks/?f=123 - transition_url += "?f=%s" % funnelcake_id + transition_url += f"?f={funnelcake_id}" if locale_in_transition: - transition_url = "/%s%s" % (locale, transition_url) + transition_url = f"/{locale}{transition_url}" download_link_direct = firefox_desktop.get_download_url( channel, @@ -259,7 +259,7 @@ def download_firefox_desktop_list(ctx, channel="release", dom_id=None, locale=No the stub installer (for aurora). """ - dom_id = dom_id or "download-platform-list-%s" % (channel) + dom_id = dom_id or f"download-platform-list-{channel}" locale = locale or get_locale(ctx["request"]) # Make sure funnelcake_id is not passed as builds are often Windows only. diff --git a/bedrock/firefox/tests/test_base.py b/bedrock/firefox/tests/test_base.py index 8fe650f28aa..f3ea174d597 100644 --- a/bedrock/firefox/tests/test_base.py +++ b/bedrock/firefox/tests/test_base.py @@ -1,8 +1,8 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. import os +from unittest.mock import Mock, call, patch from django.core.cache import caches from django.http import HttpResponse @@ -11,7 +11,6 @@ from django_jinja.backend import Jinja2 from jinja2 import Markup -from mock import Mock, call, patch from pyquery import PyQuery as pq from bedrock.base.urlresolvers import reverse diff --git a/bedrock/firefox/tests/test_firefox_details.py b/bedrock/firefox/tests/test_firefox_details.py index 93fbddbf4ef..b1bb6386d9e 100644 --- a/bedrock/firefox/tests/test_firefox_details.py +++ b/bedrock/firefox/tests/test_firefox_details.py @@ -1,14 +1,12 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. import os +from unittest.mock import Mock, patch from urllib.parse import parse_qsl, urlparse from django.core.cache import caches -from mock import Mock, patch - from bedrock.firefox.firefox_details import FirefoxAndroid, FirefoxDesktop, FirefoxIOS from bedrock.mozorg.tests import TestCase diff --git a/bedrock/firefox/tests/test_helpers.py b/bedrock/firefox/tests/test_helpers.py index 6035c4b22c9..97e17625def 100644 --- a/bedrock/firefox/tests/test_helpers.py +++ b/bedrock/firefox/tests/test_helpers.py @@ -34,7 +34,7 @@ def check_desktop_links(self, links): """Desktop links should have the correct firefox version""" # valid product strings keys = [ - "firefox-%s" % self.latest_version(), + f"firefox-{self.latest_version()}", "firefox-stub", "firefox-latest-ssl", "firefox-beta-stub", @@ -375,7 +375,7 @@ def check_desktop_links(self, links): """Desktop links should have the correct firefox version""" # valid product strings keys = [ - "firefox-%s" % self.latest_version(), + f"firefox-{self.latest_version()}", "firefox-stub", "firefox-latest-ssl", "firefox-msi-latest-ssl", @@ -483,9 +483,9 @@ class TestFirefoxURL(TestCase): def _render(self, platform, page, channel=None): req = self.rf.get("/") if channel: - tmpl = "{{ firefox_url('%s', '%s', '%s') }}" % (platform, page, channel) + tmpl = f"{{{{ firefox_url('{platform}', '{page}', '{channel}') }}}}" else: - tmpl = "{{ firefox_url('%s', '%s') }}" % (platform, page) + tmpl = f"{{{{ firefox_url('{platform}', '{page}') }}}}" return render(tmpl, {"request": req}) def test_firefox_all(self): diff --git a/bedrock/firefox/tests/test_views.py b/bedrock/firefox/tests/test_views.py index c769c360cb1..234d07dac49 100644 --- a/bedrock/firefox/tests/test_views.py +++ b/bedrock/firefox/tests/test_views.py @@ -1,10 +1,10 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. import json import os +from unittest.mock import ANY, patch from urllib.parse import parse_qs from django.http import HttpResponse @@ -12,7 +12,6 @@ from django.test.client import RequestFactory import querystringsafe_base64 -from mock import ANY, patch from pyquery import PyQuery as pq from bedrock.firefox import views diff --git a/bedrock/firefox/urls.py b/bedrock/firefox/urls.py index b8a8303682f..67dfcf7e9af 100644 --- a/bedrock/firefox/urls.py +++ b/bedrock/firefox/urls.py @@ -84,11 +84,11 @@ re_path(firstrun_re, views.FirstrunView.as_view(), name="firefox.firstrun"), re_path(whatsnew_re, views.WhatsnewView.as_view(), name="firefox.whatsnew"), # Release notes - re_path("^firefox/(?:%s/)?(?:%s/)?notes/$" % (platform_re, channel_re), bedrock.releasenotes.views.latest_notes, name="firefox.notes"), + re_path(f"^firefox/(?:{platform_re}/)?(?:{channel_re}/)?notes/$", bedrock.releasenotes.views.latest_notes, name="firefox.notes"), path("firefox/nightly/notes/feed/", bedrock.releasenotes.views.nightly_feed, name="firefox.nightly.notes.feed"), re_path("firefox/(?:latest/)?releasenotes/$", bedrock.releasenotes.views.latest_notes, {"product": "firefox"}), re_path( - "^firefox/(?:%s/)?(?:%s/)?system-requirements/$" % (platform_re, channel_re), + f"^firefox/(?:{platform_re}/)?(?:{channel_re}/)?system-requirements/$", bedrock.releasenotes.views.latest_sysreq, {"product": "firefox"}, name="firefox.sysreq", diff --git a/bedrock/firefox/views.py b/bedrock/firefox/views.py index 36c6c83e587..66837da9dd9 100644 --- a/bedrock/firefox/views.py +++ b/bedrock/firefox/views.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - # This Source Code Form is subject to the terms of the Mozilla Public # 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/. @@ -74,7 +72,7 @@ class InstallerHelpView(L10nTemplateView): ftl_files = ["firefox/installer-help"] def get_context_data(self, **kwargs): - ctx = super(InstallerHelpView, self).get_context_data(**kwargs) + ctx = super().get_context_data(**kwargs) installer_lang = self.request.GET.get("installer_lang", None) installer_channel = self.request.GET.get("channel", None) ctx["installer_lang"] = None @@ -420,10 +418,10 @@ def get(self, *args, **kwargs): if redirect_old_firstrun(version): return HttpResponsePermanentRedirect(reverse("firefox.new")) else: - return super(FirstrunView, self).get(*args, **kwargs) + return super().get(*args, **kwargs) def get_context_data(self, **kwargs): - ctx = super(FirstrunView, self).get_context_data(**kwargs) + ctx = super().get_context_data(**kwargs) # add version to context for use in templates ctx["version"] = self.kwargs.get("version") or "" @@ -481,7 +479,7 @@ class WhatsnewView(L10nTemplateView): variations = ["1", "2", "3"] def get_context_data(self, **kwargs): - ctx = super(WhatsnewView, self).get_context_data(**kwargs) + ctx = super().get_context_data(**kwargs) version = self.kwargs.get("version") or "" pre_release_channels = ["nightly", "developer", "beta"] channel = detect_channel(version) @@ -512,7 +510,7 @@ def get_context_data(self, **kwargs): ctx["analytics_version"] = analytics_version ctx["entrypoint"] = entrypoint ctx["campaign"] = campaign - ctx["utm_params"] = "utm_source={0}&utm_medium=referral&utm_campaign={1}&entrypoint={2}".format(entrypoint, campaign, entrypoint) + ctx["utm_params"] = f"utm_source={entrypoint}&utm_medium=referral&utm_campaign={campaign}&entrypoint={entrypoint}" variant = self.request.GET.get("v", None) @@ -605,7 +603,7 @@ class DownloadThanksView(L10nTemplateView): variations = [] def get_context_data(self, **kwargs): - ctx = super(DownloadThanksView, self).get_context_data(**kwargs) + ctx = super().get_context_data(**kwargs) variant = self.request.GET.get("v", None) # ensure variant matches pre-defined value @@ -662,7 +660,7 @@ def get(self, *args, **kwargs): thanks_url = "?".join([thanks_url, force_text(query_string, errors="ignore")]) return HttpResponsePermanentRedirect(thanks_url) - return super(NewView, self).get(*args, **kwargs) + return super().get(*args, **kwargs) def render_to_response(self, context, **response_kwargs): # set experimental percentages per locale with this config @@ -693,7 +691,7 @@ def render_to_response(self, context, **response_kwargs): return super().render_to_response(context, **response_kwargs) def get_context_data(self, **kwargs): - ctx = super(NewView, self).get_context_data(**kwargs) + ctx = super().get_context_data(**kwargs) # note: v and xv params only allow a-z, A-Z, 0-9, -, and _ characters variant = self.request.GET.get("v", None) @@ -776,7 +774,7 @@ class FirefoxHomeView(L10nTemplateView): variations = [] def get_context_data(self, **kwargs): - ctx = super(FirefoxHomeView, self).get_context_data(**kwargs) + ctx = super().get_context_data(**kwargs) variant = self.request.GET.get("v", None) # ensure variant matches pre-defined value diff --git a/bedrock/legal/forms.py b/bedrock/legal/forms.py index bc66c028991..a76379297ab 100644 --- a/bedrock/legal/forms.py +++ b/bedrock/legal/forms.py @@ -1,5 +1,3 @@ -# coding: utf-8 - # This Source Code Form is subject to the terms of the Mozilla Public # 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/. diff --git a/bedrock/legal/tests/test_forms.py b/bedrock/legal/tests/test_forms.py index d4eb9e0c999..1222da6a653 100644 --- a/bedrock/legal/tests/test_forms.py +++ b/bedrock/legal/tests/test_forms.py @@ -1,14 +1,13 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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 io import BytesIO +from unittest.mock import Mock, patch from django.core import mail from django.core.files.uploadedfile import SimpleUploadedFile from django.test.client import RequestFactory -from mock import Mock, patch from PIL import Image from bedrock.base.urlresolvers import reverse diff --git a/bedrock/legal/views.py b/bedrock/legal/views.py index 0ff614c3d6b..45b8581a8df 100644 --- a/bedrock/legal/views.py +++ b/bedrock/legal/views.py @@ -67,7 +67,7 @@ def fraud_report(request): # send a response to avoid problem described below. # @see https://bugzilla.mozilla.org/show_bug.cgi?id=873476 (3.2) response = redirect(reverse("legal.fraud-report"), template_vars) - response["Location"] += "?submitted=%s" % form_submitted + response["Location"] += f"?submitted={form_submitted}" return response else: diff --git a/bedrock/legal_docs/models.py b/bedrock/legal_docs/models.py index f33664dd6d5..39911932285 100644 --- a/bedrock/legal_docs/models.py +++ b/bedrock/legal_docs/models.py @@ -27,7 +27,7 @@ def process_md_file(file_path): extensions=["markdown.extensions.attr_list", "markdown.extensions.toc", OutlineExtension((("wrapper_cls", ""),))], ) content = output.getvalue().decode("utf-8") - except IOError: + except OSError: content = None finally: output.close() diff --git a/bedrock/legal_docs/tests/test_base.py b/bedrock/legal_docs/tests/test_base.py index 1618fb95a03..823e9a4f809 100644 --- a/bedrock/legal_docs/tests/test_base.py +++ b/bedrock/legal_docs/tests/test_base.py @@ -3,12 +3,11 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. from pathlib import Path +from unittest.mock import patch from django.http import Http404, HttpResponse from django.test import RequestFactory, override_settings -from mock import patch - from bedrock.legal_docs import views from bedrock.legal_docs.models import LegalDoc, get_data_from_file_path from bedrock.mozorg.tests import TestCase @@ -98,7 +97,7 @@ def test_good_doc_okay(self, render_mock, lld_mock): req.locale = "de" view = views.LegalDocView.as_view(template_name="base.html", legal_doc_name="the_dude_exists") resp = view(req) - assert resp["cache-control"] == "max-age={0!s}".format(views.CACHE_TIMEOUT) + assert resp["cache-control"] == f"max-age={views.CACHE_TIMEOUT!s}" assert resp.content.decode("utf-8") == doc_value assert render_mock.call_args[0][2]["doc"] == doc_value lld_mock.assert_called_with("the_dude_exists", "de") diff --git a/bedrock/legal_docs/views.py b/bedrock/legal_docs/views.py index 0a35747ebf1..d60f71b0322 100644 --- a/bedrock/legal_docs/views.py +++ b/bedrock/legal_docs/views.py @@ -72,7 +72,7 @@ def get_context_data(self, **kwargs): if legal_doc is None: raise Http404("Legal doc not found") - context = super(LegalDocView, self).get_context_data(**kwargs) + context = super().get_context_data(**kwargs) context[self.legal_doc_context_name] = legal_doc["content"] context["active_locales"] = legal_doc["active_locales"] return context @@ -80,4 +80,4 @@ def get_context_data(self, **kwargs): @classmethod def as_view(cls, **initkwargs): cache_timeout = initkwargs.pop("cache_timeout", cls.cache_timeout) - return cache_page(cache_timeout)(super(LegalDocView, cls).as_view(**initkwargs)) + return cache_page(cache_timeout)(super().as_view(**initkwargs)) diff --git a/bedrock/mozorg/credits.py b/bedrock/mozorg/credits.py index 51aaec5669b..25ae5e9b605 100644 --- a/bedrock/mozorg/credits.py +++ b/bedrock/mozorg/credits.py @@ -14,7 +14,7 @@ class CreditsFile(ExternalFile): def validate_content(self, content): rows = list(csv.reader(content.strip().split("\n"))) if len(rows) < 2200: # it's 2273 as of now - raise ValueError("Much smaller file than expected. {0} rows.".format(len(rows))) + raise ValueError(f"Much smaller file than expected. {len(rows)} rows.") if len(rows[0]) != 2 or len(rows[-1]) != 2: raise ValueError("CSV Content corrupted.") diff --git a/bedrock/mozorg/forms.py b/bedrock/mozorg/forms.py index 1e47331a87c..91713a18c56 100644 --- a/bedrock/mozorg/forms.py +++ b/bedrock/mozorg/forms.py @@ -1,5 +1,3 @@ -# coding: utf-8 - # This Source Code Form is subject to the terms of the Mozilla Public # 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/. @@ -32,13 +30,11 @@ class PrivacyWidget(widgets.CheckboxInput): def render(self, name, value, attrs=None, renderer=None): attrs["required"] = "required" - input_txt = super(PrivacyWidget, self).render(name, value, attrs) + input_txt = super().render(name, value, attrs) policy_txt = ftl("newsletter-form-im-okay-with-mozilla", url=reverse("privacy.notices.websites")) - return mark_safe( - '' % (attrs["id"], input_txt, policy_txt) - ) + return mark_safe(f"""""") class HoneyPotWidget(widgets.TextInput): diff --git a/bedrock/mozorg/hierarchy.py b/bedrock/mozorg/hierarchy.py index 130f8be58aa..29e571c011d 100644 --- a/bedrock/mozorg/hierarchy.py +++ b/bedrock/mozorg/hierarchy.py @@ -125,7 +125,7 @@ def url(self): return None def __repr__(self): - return '{0}(display_name="{1}", path="{2}", template="{3})"'.format(self.__class__.__name__, self.display_name, self.full_path, self.template) + return f'{self.__class__.__name__}(display_name="{self.display_name}", path="{self.full_path}", template="{self.template})"' class PageRoot(PageNode): @@ -137,7 +137,7 @@ class PageRoot(PageNode): """ def __init__(self, *args, **kwargs): - super(PageRoot, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # Buid a pre-order traversal of this tree's nodes. self.preordered_nodes = [] diff --git a/bedrock/mozorg/management/commands/update_product_details_files.py b/bedrock/mozorg/management/commands/update_product_details_files.py index b8e70f085b0..58c53cec27c 100644 --- a/bedrock/mozorg/management/commands/update_product_details_files.py +++ b/bedrock/mozorg/management/commands/update_product_details_files.py @@ -35,7 +35,7 @@ def __init__(self, stdout=None, stderr=None, no_color=False): # fake last-modified string since the releng repo doesn't store those files # and we rely on git commits for updates self.last_modified = datetime.now().isoformat() - super(Command, self).__init__(stdout, stderr, no_color) + super().__init__(stdout, stderr, no_color) def add_arguments(self, parser): parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", default=False, help="If no error occurs, swallow all output."), @@ -92,7 +92,7 @@ def count_builds(self, version_key, min_builds=20): return builds = len([locale for locale, build in self.file_storage.data("firefox_primary_builds.json").items() if version in build]) if builds < min_builds: - raise ValueError("Too few builds for {}".format(version_key)) + raise ValueError(f"Too few builds for {version_key}") def validate_data(self): self.file_storage.clear_cache() diff --git a/bedrock/mozorg/migrations/0001_initial.py b/bedrock/mozorg/migrations/0001_initial.py index eef94d55e76..b9054f05c5a 100644 --- a/bedrock/mozorg/migrations/0001_initial.py +++ b/bedrock/mozorg/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. @@ -44,6 +43,6 @@ class Migration(migrations.Migration): ), migrations.AlterUniqueTogether( name="contributoractivity", - unique_together=set([("date", "source_name", "team_name")]), + unique_together={("date", "source_name", "team_name")}, ), ] diff --git a/bedrock/mozorg/migrations/0002_blogarticle.py b/bedrock/mozorg/migrations/0002_blogarticle.py index d81299c86bd..999a5f41f89 100644 --- a/bedrock/mozorg/migrations/0002_blogarticle.py +++ b/bedrock/mozorg/migrations/0002_blogarticle.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. diff --git a/bedrock/mozorg/migrations/0003_delete_blogarticle.py b/bedrock/mozorg/migrations/0003_delete_blogarticle.py index a264422f688..799d2c2f4b2 100644 --- a/bedrock/mozorg/migrations/0003_delete_blogarticle.py +++ b/bedrock/mozorg/migrations/0003_delete_blogarticle.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. diff --git a/bedrock/mozorg/templatetags/misc.py b/bedrock/mozorg/templatetags/misc.py index 37afd480534..64ed7e72f66 100644 --- a/bedrock/mozorg/templatetags/misc.py +++ b/bedrock/mozorg/templatetags/misc.py @@ -188,7 +188,7 @@ def platform_img(ctx, url, optional_attributes=None): img_attrs["data-high-res"] = "true" img_attrs.update(optional_attributes) - attrs = " ".join('%s="%s"' % (attr, val) for attr, val in img_attrs.items()) + attrs = " ".join(f'{attr}="{val}"' for attr, val in img_attrs.items()) # Don't download any image until the javascript sets it based on # data-src so we can do platform detection. If no js, show the @@ -217,15 +217,13 @@ def high_res_img(ctx, url, optional_attributes=None): if optional_attributes: class_name = optional_attributes.pop("class", "") - attrs = " " + " ".join('%s="%s"' % (attr, val) for attr, val in optional_attributes.items()) + attrs = " " + " ".join(f'{attr}="{val}"' for attr, val in optional_attributes.items()) else: class_name = "" attrs = "" # Use native srcset attribute for high res images - markup = ('").format( - url=url, url_high_res=url_high_res, attrs=attrs, class_name=class_name - ) + markup = f'' return jinja2.Markup(markup) @@ -609,7 +607,7 @@ def f(s, *args, **kwargs): >>> {{ "{0} arguments and {x} arguments"|f('positional', x='keyword') }} "positional arguments and keyword arguments" """ - s = six.text_type(s) + s = str(s) return s.format(*args, **kwargs) @@ -803,7 +801,7 @@ def _fxa_product_url(product_url, entrypoint, optional_parameters=None): url = f"{product_url}{separator}entrypoint={entrypoint}&form_type=button&utm_source={entrypoint}&utm_medium=referral" if optional_parameters: - params = "&".join("%s=%s" % (param, val) for param, val in optional_parameters.items()) + params = "&".join(f"{param}={val}" for param, val in optional_parameters.items()) url += f"&{params}" return url @@ -824,7 +822,7 @@ def _fxa_product_button( attrs = "" if optional_attributes: - attrs += " ".join('%s="%s"' % (attr, val) for attr, val in optional_attributes.items()) + attrs += " ".join(f'{attr}="{val}"' for attr, val in optional_attributes.items()) if include_metrics: css_class += " js-fxa-product-button" diff --git a/bedrock/mozorg/templatetags/qrcode.py b/bedrock/mozorg/templatetags/qrcode.py index 2d24fa3ce05..a54bff7f35b 100644 --- a/bedrock/mozorg/templatetags/qrcode.py +++ b/bedrock/mozorg/templatetags/qrcode.py @@ -17,7 +17,7 @@ @library.global_function def qrcode(data, box_size=20): - key = sha1(f"{data}-{box_size}".encode("utf-8")).hexdigest() + key = sha1(f"{data}-{box_size}".encode()).hexdigest() svg = cache.get(key) if not svg: img = qr.make(data, image_factory=SvgPathImage, box_size=box_size) diff --git a/bedrock/mozorg/tests/__init__.py b/bedrock/mozorg/tests/__init__.py index 392238f696f..de4cade95dd 100644 --- a/bedrock/mozorg/tests/__init__.py +++ b/bedrock/mozorg/tests/__init__.py @@ -19,7 +19,7 @@ def activate(self, locale): old_prefix = get_url_prefix() old_locale = translation.get_language() rf = RequestFactory() - set_url_prefix(Prefixer(rf.get("/%s/" % (locale,)))) + set_url_prefix(Prefixer(rf.get(f"/{locale}/"))) translation.activate(locale) yield set_url_prefix(old_prefix) diff --git a/bedrock/mozorg/tests/test_commands.py b/bedrock/mozorg/tests/test_commands.py index 61865ca584b..7347f53f093 100644 --- a/bedrock/mozorg/tests/test_commands.py +++ b/bedrock/mozorg/tests/test_commands.py @@ -1,13 +1,11 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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 pathlib import Path +from unittest.mock import DEFAULT, patch from django.test import override_settings -from mock import DEFAULT, patch - from bedrock.mozorg.management.commands import update_product_details_files from bedrock.mozorg.tests import TestCase diff --git a/bedrock/mozorg/tests/test_credits.py b/bedrock/mozorg/tests/test_credits.py index a01599a6c66..f11a80a12d3 100644 --- a/bedrock/mozorg/tests/test_credits.py +++ b/bedrock/mozorg/tests/test_credits.py @@ -1,11 +1,9 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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 collections import OrderedDict from textwrap import dedent - -from mock import Mock +from unittest.mock import Mock from bedrock.mozorg import credits from bedrock.mozorg.tests import TestCase diff --git a/bedrock/mozorg/tests/test_decorators.py b/bedrock/mozorg/tests/test_decorators.py index 35159156e76..2b910fccbe0 100644 --- a/bedrock/mozorg/tests/test_decorators.py +++ b/bedrock/mozorg/tests/test_decorators.py @@ -22,7 +22,7 @@ def _test_cache_headers(self, view, hours): test_request = self.rf.get("/hi-there-dude/") resp = view(test_request) num_seconds = hours * 60 * 60 - self.assertEqual(resp["cache-control"], "max-age=%d" % num_seconds) + self.assertEqual(resp["cache-control"], f"max-age={num_seconds}") now_date = floor(time.time()) exp_date = parse_http_date(resp["expires"]) diff --git a/bedrock/mozorg/tests/test_helper_misc.py b/bedrock/mozorg/tests/test_helper_misc.py index 10db290a46f..d21e6631f58 100644 --- a/bedrock/mozorg/tests/test_helper_misc.py +++ b/bedrock/mozorg/tests/test_helper_misc.py @@ -6,6 +6,7 @@ import os.path from datetime import datetime +from unittest.mock import patch from django.conf import settings from django.test.client import RequestFactory @@ -14,7 +15,6 @@ import pytest from django_jinja.backend import Jinja2 from jinja2 import Markup -from mock import patch from pyquery import PyQuery as pq from bedrock.base.templatetags.helpers import static @@ -62,7 +62,7 @@ class TestImgL10n(TestCase): def _render(self, locale, url): req = self.rf.get("/") req.locale = locale - return render("{{{{ l10n_img('{0}') }}}}".format(url), {"request": req}) + return render(f"{{{{ l10n_img('{url}') }}}}", {"request": req}) def test_works_for_default_lang(self, media_exists_mock): """Should output correct path for default lang always.""" @@ -215,12 +215,12 @@ class TestPlatformImg(TestCase): def _render(self, url, optional_attributes=None): req = self.rf.get("/") req.locale = "en-US" - return render("{{{{ platform_img('{0}', {1}) }}}}".format(url, optional_attributes), {"request": req}) + return render(f"{{{{ platform_img('{url}', {optional_attributes}) }}}}", {"request": req}) def _render_l10n(self, url): req = self.rf.get("/") req.locale = "en-US" - return render("{{{{ l10n_img('{0}') }}}}".format(url), {"request": req}) + return render(f"{{{{ l10n_img('{url}') }}}}", {"request": req}) def test_platform_img_no_optional_attributes(self, find_static): """Should return expected markup without optional attributes""" @@ -335,7 +335,7 @@ class TestDonateUrl(TestCase): def _render(self, locale, source=""): req = self.rf.get("/") req.locale = locale - return render("{{{{ donate_url('{0}') }}}}".format(source), {"request": req}) + return render(f"{{{{ donate_url('{source}') }}}}", {"request": req}) def test_donate_url_no_locale(self): """No locale, fallback to generic link""" @@ -464,12 +464,12 @@ class TestHighResImg(TestCase): def _render(self, url, optional_attributes=None): req = self.rf.get("/") req.locale = "en-US" - return render("{{{{ high_res_img('{0}', {1}) }}}}".format(url, optional_attributes), {"request": req}) + return render(f"{{{{ high_res_img('{url}', {optional_attributes}) }}}}", {"request": req}) def _render_l10n(self, url): req = self.rf.get("/") req.locale = "en-US" - return render("{{{{ l10n_img('{0}') }}}}".format(url), {"request": req}) + return render(f"{{{{ l10n_img('{url}') }}}}", {"request": req}) def test_high_res_img_no_optional_attributes(self): """Should return expected markup without optional attributes""" @@ -695,7 +695,7 @@ def _render(self, locale, domain=None): sd_id = "firefoxbrowser" if domain: - return render("{{{{ structured_data_id('{0}', '{1}') }}}}".format(sd_id, domain), {"request": req}) + return render(f"{{{{ structured_data_id('{sd_id}', '{domain}') }}}}", {"request": req}) return render("{{ structured_data_id('%s') }}" % sd_id, {"request": req}) @@ -737,9 +737,9 @@ def _render(self, locale, redirect, adgroup, creative=None): req.locale = locale if creative: - return render("{{{{ firefox_adjust_url('{0}', '{1}', '{2}') }}}}".format(redirect, adgroup, creative), {"request": req}) + return render(f"{{{{ firefox_adjust_url('{redirect}', '{adgroup}', '{creative}') }}}}", {"request": req}) - return render("{{{{ firefox_adjust_url('{0}', '{1}') }}}}".format(redirect, adgroup), {"request": req}) + return render(f"{{{{ firefox_adjust_url('{redirect}', '{adgroup}') }}}}", {"request": req}) def test_firefox_ios_adjust_url(self): """Firefox for mobile with an App Store URL redirect""" @@ -778,9 +778,9 @@ def _render(self, locale, redirect, adgroup, creative=None): req.locale = locale if creative: - return render("{{{{ focus_adjust_url('{0}', '{1}', '{2}') }}}}".format(redirect, adgroup, creative), {"request": req}) + return render(f"{{{{ focus_adjust_url('{redirect}', '{adgroup}', '{creative}') }}}}", {"request": req}) - return render("{{{{ focus_adjust_url('{0}', '{1}') }}}}".format(redirect, adgroup), {"request": req}) + return render(f"{{{{ focus_adjust_url('{redirect}', '{adgroup}') }}}}", {"request": req}) def test_focus_ios_adjust_url(self): """Firefox Focus with an App Store URL redirect""" @@ -835,9 +835,9 @@ def _render(self, locale, redirect, adgroup, creative=None): req.locale = locale if creative: - return render("{{{{ lockwise_adjust_url('{0}', '{1}', '{2}') }}}}".format(redirect, adgroup, creative), {"request": req}) + return render(f"{{{{ lockwise_adjust_url('{redirect}', '{adgroup}', '{creative}') }}}}", {"request": req}) - return render("{{{{ lockwise_adjust_url('{0}', '{1}') }}}}".format(redirect, adgroup), {"request": req}) + return render(f"{{{{ lockwise_adjust_url('{redirect}', '{adgroup}') }}}}", {"request": req}) def test_lockwise_ios_adjust_url(self): """Firefox Lockwise for mobile with an App Store URL redirect""" @@ -876,9 +876,9 @@ def _render(self, locale, redirect, adgroup, creative=None): req.locale = locale if creative: - return render("{{{{ pocket_adjust_url('{0}', '{1}', '{2}') }}}}".format(redirect, adgroup, creative), {"request": req}) + return render(f"{{{{ pocket_adjust_url('{redirect}', '{adgroup}', '{creative}') }}}}", {"request": req}) - return render("{{{{ pocket_adjust_url('{0}', '{1}') }}}}".format(redirect, adgroup), {"request": req}) + return render(f"{{{{ pocket_adjust_url('{redirect}', '{adgroup}') }}}}", {"request": req}) def test_pocket_ios_adjust_url(self): """Pocket for mobile with an App Store URL redirect""" @@ -1135,7 +1135,7 @@ class TestFxALinkFragment(TestCase): def _render(self, entrypoint, action="signup", optional_parameters=None): req = self.rf.get("/") req.locale = "en-US" - return render("{{{{ fxa_link_fragment('{0}', '{1}', {2}) }}}}".format(entrypoint, action, optional_parameters), {"request": req}) + return render(f"{{{{ fxa_link_fragment('{entrypoint}', '{action}', {optional_parameters}) }}}}", {"request": req}) def test_fxa_button_signup(self): """Should return expected markup""" diff --git a/bedrock/mozorg/tests/test_helper_qrcode.py b/bedrock/mozorg/tests/test_helper_qrcode.py index e9e7a686f43..b3e5ad807cb 100644 --- a/bedrock/mozorg/tests/test_helper_qrcode.py +++ b/bedrock/mozorg/tests/test_helper_qrcode.py @@ -2,7 +2,8 @@ # 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 mock import patch +from unittest.mock import patch + from qrcode.image.svg import SvgPathImage from bedrock.mozorg.templatetags.qrcode import qrcode diff --git a/bedrock/mozorg/tests/test_hierarchy.py b/bedrock/mozorg/tests/test_hierarchy.py index 285354b35ed..8dd81798914 100644 --- a/bedrock/mozorg/tests/test_hierarchy.py +++ b/bedrock/mozorg/tests/test_hierarchy.py @@ -2,7 +2,7 @@ # 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 mock import patch +from unittest.mock import patch from bedrock.mozorg.hierarchy import PageNode, PageRoot from bedrock.mozorg.tests import TestCase diff --git a/bedrock/mozorg/tests/test_util.py b/bedrock/mozorg/tests/test_util.py index 3465b9b054e..a91fce43ba1 100644 --- a/bedrock/mozorg/tests/test_util.py +++ b/bedrock/mozorg/tests/test_util.py @@ -1,15 +1,12 @@ -# coding=utf-8 - # This Source Code Form is subject to the terms of the Mozilla Public # 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/. import os +from unittest.mock import ANY, patch from django.test import RequestFactory -from mock import ANY, patch - from bedrock.mozorg.tests import TestCase from bedrock.mozorg.util import get_fb_like_locale, page diff --git a/bedrock/mozorg/tests/test_views.py b/bedrock/mozorg/tests/test_views.py index 04926e42077..3f23e72bd94 100644 --- a/bedrock/mozorg/tests/test_views.py +++ b/bedrock/mozorg/tests/test_views.py @@ -1,14 +1,13 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. import os +from unittest.mock import ANY, Mock, patch from django.http.response import HttpResponse from django.test.client import RequestFactory import pytest -from mock import ANY, Mock, patch from bedrock.base.urlresolvers import reverse from bedrock.mozorg import views diff --git a/bedrock/mozorg/tests/urls.py b/bedrock/mozorg/tests/urls.py index c60345753a6..95cb8f3ae4f 100644 --- a/bedrock/mozorg/tests/urls.py +++ b/bedrock/mozorg/tests/urls.py @@ -14,7 +14,7 @@ def mock_view(request): urlpatterns = [ - path("", include("%s.urls" % settings.PROJECT_MODULE)), + path("", include(f"{settings.PROJECT_MODULE}.urls")), # Used by test_helper page("base", "base-protocol.html"), ] diff --git a/bedrock/newsletter/forms.py b/bedrock/newsletter/forms.py index cfc9f567cfa..b77637c700f 100644 --- a/bedrock/newsletter/forms.py +++ b/bedrock/newsletter/forms.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. @@ -75,7 +74,7 @@ def __init__(self, attrs=None): ("true", ftl("newsletter-form-yes")), ("false", ftl("newsletter-form-no")), ) - super(BooleanTabularRadioSelect, self).__init__(attrs, choices) + super().__init__(attrs, choices) def format_value(self, value): try: @@ -98,7 +97,7 @@ def value_from_datadict(self, data, files, name): }.get(value) def get_context(self, name, value, attrs): - context = super(BooleanTabularRadioSelect, self).get_context(name, value, attrs) + context = super().get_context(name, value, attrs) context["wrap_label"] = False return context @@ -107,7 +106,7 @@ class TableCheckboxInput(widgets.CheckboxInput): """Add table cell markup around the rendered checkbox""" def render(self, *args, **kwargs): - out = super(TableCheckboxInput, self).render(*args, **kwargs) + out = super().render(*args, **kwargs) return mark_safe("" + out + "") @@ -123,7 +122,7 @@ class CountrySelectForm(forms.Form): def __init__(self, locale, *args, **kwargs): regions = product_details.get_regions(locale) regions = sorted(iter(regions.items()), key=itemgetter(1)) - super(CountrySelectForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields["country"].choices = regions @@ -193,7 +192,7 @@ def __init__(self, locale, *args, **kwargs): initial["lang"] = lang kwargs["initial"] = initial - super(ManageSubscriptionsForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields["country"].choices = regions self.fields["lang"].choices = lang_choices @@ -205,7 +204,7 @@ def clean(self): if newsletter not in valid_newsletters: msg = ftl("newsletters-is-not-a-valid-newsletter", newsletter=newsletter, ftl_files=["mozorg/newsletters"]) raise ValidationError(msg) - return super(ManageSubscriptionsForm, self).clean() + return super().clean() class NewsletterForm(forms.Form): @@ -273,7 +272,7 @@ def __init__(self, newsletters, locale, data=None, *args, **kwargs): lang = "" lang_choices.insert(0, ("", ftl_lazy("newsletter-form-available-languages"))) - super(NewsletterFooterForm, self).__init__(data, *args, **kwargs) + super().__init__(data, *args, **kwargs) required_args = { "required": "required", diff --git a/bedrock/newsletter/management/commands/update_newsletter_data.py b/bedrock/newsletter/management/commands/update_newsletter_data.py index 1e568a0b47f..ec2242a2cec 100644 --- a/bedrock/newsletter/management/commands/update_newsletter_data.py +++ b/bedrock/newsletter/management/commands/update_newsletter_data.py @@ -23,6 +23,6 @@ def handle(self, *args, **options): count = Newsletter.objects.refresh(newsletters) if not options["quiet"]: if count: - print("Updated %d newsletters" % count) + print(f"Updated {count} newsletters") else: print("Nothing to update") diff --git a/bedrock/newsletter/migrations/0001_initial.py b/bedrock/newsletter/migrations/0001_initial.py index 6a301c26428..cdfc4aca33d 100644 --- a/bedrock/newsletter/migrations/0001_initial.py +++ b/bedrock/newsletter/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. diff --git a/bedrock/newsletter/tests/__init__.py b/bedrock/newsletter/tests/__init__.py index f22f82db3dd..edd8b577a7c 100644 --- a/bedrock/newsletter/tests/__init__.py +++ b/bedrock/newsletter/tests/__init__.py @@ -2,7 +2,7 @@ # 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 mock import Mock +from unittest.mock import Mock from bedrock.newsletter import utils diff --git a/bedrock/newsletter/tests/test_footer_form.py b/bedrock/newsletter/tests/test_footer_form.py index 45e50842296..c0f6c2dc416 100644 --- a/bedrock/newsletter/tests/test_footer_form.py +++ b/bedrock/newsletter/tests/test_footer_form.py @@ -2,9 +2,10 @@ # 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 unittest.mock import patch + from django.test.utils import override_settings -from mock import patch from pyquery import PyQuery as pq from bedrock.base.urlresolvers import reverse diff --git a/bedrock/newsletter/tests/test_forms.py b/bedrock/newsletter/tests/test_forms.py index 006c8396191..d25bf7f1566 100644 --- a/bedrock/newsletter/tests/test_forms.py +++ b/bedrock/newsletter/tests/test_forms.py @@ -1,7 +1,7 @@ # This Source Code Form is subject to the terms of the Mozilla Public # 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/. -import mock +from unittest import mock from bedrock.mozorg.tests import TestCase from bedrock.newsletter.forms import ( diff --git a/bedrock/newsletter/tests/test_misc.py b/bedrock/newsletter/tests/test_misc.py index f4b8eb9598b..ad28c88be4e 100644 --- a/bedrock/newsletter/tests/test_misc.py +++ b/bedrock/newsletter/tests/test_misc.py @@ -2,7 +2,7 @@ # 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/. -import mock +from unittest import mock from bedrock.mozorg.tests import TestCase from bedrock.newsletter import utils diff --git a/bedrock/newsletter/tests/test_views.py b/bedrock/newsletter/tests/test_views.py index 19b19c79f45..03f15d1ea91 100644 --- a/bedrock/newsletter/tests/test_views.py +++ b/bedrock/newsletter/tests/test_views.py @@ -3,13 +3,13 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. import json import uuid +from unittest.mock import ANY, DEFAULT, patch from django.http import HttpResponse from django.test.client import RequestFactory from django.test.utils import override_settings import basket -from mock import ANY, DEFAULT, patch from pyquery import PyQuery as pq from bedrock.base.urlresolvers import reverse @@ -85,14 +85,14 @@ def setUp(self): "form-3-subscribed_check": "false", "submit": "Save Preferences", } - super(TestExistingNewsletterView, self).setUp() + super().setUp() @patch("bedrock.newsletter.utils.get_newsletters") def test_will_show_confirm_copy(self, get_newsletters, mock_basket_request): # After successful confirm, ensure proper context var is set to display # confirmation-specific copy. get_newsletters.return_value = newsletters - url = "%s?confirm=1" % reverse("newsletter.existing.token", args=(self.token,)) + url = f"{reverse('newsletter.existing.token', args=(self.token,))}?confirm=1" # noinspection PyUnresolvedReferences with patch.multiple("basket", request=DEFAULT) as basket_patches: with patch("lib.l10n_utils.render") as render: @@ -138,9 +138,9 @@ def test_show(self, get_newsletters, mock_basket_request): request, template_name, context = render.call_args[0] forms = context["formset"].initial_forms - shown = set([form.initial["newsletter"] for form in forms]) - inactive = set([newsletter for newsletter, data in newsletters.items() if not data.get("active", False)]) - to_show = set([newsletter for newsletter, data in newsletters.items() if data.get("show", False)]) - inactive + shown = {form.initial["newsletter"] for form in forms} + inactive = {newsletter for newsletter, data in newsletters.items() if not data.get("active", False)} + to_show = {newsletter for newsletter, data in newsletters.items() if data.get("show", False)} - inactive subscribed = set(self.user["newsletters"]) # All subscribed newsletters except inactive ones are shown @@ -226,9 +226,9 @@ def test_subscribing(self, get_newsletters, mock_basket_request): # Should have called update_user with subscription list self.assertEqual(1, basket_patches["update_user"].call_count) kwargs = basket_patches["update_user"].call_args[1] - self.assertEqual(set(kwargs), set(["api_key", "newsletters", "lang"])) + self.assertEqual(set(kwargs), {"api_key", "newsletters", "lang"}) self.assertEqual(kwargs["lang"], "en") - self.assertEqual(set(kwargs["newsletters"].split(",")), set(["mozilla-and-you", "firefox-tips"])) + self.assertEqual(set(kwargs["newsletters"].split(",")), {"mozilla-and-you", "firefox-tips"}) # Should not have called unsubscribe self.assertEqual(0, basket_patches["unsubscribe"].call_count) # Should not have called subscribe @@ -278,8 +278,7 @@ def test_remove_all(self, get_newsletters, mock_basket_request): self.assertEqual((self.token, self.user["email"]), args) self.assertTrue(kwargs["optout"]) # Should redirect to the 'updated' view with unsub=1 and token - url = reverse("newsletter.updated") + "?unsub=1" - url += "&token=%s" % self.token + url = f"{reverse('newsletter.updated')}?unsub=1&token={self.token}" assert rsp["Location"] == url @patch("bedrock.newsletter.utils.get_newsletters") @@ -365,7 +364,7 @@ def test_normal(self): confirm.return_value = {"status": "ok"} rsp = self.client.get(self.url) self.assertEqual(302, rsp.status_code) - self.assertTrue(rsp["Location"].endswith("%s?confirm=1" % reverse("newsletter.existing.token", kwargs={"token": self.token}))) + self.assertTrue(rsp["Location"].endswith(f"{reverse('newsletter.existing.token', kwargs={'token': self.token})}?confirm=1")) def test_normal_with_query_params(self): """Confirm works with a valid token""" @@ -375,8 +374,8 @@ def test_normal_with_query_params(self): self.assertEqual(302, rsp.status_code) self.assertTrue( rsp["Location"].endswith( - "%s?confirm=1&utm_tracking=oh+definitely+yes&" - "utm_source=malibu" % reverse("newsletter.existing.token", kwargs={"token": self.token}) + f"{reverse('newsletter.existing.token', kwargs={'token': self.token})}" + "?confirm=1&utm_tracking=oh+definitely+yes&utm_source=malibu" ) ) diff --git a/bedrock/newsletter/views.py b/bedrock/newsletter/views.py index 2e939c03a6e..9ea18bf6863 100644 --- a/bedrock/newsletter/views.py +++ b/bedrock/newsletter/views.py @@ -230,7 +230,7 @@ def confirm(request, token): try: result = basket.confirm(token) except basket.BasketException as e: - log.exception("Exception confirming token %s" % token) + log.exception(f"Exception confirming token {token}") if e.code == basket.errors.BASKET_UNKNOWN_TOKEN: token_error = True elif e.code == basket.errors.BASKET_USAGE_ERROR: @@ -253,7 +253,7 @@ def confirm(request, token): qs = request.META.get("QUERY_STRING", "") if qs: qparams.append(qs) - return HttpResponseRedirect("%s?%s" % (reverse("newsletter.existing.token", kwargs={"token": token}), "&".join(qparams))) + return HttpResponseRedirect("{}?{}".format(reverse("newsletter.existing.token", kwargs={"token": token}), "&".join(qparams))) else: return l10n_utils.render( request, "newsletter/confirm.html", {"success": success, "generic_error": generic_error, "token_error": token_error}, ftl_files=FTL_FILES @@ -400,13 +400,11 @@ def existing(request, token=None): if formset.is_valid(): formset_is_valid = True # What newsletters do they say they want to be subscribed to? - newsletters = set( - [ - subform.cleaned_data["newsletter"] - for subform in formset - if (subform.cleaned_data["subscribed_radio"] or subform.cleaned_data["subscribed_check"]) - ] - ) + newsletters = { + subform.cleaned_data["newsletter"] + for subform in formset + if (subform.cleaned_data["subscribed_radio"] or subform.cleaned_data["subscribed_check"]) + } form_kwargs["newsletters"] = newsletters form = ManageSubscriptionsForm(locale, data=request.POST, initial=user, **form_kwargs) @@ -445,7 +443,7 @@ def existing(request, token=None): messages.add_message(request, messages.ERROR, general_error) return l10n_utils.render(request, "newsletter/existing.html", ftl_files=FTL_FILES) # We need to pass their token to the next view - url = reverse("newsletter.updated") + "?unsub=%s&token=%s" % (UNSUB_UNSUBSCRIBED_ALL, token) + url = reverse("newsletter.updated") + f"?unsub={UNSUB_UNSUBSCRIBED_ALL}&token={token}" return redirect(url) # We're going to redirect, so the only way to tell the next @@ -453,7 +451,7 @@ def existing(request, token=None): # template is to modify the URL url = reverse("newsletter.updated") if unsub_parm: - url += "?unsub=%s" % unsub_parm + url += f"?unsub={unsub_parm}" return redirect(url) # FALL THROUGH so page displays errors @@ -540,7 +538,7 @@ def updated(request): # paste together the English versions of the reasons they submitted, # so we can read them. (Well, except for the free-form reason.) for i, reason in enumerate(REASONS): - if _post_or_get(request, "reason%d" % i): + if _post_or_get(request, f"reason{i}"): reasons.append(str(reason)) if _post_or_get(request, "reason-text-p"): reasons.append(_post_or_get(request, "reason-text", "")) @@ -617,8 +615,8 @@ def newsletter_subscribe(request): kwargs = {"format": data["fmt"]} # add optional data kwargs.update( - dict( - (k, data[k]) + { + k: data[k] for k in [ "country", "lang", @@ -627,7 +625,7 @@ def newsletter_subscribe(request): "last_name", ] if data[k] - ) + } ) # NOTE this is not a typo; Referrer is misspelled in the HTTP spec @@ -641,7 +639,7 @@ def newsletter_subscribe(request): if e.code == basket.errors.BASKET_INVALID_EMAIL: errors.append(str(invalid_email_address)) else: - log.exception("Error subscribing %s to newsletter %s" % (data["email"], data["newsletters"])) + log.exception(f"Error subscribing {data['email']} to newsletter {data['newsletters']}") errors.append(str(general_error)) else: diff --git a/bedrock/pocketfeed/management/commands/update_pocketfeed.py b/bedrock/pocketfeed/management/commands/update_pocketfeed.py index 361c97fcd4f..8fcd1e610d2 100644 --- a/bedrock/pocketfeed/management/commands/update_pocketfeed.py +++ b/bedrock/pocketfeed/management/commands/update_pocketfeed.py @@ -23,10 +23,10 @@ def handle(self, *args, **options): if not options["quiet"]: if updated: - print("Refreshed %s articles from Pocket" % updated) + print(f"Refreshed {updated} articles from Pocket") if deleted: - print("Deleted %s old articles" % deleted) + print(f"Deleted {deleted} old articles") else: print("Pocket feed is already up to date") else: diff --git a/bedrock/pocketfeed/migrations/0001_initial.py b/bedrock/pocketfeed/migrations/0001_initial.py index f4181e383b2..bda03c290b0 100644 --- a/bedrock/pocketfeed/migrations/0001_initial.py +++ b/bedrock/pocketfeed/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. diff --git a/bedrock/pocketfeed/migrations/0002_auto_20180723_0805.py b/bedrock/pocketfeed/migrations/0002_auto_20180723_0805.py index d18ae8b593a..3b8fb9634f0 100644 --- a/bedrock/pocketfeed/migrations/0002_auto_20180723_0805.py +++ b/bedrock/pocketfeed/migrations/0002_auto_20180723_0805.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. diff --git a/bedrock/pocketfeed/models.py b/bedrock/pocketfeed/models.py index 7ea4a0ec944..0ede0d0250b 100644 --- a/bedrock/pocketfeed/models.py +++ b/bedrock/pocketfeed/models.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - # This Source Code Form is subject to the terms of the Mozilla Public # 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/. diff --git a/bedrock/pocketfeed/tests/test_api.py b/bedrock/pocketfeed/tests/test_api.py index cfb6feed223..ca87627fe3e 100644 --- a/bedrock/pocketfeed/tests/test_api.py +++ b/bedrock/pocketfeed/tests/test_api.py @@ -3,12 +3,11 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. import datetime +from unittest.mock import patch from django.test import override_settings from django.utils.timezone import make_aware, utc -from mock import patch - from bedrock.pocketfeed import api diff --git a/bedrock/press/forms.py b/bedrock/press/forms.py index 3c7dc26affa..12505c275fa 100644 --- a/bedrock/press/forms.py +++ b/bedrock/press/forms.py @@ -1,5 +1,3 @@ -# coding: utf-8 - # This Source Code Form is subject to the terms of the Mozilla Public # 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/. @@ -44,7 +42,7 @@ class PressInquiryForm(forms.Form): office_fax = forms.CharField(widget=HoneyPotWidget, required=False) def clean_office_fax(self): - cleaned_data = super(PressInquiryForm, self).clean() + cleaned_data = super().clean() honeypot = cleaned_data.pop("office_fax", None) if honeypot: @@ -299,7 +297,7 @@ class SpeakerRequestForm(forms.Form): office_fax = forms.CharField(widget=HoneyPotWidget, required=False) def clean_sr_attachment(self): - cleaned_data = super(SpeakerRequestForm, self).clean() + cleaned_data = super().clean() attachment = cleaned_data.get("sr_attachment") if attachment: @@ -309,7 +307,7 @@ def clean_sr_attachment(self): return attachment def clean_office_fax(self): - cleaned_data = super(SpeakerRequestForm, self).clean() + cleaned_data = super().clean() honeypot = cleaned_data.pop("office_fax", None) if honeypot: diff --git a/bedrock/press/tests/test_base.py b/bedrock/press/tests/test_base.py index 7fa2c7266fa..98e642fec89 100644 --- a/bedrock/press/tests/test_base.py +++ b/bedrock/press/tests/test_base.py @@ -1,15 +1,13 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. import datetime +from unittest.mock import Mock, patch from django.core import mail from django.test.client import RequestFactory -from mock import Mock, patch - from bedrock.base.urlresolvers import reverse from bedrock.mozorg.tests import TestCase from bedrock.press import forms as press_forms, views as press_views diff --git a/bedrock/press/views.py b/bedrock/press/views.py index 86ada0e645c..509f0c4892e 100644 --- a/bedrock/press/views.py +++ b/bedrock/press/views.py @@ -26,10 +26,10 @@ class PressInquiryView(FormView): @method_decorator(csrf_protect) def dispatch(self, request, *args, **kwargs): - return super(PressInquiryView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def get_context_data(self, **kwargs): - context = super(PressInquiryView, self).get_context_data(**kwargs) + context = super().get_context_data(**kwargs) context["form_success"] = "success" in self.request.GET return context @@ -38,7 +38,7 @@ def get_success_url(self): def form_valid(self, form): self.send_email(form) - return super(PressInquiryView, self).form_valid(form) + return super().form_valid(form) def send_email(self, form): subject = PRESS_INQUIRY_EMAIL_SUBJECT @@ -59,15 +59,15 @@ class SpeakerRequestView(FormView): @method_decorator(csrf_protect) def dispatch(self, request, *args, **kwargs): - return super(SpeakerRequestView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def get_form_kwargs(self): - kwargs = super(SpeakerRequestView, self).get_form_kwargs() + kwargs = super().get_form_kwargs() kwargs["auto_id"] = "%s" return kwargs def get_context_data(self, **kwargs): - context = super(SpeakerRequestView, self).get_context_data(**kwargs) + context = super().get_context_data(**kwargs) context["form_success"] = "success" in self.request.GET return context @@ -76,7 +76,7 @@ def get_success_url(self): def form_valid(self, form): self.send_email(form) - return super(SpeakerRequestView, self).form_valid(form) + return super().form_valid(form) def send_email(self, form): subject = SPEAKER_REQUEST_EMAIL_SUBJECT diff --git a/bedrock/privacy/views.py b/bedrock/privacy/views.py index 36eb26f6dc1..126cd86ed3f 100644 --- a/bedrock/privacy/views.py +++ b/bedrock/privacy/views.py @@ -34,7 +34,7 @@ def process_legal_doc(content): class PrivacyDocView(LegalDocView): def get_legal_doc(self): - doc = super(PrivacyDocView, self).get_legal_doc() + doc = super().get_legal_doc() if doc is not None: doc["content"] = process_legal_doc(doc["content"]) return doc @@ -42,7 +42,7 @@ def get_legal_doc(self): class FirefoxPrivacyDocView(PrivacyDocView): def get_legal_doc(self): - doc = super(FirefoxPrivacyDocView, self).get_legal_doc() + doc = super().get_legal_doc() if len(doc["content"].select(".privacy-header-firefox")) > 0: self.template_name = "privacy/notices/firefox.html" else: diff --git a/bedrock/products/templatetags/misc.py b/bedrock/products/templatetags/misc.py index 74210e122b3..46e8ce9d37d 100644 --- a/bedrock/products/templatetags/misc.py +++ b/bedrock/products/templatetags/misc.py @@ -29,14 +29,14 @@ def _vpn_product_link(product_url, entrypoint, link_text, class_name=None, optio href = f"{product_url}{separator}entrypoint={entrypoint}&form_type=button&service={client_id}&utm_source={entrypoint}&utm_medium=referral" if optional_parameters: - params = "&".join("%s=%s" % (param, val) for param, val in optional_parameters.items()) + params = "&".join(f"{param}={val}" for param, val in optional_parameters.items()) href += f"&{params}" css_class = "js-vpn-cta-link js-fxa-product-button" attrs = "" if optional_attributes: - attrs += " ".join('%s="%s"' % (attr, val) for attr, val in optional_attributes.items()) + attrs += " ".join(f'{attr}="{val}"' for attr, val in optional_attributes.items()) # If there's a `data-cta-position` attribute for GA, also pass that as a query param to vpn.m.o. position = optional_attributes.get("data-cta-position", None) @@ -201,7 +201,7 @@ def vpn_product_referral_link(ctx, referral_id="", page_anchor="", link_text=Non attrs = f'data-referral-id="{referral_id}" ' if optional_attributes: - attrs += " ".join('%s="%s"' % (attr, val) for attr, val in optional_attributes.items()) + attrs += " ".join(f'{attr}="{val}"' for attr, val in optional_attributes.items()) if class_name: css_class += f" {class_name}" diff --git a/bedrock/products/tests/test_helper_misc.py b/bedrock/products/tests/test_helper_misc.py index 79cb0040336..3d26bb65827 100644 --- a/bedrock/products/tests/test_helper_misc.py +++ b/bedrock/products/tests/test_helper_misc.py @@ -704,7 +704,7 @@ class TestVPNMonthlyPrice(TestCase): def _render(self, plan, country_code, lang): req = self.rf.get("/") req.locale = "en-US" - return render("{{{{ vpn_monthly_price('{0}', '{1}', '{2}') }}}}".format(plan, country_code, lang), {"request": req}) + return render(f"{{{{ vpn_monthly_price('{plan}', '{country_code}', '{lang}') }}}}", {"request": req}) def test_vpn_monthly_price_usd(self): """Should return expected markup""" diff --git a/bedrock/products/tests/test_views.py b/bedrock/products/tests/test_views.py index f1ca36d55b6..08eee946c4d 100644 --- a/bedrock/products/tests/test_views.py +++ b/bedrock/products/tests/test_views.py @@ -3,14 +3,13 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. import json +from unittest.mock import Mock, patch from django.http import HttpResponse from django.test import override_settings from django.test.client import RequestFactory from django.urls import reverse -from mock import Mock, patch - from bedrock.contentful.constants import ( CONTENT_CLASSIFICATION_VPN, CONTENT_TYPE_PAGE_RESOURCE_CENTER, diff --git a/bedrock/redirects/tests/test_util.py b/bedrock/redirects/tests/test_util.py index 51536ffd72f..f2f96c55ffc 100644 --- a/bedrock/redirects/tests/test_util.py +++ b/bedrock/redirects/tests/test_util.py @@ -1,14 +1,13 @@ # This Source Code Form is subject to the terms of the Mozilla Public # 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 unittest.mock import patch from urllib.parse import parse_qs, urlparse from django.test import TestCase from django.test.client import RequestFactory from django.urls import URLPattern -from mock import patch - from bedrock.redirects.middleware import RedirectsMiddleware from bedrock.redirects.util import ( get_resolver, diff --git a/bedrock/redirects/util.py b/bedrock/redirects/util.py index 41d45f6e093..3846e5dfe32 100644 --- a/bedrock/redirects/util.py +++ b/bedrock/redirects/util.py @@ -102,7 +102,7 @@ def no_redirect(pattern, locale_prefix=True, re_flags=None): pattern = LOCALE_RE + pattern if re_flags: - pattern = "(?{})".format(re_flags) + pattern + pattern = f"(?{re_flags})" + pattern def _view(request, *args, **kwargs): return None @@ -175,7 +175,7 @@ def redirect( pattern = LOCALE_RE + pattern if re_flags: - pattern = "(?{})".format(re_flags) + pattern + pattern = f"(?{re_flags})" + pattern view_decorators = [] if cache_timeout is not None: diff --git a/bedrock/releasenotes/management/commands/update_release_notes.py b/bedrock/releasenotes/management/commands/update_release_notes.py index 642c668a2c2..864719fc8f5 100644 --- a/bedrock/releasenotes/management/commands/update_release_notes.py +++ b/bedrock/releasenotes/management/commands/update_release_notes.py @@ -32,7 +32,7 @@ def handle(self, *args, **options): self.output("Loading releases into database") count = ProductRelease.objects.refresh() - self.output("%s release notes successfully loaded" % count) + self.output(f"{count} release notes successfully loaded") repo.set_db_latest() diff --git a/bedrock/releasenotes/migrations/0001_initial.py b/bedrock/releasenotes/migrations/0001_initial.py index be9e3956280..4d5110a5f74 100644 --- a/bedrock/releasenotes/migrations/0001_initial.py +++ b/bedrock/releasenotes/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. diff --git a/bedrock/releasenotes/models.py b/bedrock/releasenotes/models.py index 52b151a7631..4c17613d3d8 100644 --- a/bedrock/releasenotes/models.py +++ b/bedrock/releasenotes/models.py @@ -123,7 +123,7 @@ class MarkdownField(models.TextField): """Field that takes Markdown text as input and saves HTML to the database""" def pre_save(self, model_instance, add): - value = super(MarkdownField, self).pre_save(model_instance, add) + value = super().pre_save(model_instance, add) value = process_markdown(value) setattr(model_instance, self.attname, value) return value @@ -271,7 +271,7 @@ def equivalent_release_for_product(self, product): channel and major version with the highest minor version, or None if no such releases exist """ - releases = ProductRelease.objects.product(product, self.channel).filter(version__startswith="%s." % self.major_version) + releases = ProductRelease.objects.product(product, self.channel).filter(version__startswith=f"{self.major_version}.") if releases: return sorted(releases, reverse=True, key=attrgetter("version_obj"))[0] diff --git a/bedrock/releasenotes/tests/test__utils.py b/bedrock/releasenotes/tests/test__utils.py index ab6618f07f3..239e0a686de 100644 --- a/bedrock/releasenotes/tests/test__utils.py +++ b/bedrock/releasenotes/tests/test__utils.py @@ -3,11 +3,10 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. import time +from unittest.mock import Mock, patch from django.core.cache import caches -from mock import Mock, patch - from bedrock.mozorg.tests import TestCase from bedrock.releasenotes import utils diff --git a/bedrock/releasenotes/tests/test_base.py b/bedrock/releasenotes/tests/test_base.py index e88dd29bae1..03d304854b8 100644 --- a/bedrock/releasenotes/tests/test_base.py +++ b/bedrock/releasenotes/tests/test_base.py @@ -3,14 +3,13 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. from pathlib import Path +from unittest.mock import Mock, patch from django.core.cache import caches from django.http import Http404, HttpResponse from django.test.client import RequestFactory from django.test.utils import override_settings -from mock import Mock, patch - from bedrock.base.urlresolvers import reverse from bedrock.firefox.firefox_details import FirefoxDesktop from bedrock.mozorg.tests import TestCase diff --git a/bedrock/releasenotes/tests/test_models.py b/bedrock/releasenotes/tests/test_models.py index 51598abd1df..5a9dc8e3b69 100644 --- a/bedrock/releasenotes/tests/test_models.py +++ b/bedrock/releasenotes/tests/test_models.py @@ -4,12 +4,11 @@ from itertools import chain from pathlib import Path +from unittest.mock import call, patch from django.core.cache import caches from django.test.utils import override_settings -from mock import call, patch - from bedrock.mozorg.tests import TestCase from bedrock.releasenotes import models diff --git a/bedrock/releasenotes/utils.py b/bedrock/releasenotes/utils.py index efa0308b430..f8fbacd77cb 100644 --- a/bedrock/releasenotes/utils.py +++ b/bedrock/releasenotes/utils.py @@ -28,14 +28,14 @@ class ReleaseMemoizer(Memoizer): def __init__(self, version_timeout=300): self.version_timeout = version_timeout - return super(ReleaseMemoizer, self).__init__(cache=caches["release-notes"]) + return super().__init__(cache=caches["release-notes"]) def _memoize_make_version_hash(self): return get_data_version() def _memoize_version(self, f, args=None, reset=False, delete=False, timeout=None): """Use a shorter timeout for the version so that we can refresh based on git hash""" - return super(ReleaseMemoizer, self)._memoize_version(f, args, reset, delete, self.version_timeout) + return super()._memoize_version(f, args, reset, delete, self.version_timeout) memoizer = ReleaseMemoizer() diff --git a/bedrock/releasenotes/views.py b/bedrock/releasenotes/views.py index c1536e9773d..afdb7565e82 100644 --- a/bedrock/releasenotes/views.py +++ b/bedrock/releasenotes/views.py @@ -35,7 +35,7 @@ def release_notes_template(channel, product, version=None): dir = "firefox" - return "{dir}/releases/{channel}-notes.html".format(dir=dir, channel=channel.lower()) + return f"{dir}/releases/{channel.lower()}-notes.html" def equivalent_release_url(release): @@ -130,7 +130,7 @@ def release_notes(request, version, product="Firefox"): def system_requirements(request, version, product="Firefox"): release = get_release_or_404(version, product) dir = "firefox" - return l10n_utils.render(request, "{dir}/releases/system_requirements.html".format(dir=dir), {"release": release, "version": version}) + return l10n_utils.render(request, f"{dir}/releases/system_requirements.html", {"release": release, "version": version}) def latest_release(product="firefox", platform=None, channel=None): @@ -184,9 +184,7 @@ def releases_index(request, product): ), } - return l10n_utils.render( - request, "{product}/releases/index.html".format(product=product.lower()), {"releases": sorted(releases.items(), reverse=True)} - ) + return l10n_utils.render(request, f"{product.lower()}/releases/index.html", {"releases": sorted(releases.items(), reverse=True)}) def nightly_feed(request): @@ -205,7 +203,7 @@ def nightly_feed(request): continue if note.is_public and note.tag: - note.link = "%s#note-%s" % (link, note.id) + note.link = f"{link}#note-{note.id}" note.version = release.version notes[note.id] = note diff --git a/bedrock/security/management/commands/update_security_advisories.py b/bedrock/security/management/commands/update_security_advisories.py index 94b0f7cb810..e6cfce65361 100644 --- a/bedrock/security/management/commands/update_security_advisories.py +++ b/bedrock/security/management/commands/update_security_advisories.py @@ -175,7 +175,7 @@ def update_db_from_file(filename): elif filename.endswith(".yml"): parser = parse_yml_file else: - raise RuntimeError("Unknown file type %s" % filename) + raise RuntimeError(f"Unknown file type {filename}") data, html = parser(filename) if "advisories" in data: @@ -207,7 +207,7 @@ def get_files_to_delete_from_db(filenames): file_ids = set(get_ids_from_files(filenames)) db_ids = set(SecurityAdvisory.objects.values_list("id", flat=True)) to_delete = db_ids - file_ids - return ["mfsa{0}.md".format(fid) for fid in to_delete] + return [f"mfsa{fid}.md" for fid in to_delete] def delete_orphaned_products(): @@ -280,7 +280,7 @@ def printout(msg, ending=None): try: update_db_from_file(mf) except Exception as e: - errors.append("ERROR parsing %s: %s" % (mf, e)) + errors.append(f"ERROR parsing {mf}: {e}") if not quiet: sys.stdout.write("E") sys.stdout.flush() @@ -289,17 +289,17 @@ def printout(msg, ending=None): sys.stdout.write(".") sys.stdout.flush() updates += 1 - printout("\nUpdated {0} files.".format(updates)) + printout(f"\nUpdated {updates} files.") if not clear_db: deleted_files = get_files_to_delete_from_db(all_files) delete_files(deleted_files) - printout("Deleted {0} files.".format(len(deleted_files))) + printout(f"Deleted {len(deleted_files)} files.") num_products = delete_orphaned_products() if num_products: - printout("Deleted {0} orphaned products.".format(num_products)) + printout(f"Deleted {num_products} orphaned products.") if errors: - raise CommandError("Encountered {0} errors:\n\n".format(len(errors)) + "\n==========\n".join(errors)) + raise CommandError(f"Encountered {len(errors)} errors:\n\n" + "\n==========\n".join(errors)) repo.set_db_latest() diff --git a/bedrock/security/migrations/0001_initial.py b/bedrock/security/migrations/0001_initial.py index 91877af6dab..b094c5f37ec 100644 --- a/bedrock/security/migrations/0001_initial.py +++ b/bedrock/security/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. diff --git a/bedrock/security/migrations/0002_auto_20161013_0642.py b/bedrock/security/migrations/0002_auto_20161013_0642.py index 91d870c1870..b2007f49c08 100644 --- a/bedrock/security/migrations/0002_auto_20161013_0642.py +++ b/bedrock/security/migrations/0002_auto_20161013_0642.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. diff --git a/bedrock/security/migrations/0003_halloffamer.py b/bedrock/security/migrations/0003_halloffamer.py index 860fcc2c162..e288e83f903 100644 --- a/bedrock/security/migrations/0003_halloffamer.py +++ b/bedrock/security/migrations/0003_halloffamer.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. diff --git a/bedrock/security/migrations/0004_mitrecve.py b/bedrock/security/migrations/0004_mitrecve.py index e0abe3a2162..88d6a305445 100644 --- a/bedrock/security/migrations/0004_mitrecve.py +++ b/bedrock/security/migrations/0004_mitrecve.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. diff --git a/bedrock/security/migrations/0005_mitrecve_mfsa_ids.py b/bedrock/security/migrations/0005_mitrecve_mfsa_ids.py index bede135af24..10ebb77a3da 100644 --- a/bedrock/security/migrations/0005_mitrecve_mfsa_ids.py +++ b/bedrock/security/migrations/0005_mitrecve_mfsa_ids.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. diff --git a/bedrock/security/models.py b/bedrock/security/models.py index f2cb859f133..6b653344ee3 100644 --- a/bedrock/security/models.py +++ b/bedrock/security/models.py @@ -58,8 +58,8 @@ def save(self, force_insert=False, force_update=False, using=None, update_fields product, vers = self.name_and_version self.product = product self.product_slug = slugify(product) - self.slug = "{0}-{1}".format(self.product_slug, vers) - super(Product, self).save(force_insert, force_update, using, update_fields) + self.slug = f"{self.product_slug}-{vers}" + super().save(force_insert, force_update, using, update_fields) class SecurityAdvisory(models.Model): @@ -80,7 +80,7 @@ class Meta: get_latest_by = "last_modified" def __str__(self): - return "MFSA {0}".format(self.id) + return f"MFSA {self.id}" def get_absolute_url(self): return reverse("security.advisory", kwargs={"pk": self.id}) @@ -94,7 +94,7 @@ def impact_class(self): @property def products(self): - prods_set = set(v.product for v in self.fixed_in.all()) + prods_set = {v.product for v in self.fixed_in.all()} return sorted(prods_set) @@ -129,7 +129,7 @@ def year_quarter(self): @property def quarter_string(self): year, quarter = self.year_quarter - return "%s Quarter %s" % (self.ORDINALS[quarter], year) + return f"{self.ORDINALS[quarter]} Quarter {year}" class MitreCVE(models.Model): @@ -165,7 +165,7 @@ def product_versions(self): def get_description(self): versions = [] for prod_name, prod_versions in self.product_versions().items(): - versions.extend("%s < %s" % (prod_name, v) for v in prod_versions) + versions.extend(f"{prod_name} < {v}" for v in prod_versions) description = self.description.strip() if versions: @@ -182,7 +182,7 @@ def get_description(self): else: description += ". " - description += "This vulnerability affects %s." % vers_str + description += f"This vulnerability affects {vers_str}." return description @@ -201,7 +201,7 @@ def get_product_data(self): return product_data def get_reference_data(self): - reference_data = [{"url": "https://www.mozilla.org/security/advisories/mfsa{}/".format(mfsa_id)} for mfsa_id in set(self.mfsa_ids)] + reference_data = [{"url": f"https://www.mozilla.org/security/advisories/mfsa{mfsa_id}/"} for mfsa_id in set(self.mfsa_ids)] reference_data.extend([{"url": bug["url"]} for bug in self.bugs]) return reference_data diff --git a/bedrock/security/tests/test_commands.py b/bedrock/security/tests/test_commands.py index ca2d437aac8..0744321dc8e 100644 --- a/bedrock/security/tests/test_commands.py +++ b/bedrock/security/tests/test_commands.py @@ -3,11 +3,10 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. import os.path +from unittest.mock import patch from django.conf import settings -from mock import patch - from bedrock.mozorg.tests import TestCase from bedrock.security.management.commands import update_security_advisories from bedrock.security.models import Product @@ -72,7 +71,7 @@ def test_get_files_to_delete_from_db(self): make_mfsa("2015-102") make_mfsa("2015-103") all_files = ["mfsa2015-100.md", "mfsa2015-101.md"] - assert set(update_security_advisories.get_files_to_delete_from_db(all_files)) == set(["mfsa2015-102.md", "mfsa2015-103.md"]) + assert set(update_security_advisories.get_files_to_delete_from_db(all_files)) == {"mfsa2015-102.md", "mfsa2015-103.md"} def test_delete_orphaned_products(self): make_mfsa("2015-100") diff --git a/bedrock/security/tests/test_models.py b/bedrock/security/tests/test_models.py index 6331df24252..49f30f5fb6e 100644 --- a/bedrock/security/tests/test_models.py +++ b/bedrock/security/tests/test_models.py @@ -50,7 +50,7 @@ def _create_cve(self, products=None): self.cve_id_order += 1 products = products or ["Firefox 60", "Firefox 60.0.1"] return MitreCVE.objects.create( - id="CVE-2018-%s" % self.cve_id_order, + id=f"CVE-2018-{self.cve_id_order}", year=2018, order=self.cve_id_order, title="A Testing Problem", diff --git a/bedrock/security/tests/test_utils.py b/bedrock/security/tests/test_utils.py index 1b3cce49bac..32a5583a43f 100644 --- a/bedrock/security/tests/test_utils.py +++ b/bedrock/security/tests/test_utils.py @@ -4,9 +4,9 @@ from datetime import date from io import StringIO from textwrap import dedent +from unittest.mock import call, patch import pytest -from mock import call, patch from bedrock.security.utils import ( check_hof_data, diff --git a/bedrock/security/tests/test_views.py b/bedrock/security/tests/test_views.py index 0fcb9cd304a..167fb994b34 100644 --- a/bedrock/security/tests/test_views.py +++ b/bedrock/security/tests/test_views.py @@ -2,7 +2,8 @@ # 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 mock import patch +from unittest.mock import patch + from product_details.version_compare import Version from bedrock.mozorg.tests import TestCase @@ -68,7 +69,7 @@ def test_product_version_view_filter_minor(self): class TestKVRedirects(TestCase): def _test_names(self, url_component, expected): # old urls lack '/en-US' prefix, but that will be the first redirect. - path = "/en-US/security/known-vulnerabilities/{0}.html".format(url_component) + path = f"/en-US/security/known-vulnerabilities/{url_component}.html" resp = self.client.get(path) assert resp.status_code == 301 assert expected == resp["Location"].split("/")[-2] diff --git a/bedrock/security/utils.py b/bedrock/security/utils.py index e947139d514..dc4791e7597 100644 --- a/bedrock/security/utils.py +++ b/bedrock/security/utils.py @@ -83,7 +83,7 @@ def update_advisory_bugs(advisory): if advisory.get("bugs", None): for bug in advisory["bugs"]: if not bug.get("desc", None): - bug["desc"] = "Bug %s" % bug["url"] + bug["desc"] = f"Bug {bug['url']}" bug["url"] = parse_bug_url(bug["url"]) @@ -110,10 +110,10 @@ def parse_bug_url(url): # could be an int url = str(url).strip() if re.match(r"^\d+$", url): - url = "https://bugzilla.mozilla.org/show_bug.cgi?id=%s" % url + url = f"https://bugzilla.mozilla.org/show_bug.cgi?id={url}" elif re.match(r"^[\d\s,]+$", url): url = re.sub(r"\s", "", url).replace(",", "%2C") - url = "https://bugzilla.mozilla.org/buglist.cgi?bug_id=%s" % url + url = f"https://bugzilla.mozilla.org/buglist.cgi?bug_id={url}" return url @@ -153,6 +153,6 @@ def check_hof_data(data): if "date" not in name: raise ValueError('Key "date" required for every entry in "names"') if not isinstance(name["date"], date): - raise ValueError('Key "date" should be formatted as a date (YYYY-MM-DD): %s' % name["date"]) + raise ValueError(f'Key "date" should be formatted as a date (YYYY-MM-DD): {name["date"]}') if name["date"] < date(2004, 11, 9): raise ValueError("A date can't be set before the launch date of Firefox") diff --git a/bedrock/security/views.py b/bedrock/security/views.py index 87bc6f74eb8..168106037df 100644 --- a/bedrock/security/views.py +++ b/bedrock/security/views.py @@ -108,7 +108,7 @@ def get_queryset(self): return sorted(versions, reverse=True) def get_context_data(self, **kwargs): - cxt = super(ProductView, self).get_context_data(**kwargs) + cxt = super().get_context_data(**kwargs) cxt["product_name"] = cxt["product_versions"][0].product return cxt @@ -132,10 +132,10 @@ def get_queryset(self): return sorted(versions, reverse=True) def get_context_data(self, **kwargs): - cxt = super(ProductVersionView, self).get_context_data(**kwargs) + cxt = super().get_context_data(**kwargs) prod_name, version = self.kwargs["product"], self.kwargs["version"] cxt["is_obsolete"] = product_is_obsolete(prod_name, version) - cxt["product_name"] = "{0} {1}".format(cxt["product_versions"][0].product, version) + cxt["product_name"] = f"{cxt['product_versions'][0].product} {version}" cxt["product_slug"] = prod_name return cxt @@ -145,7 +145,7 @@ class CachedRedirectView(RedirectView): @method_decorator(cache_control_expires(24 * 30)) # 30 days def dispatch(self, request, *args, **kwargs): - return super(CachedRedirectView, self).dispatch(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) class OldAdvisoriesView(CachedRedirectView): @@ -175,8 +175,7 @@ def get_redirect_args(self, url_component): match = self.prod_ver_re.match(url_component) if match: product, version = match.groups() - version = "{0}.{1}".format(*version) - return dict(viewname="security.product-version-advisories", kwargs={"product": product, "version": version}) + return dict(viewname="security.product-version-advisories", kwargs={"product": product, "version": f"{version[0]}.{version[1]}"}) if url_component.endswith("ESR"): return dict(viewname="security.product-advisories", kwargs={"slug": url_component[:-3] + "-esr"}) diff --git a/bedrock/settings/base.py b/bedrock/settings/base.py index 0444f60e78e..62d858ad03f 100644 --- a/bedrock/settings/base.py +++ b/bedrock/settings/base.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # 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/. @@ -488,7 +487,7 @@ def lazy_langs(): def set_whitenoise_headers(headers, path, url): if "/fonts/" in url or "/caldata/" in url: - cache_control = "public, max-age={}".format(604800) # one week + cache_control = "public, max-age=604800" # one week headers["Cache-Control"] = cache_control if url.startswith("/.well-known/matrix/"): @@ -1127,7 +1126,7 @@ def get_default_gateway_linux(): return socket.inet_ntoa(struct.pack("