diff --git a/ditto/core/apps.py b/ditto/core/apps.py index 82f119a..22e03a3 100644 --- a/ditto/core/apps.py +++ b/ditto/core/apps.py @@ -38,7 +38,7 @@ def enabled(self): def is_installed(self, app_name): "Is this Ditto app installed?" - return apps.is_installed("ditto.%s" % app_name) + return apps.is_installed(f"ditto.{app_name}") def is_enabled(self, app_name): """Determine if a particular Ditto app is installed and enabled. @@ -52,7 +52,7 @@ def is_enabled(self, app_name): Doesn't offer much over apps.is_installed() yet, but would let us add other conditions in future, like being able to enable/disable installed apps. """ - return apps.is_installed("ditto.%s" % app_name) + return apps.is_installed(f"ditto.{app_name}") ditto_apps = Apps() diff --git a/ditto/core/management/commands/__init__.py b/ditto/core/management/commands/__init__.py index 6280c90..7232295 100644 --- a/ditto/core/management/commands/__init__.py +++ b/ditto/core/management/commands/__init__.py @@ -40,7 +40,7 @@ def output_results(self, results, verbosity=1): return for result in results: - prefix = "%s: " % result["account"] if "account" in result else "" + prefix = f"{result['account']}: " if "account" in result else "" if "fetched" in result: noun = ( self.singular_noun if result["fetched"] == 1 else self.plural_noun diff --git a/ditto/core/templatetags/ditto_core.py b/ditto/core/templatetags/ditto_core.py index cb18eae..3bff640 100644 --- a/ditto/core/templatetags/ditto_core.py +++ b/ditto/core/templatetags/ditto_core.py @@ -88,19 +88,18 @@ def display_time(dt, *, link_to_day=False, granularity=0, case=None): """ if granularity == 8: - visible_time = "circa %s" % dt.strftime(app_settings.CORE_DATE_YEAR_FORMAT) + year = dt.strftime(app_settings.CORE_DATE_YEAR_FORMAT) + visible_time = f"circa {year}" stamp = dt.strftime("%Y") elif granularity == 6: - visible_time = "sometime in %s" % dt.strftime( - app_settings.CORE_DATE_YEAR_FORMAT - ) + year = dt.strftime(app_settings.CORE_DATE_YEAR_FORMAT) + visible_time = f"sometime in {year}" stamp = dt.strftime("%Y") elif granularity == 4: - visible_time = "sometime in %s" % dt.strftime( - app_settings.CORE_DATE_YEAR_MONTH_FORMAT - ) + year_month = dt.strftime(app_settings.CORE_DATE_YEAR_MONTH_FORMAT) + visible_time = f"sometime in {year_month}" stamp = dt.strftime("%Y-%m") else: diff --git a/ditto/core/views.py b/ditto/core/views.py index 7dd6a03..2d841c9 100644 --- a/ditto/core/views.py +++ b/ditto/core/views.py @@ -246,7 +246,8 @@ def set_app_and_variety(self, **kwargs): ) raise Http404(msg) elif app_slug: - raise Http404("'%s' is not a valid app slug." % app_slug) + msg = f"'{app_slug}' is not a valid app slug." + raise Http404(msg) self.app_slug = app_slug self.variety_slug = variety_slug @@ -558,7 +559,10 @@ def get_variety_counts(self): date_field = self.get_date_field_for_app_variety(app_name, variety_name) qs = self.get_queryset_for_app_variety(app_name, variety_name) qs = qs.filter( - **{"%s__gte" % date_field: since, "%s__lt" % date_field: until} + **{ + f"{date_field}__gte": since, + f"{date_field}__lt": until, + } ) paginate_by = self.get_paginate_by(qs) # if not allow_future: diff --git a/ditto/flickr/admin.py b/ditto/flickr/admin.py index 12a3fc2..1245b7c 100644 --- a/ditto/flickr/admin.py +++ b/ditto/flickr/admin.py @@ -133,9 +133,7 @@ class UserAdmin(admin.ModelAdmin): ) def show_avatar(self, instance): - return mark_safe( - '' % (instance.avatar_url) - ) + return mark_safe(f'') show_avatar.short_description = "" diff --git a/ditto/flickr/fetch/fetchers.py b/ditto/flickr/fetch/fetchers.py index 1c0e6e6..27beb4b 100644 --- a/ditto/flickr/fetch/fetchers.py +++ b/ditto/flickr/fetch/fetchers.py @@ -74,7 +74,7 @@ def __init__(self, account): if account.user: self.return_value["account"] = account.user.username elif account.pk: - self.return_value["account"] = "Account: %s" % str(account) + self.return_value["account"] = f"Account: {account}" else: self.return_value["account"] = "Unsaved Account" else: @@ -115,14 +115,14 @@ def _fetch_page(self, **kwargs): self._call_api(**kwargs) except FetchError as e: self.return_value["success"] = False - self.return_value["messages"] = ["Error when calling Flickr API: %s" % e] + self.return_value["messages"] = [f"Error when calling Flickr API: {e}"] return try: self._fetch_extra() except FetchError as e: self.return_value["success"] = False - self.return_value["messages"] = ["Error when fetching extra data: %s" % e] + self.return_value["messages"] = [f"Error when fetching extra data: {e}"] return try: @@ -131,7 +131,7 @@ def _fetch_page(self, **kwargs): self.results = [] except FetchError as e: self.return_value["success"] = False - self.return_value["messages"] = ["Error when saving data: %s" % e] + self.return_value["messages"] = [f"Error when saving data: {e}"] return return diff --git a/ditto/flickr/management/commands/fetch_flickr_account_user.py b/ditto/flickr/management/commands/fetch_flickr_account_user.py index b0b9572..78bb637 100644 --- a/ditto/flickr/management/commands/fetch_flickr_account_user.py +++ b/ditto/flickr/management/commands/fetch_flickr_account_user.py @@ -33,7 +33,7 @@ def handle(self, *args, **options): try: account = Account.objects.get(id=options["id"]) except Account.DoesNotExist: - self.stderr.write("No Account found with an id of '%s'" % options["id"]) + self.stderr.write(f"No Account found with an id of '{options['id']}'") if account: # Then get the ID of the Flicker user for this Account's API creds. @@ -53,7 +53,7 @@ def handle(self, *args, **options): account.save() if options.get("verbosity", 1) > 0: self.stdout.write( - "Fetched and saved user '%s'" % result["user"]["name"] + f"Fetched and saved user '{result['user']['name']}'" ) else: if options.get("verbosity", 1) > 0: @@ -65,6 +65,6 @@ def handle(self, *args, **options): else: if options.get("verbosity", 1) > 0: self.stderr.write( - "Failed to fetch a Flickr ID for this Account: %s" - % id_result["messages"][0] + "Failed to fetch a Flickr ID for this Account: " + f"{id_result["messages"][0]}" ) diff --git a/ditto/flickr/templatetags/ditto_flickr.py b/ditto/flickr/templatetags/ditto_flickr.py index 64501f2..4890a98 100644 --- a/ditto/flickr/templatetags/ditto_flickr.py +++ b/ditto/flickr/templatetags/ditto_flickr.py @@ -40,9 +40,8 @@ def day_photos(date, nsid=None, time="post_time"): time -- A string, either 'post_time' (default) or 'taken_time'. """ if time not in ["post_time", "taken_time"]: - raise ValueError( - "`time` must be either 'post_time' or " "'taken_time', not '%s'." % time - ) + msg = f"`time` must be either 'post_time' or 'taken_time', not '{time}'." + raise ValueError(msg) start = datetime.combine(date, datetime_time.min).replace(tzinfo=timezone.utc) end = datetime.combine(date, datetime_time.max).replace(tzinfo=timezone.utc) @@ -107,10 +106,10 @@ def annual_photo_counts(nsid=None, count_by="post_time"): """ if count_by not in ["post_time", "taken_time"]: - raise ValueError( - "`count_by` must be either 'post_time' or " - "'taken_time', not '%s'." % count_by + msg = ( + f"`count_by` must be either 'post_time' or 'taken_time', not '{count_by}'." ) + raise ValueError(msg) qs = Photo.public_photo_objects diff --git a/ditto/lastfm/fetch.py b/ditto/lastfm/fetch.py index 526062a..e9c81e5 100644 --- a/ditto/lastfm/fetch.py +++ b/ditto/lastfm/fetch.py @@ -81,16 +81,15 @@ def fetch(self, fetch_type="recent", days=None): if self.account and self.account.is_active is False: self.return_value["success"] = False self.return_value["messages"] = [ - "The Account %s is currently marked as inactive." - % self.account.username + f"The Account {self.account.username} is currently marked as inactive." ] return self.return_value valid_fetch_types = ["all", "days", "recent"] if fetch_type not in valid_fetch_types: - raise ValueError( - "fetch_type should be one of %s" % ", ".join(valid_fetch_types) - ) + types_str = ", ".join(valid_fetch_types) + msg = f"fetch_type should be one of {types_str}" + raise ValueError(msg) if fetch_type == "days": try: diff --git a/ditto/lastfm/managers.py b/ditto/lastfm/managers.py index 70a80e9..b3f23bb 100644 --- a/ditto/lastfm/managers.py +++ b/ditto/lastfm/managers.py @@ -79,31 +79,30 @@ def with_scrobble_counts(self, **kwargs): raise ValueError(msg) if account is not None and account.__class__.__name__ != "Account": - raise TypeError( - "account must be an Account instance, " "not a %s" % type(account) - ) + msg = f"account must be an Account instance, not a {type(account)}" + raise TypeError(msg) if album is not None and album.__class__.__name__ != "Album": - raise TypeError( - "album must be an Album instance, " "not a %s" % type(album) - ) + msg = f"album must be an Album instance, not a {type(album)}" + raise TypeError(msg) if artist is not None and artist.__class__.__name__ != "Artist": - raise TypeError( - "artist must be an Artist instance, " "not a %s" % type(account) - ) + msg = f"artist must be an Artist instance, not a {type(account)}" + raise TypeError(msg) if min_post_time is not None and type(min_post_time) is not datetime: - raise TypeError( + msg = ( "min_post_time must be a datetime.datetime, " - "not a %s" % type(min_post_time) + f"not a {type(min_post_time)}" ) + raise TypeError(msg) if max_post_time is not None and type(max_post_time) is not datetime: - raise TypeError( + msg = ( "max_post_time must be a datetime.datetime, " - "not a %s" % type(max_post_time) + f"not a {type(max_post_time)}" ) + raise TypeError(msg) filter_kwargs = {} diff --git a/ditto/lastfm/templatetags/ditto_lastfm.py b/ditto/lastfm/templatetags/ditto_lastfm.py index 8090b57..8073079 100644 --- a/ditto/lastfm/templatetags/ditto_lastfm.py +++ b/ditto/lastfm/templatetags/ditto_lastfm.py @@ -22,9 +22,8 @@ def check_top_kwargs(**kwargs): period = kwargs["period"] if account is not None and not isinstance(account, Account): - raise TypeError( - "`account` must be an Account instance, " "not a %s" % type(account) - ) + msg = f"`account` must be an Account instance, not a {type(account)}" + raise TypeError(msg) if limit != "all" and isinstance(limit, int) is False: msg = "`limit` must be an integer or 'all'" @@ -35,13 +34,15 @@ def check_top_kwargs(**kwargs): and not isinstance(date, datetime.datetime) and not isinstance(date, datetime.date) ): - raise TypeError("`date` must be a datetime or date, " "not a %s" % type(date)) + msg = f"`date` must be a datetime or date, not a {type(date)}" + raise TypeError(msg) if period not in ["day", "week", "month", "year"]: - raise TypeError( + msg = ( '`period` must be one of "day", "week", "month" or "year", ' - "not %s" % type(period) + f"not {type(period)}" ) + raise TypeError(msg) def get_period_times(date, period): @@ -120,7 +121,8 @@ def top_albums(account=None, artist=None, limit=10, date=None, period="day"): check_top_kwargs(account=account, limit=limit, date=date, period=period) if artist is not None and not isinstance(artist, Artist): - raise TypeError("artist must be an Artist instance, " "not a %s" % type(artist)) + msg = f"artist must be an Artist instance, not a {type(artist)}" + raise TypeError(msg) qs_kwargs = {} @@ -208,10 +210,12 @@ def top_tracks( check_top_kwargs(account=account, limit=limit, date=date, period=period) if album is not None and type(album) is not Album: - raise TypeError("album must be an Album instance, " "not a %s" % type(album)) + msg = f"album must be an Album instance, not a {type(album)}" + raise TypeError(msg) if artist is not None and type(artist) is not Artist: - raise TypeError("artist must be an Artist instance, " "not a %s" % type(artist)) + msg = f"artist must be an Artist instance, not a {type(artist)}" + raise TypeError(msg) qs_kwargs = {} @@ -247,9 +251,8 @@ def recent_scrobbles(account=None, limit=10): limit -- Maximum number to fetch. Default is 10. """ if account is not None and not isinstance(account, Account): - raise TypeError( - "account must be an Account instance, " "not a %s" % type(account) - ) + msg = f"account must be an Account instance, not a {type(account)}" + raise TypeError(msg) if isinstance(limit, int) is False: msg = "`limit` must be an integer" @@ -279,12 +282,12 @@ def day_scrobbles(date, account=None): account -- An Account object or None (default, Scrobbles by all Accounts). """ if not isinstance(date, datetime.datetime) and not isinstance(date, datetime.date): - raise TypeError("date must be a datetime or date, " "not a %s" % type(date)) + msg = f"date must be a datetime or date, not a {type(date)}" + raise TypeError(msg) if account is not None and not isinstance(account, Account): - raise TypeError( - "account must be an Account instance, " "not a %s" % type(account) - ) + msg = f"account must be an Account instance, not a {type(account)}" + raise TypeError(msg) qs_kwargs = {} @@ -322,9 +325,8 @@ def annual_scrobble_counts(account=None): """ if account is not None and not isinstance(account, Account): - raise TypeError( - "account must be an Account instance, " "not a %s" % type(account) - ) + msg = f"account must be an Account instance, not a {type(account)}" + raise TypeError(msg) qs = Scrobble.objects diff --git a/ditto/lastfm/urls.py b/ditto/lastfm/urls.py index 079b868..a9e31cf 100644 --- a/ditto/lastfm/urls.py +++ b/ditto/lastfm/urls.py @@ -28,12 +28,12 @@ name="track_list", ), re_path( - r"^music/(?P%s)/$" % slug_chars, + rf"^music/(?P{slug_chars})/$", view=views.ArtistDetailView.as_view(), name="artist_detail", ), re_path( - r"^music/(?P%s)/\+albums/$" % slug_chars, + rf"^music/(?P{slug_chars})/\+albums/$", view=views.ArtistAlbumsView.as_view(), name="artist_albums", ), diff --git a/ditto/pinboard/factories.py b/ditto/pinboard/factories.py index f1abfc8..d3d526e 100644 --- a/ditto/pinboard/factories.py +++ b/ditto/pinboard/factories.py @@ -12,8 +12,8 @@ class Meta: model = models.Account username = factory.Sequence(lambda n: "user%d" % n) - url = factory.LazyAttribute(lambda obj: "https://pinboard.com/%s" % obj.username) - api_token = factory.LazyAttribute(lambda obj: "%s:123ABC" % obj.username) + url = factory.LazyAttribute(lambda obj: f"https://pinboard.com/{obj.username}") + api_token = factory.LazyAttribute(lambda obj: f"{obj.username}:123ABC") class BookmarkFactory(factory.django.DjangoModelFactory): diff --git a/ditto/pinboard/fetch.py b/ditto/pinboard/fetch.py index dce9d16..34845aa 100644 --- a/ditto/pinboard/fetch.py +++ b/ditto/pinboard/fetch.py @@ -85,9 +85,8 @@ def _get_accounts(self, username): if account.is_active: accounts = [account] else: - raise FetchError( - "The account %s is curently marked as inactive." % username - ) + msg = f"The account {username} is curently marked as inactive." + raise FetchError(msg) return accounts def _send_request(self, fetch_type, params, account): @@ -141,7 +140,7 @@ def _send_request(self, fetch_type, params, account): response.raise_for_status() except requests.exceptions.HTTPError: # 4xx or 5xx errors: - error_message = "HTTP Error: %s" % response.status_code + error_message = f"HTTP Error: {response.status_code}" except NameError: if error_message == "": error_message = "Something unusual went wrong." @@ -251,7 +250,8 @@ def fetch(self, post_date, username=None): try: dt = datetime.strptime(post_date, "%Y-%m-%d").astimezone(timezone.utc) except ValueError as err: - raise FetchError("Invalid date format ('%s')" % post_date) from err + msg = f"Invalid date format ('{post_date}')" + raise FetchError(msg) from err else: return self._fetch(fetch_type="date", params={"dt": dt}, username=username) diff --git a/ditto/twitter/admin.py b/ditto/twitter/admin.py index 2ea2ef8..1846274 100644 --- a/ditto/twitter/admin.py +++ b/ditto/twitter/admin.py @@ -347,8 +347,6 @@ class UserAdmin(admin.ModelAdmin): ) def show_avatar(self, instance): - return mark_safe( - '' % (instance.avatar_url) - ) + return mark_safe(f'') show_avatar.short_description = "" diff --git a/ditto/twitter/fetch/fetch.py b/ditto/twitter/fetch/fetch.py index 3536162..5cdcfb6 100644 --- a/ditto/twitter/fetch/fetch.py +++ b/ditto/twitter/fetch/fetch.py @@ -77,7 +77,7 @@ def fetch(self): if self.account.user: self.return_value["account"] = self.account.user.screen_name elif self.account.pk: - self.return_value["account"] = "Account: %s" % str(self.account) + self.return_value["account"] = f"Account: {self.account}" else: self.return_value["account"] = "Unsaved Account" @@ -110,7 +110,7 @@ def _fetch_pages(self): self._call_api() except TwythonError as e: self.return_value["success"] = False - self.return_value["messages"] = ["Error when calling API: %s" % e] + self.return_value["messages"] = [f"Error when calling API: {e}"] else: # If we've got to the last 'page' of tweet results, we'll receive # an empty list from the API. diff --git a/ditto/twitter/fetch/fetchers.py b/ditto/twitter/fetch/fetchers.py index 35cc184..88d54c7 100644 --- a/ditto/twitter/fetch/fetchers.py +++ b/ditto/twitter/fetch/fetchers.py @@ -109,15 +109,15 @@ def _set_accounts(self, screen_name=None): try: accounts = [Account.objects.get(user__screen_name=screen_name)] except Account.DoesNotExist as err: - raise FetchError( - "There is no Account in the database with a screen_name of '%s'" - % screen_name - ) from err + msg = ( + "There is no Account in the database with a " + f"screen_name of '{screen_name}'" + ) + raise FetchError(msg) from err else: if accounts[0].is_active is False: - raise FetchError( - "The '%s' Account is marked as inactive." % screen_name - ) + msg = f"The '{screen_name}' Account is marked as inactive." + raise FetchError(msg) self.accounts = accounts diff --git a/ditto/twitter/ingest.py b/ditto/twitter/ingest.py index 7af102c..c80c217 100644 --- a/ditto/twitter/ingest.py +++ b/ditto/twitter/ingest.py @@ -142,7 +142,8 @@ def _load_data(self, directory): raise IngestError(err) from err if self.file_count == 0: - raise IngestError("No .js files found in %s" % directory) + msg = f"No .js files found in {directory}" + raise IngestError(msg) def _get_data_from_file(self, filepath): """Looks in a file, parses its JSON, and adds a dict of data about diff --git a/ditto/twitter/management/commands/__init__.py b/ditto/twitter/management/commands/__init__.py index 8c65de8..923bcfa 100644 --- a/ditto/twitter/management/commands/__init__.py +++ b/ditto/twitter/management/commands/__init__.py @@ -73,9 +73,8 @@ def handle(self, *args, **options): try: Account.objects.get(user__screen_name=screen_name) except Account.DoesNotExist as err: - raise CommandError( - "There's no Account with a screen name of '%s'" % screen_name - ) from err + msg = "There's no Account with a screen name of '{screen_name}'" + raise CommandError(msg) from err else: msg = "Specify --account, eg --account=philgyford." raise CommandError(msg) diff --git a/ditto/twitter/management/commands/fetch_twitter_accounts.py b/ditto/twitter/management/commands/fetch_twitter_accounts.py index a55d6eb..f182bf7 100644 --- a/ditto/twitter/management/commands/fetch_twitter_accounts.py +++ b/ditto/twitter/management/commands/fetch_twitter_accounts.py @@ -41,7 +41,7 @@ def handle(self, *args, **options): if options.get("verbosity", 1) > 0: for result in results: if result["success"]: - self.stdout.write("Fetched @%s" % result["account"]) + self.stdout.write(f"Fetched @{result['account']}") else: self.stderr.write( "Could not fetch @{}: {}".format( diff --git a/ditto/twitter/management/commands/generate_twitter_tweet_html.py b/ditto/twitter/management/commands/generate_twitter_tweet_html.py index d62cb6e..b598d2c 100644 --- a/ditto/twitter/management/commands/generate_twitter_tweet_html.py +++ b/ditto/twitter/management/commands/generate_twitter_tweet_html.py @@ -33,9 +33,8 @@ def handle(self, *args, **options): try: Account.objects.get(user__screen_name=screen_name) except Account.DoesNotExist as err: - raise CommandError( - "There's no Account with a screen name of '%s'" % screen_name - ) from err + msg = f"There's no Account with a screen name of '{screen_name}'" + raise CommandError(msg) from err tweets = tweets.filter(user__screen_name=screen_name) for tweet in tweets: diff --git a/ditto/twitter/models.py b/ditto/twitter/models.py index f173c71..e757fd3 100644 --- a/ditto/twitter/models.py +++ b/ditto/twitter/models.py @@ -807,7 +807,7 @@ class Meta: ordering = ["screen_name"] def __str__(self): - return "@%s" % self.screen_name + return f"@{self.screen_name}" def save(self, *args, **kwargs): """If the user's privacy status has changed, we need to change the @@ -835,7 +835,7 @@ def make_description_html(self): @property def permalink(self): - return "https://twitter.com/%s" % self.screen_name + return f"https://twitter.com/{self.screen_name}" @property def avatar_url(self): diff --git a/ditto/twitter/utils.py b/ditto/twitter/utils.py index 32533ac..8b97f1c 100644 --- a/ditto/twitter/utils.py +++ b/ditto/twitter/utils.py @@ -118,8 +118,8 @@ def htmlify_tweet(json_data): if (urls_count + media_count) > 0 and urls_count > 0: for url in ents["urls"]: html = html.replace( - '' % url["url"], - '' % url["expanded_url"], + f'', + f'', ) if media_count > 0: diff --git a/docs/conf.py b/docs/conf.py index 176e121..9794b68 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -69,7 +69,7 @@ def get_entity(package, entity): path = os.path.join(os.path.dirname(__file__), "..", "ditto", "__init__.py") with open(path) as f: init_py = f.read() - find = "__%s__ = ['\"]([^'\"]+)['\"]" % entity + find = f"__{entity}__ = ['\"]([^'\"]+)['\"]" return re.search(find, init_py).group(1) diff --git a/setup.py b/setup.py index 3d23ad1..0685fdb 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ def get_entity(package, entity): """ with open(os.path.join(package, "__init__.py")) as f: init_py = f.read() - find = "__%s__ = ['\"]([^'\"]+)['\"]" % entity + find = f"__{entity}__ = ['\"]([^'\"]+)['\"]" return re.search(find, init_py).group(1) @@ -53,8 +53,7 @@ def get_author_email(): if sys.argv[-1] == "publish": os.system("python setup.py sdist") os.system( - "twine upload --config-file=.pypirc dist/django-ditto-%s.tar.gz" - % (get_version()) + f"twine upload --config-file=.pypirc dist/django-ditto-{get_version()}.tar.gz" ) sys.exit() @@ -63,8 +62,7 @@ def get_author_email(): if sys.argv[-1] == "testpublish": os.system("python setup.py sdist") os.system( - "twine upload --config-file=.pypirc --repository-url https://test.pypi.org/legacy/ dist/django-ditto-%s.tar.gz" # noqa: E501 - % (get_version()) + f"twine upload --config-file=.pypirc --repository-url https://test.pypi.org/legacy/ dist/django-ditto-{get_version()}.tar.gz" # noqa: E501 ) # os.system("python setup.py bdist_wheel upload") sys.exit() diff --git a/tests/flickr/test_fetch_fetchers.py b/tests/flickr/test_fetch_fetchers.py index b00d9d7..e2ba188 100644 --- a/tests/flickr/test_fetch_fetchers.py +++ b/tests/flickr/test_fetch_fetchers.py @@ -184,10 +184,8 @@ def test_downloads_and_saves_avatar(self, download): ["image/jpeg", "image/jpg", "image/png", "image/gif"], ) - self.assertEqual( - user.avatar, - "flickr/60/50/35034346050N01/avatars/%s" % os.path.basename(temp_filepath), - ) + path = os.path.basename(temp_filepath) + self.assertEqual(user.avatar, f"flickr/60/50/35034346050N01/avatars/{path}") def test_returns_correct_success_result(self): self.expect_response("people.getInfo") diff --git a/tests/flickr/test_models.py b/tests/flickr/test_models.py index 0921ba2..b7a0c7f 100644 --- a/tests/flickr/test_models.py +++ b/tests/flickr/test_models.py @@ -440,7 +440,7 @@ def test_image_urls(self): for size, prop in self.photo_sizes.items(): self.assertEqual( getattr(photo, prop), - "https://farm3.static.flickr.com/1234/4567_9876_%s.jpg" % size, + f"https://farm3.static.flickr.com/1234/4567_9876_{size}.jpg", ) def test_image_url_with_invalid_size(self): @@ -489,7 +489,7 @@ def test_original_url(self): filename = os.path.basename(self.photo.original_file.name) self.assertEqual( self.photo.original_url, - "/media/flickr/34/56/123456N01/photos/2015/08/14/%s" % filename, + f"/media/flickr/34/56/123456N01/photos/2015/08/14/{filename}", ) def test_remote_original_url(self): diff --git a/tests/lastfm/test_fetch.py b/tests/lastfm/test_fetch.py index bb17b50..bffefc6 100644 --- a/tests/lastfm/test_fetch.py +++ b/tests/lastfm/test_fetch.py @@ -171,11 +171,11 @@ def add_recent_tracks_response(self, body=None, page=1, status=200, from_time=No url = ( "http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=bob&" - "api_key=1234&format=json&page=%s&limit=200" % page + f"api_key=1234&format=json&page={page}&limit=200" ) if from_time is not None: - url += "&from=%s" % from_time + url += f"&from={from_time}" if body is None: # Default success response diff --git a/tests/lastfm/test_views.py b/tests/lastfm/test_views.py index 2995c02..f496121 100644 --- a/tests/lastfm/test_views.py +++ b/tests/lastfm/test_views.py @@ -118,7 +118,8 @@ def test_all_days(self): album=album, post_time=datetime_from_str("2016-10-01 12:00:00"), ) - response = self.client.get("%s?days=all" % reverse("lastfm:album_list")) + url = reverse("lastfm:album_list") + response = self.client.get(f"{url}?days=all") self.assertEqual(response.context["album_list"][0].scrobble_count, 2) @freeze_time("2016-10-05 12:00:00", tz_offset=-8) @@ -136,7 +137,8 @@ def test_7_days(self): album=album, post_time=datetime_from_str("2016-10-01 12:00:00"), ) - response = self.client.get("%s?days=7" % reverse("lastfm:album_list")) + url = reverse("lastfm:album_list") + response = self.client.get(f"{url}?days=7") self.assertEqual(response.context["album_list"][0].scrobble_count, 1) @@ -258,7 +260,8 @@ def test_all_days(self): track=track, post_time=datetime_from_str("2016-10-01 12:00:00"), ) - response = self.client.get("%s?days=all" % reverse("lastfm:artist_list")) + url = reverse("lastfm:artist_list") + response = self.client.get(f"{url}?days=all") self.assertEqual(response.context["artist_list"][0].scrobble_count, 2) @freeze_time("2016-10-05 12:00:00", tz_offset=-8) @@ -276,7 +279,8 @@ def test_7_days(self): track=track, post_time=datetime_from_str("2016-10-01 12:00:00"), ) - response = self.client.get("%s?days=7" % reverse("lastfm:artist_list")) + url = reverse("lastfm:artist_list") + response = self.client.get(f"{url}?days=7") self.assertEqual(response.context["artist_list"][0].scrobble_count, 1) @@ -424,7 +428,8 @@ def test_all_days(self): track=track, post_time=datetime_from_str("2016-10-01 12:00:00"), ) - response = self.client.get("%s?days=all" % reverse("lastfm:track_list")) + url = reverse("lastfm:track_list") + response = self.client.get(f"{url}?days=all") self.assertEqual(response.context["track_list"][0].scrobble_count, 2) @freeze_time("2016-10-05 12:00:00", tz_offset=-8) @@ -442,7 +447,8 @@ def test_7_days(self): track=track, post_time=datetime_from_str("2016-10-01 12:00:00"), ) - response = self.client.get("%s?days=7" % reverse("lastfm:track_list")) + url = reverse("lastfm:track_list") + response = self.client.get(f"{url}?days=7") self.assertEqual(response.context["track_list"][0].scrobble_count, 1) @@ -489,10 +495,10 @@ def setUp(self): def test_templates(self): "Uses the correct templates" response = self.client.get( - reverse("lastfm:%s" % self.view_name, kwargs={"username": "bob"}) + reverse(f"lastfm:{self.view_name}", kwargs={"username": "bob"}) ) self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "lastfm/%s.html" % self.view_name) + self.assertTemplateUsed(response, f"lastfm/{self.view_name}.html") self.assertTemplateUsed(response, "lastfm/base.html") self.assertTemplateUsed(response, "ditto/base.html") @@ -501,7 +507,7 @@ def test_context_counts(self): All user_* views should have these same counts in their context. """ response = self.client.get( - reverse("lastfm:%s" % self.view_name, kwargs={"username": "bob"}) + reverse(f"lastfm:{self.view_name}", kwargs={"username": "bob"}) ) self.assertIn("counts", response.context) self.assertEqual(response.context["counts"]["albums"], 1) @@ -512,7 +518,7 @@ def test_context_counts(self): def test_404s(self): "Responds with 404 if we request a user that doesn't exist." response = self.client.get( - reverse("lastfm:%s" % self.view_name, kwargs={"username": "thelma"}) + reverse(f"lastfm:{self.view_name}", kwargs={"username": "thelma"}) ) self.assertEqual(response.status_code, 404) @@ -527,7 +533,7 @@ class UserAlbumListViewTestCase(UserCommonTests, TestCase): def test_context_albums(self): "Sends the correct album data to the templates" response = self.client.get( - reverse("lastfm:%s" % self.view_name, kwargs={"username": "bob"}) + reverse(f"lastfm:{self.view_name}", kwargs={"username": "bob"}) ) self.assertIn("album_list", response.context) albums = response.context["album_list"] @@ -542,7 +548,7 @@ class UserArtistListViewTestCase(UserCommonTests, TestCase): def test_context_albums(self): "Sends the correct album data to the templates" response = self.client.get( - reverse("lastfm:%s" % self.view_name, kwargs={"username": "bob"}) + reverse(f"lastfm:{self.view_name}", kwargs={"username": "bob"}) ) self.assertIn("artist_list", response.context) artists = response.context["artist_list"] @@ -559,7 +565,7 @@ class UserScrobbleListViewTestCase(UserCommonTests, TestCase): def test_context_scrobbles(self): "Sends the correct scrobble data to the templates" response = self.client.get( - reverse("lastfm:%s" % self.view_name, kwargs={"username": "bob"}) + reverse(f"lastfm:{self.view_name}", kwargs={"username": "bob"}) ) self.assertIn("scrobble_list", response.context) scrobbles = response.context["scrobble_list"] @@ -572,7 +578,7 @@ class UserTrackListViewTestCase(UserCommonTests, TestCase): def test_context_tracks(self): "Sends the correct track data to the templates" response = self.client.get( - reverse("lastfm:%s" % self.view_name, kwargs={"username": "bob"}) + reverse(f"lastfm:{self.view_name}", kwargs={"username": "bob"}) ) self.assertIn("track_list", response.context) tracks = response.context["track_list"] diff --git a/tests/pinboard/test_fetch.py b/tests/pinboard/test_fetch.py index 8d2a491..b3730a2 100644 --- a/tests/pinboard/test_fetch.py +++ b/tests/pinboard/test_fetch.py @@ -50,7 +50,7 @@ def add_response(self, body, method="get", status=200): """ responses.add( responses.GET, - "https://api.pinboard.in/v1/posts/%s" % method, + f"https://api.pinboard.in/v1/posts/{method}", status=status, match_querystring=False, body=body, @@ -69,7 +69,8 @@ def make_success_body( % (n, n, n, post_date) ) - posts_json = "[%s]\t\n" % (",".join(posts)) + posts_str = ",".join(posts) + posts_json = f"[{posts_str}]\t\n" if method == "all": return posts_json diff --git a/tests/twitter/test_fetch_savers.py b/tests/twitter/test_fetch_savers.py index 97a7acb..e0e3e79 100644 --- a/tests/twitter/test_fetch_savers.py +++ b/tests/twitter/test_fetch_savers.py @@ -492,10 +492,8 @@ def test_downloads_and_saves_avatar(self, download): ["image/jpeg", "image/jpg", "image/png", "image/gif"], ) - self.assertEqual( - saved_user.avatar, - "twitter/avatars/25/52/12552/%s" % os.path.basename(temp_filepath), - ) + path = os.path.basename(temp_filepath) + self.assertEqual(saved_user.avatar, f"twitter/avatars/25/52/12552/{path}") @patch.object(filedownloader, "download") @patch.object(os.path, "exists") diff --git a/tests/twitter/test_models.py b/tests/twitter/test_models.py index ff6ee0b..149adea 100644 --- a/tests/twitter/test_models.py +++ b/tests/twitter/test_models.py @@ -60,7 +60,7 @@ def test_str_2(self): "Has the correct string represntation when it has a user" user = UserFactory() account = AccountFactory(user=user) - self.assertEqual(account.__str__(), "@%s" % user.screen_name) + self.assertEqual(account.__str__(), f"@{user.screen_name}") def test_ordering(self): """Multiple accounts are by user.screen_name time ascending""" @@ -217,11 +217,11 @@ def test_default_manager(self): def test_size_urls(self): url = "http://www.example.org/image.jpg" photo = PhotoFactory(image_url=url) - self.assertEqual(photo.large_url, "%s:large" % url) - self.assertEqual(photo.medium_url, "%s:medium" % url) - self.assertEqual(photo.small_url, "%s:small" % url) - self.assertEqual(photo.thumb_url, "%s:thumb" % url) - self.assertEqual(photo.thumbnail_url, "%s:thumb" % url) + self.assertEqual(photo.large_url, f"{url}:large") + self.assertEqual(photo.medium_url, f"{url}:medium") + self.assertEqual(photo.small_url, f"{url}:small") + self.assertEqual(photo.thumb_url, f"{url}:thumb") + self.assertEqual(photo.thumbnail_url, f"{url}:thumb") def test_tweets(self): "It should be possible to belong to more than one tweet." @@ -392,7 +392,7 @@ def tearDown(self): def test_video_url_mp4(self): gif = AnimatedGifFactory(mp4_url="https://example.org/test.mp4") filename = os.path.basename(gif.mp4_file.name) - self.assertEqual(gif.video_url, "/media/twitter/media/mp/le/%s" % filename) + self.assertEqual(gif.video_url, f"/media/twitter/media/mp/le/{filename}") class TweetTestCase(TestCase):