From 9dbe33b6ded38bbbcaffbb764bafee13cbc49c36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20F=C3=A4hrmann?= Date: Sat, 28 Jun 2025 19:36:16 +0200 Subject: [PATCH] =?UTF-8?q?replace=20old=20%-formatted=20and=20.format(?= =?UTF-8?q?=E2=80=A6)=20strings=20with=20f-strings=20(#7671)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mostly using flynt https://github.com/ikamensh/flynt --- docs/gallery-dl.conf | 2 +- gallery_dl/__init__.py | 2 +- gallery_dl/aes.py | 6 +-- gallery_dl/cache.py | 8 ++-- gallery_dl/config.py | 3 +- gallery_dl/cookies.py | 44 +++++++++---------- gallery_dl/downloader/http.py | 9 ++-- gallery_dl/exception.py | 6 +-- gallery_dl/extractor/2ch.py | 14 +++--- gallery_dl/extractor/2chan.py | 4 +- gallery_dl/extractor/2chen.py | 4 +- gallery_dl/extractor/35photo.py | 6 +-- gallery_dl/extractor/4archive.py | 8 ++-- gallery_dl/extractor/4chan.py | 13 +++--- gallery_dl/extractor/4chanarchives.py | 5 +-- gallery_dl/extractor/8chan.py | 9 ++-- gallery_dl/extractor/8muses.py | 3 +- gallery_dl/extractor/agnph.py | 5 +-- gallery_dl/extractor/ao3.py | 4 +- gallery_dl/extractor/arcalive.py | 6 +-- gallery_dl/extractor/architizer.py | 7 ++- gallery_dl/extractor/artstation.py | 37 +++++++--------- gallery_dl/extractor/aryion.py | 12 ++--- gallery_dl/extractor/batoto.py | 6 +-- gallery_dl/extractor/bbc.py | 4 +- gallery_dl/extractor/behance.py | 2 +- gallery_dl/extractor/bilibili.py | 4 +- gallery_dl/extractor/bluesky.py | 41 ++++++++--------- gallery_dl/extractor/boosty.py | 12 ++--- gallery_dl/extractor/bunkr.py | 2 +- gallery_dl/extractor/cien.py | 7 ++- gallery_dl/extractor/civitai.py | 28 +++++------- gallery_dl/extractor/common.py | 15 +++---- gallery_dl/extractor/cyberdrop.py | 4 +- gallery_dl/extractor/danbooru.py | 23 +++++----- gallery_dl/extractor/desktopography.py | 4 +- gallery_dl/extractor/deviantart.py | 35 ++++++++------- gallery_dl/extractor/dynastyscans.py | 4 +- gallery_dl/extractor/e621.py | 10 ++--- gallery_dl/extractor/erome.py | 4 +- gallery_dl/extractor/everia.py | 4 +- gallery_dl/extractor/exhentai.py | 16 +++---- gallery_dl/extractor/fanbox.py | 2 +- gallery_dl/extractor/fantia.py | 2 +- gallery_dl/extractor/fapachi.py | 7 ++- gallery_dl/extractor/fapello.py | 9 ++-- gallery_dl/extractor/flickr.py | 4 +- gallery_dl/extractor/furaffinity.py | 18 ++++---- gallery_dl/extractor/furry34.py | 8 ++-- gallery_dl/extractor/fuskator.py | 2 +- gallery_dl/extractor/gelbooru.py | 4 +- gallery_dl/extractor/gelbooru_v01.py | 3 +- gallery_dl/extractor/girlswithmuscle.py | 11 +++-- gallery_dl/extractor/hentaicosplays.py | 2 +- gallery_dl/extractor/hentaifoundry.py | 24 +++++----- gallery_dl/extractor/hentaihand.py | 6 +-- gallery_dl/extractor/hentaihere.py | 2 +- gallery_dl/extractor/hentainexus.py | 16 +++---- gallery_dl/extractor/hiperdex.py | 2 +- gallery_dl/extractor/hitomi.py | 49 +++++++++------------ gallery_dl/extractor/hotleak.py | 7 ++- gallery_dl/extractor/imagefap.py | 29 ++++++------- gallery_dl/extractor/imagehosts.py | 3 +- gallery_dl/extractor/imgbb.py | 2 +- gallery_dl/extractor/imgth.py | 7 ++- gallery_dl/extractor/imgur.py | 21 +++++---- gallery_dl/extractor/imhentai.py | 2 +- gallery_dl/extractor/inkbunny.py | 6 +-- gallery_dl/extractor/instagram.py | 40 ++++++++--------- gallery_dl/extractor/itaku.py | 4 +- gallery_dl/extractor/itchio.py | 6 +-- gallery_dl/extractor/kabeuchi.py | 16 +++---- gallery_dl/extractor/kemono.py | 58 +++++++++++-------------- gallery_dl/extractor/lensdump.py | 8 ++-- gallery_dl/extractor/lexica.py | 2 +- gallery_dl/extractor/livedoor.py | 5 +-- gallery_dl/extractor/lolisafe.py | 4 +- gallery_dl/extractor/luscious.py | 2 +- gallery_dl/extractor/mangadex.py | 6 +-- gallery_dl/extractor/mangafox.py | 2 +- gallery_dl/extractor/mangahere.py | 2 +- gallery_dl/extractor/mangoxo.py | 4 +- gallery_dl/extractor/mastodon.py | 8 ++-- gallery_dl/extractor/moebooru.py | 7 +-- gallery_dl/extractor/motherless.py | 2 +- gallery_dl/extractor/myhentaigallery.py | 2 +- gallery_dl/extractor/naver.py | 12 ++--- gallery_dl/extractor/naverwebtoon.py | 5 +-- gallery_dl/extractor/nekohouse.py | 5 +-- gallery_dl/extractor/newgrounds.py | 20 ++++----- gallery_dl/extractor/nhentai.py | 2 +- gallery_dl/extractor/nijie.py | 12 ++--- gallery_dl/extractor/nitter.py | 13 +++--- gallery_dl/extractor/nozomi.py | 16 +++---- gallery_dl/extractor/nsfwalbum.py | 4 +- gallery_dl/extractor/oauth.py | 29 +++++-------- gallery_dl/extractor/paheal.py | 8 ++-- gallery_dl/extractor/pexels.py | 6 +-- gallery_dl/extractor/pictoa.py | 4 +- gallery_dl/extractor/piczel.py | 6 +-- gallery_dl/extractor/pillowfort.py | 4 +- gallery_dl/extractor/pinterest.py | 12 ++--- gallery_dl/extractor/pixeldrain.py | 16 +++---- gallery_dl/extractor/pixiv.py | 43 +++++++++--------- gallery_dl/extractor/pixnet.py | 6 +-- gallery_dl/extractor/plurk.py | 4 +- gallery_dl/extractor/poipiku.py | 2 +- gallery_dl/extractor/poringa.py | 2 +- gallery_dl/extractor/pornhub.py | 15 +++---- gallery_dl/extractor/pornpics.py | 4 +- gallery_dl/extractor/rawkuma.py | 4 +- gallery_dl/extractor/readcomiconline.py | 2 +- gallery_dl/extractor/realbooru.py | 5 +-- gallery_dl/extractor/reddit.py | 9 ++-- gallery_dl/extractor/redgifs.py | 15 +++---- gallery_dl/extractor/rule34us.py | 2 +- gallery_dl/extractor/rule34vault.py | 8 ++-- gallery_dl/extractor/rule34xyz.py | 8 ++-- gallery_dl/extractor/sankaku.py | 6 +-- gallery_dl/extractor/sankakucomplex.py | 4 +- gallery_dl/extractor/schalenetwork.py | 15 +++---- gallery_dl/extractor/seiga.py | 8 ++-- gallery_dl/extractor/sexcom.py | 12 ++--- gallery_dl/extractor/shimmie2.py | 19 ++++---- gallery_dl/extractor/skeb.py | 9 ++-- gallery_dl/extractor/slickpic.py | 4 +- gallery_dl/extractor/slideshare.py | 10 ++--- gallery_dl/extractor/smugmug.py | 2 +- gallery_dl/extractor/soundgasm.py | 2 +- gallery_dl/extractor/speakerdeck.py | 4 +- gallery_dl/extractor/steamgriddb.py | 6 +-- gallery_dl/extractor/subscribestar.py | 6 +-- gallery_dl/extractor/tapas.py | 13 +++--- gallery_dl/extractor/tiktok.py | 10 ++--- gallery_dl/extractor/tmohentai.py | 7 ++- gallery_dl/extractor/toyhouse.py | 4 +- gallery_dl/extractor/tsumino.py | 21 +++++---- gallery_dl/extractor/tumblr.py | 14 +++--- gallery_dl/extractor/tumblrgallery.py | 11 ++--- gallery_dl/extractor/twitter.py | 47 +++++++++----------- gallery_dl/extractor/unsplash.py | 8 ++-- gallery_dl/extractor/uploadir.py | 2 +- gallery_dl/extractor/urlgalleries.py | 3 +- gallery_dl/extractor/vipergirls.py | 6 +-- gallery_dl/extractor/vk.py | 9 ++-- gallery_dl/extractor/vsco.py | 32 +++++++------- gallery_dl/extractor/wallhaven.py | 8 ++-- gallery_dl/extractor/warosu.py | 2 +- gallery_dl/extractor/weasyl.py | 8 ++-- gallery_dl/extractor/webmshare.py | 2 +- gallery_dl/extractor/weebcentral.py | 4 +- gallery_dl/extractor/weibo.py | 15 +++---- gallery_dl/extractor/wikiart.py | 17 +++----- gallery_dl/extractor/wikimedia.py | 5 ++- gallery_dl/extractor/xfolio.py | 6 +-- gallery_dl/extractor/xhamster.py | 2 +- gallery_dl/extractor/xvideos.py | 9 ++-- gallery_dl/extractor/yiffverse.py | 8 ++-- gallery_dl/extractor/zerochan.py | 4 +- gallery_dl/extractor/zzup.py | 11 ++--- gallery_dl/job.py | 18 ++++---- gallery_dl/option.py | 6 +-- gallery_dl/output.py | 12 +++-- gallery_dl/postprocessor/ugoira.py | 27 +++++------- gallery_dl/transaction_id.py | 3 +- gallery_dl/update.py | 9 ++-- gallery_dl/ytdl.py | 6 +-- 167 files changed, 756 insertions(+), 891 deletions(-) diff --git a/docs/gallery-dl.conf b/docs/gallery-dl.conf index 3f7a4df2..222418f3 100644 --- a/docs/gallery-dl.conf +++ b/docs/gallery-dl.conf @@ -1,4 +1,4 @@ - { +{ "#": "gallery-dl default configuration file", "#": "full documentation at", diff --git a/gallery_dl/__init__.py b/gallery_dl/__init__.py index b19507f8..8ed98070 100644 --- a/gallery_dl/__init__.py +++ b/gallery_dl/__init__.py @@ -139,7 +139,7 @@ def main(): extra = "" if util.EXECUTABLE: - extra = " - Executable ({})".format(version.__variant__) + extra = f" - Executable ({version.__variant__})" else: git_head = util.git_head() if git_head: diff --git a/gallery_dl/aes.py b/gallery_dl/aes.py index 3fd1d5e1..c671de90 100644 --- a/gallery_dl/aes.py +++ b/gallery_dl/aes.py @@ -58,7 +58,7 @@ bytes_to_intlist = list def intlist_to_bytes(xs): if not xs: return b"" - return struct.pack("%dB" % len(xs), *xs) + return struct.pack(f"{len(xs)}B", *xs) def unpad_pkcs7(data): @@ -615,7 +615,7 @@ def block_product(block_x, block_y): if len(block_x) != BLOCK_SIZE_BYTES or len(block_y) != BLOCK_SIZE_BYTES: raise ValueError( - "Length of blocks need to be %d bytes" % BLOCK_SIZE_BYTES) + f"Length of blocks need to be {BLOCK_SIZE_BYTES} bytes") block_r = [0xE1] + [0] * (BLOCK_SIZE_BYTES - 1) block_v = block_y[:] @@ -639,7 +639,7 @@ def ghash(subkey, data): if len(data) % BLOCK_SIZE_BYTES: raise ValueError( - "Length of data should be %d bytes" % BLOCK_SIZE_BYTES) + f"Length of data should be {BLOCK_SIZE_BYTES} bytes") last_y = [0] * BLOCK_SIZE_BYTES for i in range(0, len(data), BLOCK_SIZE_BYTES): diff --git a/gallery_dl/cache.py b/gallery_dl/cache.py index 923ed32c..b04552e8 100644 --- a/gallery_dl/cache.py +++ b/gallery_dl/cache.py @@ -73,7 +73,7 @@ class DatabaseCacheDecorator(): _init = True def __init__(self, func, keyarg, maxage): - self.key = "%s.%s" % (func.__module__, func.__name__) + self.key = f"{func.__module__}.{func.__name__}" self.func = func self.cache = {} self.keyarg = keyarg @@ -95,7 +95,7 @@ class DatabaseCacheDecorator(): pass # database lookup - fullkey = "%s-%s" % (self.key, key) + fullkey = f"{self.key}-{key}" with self.database() as db: cursor = db.cursor() try: @@ -128,7 +128,7 @@ class DatabaseCacheDecorator(): with self.database() as db: db.execute( "INSERT OR REPLACE INTO data VALUES (?,?,?)", - ("%s-%s" % (self.key, key), pickle.dumps(value), expires), + (f"{self.key}-{key}", pickle.dumps(value), expires), ) def invalidate(self, key): @@ -139,7 +139,7 @@ class DatabaseCacheDecorator(): with self.database() as db: db.execute( "DELETE FROM data WHERE key=?", - ("%s-%s" % (self.key, key),), + (f"{self.key}-{key}",), ) def database(self): diff --git a/gallery_dl/config.py b/gallery_dl/config.py index 35294f95..5229b547 100644 --- a/gallery_dl/config.py +++ b/gallery_dl/config.py @@ -155,8 +155,7 @@ def status(): paths.append((path, status)) - fmt = "{{:<{}}} : {{}}\n".format( - max(len(p[0]) for p in paths)).format + fmt = f"{{:<{max(len(p[0]) for p in paths)}}} : {{}}\n".format for path, status in paths: stdout_write(fmt(path, status)) diff --git a/gallery_dl/cookies.py b/gallery_dl/cookies.py index 6d0b5613..5d6c3d7b 100644 --- a/gallery_dl/cookies.py +++ b/gallery_dl/cookies.py @@ -43,7 +43,7 @@ def load_cookies(browser_specification): elif browser_name in SUPPORTED_BROWSERS_CHROMIUM: return load_cookies_chromium(browser_name, profile, keyring, domain) else: - raise ValueError("unknown browser '{}'".format(browser_name)) + raise ValueError(f"unknown browser '{browser_name}'") def load_cookies_firefox(browser_name, profile=None, @@ -59,7 +59,7 @@ def load_cookies_firefox(browser_name, profile=None, if container_id is False: conditions.append("NOT INSTR(originAttributes,'userContextId=')") elif container_id: - uid = "%userContextId={}".format(container_id) + uid = f"%userContextId={container_id}" conditions.append("originAttributes LIKE ? OR originAttributes LIKE ?") parameters += (uid, uid + "&%") @@ -72,7 +72,7 @@ def load_cookies_firefox(browser_name, profile=None, parameters += (domain, "." + domain) if conditions: - sql = "{} WHERE ( {} )".format(sql, " ) AND ( ".join(conditions)) + sql = f"{sql} WHERE ( {' ) AND ( '.join(conditions)} )" with DatabaseConnection(path) as db: cookies = [ @@ -186,7 +186,7 @@ def load_cookies_chromium(browser_name, profile=None, )) if failed_cookies > 0: - failed_message = " ({} could not be decrypted)".format(failed_cookies) + failed_message = f" ({failed_cookies} could not be decrypted)" else: failed_message = "" @@ -212,9 +212,8 @@ def _firefox_cookies_database(browser_name, profile=None, container=None): path = _find_most_recently_used_file(search_root, "cookies.sqlite") if path is None: - raise FileNotFoundError( - "Unable to find {} cookies database in {}".format( - browser_name.capitalize(), search_root)) + raise FileNotFoundError(f"Unable to find {browser_name.capitalize()} " + f"cookies database in {search_root}") _log_debug("Extracting cookies from %s", path) @@ -245,8 +244,7 @@ def _firefox_cookies_database(browser_name, profile=None, container=None): container_id = context["userContextId"] break else: - raise ValueError("Unable to find Firefox container '{}'".format( - container)) + raise ValueError(f"Unable to find Firefox container '{container}'") _log_debug("Only loading cookies from container '%s' (ID %s)", container, container_id) @@ -391,8 +389,8 @@ def _chromium_cookies_database(profile, config): path = _find_most_recently_used_file(search_root, "Cookies") if path is None: - raise FileNotFoundError("Unable to find {} cookies database in " - "'{}'".format(config["browser"], search_root)) + raise FileNotFoundError(f"Unable to find {config['browser']} cookies " + f"database in '{search_root}'") return path @@ -716,9 +714,9 @@ def _get_kwallet_password(browser_keyring_name): ) if proc.returncode != 0: - _log_error("kwallet-query failed with return code {}. " - "Please consult the kwallet-query man page " - "for details".format(proc.returncode)) + _log_error(f"kwallet-query failed with return code " + f"{proc.returncode}. Please consult the kwallet-query " + f"man page for details") return b"" if stdout.lower().startswith(b"failed to read"): @@ -847,7 +845,7 @@ class DataParser: def read_bytes(self, num_bytes): if num_bytes < 0: - raise ParserError("invalid read of {} bytes".format(num_bytes)) + raise ParserError(f"invalid read of {num_bytes} bytes") end = self.cursor + num_bytes if end > len(self._data): raise ParserError("reached end of input") @@ -858,8 +856,8 @@ class DataParser: def expect_bytes(self, expected_value, message): value = self.read_bytes(len(expected_value)) if value != expected_value: - raise ParserError("unexpected value: {} != {} ({})".format( - value, expected_value, message)) + raise ParserError(f"unexpected value: {value} != {expected_value} " + f"({message})") def read_uint(self, big_endian=False): data_format = ">I" if big_endian else " 0: - _log_debug("Skipping {} bytes ({}): {!r}".format( - num_bytes, description, self.read_bytes(num_bytes))) + _log_debug(f"Skipping {num_bytes} bytes ({description}): " + f"{self.read_bytes(num_bytes)!r}") elif num_bytes < 0: - raise ParserError("Invalid skip of {} bytes".format(num_bytes)) + raise ParserError(f"Invalid skip of {num_bytes} bytes") def skip_to(self, offset, description="unknown"): self.skip(offset - self.cursor, description) @@ -906,7 +904,7 @@ class DatabaseConnection(): if util.WINDOWS: path = "/" + os.path.abspath(path) - uri = "file:{}?mode=ro&immutable=1".format(path) + uri = f"file:{path}?mode=ro&immutable=1" self.database = sqlite3.connect( uri, uri=True, isolation_level=None, check_same_thread=False) return self.database @@ -1104,9 +1102,9 @@ def _parse_browser_specification( browser, profile=None, keyring=None, container=None, domain=None): browser = browser.lower() if browser not in SUPPORTED_BROWSERS: - raise ValueError("Unsupported browser '{}'".format(browser)) + raise ValueError(f"Unsupported browser '{browser}'") if keyring and keyring not in SUPPORTED_KEYRINGS: - raise ValueError("Unsupported keyring '{}'".format(keyring)) + raise ValueError(f"Unsupported keyring '{keyring}'") if profile and _is_path(profile): profile = os.path.expanduser(profile) return browser, profile, keyring, container, domain diff --git a/gallery_dl/downloader/http.py b/gallery_dl/downloader/http.py index c82bc50a..6fcc1fa0 100644 --- a/gallery_dl/downloader/http.py +++ b/gallery_dl/downloader/http.py @@ -149,7 +149,7 @@ class HttpDownloader(DownloaderBase): # partial content file_size = pathfmt.part_size() if file_size: - headers["Range"] = "bytes={}-".format(file_size) + headers["Range"] = f"bytes={file_size}-" # connect to (remote) source try: @@ -167,7 +167,7 @@ class HttpDownloader(DownloaderBase): reason = exc.args[0].reason cls = reason.__class__.__name__ pre, _, err = str(reason.args[-1]).partition(":") - msg = "{}: {}".format(cls, (err or pre).lstrip()) + msg = f"{cls}: {(err or pre).lstrip()}" except Exception: msg = str(exc) continue @@ -189,7 +189,7 @@ class HttpDownloader(DownloaderBase): elif code == 416 and file_size: # Requested Range Not Satisfiable break else: - msg = "'{} {}' for '{}'".format(code, response.reason, url) + msg = f"'{code} {response.reason}' for '{url}'" challenge = util.detect_challenge(response) if challenge is not None: @@ -339,8 +339,7 @@ class HttpDownloader(DownloaderBase): # check file size if size and fp.tell() < size: - msg = "file size mismatch ({} < {})".format( - fp.tell(), size) + msg = f"file size mismatch ({fp.tell()} < {size})" output.stderr_write("\n") continue diff --git a/gallery_dl/exception.py b/gallery_dl/exception.py index 6b2ce3a8..3d1fef2b 100644 --- a/gallery_dl/exception.py +++ b/gallery_dl/exception.py @@ -39,7 +39,7 @@ class GalleryDLException(Exception): if not message: message = self.default elif isinstance(message, Exception): - message = "{}: {}".format(message.__class__.__name__, message) + message = f"{message.__class__.__name__}: {message}" if self.msgfmt and fmt: message = self.msgfmt.format(message) Exception.__init__(self, message) @@ -61,8 +61,8 @@ class HttpError(ExtractionError): else: self.status = response.status_code if not message: - message = "'{} {}' for '{}'".format( - response.status_code, response.reason, response.url) + message = (f"'{response.status_code} {response.reason}' " + f"for '{response.url}'") ExtractionError.__init__(self, message) diff --git a/gallery_dl/extractor/2ch.py b/gallery_dl/extractor/2ch.py index e4381b64..4e9a13fe 100644 --- a/gallery_dl/extractor/2ch.py +++ b/gallery_dl/extractor/2ch.py @@ -26,7 +26,7 @@ class _2chThreadExtractor(Extractor): self.board, self.thread = match.groups() def items(self): - url = "{}/{}/res/{}.json".format(self.root, self.board, self.thread) + url = f"{self.root}/{self.board}/res/{self.thread}.json" posts = self.request(url).json()["threads"][0]["posts"] op = posts[0] @@ -71,21 +71,21 @@ class _2chBoardExtractor(Extractor): self.board = match[1] def items(self): + base = f"{self.root}/{self.board}" + # index page - url = "{}/{}/index.json".format(self.root, self.board) + url = f"{base}/index.json" index = self.request(url).json() index["_extractor"] = _2chThreadExtractor for thread in index["threads"]: - url = "{}/{}/res/{}.html".format( - self.root, self.board, thread["thread_num"]) + url = f"{base}/res/{thread['thread_num']}.html" yield Message.Queue, url, index # pages 1..n for n in util.advance(index["pages"], 1): - url = "{}/{}/{}.json".format(self.root, self.board, n) + url = f"{base}/{n}.json" page = self.request(url).json() page["_extractor"] = _2chThreadExtractor for thread in page["threads"]: - url = "{}/{}/res/{}.html".format( - self.root, self.board, thread["thread_num"]) + url = f"{base}/res/{thread['thread_num']}.html" yield Message.Queue, url, page diff --git a/gallery_dl/extractor/2chan.py b/gallery_dl/extractor/2chan.py index b1bfa26d..b78d08df 100644 --- a/gallery_dl/extractor/2chan.py +++ b/gallery_dl/extractor/2chan.py @@ -28,8 +28,8 @@ class _2chanThreadExtractor(Extractor): self.server, self.board, self.thread = match.groups() def items(self): - url = "https://{}.2chan.net/{}/res/{}.htm".format( - self.server, self.board, self.thread) + url = (f"https://{self.server}.2chan.net" + f"/{self.board}/res/{self.thread}.htm") page = self.request(url).text data = self.metadata(page) yield Message.Directory, data diff --git a/gallery_dl/extractor/2chen.py b/gallery_dl/extractor/2chen.py index 3fb16a24..ee3510cd 100644 --- a/gallery_dl/extractor/2chen.py +++ b/gallery_dl/extractor/2chen.py @@ -28,7 +28,7 @@ class _2chenThreadExtractor(Extractor): self.board, self.thread = match.groups() def items(self): - url = "{}/{}/{}".format(self.root, self.board, self.thread) + url = f"{self.root}/{self.board}/{self.thread}" page = self.request(url, encoding="utf-8", notfound="thread").text data = self.metadata(page) yield Message.Directory, data @@ -89,7 +89,7 @@ class _2chenBoardExtractor(Extractor): self.board = match[1] def items(self): - url = "{}/{}/catalog".format(self.root, self.board) + url = f"{self.root}/{self.board}/catalog" page = self.request(url, notfound="board").text data = {"_extractor": _2chenThreadExtractor} for thread in text.extract_iter( diff --git a/gallery_dl/extractor/35photo.py b/gallery_dl/extractor/35photo.py index 6398bcbe..2eeb5041 100644 --- a/gallery_dl/extractor/35photo.py +++ b/gallery_dl/extractor/35photo.py @@ -108,7 +108,7 @@ class _35photoUserExtractor(_35photoExtractor): self.user_id = 0 def metadata(self): - url = "{}/{}/".format(self.root, self.user) + url = f"{self.root}/{self.user}/" page = self.request(url).text self.user_id = text.parse_int(text.extr(page, "/user_", ".xml")) return { @@ -142,7 +142,7 @@ class _35photoTagExtractor(_35photoExtractor): num = 1 while True: - url = "{}/tags/{}/list_{}/".format(self.root, self.tag, num) + url = f"{self.root}/tags/{self.tag}/list_{num}/" page = self.request(url).text prev = None @@ -170,7 +170,7 @@ class _35photoGenreExtractor(_35photoExtractor): self.photo_ids = None def metadata(self): - url = "{}/genre_{}{}".format(self.root, self.genre_id, self.new or "/") + url = f"{self.root}/genre_{self.genre_id}{self.new or '/'}" page = self.request(url).text self.photo_ids = self._photo_ids(text.extr( page, ' class="photo', '\n')) diff --git a/gallery_dl/extractor/4archive.py b/gallery_dl/extractor/4archive.py index ed61b6f5..c9be2a4e 100644 --- a/gallery_dl/extractor/4archive.py +++ b/gallery_dl/extractor/4archive.py @@ -27,8 +27,7 @@ class _4archiveThreadExtractor(Extractor): self.board, self.thread = match.groups() def items(self): - url = "{}/board/{}/thread/{}".format( - self.root, self.board, self.thread) + url = f"{self.root}/board/{self.board}/thread/{self.thread}" page = self.request(url).text data = self.metadata(page) posts = self.posts(page) @@ -99,12 +98,11 @@ class _4archiveBoardExtractor(Extractor): def items(self): data = {"_extractor": _4archiveThreadExtractor} while True: - url = "{}/board/{}/{}".format(self.root, self.board, self.num) + url = f"{self.root}/board/{self.board}/{self.num}" page = self.request(url).text if 'class="thread"' not in page: return for thread in text.extract_iter(page, 'class="thread" id="t', '"'): - url = "{}/board/{}/thread/{}".format( - self.root, self.board, thread) + url = f"{self.root}/board/{self.board}/thread/{thread}" yield Message.Queue, url, data self.num += 1 diff --git a/gallery_dl/extractor/4chan.py b/gallery_dl/extractor/4chan.py index 710cefcd..1ab6b963 100644 --- a/gallery_dl/extractor/4chan.py +++ b/gallery_dl/extractor/4chan.py @@ -28,8 +28,7 @@ class _4chanThreadExtractor(Extractor): self.board, self.thread = match.groups() def items(self): - url = "https://a.4cdn.org/{}/thread/{}.json".format( - self.board, self.thread) + url = f"https://a.4cdn.org/{self.board}/thread/{self.thread}.json" posts = self.request(url).json()["posts"] title = posts[0].get("sub") or text.remove_html(posts[0]["com"]) @@ -45,8 +44,8 @@ class _4chanThreadExtractor(Extractor): post.update(data) post["extension"] = post["ext"][1:] post["filename"] = text.unescape(post["filename"]) - url = "https://i.4cdn.org/{}/{}{}".format( - post["board"], post["tim"], post["ext"]) + url = (f"https://i.4cdn.org" + f"/{post['board']}/{post['tim']}{post['ext']}") yield Message.Url, url, post @@ -62,13 +61,13 @@ class _4chanBoardExtractor(Extractor): self.board = match[1] def items(self): - url = "https://a.4cdn.org/{}/threads.json".format(self.board) + url = f"https://a.4cdn.org/{self.board}/threads.json" threads = self.request(url).json() for page in threads: for thread in page["threads"]: - url = "https://boards.4chan.org/{}/thread/{}/".format( - self.board, thread["no"]) + url = (f"https://boards.4chan.org" + f"/{self.board}/thread/{thread['no']}/") thread["page"] = page["page"] thread["_extractor"] = _4chanThreadExtractor yield Message.Queue, url, thread diff --git a/gallery_dl/extractor/4chanarchives.py b/gallery_dl/extractor/4chanarchives.py index a1ff9fd7..c187b41d 100644 --- a/gallery_dl/extractor/4chanarchives.py +++ b/gallery_dl/extractor/4chanarchives.py @@ -29,8 +29,7 @@ class _4chanarchivesThreadExtractor(Extractor): self.board, self.thread = match.groups() def items(self): - url = "{}/board/{}/thread/{}".format( - self.root, self.board, self.thread) + url = f"{self.root}/board/{self.board}/thread/{self.thread}" page = self.request(url).text data = self.metadata(page) posts = self.posts(page) @@ -104,7 +103,7 @@ class _4chanarchivesBoardExtractor(Extractor): data["pageCount"]: return - url = "{}/{}/{}.json".format(self.root, board, pnum) + url = f"{self.root}/{board}/{pnum}.json" threads = self.request(url).json()["threads"] diff --git a/gallery_dl/extractor/8muses.py b/gallery_dl/extractor/8muses.py index 21c0ca0f..a98561da 100644 --- a/gallery_dl/extractor/8muses.py +++ b/gallery_dl/extractor/8muses.py @@ -74,8 +74,7 @@ class _8musesAlbumExtractor(Extractor): return path, _, num = self.path.rstrip("/").rpartition("/") path = path if num.isdecimal() else self.path - url = "{}{}/{}{}".format( - self.root, path, data["page"] + 1, self.params) + url = f"{self.root}{path}/{data['page'] + 1}{self.params}" def _make_album(self, album): return { diff --git a/gallery_dl/extractor/agnph.py b/gallery_dl/extractor/agnph.py index 66d378da..5bb1835d 100644 --- a/gallery_dl/extractor/agnph.py +++ b/gallery_dl/extractor/agnph.py @@ -60,7 +60,7 @@ class AgnphExtractor(booru.BooruExtractor): params["page"] += 1 def _html(self, post): - url = "{}/gallery/post/show/{}/".format(self.root, post["id"]) + url = f"{self.root}/gallery/post/show/{post['id']}/" return self.request(url).text def _tags(self, post, page): @@ -103,7 +103,6 @@ class AgnphPostExtractor(AgnphExtractor): example = "https://agn.ph/gallery/post/show/12345/" def posts(self): - url = "{}/gallery/post/show/{}/?api=xml".format( - self.root, self.groups[0]) + url = f"{self.root}/gallery/post/show/{self.groups[0]}/?api=xml" post = self.request_xml(url) return (self._xml_to_dict(post),) diff --git a/gallery_dl/extractor/ao3.py b/gallery_dl/extractor/ao3.py index af3346b8..3f361fc4 100644 --- a/gallery_dl/extractor/ao3.py +++ b/gallery_dl/extractor/ao3.py @@ -135,7 +135,7 @@ class Ao3WorkExtractor(Ao3Extractor): self.login() work_id = self.groups[0] - url = "{}/works/{}".format(self.root, work_id) + url = f"{self.root}/works/{work_id}" response = self.request(url, notfound="work") if response.url.endswith("/users/login?restricted=true"): @@ -256,7 +256,7 @@ class Ao3UserExtractor(Dispatch, Ao3Extractor): example = "https://archiveofourown.org/users/USER" def items(self): - base = "{}/users/{}/".format(self.root, self.groups[0]) + base = f"{self.root}/users/{self.groups[0]}/" return self._dispatch_extractors(( (Ao3UserWorksExtractor , base + "works"), (Ao3UserSeriesExtractor , base + "series"), diff --git a/gallery_dl/extractor/arcalive.py b/gallery_dl/extractor/arcalive.py index 114c124f..bb8c1e3f 100644 --- a/gallery_dl/extractor/arcalive.py +++ b/gallery_dl/extractor/arcalive.py @@ -26,7 +26,7 @@ class ArcaliveExtractor(Extractor): for article in self.articles(): article["_extractor"] = ArcalivePostExtractor board = self.board or article.get("boardSlug") or "breaking" - url = "{}/b/{}/{}".format(self.root, board, article["id"]) + url = f"{self.root}/b/{board}/{article['id']}" yield Message.Queue, url, article @@ -51,8 +51,8 @@ class ArcalivePostExtractor(ArcaliveExtractor): post["count"] = len(files) post["date"] = text.parse_datetime( post["createdAt"][:19], "%Y-%m-%dT%H:%M:%S") - post["post_url"] = post_url = "{}/b/{}/{}".format( - self.root, post["boardSlug"], post["id"]) + post["post_url"] = post_url = \ + f"{self.root}/b/{post['boardSlug']}/{post['id']}" post["_http_headers"] = {"Referer": post_url + "?p=1"} yield Message.Directory, post diff --git a/gallery_dl/extractor/architizer.py b/gallery_dl/extractor/architizer.py index 202245da..e39d3d26 100644 --- a/gallery_dl/extractor/architizer.py +++ b/gallery_dl/extractor/architizer.py @@ -24,7 +24,7 @@ class ArchitizerProjectExtractor(GalleryExtractor): example = "https://architizer.com/projects/NAME/" def __init__(self, match): - url = "{}/projects/{}/".format(self.root, match[1]) + url = f"{self.root}/projects/{match[1]}/" GalleryExtractor.__init__(self, match, url) def metadata(self, page): @@ -71,12 +71,11 @@ class ArchitizerFirmExtractor(Extractor): self.firm = match[1] def items(self): - url = url = "{}/firms/{}/?requesting_merlin=pages".format( - self.root, self.firm) + url = url = f"{self.root}/firms/{self.firm}/?requesting_merlin=pages" page = self.request(url).text data = {"_extractor": ArchitizerProjectExtractor} for project in text.extract_iter(page, '= 400: @@ -141,9 +141,9 @@ class AryionExtractor(Extractor): # fix 'Last-Modified' header lmod = headers["last-modified"] if lmod[22] != ":": - lmod = "{}:{} GMT".format(lmod[:22], lmod[22:24]) + lmod = f"{lmod[:22]}:{lmod[22:24]} GMT" - post_url = "{}/g4/view/{}".format(self.root, post_id) + post_url = f"{self.root}/g4/view/{post_id}" extr = text.extract_from(self.request(post_url).text) title, _, artist = text.unescape(extr( @@ -195,10 +195,10 @@ class AryionGalleryExtractor(AryionExtractor): def posts(self): if self.recursive: - url = "{}/g4/gallery/{}".format(self.root, self.user) + url = f"{self.root}/g4/gallery/{self.user}" return self._pagination_params(url) else: - url = "{}/g4/latest.php?name={}".format(self.root, self.user) + url = f"{self.root}/g4/latest.php?name={self.user}" return util.advance(self._pagination_next(url), self.offset) @@ -212,7 +212,7 @@ class AryionFavoriteExtractor(AryionExtractor): example = "https://aryion.com/g4/favorites/USER" def posts(self): - url = "{}/g4/favorites/{}".format(self.root, self.user) + url = f"{self.root}/g4/favorites/{self.user}" return self._pagination_params( url, None, "class='gallery-item favorite' id='") diff --git a/gallery_dl/extractor/batoto.py b/gallery_dl/extractor/batoto.py index 84e7288d..9f7f061d 100644 --- a/gallery_dl/extractor/batoto.py +++ b/gallery_dl/extractor/batoto.py @@ -86,7 +86,7 @@ class BatotoChapterExtractor(BatotoBase, ChapterExtractor): ChapterExtractor.__init__(self, match, False) self._init_root() self.chapter_id = self.groups[1] - self.page_url = "{}/title/0/{}".format(self.root, self.chapter_id) + self.page_url = f"{self.root}/title/0/{self.chapter_id}" def metadata(self, page): extr = text.extract_from(page) @@ -147,7 +147,7 @@ class BatotoMangaExtractor(BatotoBase, MangaExtractor): MangaExtractor.__init__(self, match, False) self._init_root() self.manga_id = self.groups[1] or self.groups[2] - self.page_url = "{}/title/{}".format(self.root, self.manga_id) + self.page_url = f"{self.root}/title/{self.manga_id}" def chapters(self, page): extr = text.extract_from(page) @@ -177,6 +177,6 @@ class BatotoMangaExtractor(BatotoBase, MangaExtractor): data["date"] = text.parse_datetime( extr('time="', '"'), "%Y-%m-%dT%H:%M:%S.%fZ") - url = "{}/title/{}".format(self.root, href) + url = f"{self.root}/title/{href}" results.append((url, data.copy())) return results diff --git a/gallery_dl/extractor/bbc.py b/gallery_dl/extractor/bbc.py index 61d63170..8efb3dbc 100644 --- a/gallery_dl/extractor/bbc.py +++ b/gallery_dl/extractor/bbc.py @@ -43,7 +43,7 @@ class BbcGalleryExtractor(GalleryExtractor): def images(self, page): width = self.config("width") width = width - width % 16 if width else 1920 - dimensions = "/{}xn/".format(width) + dimensions = f"/{width}xn/" results = [] for img in text.extract_iter(page, 'class="gallery__thumbnail', ">"): @@ -64,7 +64,7 @@ class BbcGalleryExtractor(GalleryExtractor): front, _, back = src.partition("/320x180_b/") for width in (1920, 1600, 1280, 976): if width < max_width: - yield "{}/{}xn/{}".format(front, width, back) + yield f"{front}/{width}xn/{back}" class BbcProgrammeExtractor(Extractor): diff --git a/gallery_dl/extractor/behance.py b/gallery_dl/extractor/behance.py index ef1424dd..3426f2aa 100644 --- a/gallery_dl/extractor/behance.py +++ b/gallery_dl/extractor/behance.py @@ -115,7 +115,7 @@ class BehanceGalleryExtractor(BehanceExtractor): def get_gallery_data(self): """Collect gallery info dict""" - url = "{}/gallery/{}/a".format(self.root, self.gallery_id) + url = f"{self.root}/gallery/{self.gallery_id}/a" cookies = { "gki": '{"feature_project_view":false,' '"feature_discover_login_prompt":false,' diff --git a/gallery_dl/extractor/bilibili.py b/gallery_dl/extractor/bilibili.py index 597ec40e..c38d7eec 100644 --- a/gallery_dl/extractor/bilibili.py +++ b/gallery_dl/extractor/bilibili.py @@ -30,7 +30,7 @@ class BilibiliUserArticlesExtractor(BilibiliExtractor): def items(self): for article in self.api.user_articles(self.groups[0]): article["_extractor"] = BilibiliArticleExtractor - url = "{}/opus/{}".format(self.root, article["opus_id"]) + url = f"{self.root}/opus/{article['opus_id']}" yield Message.Queue, url, article @@ -98,7 +98,7 @@ class BilibiliUserArticlesFavoriteExtractor(BilibiliExtractor): def items(self): for article in self.api.user_favlist(): article["_extractor"] = BilibiliArticleExtractor - url = "{}/opus/{}".format(self.root, article["opus_id"]) + url = f"{self.root}/opus/{article['opus_id']}" yield Message.Queue, url, article diff --git a/gallery_dl/extractor/bluesky.py b/gallery_dl/extractor/bluesky.py index a484c3fd..fb32df3c 100644 --- a/gallery_dl/extractor/bluesky.py +++ b/gallery_dl/extractor/bluesky.py @@ -62,9 +62,8 @@ class BlueskyExtractor(Extractor): yield Message.Directory, post if files: did = post["author"]["did"] - base = ( - "{}/xrpc/com.atproto.sync.getBlob?did={}&cid=".format( - self.api.service_endpoint(did), did)) + base = (f"{self.api.service_endpoint(did)}/xrpc" + f"/com.atproto.sync.getBlob?did={did}&cid=") for post["num"], file in enumerate(files, 1): post.update(file) yield Message.Url, base + file["filename"], post @@ -215,7 +214,7 @@ class BlueskyUserExtractor(Dispatch, BlueskyExtractor): example = "https://bsky.app/profile/HANDLE" def items(self): - base = "{}/profile/{}/".format(self.root, self.groups[0]) + base = f"{self.root}/profile/{self.groups[0]}/" default = ("posts" if self.config("quoted", False) or self.config("reposts", False) else "media") return self._dispatch_extractors(( @@ -411,11 +410,9 @@ class BlueskyAPI(): def get_feed(self, actor, feed): endpoint = "app.bsky.feed.getFeed" - params = { - "feed" : "at://{}/app.bsky.feed.generator/{}".format( - self._did_from_actor(actor), feed), - "limit": "100", - } + uri = (f"at://{self._did_from_actor(actor)}" + f"/app.bsky.feed.generator/{feed}") + params = {"feed": uri, "limit": "100"} return self._pagination(endpoint, params) def get_follows(self, actor): @@ -428,16 +425,13 @@ class BlueskyAPI(): def get_list_feed(self, actor, list): endpoint = "app.bsky.feed.getListFeed" - params = { - "list" : "at://{}/app.bsky.graph.list/{}".format( - self._did_from_actor(actor), list), - "limit": "100", - } + uri = f"at://{self._did_from_actor(actor)}/app.bsky.graph.list/{list}" + params = {"list" : uri, "limit": "100"} return self._pagination(endpoint, params) def get_post_thread(self, actor, post_id): - uri = "at://{}/app.bsky.feed.post/{}".format( - self._did_from_actor(actor), post_id) + uri = (f"at://{self._did_from_actor(actor)}" + f"/app.bsky.feed.post/{post_id}") depth = self.extractor.config("depth", "0") return self.get_post_thread_uri(uri, depth) @@ -547,15 +541,15 @@ class BlueskyAPI(): "password" : self.password, } - url = "{}/xrpc/{}".format(self.root, endpoint) + url = f"{self.root}/xrpc/{endpoint}" response = self.extractor.request( url, method="POST", headers=headers, json=data, fatal=None) data = response.json() if response.status_code != 200: self.log.debug("Server response: %s", data) - raise exception.AuthenticationError('"{}: {}"'.format( - data.get("error"), data.get("message"))) + raise exception.AuthenticationError( + f"\"{data.get('error')}: {data.get('message')}\"") _refresh_token_cache.update(self.username, data["refreshJwt"]) return "Bearer " + data["accessJwt"] @@ -563,7 +557,7 @@ class BlueskyAPI(): def _call(self, endpoint, params, root=None): if root is None: root = self.root - url = "{}/xrpc/{}".format(root, endpoint) + url = f"{root}/xrpc/{endpoint}" while True: self.authenticate() @@ -577,13 +571,12 @@ class BlueskyAPI(): self.extractor.wait(until=until) continue + msg = "API request failed" try: data = response.json() - msg = "API request failed ('{}: {}')".format( - data["error"], data["message"]) + msg = f"{msg} ('{data['error']}: {data['message']}')" except Exception: - msg = "API request failed ({} {})".format( - response.status_code, response.reason) + msg = f"{msg} ({response.status_code} {response.reason})" self.extractor.log.debug("Server response: %s", response.text) raise exception.StopExtraction(msg) diff --git a/gallery_dl/extractor/boosty.py b/gallery_dl/extractor/boosty.py index f3e441b1..3df26a4f 100644 --- a/gallery_dl/extractor/boosty.py +++ b/gallery_dl/extractor/boosty.py @@ -218,7 +218,7 @@ class BoostyFollowingExtractor(BoostyExtractor): def items(self): for user in self.api.user_subscriptions(): - url = "{}/{}".format(self.root, user["blog"]["blogUrl"]) + url = f"{self.root}/{user['blog']['blogUrl']}" user["_extractor"] = BoostyUserExtractor yield Message.Queue, url, user @@ -288,7 +288,7 @@ class BoostyAPI(): self.headers["Authorization"] = "Bearer " + access_token def blog_posts(self, username, params): - endpoint = "/v1/blog/{}/post/".format(username) + endpoint = f"/v1/blog/{username}/post/" params = self._merge_params(params, { "limit" : "5", "offset" : None, @@ -298,7 +298,7 @@ class BoostyAPI(): return self._pagination(endpoint, params) def blog_media_album(self, username, type="all", params=()): - endpoint = "/v1/blog/{}/media_album/".format(username) + endpoint = f"/v1/blog/{username}/media_album/" params = self._merge_params(params, { "type" : type.rstrip("s"), "limit" : "15", @@ -318,7 +318,7 @@ class BoostyAPI(): return posts def post(self, username, post_id): - endpoint = "/v1/blog/{}/post/{}".format(username, post_id) + endpoint = f"/v1/blog/{username}/post/{post_id}" return self._call(endpoint) def feed_posts(self, params=None): @@ -418,11 +418,11 @@ class BoostyAPI(): params["offset"] = offset def dialog(self, dialog_id): - endpoint = "/v1/dialog/{}".format(dialog_id) + endpoint = f"/v1/dialog/{dialog_id}" return self._call(endpoint) def dialog_messages(self, dialog_id, limit=300, offset=None): - endpoint = "/v1/dialog/{}/message/".format(dialog_id) + endpoint = f"/v1/dialog/{dialog_id}/message/" params = { "limit": limit, "reverse": "true", diff --git a/gallery_dl/extractor/bunkr.py b/gallery_dl/extractor/bunkr.py index 8f8a15af..c084deed 100644 --- a/gallery_dl/extractor/bunkr.py +++ b/gallery_dl/extractor/bunkr.py @@ -184,7 +184,7 @@ class BunkrAlbumExtractor(LolisafeAlbumExtractor): json={"id": data_id}).json() if data.get("encrypted"): - key = "SECRET_KEY_{}".format(data["timestamp"] // 3600) + key = f"SECRET_KEY_{data['timestamp'] // 3600}" file_url = util.decrypt_xor(data["url"], key.encode()) else: file_url = data["url"] diff --git a/gallery_dl/extractor/cien.py b/gallery_dl/extractor/cien.py index b286f9e3..ea864121 100644 --- a/gallery_dl/extractor/cien.py +++ b/gallery_dl/extractor/cien.py @@ -52,8 +52,7 @@ class CienArticleExtractor(CienExtractor): example = "https://ci-en.net/creator/123/article/12345" def items(self): - url = "{}/creator/{}/article/{}".format( - self.root, self.groups[0], self.groups[1]) + url = f"{self.root}/creator/{self.groups[0]}/article/{self.groups[1]}" page = self.request(url, notfound="article").text files = self._extract_files(page) @@ -121,7 +120,7 @@ class CienArticleExtractor(CienExtractor): auth = text.extr(video, ' auth-key="', '"') file = text.nameext_from_url(name) - file["url"] = "{}video-web.mp4?{}".format(path, auth) + file["url"] = f"{path}video-web.mp4?{auth}" file["type"] = "video" files.append(file) @@ -163,7 +162,7 @@ class CienCreatorExtractor(CienExtractor): example = "https://ci-en.net/creator/123" def items(self): - url = "{}/creator/{}/article".format(self.root, self.groups[0]) + url = f"{self.root}/creator/{self.groups[0]}/article" params = text.parse_query(self.groups[1]) params["mode"] = "list" return self._pagination_articles(url, params) diff --git a/gallery_dl/extractor/civitai.py b/gallery_dl/extractor/civitai.py index 5dec4fd7..a12d058a 100644 --- a/gallery_dl/extractor/civitai.py +++ b/gallery_dl/extractor/civitai.py @@ -75,7 +75,7 @@ class CivitaiExtractor(Extractor): if models: data = {"_extractor": CivitaiModelExtractor} for model in models: - url = "{}/models/{}".format(self.root, model["id"]) + url = f"{self.root}/models/{model['id']}" yield Message.Queue, url, data return @@ -152,11 +152,9 @@ class CivitaiExtractor(Extractor): name = image.get("name") if not name: mime = image.get("mimeType") or self._image_ext - name = "{}.{}".format(image.get("id"), mime.rpartition("/")[2]) - return ( - "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/{}/{}/{}".format( - url, quality, name) - ) + name = f"{image.get('id')}.{mime.rpartition('/')[2]}" + return (f"https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA" + f"/{url}/{quality}/{name}") def _image_results(self, images): for num, file in enumerate(images, 1): @@ -298,16 +296,15 @@ class CivitaiModelExtractor(CivitaiExtractor): if not sep: name = ext ext = "bin" - file["uuid"] = "model-{}-{}-{}".format( - model["id"], version["id"], file["id"]) + file["uuid"] = f"model-{model['id']}-{version['id']}-{file['id']}" files.append({ "num" : num, "file" : file, "filename" : name, "extension": ext, - "url" : (file.get("downloadUrl") or - "{}/api/download/models/{}".format( - self.root, version["id"])), + "url" : ( + file.get("downloadUrl") or + f"{self.root}/api/download/models/{version['id']}"), "_http_headers" : { "Authorization": self.api.headers.get("Authorization")}, "_http_validate": self._validate_file_model, @@ -340,8 +337,7 @@ class CivitaiModelExtractor(CivitaiExtractor): alert = text.extr( response.text, 'mantine-Alert-message">', "") if alert: - msg = "\"{}\" - 'api-key' required".format( - text.remove_html(alert)) + msg = f"\"{text.remove_html(alert)}\" - 'api-key' required" else: msg = "'api-key' required to download this file" self.log.warning(msg) @@ -436,7 +432,7 @@ class CivitaiUserExtractor(Dispatch, CivitaiExtractor): example = "https://civitai.com/user/USER" def items(self): - base = "{}/user/{}/".format(self.root, self.groups[0]) + base = f"{self.root}/user/{self.groups[0]}/" return self._dispatch_extractors(( (CivitaiUserModelsExtractor, base + "models"), (CivitaiUserPostsExtractor , base + "posts"), @@ -552,12 +548,12 @@ class CivitaiRestAPI(): }) def model(self, model_id): - endpoint = "/v1/models/{}".format(model_id) + endpoint = f"/v1/models/{model_id}" return self._call(endpoint) @memcache(keyarg=1) def model_version(self, model_version_id): - endpoint = "/v1/model-versions/{}".format(model_version_id) + endpoint = f"/v1/model-versions/{model_version_id}" return self._call(endpoint) def models(self, params): diff --git a/gallery_dl/extractor/common.py b/gallery_dl/extractor/common.py index 03956654..e206e687 100644 --- a/gallery_dl/extractor/common.py +++ b/gallery_dl/extractor/common.py @@ -181,7 +181,7 @@ class Extractor(): reason = exc.args[0].reason cls = reason.__class__.__name__ pre, _, err = str(reason.args[-1]).partition(":") - msg = " {}: {}".format(cls, (err or pre).lstrip()) + msg = f" {cls}: {(err or pre).lstrip()}" except Exception: msg = exc code = 0 @@ -209,8 +209,7 @@ class Extractor(): if notfound and code == 404: raise exception.NotFoundError(notfound) - msg = "'{} {}' for '{}'".format( - code, response.reason, response.url) + msg = f"'{code} {response.reason}' for '{response.url}'" challenge = util.detect_challenge(response) if challenge is not None: @@ -306,7 +305,7 @@ class Extractor(): if reason: t = datetime.fromtimestamp(until).time() - isotime = "{:02}:{:02}:{:02}".format(t.hour, t.minute, t.second) + isotime = f"{t.hour:02}:{t.minute:02}:{t.second:02}" self.log.info("Waiting until %s (%s)", isotime, reason) time.sleep(seconds) @@ -696,10 +695,8 @@ class Extractor(): Extractor._dump_sanitize = util.re_compile( r"[\\\\|/<>:\"?*&=#]+").sub - fname = "{:>02}_{}".format( - Extractor._dump_index, - Extractor._dump_sanitize('_', response.url), - ) + fname = (f"{Extractor._dump_index:>02}_" + f"{Extractor._dump_sanitize('_', response.url)}") if util.WINDOWS: path = os.path.abspath(fname)[:255] @@ -1041,7 +1038,7 @@ def _browser_useragent(): server.listen(1) host, port = server.getsockname() - webbrowser.open("http://{}:{}/user-agent".format(host, port)) + webbrowser.open(f"http://{host}:{port}/user-agent") client = server.accept()[0] server.close() diff --git a/gallery_dl/extractor/cyberdrop.py b/gallery_dl/extractor/cyberdrop.py index e1508297..a547c4c5 100644 --- a/gallery_dl/extractor/cyberdrop.py +++ b/gallery_dl/extractor/cyberdrop.py @@ -32,7 +32,7 @@ class CyberdropAlbumExtractor(lolisafe.LolisafeAlbumExtractor): yield Message.Url, file["url"], file def fetch_album(self, album_id): - url = "{}/a/{}".format(self.root, album_id) + url = f"{self.root}/a/{album_id}" page = self.request(url).text extr = text.extract_from(page) @@ -60,7 +60,7 @@ class CyberdropAlbumExtractor(lolisafe.LolisafeAlbumExtractor): def _extract_files(self, file_ids): for file_id in file_ids: try: - url = "{}/api/file/info/{}".format(self.root_api, file_id) + url = f"{self.root_api}/api/file/info/{file_id}" file = self.request(url).json() auth = self.request(file["auth_url"]).json() file["url"] = auth["url"] diff --git a/gallery_dl/extractor/danbooru.py b/gallery_dl/extractor/danbooru.py index 8bd9c62d..2aca34fb 100644 --- a/gallery_dl/extractor/danbooru.py +++ b/gallery_dl/extractor/danbooru.py @@ -112,8 +112,7 @@ class DanbooruExtractor(BaseExtractor): def items_artists(self): for artist in self.artists(): artist["_extractor"] = DanbooruTagExtractor - url = "{}/posts?tags={}".format( - self.root, text.quote(artist["name"])) + url = f"{self.root}/posts?tags={text.quote(artist['name'])}" yield Message.Queue, url, artist def metadata(self): @@ -156,7 +155,7 @@ class DanbooruExtractor(BaseExtractor): return if prefix: - params["page"] = "{}{}".format(prefix, posts[-1]["id"]) + params["page"] = f"{prefix}{posts[-1]['id']}" elif params["page"]: params["page"] += 1 else: @@ -164,8 +163,8 @@ class DanbooruExtractor(BaseExtractor): first = False def _ugoira_frames(self, post): - data = self.request_json("{}/posts/{}.json?only=media_metadata".format( - self.root, post["id"]) + data = self.request_json( + f"{self.root}/posts/{post['id']}.json?only=media_metadata" )["media_metadata"]["metadata"] if "Ugoira:FrameMimeType" in data: @@ -185,15 +184,15 @@ class DanbooruExtractor(BaseExtractor): order = self.config("order-posts") if not order or order in {"asc", "pool", "pool_asc", "asc_pool"}: - params = {"tags": "ord{}:{}".format(ctype, cid)} + params = {"tags": f"ord{ctype}:{cid}"} elif order in {"id", "desc_id", "id_desc"}: - params = {"tags": "{}:{}".format(ctype, cid)} + params = {"tags": f"{ctype}:{cid}"} prefix = "b" elif order in {"desc", "desc_pool", "pool_desc"}: - params = {"tags": "ord{}:{}".format(ctype, cid)} + params = {"tags": f"ord{ctype}:{cid}"} reverse = True elif order in {"asc_id", "id_asc"}: - params = {"tags": "{}:{}".format(ctype, cid)} + params = {"tags": f"{ctype}:{cid}"} reverse = True posts = self._pagination("/posts.json", params, prefix) @@ -204,7 +203,7 @@ class DanbooruExtractor(BaseExtractor): return self._collection_enumerate(posts) def _collection_metadata(self, cid, ctype, cname=None): - url = "{}/{}s/{}.json".format(self.root, cname or ctype, cid) + url = f"{self.root}/{cname or ctype}s/{cid}.json" collection = self.request_json(url) collection["name"] = collection["name"].replace("_", " ") self.post_ids = collection.pop("post_ids", ()) @@ -320,7 +319,7 @@ class DanbooruPostExtractor(DanbooruExtractor): example = "https://danbooru.donmai.us/posts/12345" def posts(self): - url = "{}/posts/{}.json".format(self.root, self.groups[-1]) + url = f"{self.root}/posts/{self.groups[-1]}.json" post = self.request_json(url) if self.includes: params = {"only": self.includes} @@ -362,7 +361,7 @@ class DanbooruArtistExtractor(DanbooruExtractor): items = DanbooruExtractor.items_artists def artists(self): - url = "{}/artists/{}.json".format(self.root, self.groups[-1]) + url = f"{self.root}/artists/{self.groups[-1]}.json" return (self.request_json(url),) diff --git a/gallery_dl/extractor/desktopography.py b/gallery_dl/extractor/desktopography.py index b0f29882..364d88fc 100644 --- a/gallery_dl/extractor/desktopography.py +++ b/gallery_dl/extractor/desktopography.py @@ -49,7 +49,7 @@ class DesktopographyExhibitionExtractor(DesktopographyExtractor): self.year = match[1] def items(self): - url = "{}/exhibition-{}/".format(self.root, self.year) + url = f"{self.root}/exhibition-{self.year}/" base_entry_url = "https://desktopography.net/portfolios/" page = self.request(url).text @@ -78,7 +78,7 @@ class DesktopographyEntryExtractor(DesktopographyExtractor): self.entry = match[1] def items(self): - url = "{}/portfolios/{}".format(self.root, self.entry) + url = f"{self.root}/portfolios/{self.entry}" page = self.request(url).text entry_data = {"entry": self.entry} diff --git a/gallery_dl/extractor/deviantart.py b/gallery_dl/extractor/deviantart.py index eef0aec0..af0704ab 100644 --- a/gallery_dl/extractor/deviantart.py +++ b/gallery_dl/extractor/deviantart.py @@ -67,7 +67,7 @@ class DeviantartExtractor(Extractor): self.quality = "-fullview.png?" self.quality_sub = util.re(r"-fullview\.[a-z0-9]+\?").sub else: - self.quality = ",q_{}".format(self.quality) + self.quality = f",q_{self.quality}" self.quality_sub = util.re(r",q_\d+").sub if self.intermediary: @@ -196,7 +196,7 @@ class DeviantartExtractor(Extractor): continue _user_details.update(name, user) - url = "{}/{}/avatar/".format(self.root, name) + url = f"{self.root}/{name}/avatar/" comment["_extractor"] = DeviantartAvatarExtractor yield Message.Queue, url, comment @@ -701,10 +701,10 @@ x2="45.4107524%" y2="71.4898596%" id="app-root-3">\ raise exception.NotFoundError("folder") def _folder_urls(self, folders, category, extractor): - base = "{}/{}/{}/".format(self.root, self.user, category) + base = f"{self.root}/{self.user}/{category}/" for folder in folders: folder["_extractor"] = extractor - url = "{}{}/{}".format(base, folder["folderid"], folder["name"]) + url = f"{base}{folder['folderid']}/{folder['name']}" yield url, folder def _update_content_default(self, deviation, content): @@ -878,7 +878,7 @@ class DeviantartUserExtractor(Dispatch, DeviantartExtractor): example = "https://www.deviantart.com/USER" def items(self): - base = "{}/{}/".format(self.root, self.user) + base = f"{self.root}/{self.user}/" return self._dispatch_extractors(( (DeviantartAvatarExtractor , base + "avatar"), (DeviantartBackgroundExtractor, base + "banner"), @@ -943,8 +943,8 @@ class DeviantartAvatarExtractor(DeviantartExtractor): fmt, _, ext = fmt.rpartition(".") if fmt: fmt = "-" + fmt - url = "https://a.deviantart.net/avatars{}/{}/{}/{}.{}?{}".format( - fmt, name[0], name[1], name, ext, index) + url = (f"https://a.deviantart.net/avatars{fmt}" + f"/{name[0]}/{name[1]}/{name}.{ext}?{index}") results.append(self._make_deviation(url, user, index, fmt)) return results @@ -1282,10 +1282,10 @@ class DeviantartDeviationExtractor(DeviantartExtractor): def deviations(self): if self.user: - url = "{}/{}/{}/{}".format( - self.root, self.user, self.type or "art", self.deviation_id) + url = (f"{self.root}/{self.user}" + f"/{self.type or 'art'}/{self.deviation_id}") else: - url = "{}/view/{}/".format(self.root, self.deviation_id) + url = f"{self.root}/view/{self.deviation_id}/" page = self._limited_request(url, notfound="deviation").text uuid = text.extr(page, '"deviationUuid\\":\\"', '\\') @@ -1431,7 +1431,7 @@ class DeviantartFollowingExtractor(DeviantartExtractor): api = DeviantartOAuthAPI(self) for user in api.user_friends(self.user): - url = "{}/{}".format(self.root, user["user"]["username"]) + url = f"{self.root}/{user['user']['username']}" user["_extractor"] = DeviantartUserExtractor yield Message.Queue, url, user @@ -1579,7 +1579,7 @@ class DeviantartOAuthAPI(): def comments(self, target_id, target_type="deviation", comment_id=None, offset=0): """Fetch comments posted on a target""" - endpoint = "/comments/{}/{}".format(target_type, target_id) + endpoint = f"/comments/{target_type}/{target_id}" params = { "commentid" : comment_id, "maxdepth" : "5", @@ -1633,7 +1633,7 @@ class DeviantartOAuthAPI(): def deviation_metadata(self, deviations): """ Fetch deviation metadata for a set of deviations""" endpoint = "/deviation/metadata?" + "&".join( - "deviationids[{}]={}".format(num, deviation["deviationid"]) + f"deviationids[{num}]={deviation['deviationid']}" for num, deviation in enumerate(deviations) ) return self._call( @@ -1740,8 +1740,8 @@ class DeviantartOAuthAPI(): if response.status_code != 200: self.log.debug("Server response: %s", data) - raise exception.AuthenticationError('"{}" ({})'.format( - data.get("error_description"), data.get("error"))) + raise exception.AuthenticationError( + f"\"{data.get('error_description')}\" ({data.get('error')})") if refresh_token_key: _refresh_token_cache.update( refresh_token_key, data["refresh_token"]) @@ -1784,8 +1784,7 @@ class DeviantartOAuthAPI(): raise exception.AuthorizationError() self.log.debug(response.text) - msg = "API responded with {} {}".format( - status, response.reason) + msg = f"API responded with {status} {response.reason}" if status == 429: if self.delay < 30: self.delay += 1 @@ -2068,7 +2067,7 @@ class DeviantartEclipseAPI(): params["offset"] = int(params["offset"]) + len(results) def _ids_watching(self, user): - url = "{}/{}/about".format(self.extractor.root, user) + url = f"{self.extractor.root}/{user}/about" page = self.request(url).text gruser_id = text.extr(page, ' data-userid="', '"') diff --git a/gallery_dl/extractor/dynastyscans.py b/gallery_dl/extractor/dynastyscans.py index f8abaaba..3e0424d3 100644 --- a/gallery_dl/extractor/dynastyscans.py +++ b/gallery_dl/extractor/dynastyscans.py @@ -20,7 +20,7 @@ class DynastyscansBase(): root = "https://dynasty-scans.com" def _parse_image_page(self, image_id): - url = "{}/images/{}".format(self.root, image_id) + url = f"{self.root}/images/{image_id}" extr = text.extract_from(self.request(url).text) date = extr("class='create_at'>", "") @@ -140,7 +140,7 @@ class DynastyscansAnthologyExtractor(DynastyscansSearchExtractor): example = "https://dynasty-scans.com/anthologies/TITLE" def items(self): - url = "{}/anthologies/{}.atom".format(self.root, self.groups[0]) + url = f"{self.root}/anthologies/{self.groups[0]}.atom" root = self.request_xml(url, xmlns=False) data = { diff --git a/gallery_dl/extractor/e621.py b/gallery_dl/extractor/e621.py index 2e54232c..8b7e17b7 100644 --- a/gallery_dl/extractor/e621.py +++ b/gallery_dl/extractor/e621.py @@ -40,8 +40,8 @@ class E621Extractor(danbooru.DanbooruExtractor): if not file["url"]: md5 = file["md5"] - file["url"] = "https://static1.{}/data/{}/{}/{}.{}".format( - self.root[8:], md5[0:2], md5[2:4], md5, file["ext"]) + file["url"] = (f"https://static1.{self.root[8:]}/data" + f"/{md5[0:2]}/{md5[2:4]}/{md5}.{file['ext']}") if notes and post.get("has_notes"): post["notes"] = self._get_notes(post["id"]) @@ -61,12 +61,12 @@ class E621Extractor(danbooru.DanbooruExtractor): def _get_notes(self, id): return self.request( - "{}/notes.json?search[post_id]={}".format(self.root, id)).json() + f"{self.root}/notes.json?search[post_id]={id}").json() @memcache(keyarg=1) def _get_pools(self, ids): pools = self.request( - "{}/pools.json?search[id]={}".format(self.root, ids)).json() + f"{self.root}/pools.json?search[id]={ids}").json() for pool in pools: pool["name"] = pool["name"].replace("_", " ") return pools @@ -126,7 +126,7 @@ class E621PostExtractor(E621Extractor, danbooru.DanbooruPostExtractor): example = "https://e621.net/posts/12345" def posts(self): - url = "{}/posts/{}.json".format(self.root, self.groups[-1]) + url = f"{self.root}/posts/{self.groups[-1]}.json" return (self.request(url).json()["post"],) diff --git a/gallery_dl/extractor/erome.py b/gallery_dl/extractor/erome.py index 12736853..51faec83 100644 --- a/gallery_dl/extractor/erome.py +++ b/gallery_dl/extractor/erome.py @@ -26,7 +26,7 @@ class EromeExtractor(Extractor): def items(self): self.__cookies = True for album_id in self.albums(): - url = "{}/a/{}".format(self.root, album_id) + url = f"{self.root}/a/{album_id}" try: page = self.request(url).text @@ -116,7 +116,7 @@ class EromeUserExtractor(EromeExtractor): example = "https://www.erome.com/USER" def albums(self): - url = "{}/{}".format(self.root, self.groups[0]) + url = f"{self.root}/{self.groups[0]}" return self._pagination(url, {}) diff --git a/gallery_dl/extractor/everia.py b/gallery_dl/extractor/everia.py index 9bae49ca..787786e1 100644 --- a/gallery_dl/extractor/everia.py +++ b/gallery_dl/extractor/everia.py @@ -29,9 +29,9 @@ class EveriaExtractor(Extractor): while True: if pnum == 1: - url = "{}{}/".format(self.root, path) + url = f"{self.root}{path}/" else: - url = "{}{}/page/{}/".format(self.root, path, pnum) + url = f"{self.root}{path}/page/{pnum}/" response = self.request(url, params=params, allow_redirects=False) if response.status_code >= 300: diff --git a/gallery_dl/extractor/exhentai.py b/gallery_dl/extractor/exhentai.py index 19cfad66..63317c48 100644 --- a/gallery_dl/extractor/exhentai.py +++ b/gallery_dl/extractor/exhentai.py @@ -221,7 +221,7 @@ class ExhentaiGalleryExtractor(ExhentaiExtractor): data = {} from .hitomi import HitomiGalleryExtractor - url = "https://hitomi.la/galleries/{}.html".format(self.gallery_id) + url = f"https://hitomi.la/galleries/{self.gallery_id}.html" data["_extractor"] = HitomiGalleryExtractor yield Message.Queue, url, data @@ -491,8 +491,7 @@ class ExhentaiGalleryExtractor(ExhentaiExtractor): _limits_update = _request_home def _gallery_page(self): - url = "{}/g/{}/{}/".format( - self.root, self.gallery_id, self.gallery_token) + url = f"{self.root}/g/{self.gallery_id}/{self.gallery_token}/" response = self.request(url, fatal=False) page = response.text @@ -505,8 +504,8 @@ class ExhentaiGalleryExtractor(ExhentaiExtractor): return page def _image_page(self): - url = "{}/s/{}/{}-{}".format( - self.root, self.image_token, self.gallery_id, self.image_num) + url = (f"{self.root}/s/{self.image_token}" + f"/{self.gallery_id}-{self.image_num}") page = self.request(url, fatal=False).text if page.startswith(("Invalid page", "Keep trying")): @@ -514,7 +513,7 @@ class ExhentaiGalleryExtractor(ExhentaiExtractor): return page def _fallback_original(self, nl, fullimg): - url = "{}?nl={}".format(fullimg, nl) + url = f"{fullimg}?nl={nl}" for _ in util.repeat(self.fallback_retries): yield url @@ -523,8 +522,7 @@ class ExhentaiGalleryExtractor(ExhentaiExtractor): token = self.key_start for _ in util.repeat(self.fallback_retries): - url = "{}/s/{}/{}-{}?nl={}".format( - self.root, token, self.gallery_id, num, nl) + url = f"{self.root}/s/{token}/{self.gallery_id}-{num}?nl={nl}" page = self.request(url, fatal=False).text if page.startswith(("Invalid page", "Keep trying")): @@ -577,7 +575,7 @@ class ExhentaiSearchExtractor(ExhentaiExtractor): if tag: if "+" in tag: ns, _, tag = tag.rpartition(":") - tag = '{}:"{}$"'.format(ns, tag.replace("+", " ")) + tag = f"{ns}:\"{tag.replace('+', ' ')}$\"" else: tag += "$" self.params = {"f_search": tag, "page": 0} diff --git a/gallery_dl/extractor/fanbox.py b/gallery_dl/extractor/fanbox.py index 6c23b68b..566e470c 100644 --- a/gallery_dl/extractor/fanbox.py +++ b/gallery_dl/extractor/fanbox.py @@ -340,7 +340,7 @@ class FanboxExtractor(Extractor): templ = "https://docs.google.com/forms/d/e/{}/viewform?usp=sf_link" url = templ.format(content_id) else: - self.log.warning("service not recognized: {}".format(provider)) + self.log.warning(f"service not recognized: {provider}") if url: final_post["embed"] = embed diff --git a/gallery_dl/extractor/fantia.py b/gallery_dl/extractor/fantia.py index 2e3f0d8b..9a2b2146 100644 --- a/gallery_dl/extractor/fantia.py +++ b/gallery_dl/extractor/fantia.py @@ -184,7 +184,7 @@ class FantiaCreatorExtractor(FantiaExtractor): self.creator_id = match[1] def posts(self): - url = "{}/fanclubs/{}/posts".format(self.root, self.creator_id) + url = f"{self.root}/fanclubs/{self.creator_id}/posts" return self._pagination(url) diff --git a/gallery_dl/extractor/fapachi.py b/gallery_dl/extractor/fapachi.py index 6be2d626..71b22755 100644 --- a/gallery_dl/extractor/fapachi.py +++ b/gallery_dl/extractor/fapachi.py @@ -31,8 +31,7 @@ class FapachiPostExtractor(Extractor): "user": self.user, "id" : self.id, } - page = self.request("{}/{}/media/{}".format( - self.root, self.user, self.id)).text + page = self.request(f"{self.root}/{self.user}/media/{self.id}").text url = self.root + text.extract( page, 'data-src="', '"', page.index('class="media-img'))[0] yield Message.Directory, data @@ -56,8 +55,8 @@ class FapachiUserExtractor(Extractor): def items(self): data = {"_extractor": FapachiPostExtractor} while True: - page = self.request("{}/{}/page/{}".format( - self.root, self.user, self.num)).text + url = f"{self.root}/{self.user}/page/{self.num}" + page = self.request(url).text for post in text.extract_iter(page, 'model-media-prew">', ">"): path = text.extr(post, '", None) @@ -66,8 +66,7 @@ class FapelloModelExtractor(Extractor): num = 1 data = {"_extractor": FapelloPostExtractor} while True: - url = "{}/ajax/model/{}/page-{}/".format( - self.root, self.model, num) + url = f"{self.root}/ajax/model/{self.model}/page-{num}/" page = self.request(url).text if not page: return @@ -109,8 +108,8 @@ class FapelloPathExtractor(Extractor): data = {"_extractor": FapelloModelExtractor} while True: - page = self.request("{}/ajax/{}/page-{}/".format( - self.root, self.path, num)).text + url = f"{self.root}/ajax/{self.path}/page-{num}/" + page = self.request(url).text if not page: return diff --git a/gallery_dl/extractor/flickr.py b/gallery_dl/extractor/flickr.py index 505216a7..36943027 100644 --- a/gallery_dl/extractor/flickr.py +++ b/gallery_dl/extractor/flickr.py @@ -134,8 +134,8 @@ class FlickrAlbumExtractor(FlickrExtractor): for album in self.api.photosets_getList(self.user["nsid"]): self.api._clean_info(album).update(data) - url = "https://www.flickr.com/photos/{}/albums/{}".format( - self.user["path_alias"], album["id"]) + url = (f"https://www.flickr.com/photos/{self.user['path_alias']}" + f"/albums/{album['id']}") yield Message.Queue, url, album def metadata(self): diff --git a/gallery_dl/extractor/furaffinity.py b/gallery_dl/extractor/furaffinity.py index 395d47d1..2cf6d95b 100644 --- a/gallery_dl/extractor/furaffinity.py +++ b/gallery_dl/extractor/furaffinity.py @@ -71,7 +71,7 @@ class FuraffinityExtractor(Extractor): return num def _parse_post(self, post_id): - url = "{}/view/{}/".format(self.root, post_id) + url = f"{self.root}/view/{post_id}/" extr = text.extract_from(self.request(url).text) if self._new_layout is None: @@ -147,9 +147,8 @@ class FuraffinityExtractor(Extractor): data["user"] = self.user or data["artist_url"] data["date"] = text.parse_timestamp(data["filename"].partition(".")[0]) data["description"] = self._process_description(data["_description"]) - data["thumbnail"] = "https://t.furaffinity.net/{}@600-{}.jpg".format( - post_id, path.rsplit("/", 2)[1]) - + data["thumbnail"] = (f"https://t.furaffinity.net/{post_id}@600-" + f"{path.rsplit('/', 2)[1]}.jpg") return data def _process_description(self, description): @@ -157,11 +156,10 @@ class FuraffinityExtractor(Extractor): def _pagination(self, path, folder=None): num = 1 - folder = "" if folder is None else "/folder/{}/a".format(folder) + folder = "" if folder is None else f"/folder/{folder}/a" while True: - url = "{}/{}/{}{}/{}/".format( - self.root, path, self.user, folder, num) + url = f"{self.root}/{path}/{self.user}{folder}/{num}/" page = self.request(url).text post_id = None @@ -173,7 +171,7 @@ class FuraffinityExtractor(Extractor): num += 1 def _pagination_favorites(self): - path = "/favorites/{}/".format(self.user) + path = f"/favorites/{self.user}/" while path: page = self.request(self.root + path).text @@ -326,7 +324,7 @@ class FuraffinityUserExtractor(Dispatch, FuraffinityExtractor): example = "https://www.furaffinity.net/user/USER/" def items(self): - base = "{}/{{}}/{}/".format(self.root, self.user) + base = f"{self.root}/{{}}/{self.user}/" return self._dispatch_extractors(( (FuraffinityGalleryExtractor , base.format("gallery")), (FuraffinityScrapsExtractor , base.format("scraps")), @@ -341,7 +339,7 @@ class FuraffinityFollowingExtractor(FuraffinityExtractor): example = "https://www.furaffinity.net/watchlist/by/USER/" def items(self): - url = "{}/watchlist/by/{}/".format(self.root, self.user) + url = f"{self.root}/watchlist/by/{self.user}/" data = {"_extractor": FuraffinityUserExtractor} while True: diff --git a/gallery_dl/extractor/furry34.py b/gallery_dl/extractor/furry34.py index e0c7fdb5..92307b36 100644 --- a/gallery_dl/extractor/furry34.py +++ b/gallery_dl/extractor/furry34.py @@ -46,8 +46,8 @@ class Furry34Extractor(BooruExtractor): post_id = post["id"] root = self.root_cdn if files[fmt][0] else self.root - post["file_url"] = url = "{}/posts/{}/{}/{}.{}".format( - root, post_id // 1000, post_id, post_id, extension) + post["file_url"] = url = \ + f"{root}/posts/{post_id // 1000}/{post_id}/{post_id}.{extension}" post["format_id"] = fmt post["format"] = extension.partition(".")[0] @@ -73,11 +73,11 @@ class Furry34Extractor(BooruExtractor): post["tags_" + types[type]] = values def _fetch_post(self, post_id): - url = "{}/api/v2/post/{}".format(self.root, post_id) + url = f"{self.root}/api/v2/post/{post_id}" return self.request(url).json() def _pagination(self, endpoint, params=None): - url = "{}/api{}".format(self.root, endpoint) + url = f"{self.root}/api{endpoint}" if params is None: params = {} diff --git a/gallery_dl/extractor/fuskator.py b/gallery_dl/extractor/fuskator.py index 943f43f2..a34e4399 100644 --- a/gallery_dl/extractor/fuskator.py +++ b/gallery_dl/extractor/fuskator.py @@ -22,7 +22,7 @@ class FuskatorGalleryExtractor(GalleryExtractor): def __init__(self, match): self.gallery_hash = match[1] - url = "{}/thumbs/{}/index.html".format(self.root, self.gallery_hash) + url = f"{self.root}/thumbs/{self.gallery_hash}/index.html" GalleryExtractor.__init__(self, match, url) def metadata(self, page): diff --git a/gallery_dl/extractor/gelbooru.py b/gallery_dl/extractor/gelbooru.py index fdc0764c..b4a2d011 100644 --- a/gallery_dl/extractor/gelbooru.py +++ b/gallery_dl/extractor/gelbooru.py @@ -73,7 +73,7 @@ class GelbooruBase(): if id: tag = "id:" + op tags = [t for t in tags if not t.startswith(tag)] - tags = "{} id:{}".format(" ".join(tags), op) + tags = f"{' '.join(tags)} id:{op}" while True: posts = self._api_request(params) @@ -113,7 +113,7 @@ class GelbooruBase(): post["_fallback"] = (url,) md5 = post["md5"] root = text.root_from_url(post["preview_url"]) - path = "/images/{}/{}/{}.webm".format(md5[0:2], md5[2:4], md5) + path = f"/images/{md5[0:2]}/{md5[2:4]}/{md5}.webm" url = root + path return url diff --git a/gallery_dl/extractor/gelbooru_v01.py b/gallery_dl/extractor/gelbooru_v01.py index da8e8290..61d0545e 100644 --- a/gallery_dl/extractor/gelbooru_v01.py +++ b/gallery_dl/extractor/gelbooru_v01.py @@ -17,8 +17,7 @@ class GelbooruV01Extractor(booru.BooruExtractor): per_page = 20 def _parse_post(self, post_id): - url = "{}/index.php?page=post&s=view&id={}".format( - self.root, post_id) + url = f"{self.root}/index.php?page=post&s=view&id={post_id}" extr = text.extract_from(self.request(url).text) post = { diff --git a/gallery_dl/extractor/girlswithmuscle.py b/gallery_dl/extractor/girlswithmuscle.py index c76abfdd..38be246d 100644 --- a/gallery_dl/extractor/girlswithmuscle.py +++ b/gallery_dl/extractor/girlswithmuscle.py @@ -66,7 +66,7 @@ class GirlswithmusclePostExtractor(GirlswithmuscleExtractor): def items(self): self.login() - url = "{}/{}/".format(self.root, self.groups[0]) + url = f"{self.root}/{self.groups[0]}/" page = self.request(url).text if not page: raise exception.NotFoundError("post") @@ -150,11 +150,10 @@ class GirlswithmuscleSearchExtractor(GirlswithmuscleExtractor): def pages(self): query = self.groups[0] - url = "{}/images/{}".format(self.root, query) + url = f"{self.root}/images/{query}" response = self.request(url) if response.history: - msg = 'Request was redirected to "{}", try logging in'.format( - response.url) + msg = f'Request was redirected to "{response.url}", try logging in' raise exception.AuthorizationError(msg) page = response.text @@ -164,7 +163,7 @@ class GirlswithmuscleSearchExtractor(GirlswithmuscleExtractor): yield page for i in range(current + 1, total + 1): - url = "{}/images/{}/{}".format(self.root, i, query) + url = f"{self.root}/images/{i}/{query}" yield self.request(url).text def items(self): @@ -175,5 +174,5 @@ class GirlswithmuscleSearchExtractor(GirlswithmuscleExtractor): "gallery_name": text.unescape(text.extr(page, "", "<")), } for imgid in text.extract_iter(page, 'id="imgid-', '"'): - url = "{}/{}/".format(self.root, imgid) + url = f"{self.root}/{imgid}/" yield Message.Queue, url, data diff --git a/gallery_dl/extractor/hentaicosplays.py b/gallery_dl/extractor/hentaicosplays.py index 14db971b..5c2628fa 100644 --- a/gallery_dl/extractor/hentaicosplays.py +++ b/gallery_dl/extractor/hentaicosplays.py @@ -44,7 +44,7 @@ class HentaicosplaysGalleryExtractor( def __init__(self, match): BaseExtractor.__init__(self, match) self.slug = self.groups[-1] - self.page_url = "{}/story/{}/".format(self.root, self.slug) + self.page_url = f"{self.root}/story/{self.slug}/" def _init(self): self.session.headers["Referer"] = self.page_url diff --git a/gallery_dl/extractor/hentaifoundry.py b/gallery_dl/extractor/hentaifoundry.py index 139d5463..e5299400 100644 --- a/gallery_dl/extractor/hentaifoundry.py +++ b/gallery_dl/extractor/hentaifoundry.py @@ -58,7 +58,7 @@ class HentaifoundryExtractor(Extractor): num = self.start_page while True: - page = self.request("{}/page/{}".format(url, num)).text + page = self.request(f"{url}/page/{num}").text yield from text.extract_iter(page, begin, end) if 'class="pager"' not in page or 'class="last hidden"' in page: @@ -220,7 +220,7 @@ class HentaifoundryPicturesExtractor(HentaifoundryExtractor): def __init__(self, match): HentaifoundryExtractor.__init__(self, match) - self.page_url = "{}/pictures/user/{}".format(self.root, self.user) + self.page_url = f"{self.root}/pictures/user/{self.user}" class HentaifoundryScrapsExtractor(HentaifoundryExtractor): @@ -232,8 +232,7 @@ class HentaifoundryScrapsExtractor(HentaifoundryExtractor): def __init__(self, match): HentaifoundryExtractor.__init__(self, match) - self.page_url = "{}/pictures/user/{}/scraps".format( - self.root, self.user) + self.page_url = f"{self.root}/pictures/user/{self.user}/scraps" class HentaifoundryFavoriteExtractor(HentaifoundryExtractor): @@ -246,8 +245,7 @@ class HentaifoundryFavoriteExtractor(HentaifoundryExtractor): def __init__(self, match): HentaifoundryExtractor.__init__(self, match) - self.page_url = "{}/user/{}/faves/pictures".format( - self.root, self.user) + self.page_url = f"{self.root}/user/{self.user}/faves/pictures" class HentaifoundryTagExtractor(HentaifoundryExtractor): @@ -260,7 +258,7 @@ class HentaifoundryTagExtractor(HentaifoundryExtractor): def __init__(self, match): HentaifoundryExtractor.__init__(self, match) - self.page_url = "{}/pictures/tagged/{}".format(self.root, self.user) + self.page_url = f"{self.root}/pictures/tagged/{self.user}" def metadata(self): return {"search_tags": self.user} @@ -276,7 +274,7 @@ class HentaifoundryRecentExtractor(HentaifoundryExtractor): def __init__(self, match): HentaifoundryExtractor.__init__(self, match) - self.page_url = "{}/pictures/recent/{}".format(self.root, self.user) + self.page_url = f"{self.root}/pictures/recent/{self.user}" def metadata(self): return {"date": self.user} @@ -309,8 +307,8 @@ class HentaifoundryImageExtractor(HentaifoundryExtractor): self.index = match[3] def items(self): - post_url = "{}/pictures/user/{}/{}/?enterAgree=1".format( - self.root, self.user, self.index) + post_url = (f"{self.root}/pictures/user/{self.user}" + f"/{self.index}/?enterAgree=1") image = self._parse_post(post_url) image["user"] = self.user yield Message.Directory, image @@ -332,7 +330,7 @@ class HentaifoundryStoriesExtractor(HentaifoundryExtractor): yield Message.Url, story["src"], story def stories(self): - url = "{}/stories/user/{}".format(self.root, self.user) + url = f"{self.root}/stories/user/{self.user}" return self._pagination(url, '<div class="storyRow">', '</tr></table>') @@ -350,8 +348,8 @@ class HentaifoundryStoryExtractor(HentaifoundryExtractor): self.index = match[3] def items(self): - story_url = "{}/stories/user/{}/{}/x?enterAgree=1".format( - self.root, self.user, self.index) + story_url = (f"{self.root}/stories/user/{self.user}" + f"/{self.index}/x?enterAgree=1") story = self._parse_story(self.request(story_url).text) yield Message.Directory, story yield Message.Url, story["src"], story diff --git a/gallery_dl/extractor/hentaihand.py b/gallery_dl/extractor/hentaihand.py index 6ac818fa..67121696 100644 --- a/gallery_dl/extractor/hentaihand.py +++ b/gallery_dl/extractor/hentaihand.py @@ -21,7 +21,7 @@ class HentaihandGalleryExtractor(GalleryExtractor): def __init__(self, match): self.slug = match[1] - url = "{}/api/comics/{}".format(self.root, self.slug) + url = f"{self.root}/api/comics/{self.slug}" GalleryExtractor.__init__(self, match, url) def metadata(self, page): @@ -68,7 +68,7 @@ class HentaihandTagExtractor(Extractor): else: tpl = self.type + "s" - url = "{}/api/{}/{}".format(self.root, tpl, self.key) + url = f"{self.root}/api/{tpl}/{self.key}" tid = self.request(url, notfound=self.type).json()["id"] url = self.root + "/api/comics" @@ -85,7 +85,7 @@ class HentaihandTagExtractor(Extractor): info = self.request(url, params=params).json() for gallery in info["data"]: - gurl = "{}/en/comic/{}".format(self.root, gallery["slug"]) + gurl = f"{self.root}/en/comic/{gallery['slug']}" gallery["_extractor"] = HentaihandGalleryExtractor yield Message.Queue, gurl, gallery diff --git a/gallery_dl/extractor/hentaihere.py b/gallery_dl/extractor/hentaihere.py index 9224246e..b894d77d 100644 --- a/gallery_dl/extractor/hentaihere.py +++ b/gallery_dl/extractor/hentaihere.py @@ -26,7 +26,7 @@ class HentaihereChapterExtractor(HentaihereBase, ChapterExtractor): def __init__(self, match): self.manga_id, self.chapter = match.groups() - url = "{}/m/S{}/{}/1".format(self.root, self.manga_id, self.chapter) + url = f"{self.root}/m/S{self.manga_id}/{self.chapter}/1" ChapterExtractor.__init__(self, match, url) def metadata(self, page): diff --git a/gallery_dl/extractor/hentainexus.py b/gallery_dl/extractor/hentainexus.py index 0d88bd80..d3901acf 100644 --- a/gallery_dl/extractor/hentainexus.py +++ b/gallery_dl/extractor/hentainexus.py @@ -23,7 +23,7 @@ class HentainexusGalleryExtractor(GalleryExtractor): def __init__(self, match): self.gallery_id = match[1] - url = "{}/view/{}".format(self.root, self.gallery_id) + url = f"{self.root}/view/{self.gallery_id}" GalleryExtractor.__init__(self, match, url) def metadata(self, page): @@ -59,7 +59,7 @@ class HentainexusGalleryExtractor(GalleryExtractor): return data def images(self, _): - url = "{}/read/{}".format(self.root, self.gallery_id) + url = f"{self.root}/read/{self.gallery_id}" page = self.request(url).text imgs = util.json_loads(self._decode(text.extr( page, 'initReader("', '"'))) @@ -135,18 +135,18 @@ class HentainexusGalleryExtractor(GalleryExtractor): jt = '' if event: - jt += '({}) '.format(event) + jt += f'({event}) ' if circle: - jt += '[{} ({})] '.format(circle, artist) + jt += f'[{circle} ({artist})] ' else: - jt += '[{}] '.format(artist) + jt += f'[{artist}] ' jt += title if parody.lower() != 'original work': - jt += ' ({})'.format(parody) + jt += f' ({parody})' if book: - jt += ' ({})'.format(book) + jt += f' ({book})' if magazine: - jt += ' ({})'.format(magazine) + jt += f' ({magazine})' return jt diff --git a/gallery_dl/extractor/hiperdex.py b/gallery_dl/extractor/hiperdex.py index 3a8a0c7d..a75eee0c 100644 --- a/gallery_dl/extractor/hiperdex.py +++ b/gallery_dl/extractor/hiperdex.py @@ -24,7 +24,7 @@ class HiperdexBase(): @memcache(keyarg=1) def manga_data(self, manga, page=None): if not page: - url = "{}/manga/{}/".format(self.root, manga) + url = f"{self.root}/manga/{manga}/" page = self.request(url).text extr = text.extract_from(page) diff --git a/gallery_dl/extractor/hitomi.py b/gallery_dl/extractor/hitomi.py index 6f5ee133..0c2fa9bf 100644 --- a/gallery_dl/extractor/hitomi.py +++ b/gallery_dl/extractor/hitomi.py @@ -32,12 +32,10 @@ class HitomiGalleryExtractor(HitomiExtractor, GalleryExtractor): def __init__(self, match): GalleryExtractor.__init__(self, match, False) self.gid = gid = self.groups[0] - self.page_url = "https://ltn.{}/galleries/{}.js".format( - self.domain, gid) + self.page_url = f"https://ltn.{self.domain}/galleries/{gid}.js" def _init(self): - self.session.headers["Referer"] = "{}/reader/{}.html".format( - self.root, self.gid) + self.session.headers["Referer"] = f"{self.root}/reader/{self.gid}.html" def metadata(self, page): self.info = info = util.json_loads(page.partition("=")[2]) @@ -93,10 +91,8 @@ class HitomiGalleryExtractor(HitomiExtractor, GalleryExtractor): # https://ltn.gold-usergeneratedcontent.net/common.js inum = int(ihash[-1] + ihash[-3:-1], 16) - url = "https://{}{}.{}/{}/{}/{}.{}".format( - ext[0], gg_m.get(inum, gg_default) + 1, self.domain, - gg_b, inum, ihash, ext, - ) + url = (f"https://{ext[0]}{gg_m.get(inum, gg_default) + 1}." + f"{self.domain}/{gg_b}/{inum}/{ihash}.{ext}") result.append((url, idata)) return result @@ -122,8 +118,7 @@ class HitomiTagExtractor(HitomiExtractor): "_extractor": HitomiGalleryExtractor, "search_tags": text.unquote(self.tag.rpartition("-")[0]), } - nozomi_url = "https://ltn.{}/{}/{}.nozomi".format( - self.domain, self.type, self.tag) + nozomi_url = f"https://ltn.{self.domain}/{self.type}/{self.tag}.nozomi" headers = { "Origin": self.root, "Cache-Control": "max-age=0", @@ -132,14 +127,13 @@ class HitomiTagExtractor(HitomiExtractor): offset = 0 total = None while True: - headers["Referer"] = "{}/{}/{}.html?page={}".format( - self.root, self.type, self.tag, offset // 100 + 1) - headers["Range"] = "bytes={}-{}".format(offset, offset+99) + headers["Referer"] = (f"{self.root}/{self.type}/{self.tag}.html" + f"?page={offset // 100 + 1}") + headers["Range"] = f"bytes={offset}-{offset + 99}" response = self.request(nozomi_url, headers=headers) for gallery_id in decode_nozomi(response.content): - gallery_url = "{}/galleries/{}.html".format( - self.root, gallery_id) + gallery_url = f"{self.root}/galleries/{gallery_id}.html" yield Message.Queue, gallery_url, data offset += 100 @@ -162,8 +156,8 @@ class HitomiIndexExtractor(HitomiTagExtractor): def items(self): data = {"_extractor": HitomiGalleryExtractor} - nozomi_url = "https://ltn.{}/{}-{}.nozomi".format( - self.domain, self.tag, self.language) + nozomi_url = (f"https://ltn.{self.domain}" + f"/{self.tag}-{self.language}.nozomi") headers = { "Origin": self.root, "Cache-Control": "max-age=0", @@ -172,14 +166,13 @@ class HitomiIndexExtractor(HitomiTagExtractor): offset = 0 total = None while True: - headers["Referer"] = "{}/{}-{}.html?page={}".format( - self.root, self.tag, self.language, offset // 100 + 1) - headers["Range"] = "bytes={}-{}".format(offset, offset+99) + headers["Referer"] = (f"{self.root}/{self.tag}-{self.language}" + f".html?page={offset // 100 + 1}") + headers["Range"] = f"bytes={offset}-{offset + 99}" response = self.request(nozomi_url, headers=headers) for gallery_id in decode_nozomi(response.content): - gallery_url = "{}/galleries/{}.html".format( - self.root, gallery_id) + gallery_url = f"{self.root}/galleries/{gallery_id}.html" yield Message.Queue, gallery_url, data offset += 100 @@ -210,24 +203,22 @@ class HitomiSearchExtractor(HitomiExtractor): intersects = set.intersection(*results) for gallery_id in sorted(intersects, reverse=True): - gallery_url = "{}/galleries/{}.html".format( - self.root, gallery_id) + gallery_url = f"{self.root}/galleries/{gallery_id}.html" yield Message.Queue, gallery_url, data def get_nozomi_items(self, full_tag): area, tag, language = self.get_nozomi_args(full_tag) + base = f"https://ltn.{self.domain}/n/" if area: - nozomi_url = "https://ltn.{}/n/{}/{}-{}.nozomi".format( - self.domain, area, tag, language) + nozomi_url = f"{base}{area}/{tag}-{language}.nozomi" else: - nozomi_url = "https://ltn.{}/n/{}-{}.nozomi".format( - self.domain, tag, language) + nozomi_url = f"{base}{tag}-{language}.nozomi" headers = { "Origin": self.root, "Cache-Control": "max-age=0", - "Referer": "{}/search.html?{}".format(self.root, self.query), + "Referer": f"{self.root}/search.html?{self.query}", } response = self.request(nozomi_url, headers=headers) diff --git a/gallery_dl/extractor/hotleak.py b/gallery_dl/extractor/hotleak.py index b11d60f0..587d88cc 100644 --- a/gallery_dl/extractor/hotleak.py +++ b/gallery_dl/extractor/hotleak.py @@ -70,8 +70,7 @@ class HotleakPostExtractor(HotleakExtractor): self.creator, self.type, self.id = match.groups() def posts(self): - url = "{}/{}/{}/{}".format( - self.root, self.creator, self.type, self.id) + url = f"{self.root}/{self.creator}/{self.type}/{self.id}" page = self.request(url).text page = text.extr( page, '<div class="movie-image thumb">', '</article>') @@ -106,7 +105,7 @@ class HotleakCreatorExtractor(HotleakExtractor): self.creator = match[1] def posts(self): - url = "{}/{}".format(self.root, self.creator) + url = f"{self.root}/{self.creator}" return self._pagination(url) def _pagination(self, url): @@ -159,7 +158,7 @@ class HotleakCategoryExtractor(HotleakExtractor): self._category, self.params = match.groups() def items(self): - url = "{}/{}".format(self.root, self._category) + url = f"{self.root}/{self._category}" if self._category in ("hot", "creators"): data = {"_extractor": HotleakCreatorExtractor} diff --git a/gallery_dl/extractor/imagefap.py b/gallery_dl/extractor/imagefap.py index ea44016c..1a235628 100644 --- a/gallery_dl/extractor/imagefap.py +++ b/gallery_dl/extractor/imagefap.py @@ -49,7 +49,7 @@ class ImagefapGalleryExtractor(ImagefapExtractor): self.image_id = "" def items(self): - url = "{}/gallery/{}".format(self.root, self.gid) + url = f"{self.root}/gallery/{self.gid}" page = self.request(url).text data = self.get_job_metadata(page) yield Message.Directory, data @@ -81,12 +81,12 @@ class ImagefapGalleryExtractor(ImagefapExtractor): def get_images(self): """Collect image-urls and -metadata""" - url = "{}/photo/{}/".format(self.root, self.image_id) + url = f"{self.root}/photo/{self.image_id}/" params = {"gid": self.gid, "idx": 0, "partial": "true"} headers = { "Content-Type": "application/x-www-form-urlencoded", "X-Requested-With": "XMLHttpRequest", - "Referer": "{}?pgid=&gid={}&page=0".format(url, self.image_id) + "Referer": f"{url}?pgid=&gid={self.image_id}&page=0" } num = 0 @@ -124,7 +124,7 @@ class ImagefapImageExtractor(ImagefapExtractor): yield Message.Url, url, data def get_image(self): - url = "{}/photo/{}/".format(self.root, self.image_id) + url = f"{self.root}/photo/{self.image_id}/" page = self.request(url).text url, pos = text.extract( @@ -161,7 +161,7 @@ class ImagefapFolderExtractor(ImagefapExtractor): def items(self): for gallery_id, name, folder in self.galleries(self.folder_id): - url = "{}/gallery/{}".format(self.root, gallery_id) + url = f"{self.root}/gallery/{gallery_id}" data = { "gallery_id": gallery_id, "title" : text.unescape(name), @@ -175,14 +175,13 @@ class ImagefapFolderExtractor(ImagefapExtractor): if folder_id == "-1": folder_name = "Uncategorized" if self._id: - url = "{}/usergallery.php?userid={}&folderid=-1".format( - self.root, self.user) + url = (f"{self.root}/usergallery.php" + f"?userid={self.user}&folderid=-1") else: - url = "{}/profile/{}/galleries?folderid=-1".format( - self.root, self.user) + url = f"{self.root}/profile/{self.user}/galleries?folderid=-1" else: folder_name = None - url = "{}/organizer/{}/".format(self.root, folder_id) + url = f"{self.root}/organizer/{folder_id}/" params = {"page": 0} extr = text.extract_from(self.request(url, params=params).text) @@ -222,19 +221,17 @@ class ImagefapUserExtractor(ImagefapExtractor): for folder_id in self.folders(): if folder_id == "-1": - url = "{}/profile/{}/galleries?folderid=-1".format( - self.root, self.user) + url = f"{self.root}/profile/{self.user}/galleries?folderid=-1" else: - url = "{}/organizer/{}/".format(self.root, folder_id) + url = f"{self.root}/organizer/{folder_id}/" yield Message.Queue, url, data def folders(self): """Return a list of folder IDs of a user""" if self.user: - url = "{}/profile/{}/galleries".format(self.root, self.user) + url = f"{self.root}/profile/{self.user}/galleries" else: - url = "{}/usergallery.php?userid={}".format( - self.root, self.user_id) + url = f"{self.root}/usergallery.php?userid={self.user_id}" response = self.request(url) self.user = response.url.split("/")[-2] diff --git a/gallery_dl/extractor/imagehosts.py b/gallery_dl/extractor/imagehosts.py index 5b0de36d..f3c0075a 100644 --- a/gallery_dl/extractor/imagehosts.py +++ b/gallery_dl/extractor/imagehosts.py @@ -27,8 +27,7 @@ class ImagehostImageExtractor(Extractor): def __init__(self, match): Extractor.__init__(self, match) - self.page_url = "http{}://{}".format( - "s" if self._https else "", match[1]) + self.page_url = f"http{'s' if self._https else ''}://{match[1]}" self.token = match[2] if self._params == "simple": diff --git a/gallery_dl/extractor/imgbb.py b/gallery_dl/extractor/imgbb.py index 95f8430a..fd6b0554 100644 --- a/gallery_dl/extractor/imgbb.py +++ b/gallery_dl/extractor/imgbb.py @@ -164,7 +164,7 @@ class ImgbbUserExtractor(ImgbbExtractor): ImgbbExtractor.__init__(self, match) self.user = match[1] self.sort = text.parse_query(match[2]).get("sort", "date_desc") - self.page_url = "https://{}.imgbb.com/".format(self.user) + self.page_url = f"https://{self.user}.imgbb.com/" def metadata(self, page): user = self._extract_user(page) diff --git a/gallery_dl/extractor/imgth.py b/gallery_dl/extractor/imgth.py index f93596ac..7e5e6cf6 100644 --- a/gallery_dl/extractor/imgth.py +++ b/gallery_dl/extractor/imgth.py @@ -21,7 +21,7 @@ class ImgthGalleryExtractor(GalleryExtractor): def __init__(self, match): self.gallery_id = gid = match[1] - url = "{}/gallery/{}/g/".format(self.root, gid) + url = f"{self.root}/gallery/{gid}/g/" GalleryExtractor.__init__(self, match, url) def metadata(self, page): @@ -45,12 +45,11 @@ class ImgthGalleryExtractor(GalleryExtractor): thumbs = text.extr(page, '<ul class="thumbnails">', '</ul>') for url in text.extract_iter(thumbs, '<img src="', '"'): path = url.partition("/thumbs/")[2] - yield ("{}/images/{}".format(self.root, path), None) + yield (f"{self.root}/images/{path}", None) if '<li class="next">' not in page: return pnum += 1 - url = "{}/gallery/{}/g/page/{}".format( - self.root, self.gallery_id, pnum) + url = f"{self.root}/gallery/{self.gallery_id}/g/page/{pnum}" page = self.request(url).text diff --git a/gallery_dl/extractor/imgur.py b/gallery_dl/extractor/imgur.py index 17d6030d..88578b07 100644 --- a/gallery_dl/extractor/imgur.py +++ b/gallery_dl/extractor/imgur.py @@ -36,8 +36,8 @@ class ImgurExtractor(Extractor): elif image["is_animated"] and self.mp4 and image["ext"] == "gif": image["ext"] = "mp4" - image["url"] = url = "https://i.imgur.com/{}.{}".format( - image["id"], image["ext"]) + image["url"] = url = \ + f"https://i.imgur.com/{image['id']}.{image['ext']}" image["date"] = text.parse_datetime(image["created_at"]) image["_http_validate"] = self._validate text.nameext_from_url(url, image) @@ -131,10 +131,10 @@ class ImgurGalleryExtractor(ImgurExtractor): def items(self): if self.api.gallery(self.key)["is_album"]: - url = "{}/a/{}".format(self.root, self.key) + url = f"{self.root}/a/{self.key}" extr = ImgurAlbumExtractor else: - url = "{}/{}".format(self.root, self.key) + url = f"{self.root}/{self.key}" extr = ImgurImageExtractor yield Message.Queue, url, {"_extractor": extr} @@ -234,16 +234,15 @@ class ImgurAPI(): self.headers = {"Authorization": "Client-ID " + self.client_id} def account_submissions(self, account): - endpoint = "/3/account/{}/submissions".format(account) + endpoint = f"/3/account/{account}/submissions" return self._pagination(endpoint) def account_favorites(self, account): - endpoint = "/3/account/{}/gallery_favorites".format(account) + endpoint = f"/3/account/{account}/gallery_favorites" return self._pagination(endpoint) def account_favorites_folder(self, account, folder_id): - endpoint = "/3/account/{}/folders/{}/favorites".format( - account, folder_id) + endpoint = f"/3/account/{account}/folders/{folder_id}/favorites" return self._pagination_v2(endpoint) def accounts_me_allposts(self): @@ -270,11 +269,11 @@ class ImgurAPI(): return self._pagination(endpoint, params) def gallery_subreddit(self, subreddit): - endpoint = "/3/gallery/r/{}".format(subreddit) + endpoint = f"/3/gallery/r/{subreddit}" return self._pagination(endpoint) def gallery_tag(self, tag): - endpoint = "/3/gallery/t/{}".format(tag) + endpoint = f"/3/gallery/t/{tag}" return self._pagination(endpoint, key="items") def image(self, image_hash): @@ -308,7 +307,7 @@ class ImgurAPI(): num = 0 while True: - data = self._call("{}/{}".format(endpoint, num), params)["data"] + data = self._call(f"{endpoint}/{num}", params)["data"] if key: data = data[key] if not data: diff --git a/gallery_dl/extractor/imhentai.py b/gallery_dl/extractor/imhentai.py index 52e54108..5ad1c30a 100644 --- a/gallery_dl/extractor/imhentai.py +++ b/gallery_dl/extractor/imhentai.py @@ -85,7 +85,7 @@ class ImhentaiGalleryExtractor(ImhentaiExtractor, GalleryExtractor): def __init__(self, match): ImhentaiExtractor.__init__(self, match) self.gallery_id = self.groups[-1] - self.page_url = "{}/gallery/{}/".format(self.root, self.gallery_id) + self.page_url = f"{self.root}/gallery/{self.gallery_id}/" def metadata(self, page): extr = text.extract_from(page) diff --git a/gallery_dl/extractor/inkbunny.py b/gallery_dl/extractor/inkbunny.py index 264611fd..e92fef4d 100644 --- a/gallery_dl/extractor/inkbunny.py +++ b/gallery_dl/extractor/inkbunny.py @@ -153,8 +153,8 @@ class InkbunnyFavoriteExtractor(InkbunnyExtractor): def metadata(self): # Lookup fav user ID as username - url = "{}/userfavorites_process.php?favs_user_id={}".format( - self.root, self.user_id) + url = (f"{self.root}/userfavorites_process.php" + f"?favs_user_id={self.user_id}") page = self.request(url).text user_link = text.extr(page, '<a rel="author"', '</a>') favs_username = text.extr(user_link, 'href="/', '"') @@ -221,7 +221,7 @@ class InkbunnySearchExtractor(InkbunnyExtractor): favsby = pop("favsby", None) if favsby: # get user_id from user profile - url = "{}/{}".format(self.root, favsby) + url = f"{self.root}/{favsby}" page = self.request(url).text user_id = text.extr(page, "?user_id=", "'") params["favs_user_id"] = user_id.partition("&")[0] diff --git a/gallery_dl/extractor/instagram.py b/gallery_dl/extractor/instagram.py index 435efbcd..243133e3 100644 --- a/gallery_dl/extractor/instagram.py +++ b/gallery_dl/extractor/instagram.py @@ -179,7 +179,7 @@ class InstagramExtractor(Extractor): data = { "post_id" : post["pk"], "post_shortcode": post["code"], - "post_url": "{}/p/{}/".format(self.root, post["code"]), + "post_url": f"{self.root}/p/{post['code']}/", "likes": post.get("like_count", 0), "liked": post.get("has_liked", False), "pinned": self._extract_pinned(post), @@ -197,8 +197,8 @@ class InstagramExtractor(Extractor): slug = location["short_name"].replace(" ", "-").lower() data["location_id"] = location["pk"] data["location_slug"] = slug - data["location_url"] = "{}/explore/locations/{}/{}/".format( - self.root, location["pk"], slug) + data["location_url"] = \ + f"{self.root}/explore/locations/{location['pk']}/{slug}/" coauthors = post.get("coauthor_producers") if coauthors: @@ -292,7 +292,7 @@ class InstagramExtractor(Extractor): "fullname" : owner.get("full_name"), "post_id" : post["id"], "post_shortcode": post["shortcode"], - "post_url" : "{}/p/{}/".format(self.root, post["shortcode"]), + "post_url" : f"{self.root}/p/{post['shortcode']}/", "post_date" : text.parse_timestamp(post["taken_at_timestamp"]), "description": text.parse_unicode_escapes("\n".join( edge["node"]["text"] @@ -309,8 +309,8 @@ class InstagramExtractor(Extractor): if location: data["location_id"] = location["id"] data["location_slug"] = location["slug"] - data["location_url"] = "{}/explore/locations/{}/{}/".format( - self.root, location["id"], location["slug"]) + data["location_url"] = (f"{self.root}/explore/locations/" + f"{location['id']}/{location['slug']}/") coauthors = post.get("coauthor_producers") if coauthors: @@ -434,8 +434,8 @@ class InstagramUserExtractor(Dispatch, InstagramExtractor): example = "https://www.instagram.com/USER/" def items(self): - base = "{}/{}/".format(self.root, self.item) - stories = "{}/stories/{}/".format(self.root, self.item) + base = f"{self.root}/{self.item}/" + stories = f"{self.root}/stories/{self.item}/" return self._dispatch_extractors(( (InstagramInfoExtractor , base + "info/"), (InstagramAvatarExtractor , base + "avatar/"), @@ -623,7 +623,7 @@ class InstagramFollowersExtractor(InstagramExtractor): uid = self.api.user_id(self.item) for user in self.api.user_followers(uid): user["_extractor"] = InstagramUserExtractor - url = "{}/{}".format(self.root, user["username"]) + url = f"{self.root}/{user['username']}" yield Message.Queue, url, user @@ -637,7 +637,7 @@ class InstagramFollowingExtractor(InstagramExtractor): uid = self.api.user_id(self.item) for user in self.api.user_following(uid): user["_extractor"] = InstagramUserExtractor - url = "{}/{}".format(self.root, user["username"]) + url = f"{self.root}/{user['username']}" yield Message.Queue, url, user @@ -742,7 +742,7 @@ class InstagramRestAPI(): return self._call(endpoint, params=params) def guide_media(self, guide_id): - endpoint = "/v1/guides/guide/{}/".format(guide_id) + endpoint = f"/v1/guides/guide/{guide_id}/" return self._pagination_guides(endpoint) def highlights_media(self, user_id, chunk_size=5): @@ -764,13 +764,13 @@ class InstagramRestAPI(): reel_ids[offset : offset+chunk_size]) def highlights_tray(self, user_id): - endpoint = "/v1/highlights/{}/highlights_tray/".format(user_id) + endpoint = f"/v1/highlights/{user_id}/highlights_tray/" return self._call(endpoint)["tray"] def media(self, shortcode): if len(shortcode) > 28: shortcode = shortcode[:-28] - endpoint = "/v1/media/{}/info/".format(id_from_shortcode(shortcode)) + endpoint = f"/v1/media/{id_from_shortcode(shortcode)}/info/" return self._pagination(endpoint) def reels_media(self, reel_ids): @@ -787,7 +787,7 @@ class InstagramRestAPI(): yield media["media"] def tags_sections(self, tag): - endpoint = "/v1/tags/{}/sections/".format(tag) + endpoint = f"/v1/tags/{tag}/sections/" data = { "include_persistent": "0", "max_id" : None, @@ -806,7 +806,7 @@ class InstagramRestAPI(): @memcache(keyarg=1) def user_by_id(self, user_id): - endpoint = "/v1/users/{}/info/".format(user_id) + endpoint = f"/v1/users/{user_id}/info/" return self._call(endpoint)["user"] def user_id(self, screen_name, check_private=True): @@ -838,22 +838,22 @@ class InstagramRestAPI(): return self._pagination_post(endpoint, data) def user_collection(self, collection_id): - endpoint = "/v1/feed/collection/{}/posts/".format(collection_id) + endpoint = f"/v1/feed/collection/{collection_id}/posts/" params = {"count": 50} return self._pagination(endpoint, params, media=True) def user_feed(self, user_id): - endpoint = "/v1/feed/user/{}/".format(user_id) + endpoint = f"/v1/feed/user/{user_id}/" params = {"count": 30} return self._pagination(endpoint, params) def user_followers(self, user_id): - endpoint = "/v1/friendships/{}/followers/".format(user_id) + endpoint = f"/v1/friendships/{user_id}/followers/" params = {"count": 12} return self._pagination_following(endpoint, params) def user_following(self, user_id): - endpoint = "/v1/friendships/{}/following/".format(user_id) + endpoint = f"/v1/friendships/{user_id}/following/" params = {"count": 12} return self._pagination_following(endpoint, params) @@ -863,7 +863,7 @@ class InstagramRestAPI(): return self._pagination(endpoint, params, media=True) def user_tagged(self, user_id): - endpoint = "/v1/usertags/{}/feed/".format(user_id) + endpoint = f"/v1/usertags/{user_id}/feed/" params = {"count": 20} return self._pagination(endpoint, params) diff --git a/gallery_dl/extractor/itaku.py b/gallery_dl/extractor/itaku.py index e5f385a3..e188abb2 100644 --- a/gallery_dl/extractor/itaku.py +++ b/gallery_dl/extractor/itaku.py @@ -164,12 +164,12 @@ class ItakuAPI(): return self._pagination(endpoint, params, self.image) def image(self, image_id): - endpoint = "/galleries/images/{}/".format(image_id) + endpoint = f"/galleries/images/{image_id}/" return self._call(endpoint) @memcache(keyarg=1) def user(self, username): - return self._call("/user_profiles/{}/".format(username)) + return self._call(f"/user_profiles/{username}/") def _call(self, endpoint, params=None): if not endpoint.startswith("http"): diff --git a/gallery_dl/extractor/itchio.py b/gallery_dl/extractor/itchio.py index 799dd66e..2c2fd725 100644 --- a/gallery_dl/extractor/itchio.py +++ b/gallery_dl/extractor/itchio.py @@ -28,7 +28,7 @@ class ItchioGameExtractor(Extractor): Extractor.__init__(self, match) def items(self): - game_url = "https://{}.itch.io/{}".format(self.user, self.slug) + game_url = f"https://{self.user}.itch.io/{self.slug}" page = self.request(game_url).text params = { @@ -39,14 +39,14 @@ class ItchioGameExtractor(Extractor): headers = { "Referer": game_url, "X-Requested-With": "XMLHttpRequest", - "Origin": "https://{}.itch.io".format(self.user), + "Origin": f"https://{self.user}.itch.io", } data = { "csrf_token": text.unquote(self.cookies["itchio_token"]), } for upload_id in text.extract_iter(page, 'data-upload_id="', '"'): - file_url = "{}/file/{}".format(game_url, upload_id) + file_url = f"{game_url}/file/{upload_id}" info = self.request(file_url, method="POST", params=params, headers=headers, data=data).json() diff --git a/gallery_dl/extractor/kabeuchi.py b/gallery_dl/extractor/kabeuchi.py index 1206cd8a..9c1e4352 100644 --- a/gallery_dl/extractor/kabeuchi.py +++ b/gallery_dl/extractor/kabeuchi.py @@ -23,16 +23,12 @@ class KabeuchiUserExtractor(Extractor): pattern = r"(?:https?://)?kabe-uchiroom\.com/mypage/?\?id=(\d+)" example = "https://kabe-uchiroom.com/mypage/?id=12345" - def __init__(self, match): - Extractor.__init__(self, match) - self.user_id = match[1] - def items(self): - base = "{}/accounts/upfile/{}/{}/".format( - self.root, self.user_id[-1], self.user_id) + uid = self.groups[0] + base = f"{self.root}/accounts/upfile/{uid[-1]}/{uid}/" keys = ("image1", "image2", "image3", "image4", "image5", "image6") - for post in self.posts(): + for post in self.posts(uid): if post.get("is_ad") or not post["image1"]: continue @@ -48,8 +44,8 @@ class KabeuchiUserExtractor(Extractor): post["num"] = ord(key[-1]) - 48 yield Message.Url, url, text.nameext_from_url(name, post) - def posts(self): - url = "{}/mypage/?id={}".format(self.root, self.user_id) + def posts(self, uid): + url = f"{self.root}/mypage/?id={uid}" response = self.request(url) if response.history and response.url == self.root + "/": raise exception.NotFoundError("user") @@ -57,7 +53,7 @@ class KabeuchiUserExtractor(Extractor): return self._pagination(target_id) def _pagination(self, target_id): - url = "{}/get_posts.php".format(self.root) + url = f"{self.root}/get_posts.php" data = { "user_id" : "0", "target_id" : target_id, diff --git a/gallery_dl/extractor/kemono.py b/gallery_dl/extractor/kemono.py index c2067bbc..38e2ae2e 100644 --- a/gallery_dl/extractor/kemono.py +++ b/gallery_dl/extractor/kemono.py @@ -32,7 +32,7 @@ class KemonoExtractor(Extractor): tld = match[2] self.category = domain = match[1] self.root = text.root_from_url(match[0]) - self.cookies_domain = ".{}.{}".format(domain, tld) + self.cookies_domain = f".{domain}.{tld}" Extractor.__init__(self, match) def _init(self): @@ -81,8 +81,8 @@ class KemonoExtractor(Extractor): posts = self._revisions(posts) for post in posts: - headers["Referer"] = "{}/{}/user/{}/post/{}".format( - self.root, post["service"], post["user"], post["id"]) + headers["Referer"] = (f"{self.root}/{post['service']}/user/" + f"{post['user']}/post/{post['id']}") post["_http_headers"] = headers post["date"] = self._parse_datetime( post.get("published") or post.get("added") or "") @@ -90,7 +90,7 @@ class KemonoExtractor(Extractor): creator_id = post["user"] if creator_info is not None: - key = "{}_{}".format(service, creator_id) + key = f"{service}_{creator_id}" if key not in creator_info: creator = creator_info[key] = self.api.creator_profile( service, creator_id) @@ -468,8 +468,8 @@ class KemonoDiscordServerExtractor(KemonoExtractor): server_id = self.groups[2] server, channels = discord_server_info(self, server_id) for channel in channels.values(): - url = "{}/discord/server/{}/{}#{}".format( - self.root, server_id, channel["id"], channel["name"]) + url = (f"{self.root}/discord/server/{server_id}/" + f"{channel['id']}#{channel['name']}") yield Message.Queue, url, { "server" : server, "channel" : channel, @@ -513,12 +513,10 @@ class KemonoFavoriteExtractor(KemonoExtractor): service = user["service"] if service == "discord": user["_extractor"] = KemonoDiscordServerExtractor - url = "{}/discord/server/{}".format( - self.root, user["id"]) + url = f"{self.root}/discord/server/{user['id']}" else: user["_extractor"] = KemonoUserExtractor - url = "{}/{}/user/{}".format( - self.root, service, user["id"]) + url = f"{self.root}/{service}/user/{user['id']}" yield Message.Queue, url, user elif type == "post": @@ -531,8 +529,8 @@ class KemonoFavoriteExtractor(KemonoExtractor): for post in posts: post["_extractor"] = KemonoPostExtractor - url = "{}/{}/user/{}/post/{}".format( - self.root, post["service"], post["user"], post["id"]) + url = (f"{self.root}/{post['service']}/user/" + f"{post['user']}/post/{post['id']}") yield Message.Queue, url, post @@ -565,12 +563,10 @@ class KemonoArtistsExtractor(KemonoExtractor): service = user["service"] if service == "discord": user["_extractor"] = KemonoDiscordServerExtractor - url = "{}/discord/server/{}".format( - self.root, user["id"]) + url = f"{self.root}/discord/server/{user['id']}" else: user["_extractor"] = KemonoUserExtractor - url = "{}/{}/user/{}".format( - self.root, service, user["id"]) + url = f"{self.root}/{service}/user/{user['id']}" yield Message.Queue, url, user @@ -599,64 +595,62 @@ class KemonoAPI(): def creator_posts(self, service, creator_id, offset=0, query=None, tags=None): - endpoint = "/{}/user/{}".format(service, creator_id) + endpoint = f"/{service}/user/{creator_id}" params = {"q": query, "tag": tags, "o": offset} return self._pagination(endpoint, params, 50) def creator_posts_legacy(self, service, creator_id, offset=0, query=None, tags=None): - endpoint = "/{}/user/{}/posts-legacy".format(service, creator_id) + endpoint = f"/{service}/user/{creator_id}/posts-legacy" params = {"o": offset, "tag": tags, "q": query} return self._pagination(endpoint, params, 50, "results") def creator_announcements(self, service, creator_id): - endpoint = "/{}/user/{}/announcements".format(service, creator_id) + endpoint = f"/{service}/user/{creator_id}/announcements" return self._call(endpoint) def creator_dms(self, service, creator_id): - endpoint = "/{}/user/{}/dms".format(service, creator_id) + endpoint = f"/{service}/user/{creator_id}/dms" return self._call(endpoint) def creator_fancards(self, service, creator_id): - endpoint = "/{}/user/{}/fancards".format(service, creator_id) + endpoint = f"/{service}/user/{creator_id}/fancards" return self._call(endpoint) def creator_post(self, service, creator_id, post_id): - endpoint = "/{}/user/{}/post/{}".format(service, creator_id, post_id) + endpoint = f"/{service}/user/{creator_id}/post/{post_id}" return self._call(endpoint) def creator_post_comments(self, service, creator_id, post_id): - endpoint = "/{}/user/{}/post/{}/comments".format( - service, creator_id, post_id) + endpoint = f"/{service}/user/{creator_id}/post/{post_id}/comments" return self._call(endpoint) def creator_post_revisions(self, service, creator_id, post_id): - endpoint = "/{}/user/{}/post/{}/revisions".format( - service, creator_id, post_id) + endpoint = f"/{service}/user/{creator_id}/post/{post_id}/revisions" return self._call(endpoint) def creator_profile(self, service, creator_id): - endpoint = "/{}/user/{}/profile".format(service, creator_id) + endpoint = f"/{service}/user/{creator_id}/profile" return self._call(endpoint) def creator_links(self, service, creator_id): - endpoint = "/{}/user/{}/links".format(service, creator_id) + endpoint = f"/{service}/user/{creator_id}/links" return self._call(endpoint) def creator_tags(self, service, creator_id): - endpoint = "/{}/user/{}/tags".format(service, creator_id) + endpoint = f"/{service}/user/{creator_id}/tags" return self._call(endpoint) def discord_channel(self, channel_id): - endpoint = "/discord/channel/{}".format(channel_id) + endpoint = f"/discord/channel/{channel_id}" return self._pagination(endpoint, {}, 150) def discord_channel_lookup(self, server_id): - endpoint = "/discord/channel/lookup/{}".format(server_id) + endpoint = f"/discord/channel/lookup/{server_id}" return self._call(endpoint) def discord_server(self, server_id): - endpoint = "/discord/server/{}".format(server_id) + endpoint = f"/discord/server/{server_id}" return self._call(endpoint) def account_favorites(self, type): diff --git a/gallery_dl/extractor/lensdump.py b/gallery_dl/extractor/lensdump.py index 72a64537..c700a295 100644 --- a/gallery_dl/extractor/lensdump.py +++ b/gallery_dl/extractor/lensdump.py @@ -37,9 +37,9 @@ class LensdumpAlbumExtractor(LensdumpBase, GalleryExtractor): def __init__(self, match): self.gallery_id, query = match.groups() if query: - url = "{}/a/{}/?{}".format(self.root, self.gallery_id, query) + url = f"{self.root}/a/{self.gallery_id}/?{query}" else: - url = "{}/a/{}".format(self.root, self.gallery_id) + url = f"{self.root}/a/{self.gallery_id}" GalleryExtractor.__init__(self, match, url) def metadata(self, page): @@ -81,7 +81,7 @@ class LensdumpAlbumsExtractor(LensdumpBase, Extractor): def items(self): user, query = self.groups - url = "{}/{}/".format(self.root, user) + url = f"{self.root}/{user}/" if query: params = text.parse_query(query) else: @@ -105,7 +105,7 @@ class LensdumpImageExtractor(LensdumpBase, Extractor): def items(self): key = self.groups[0] - url = "{}/i/{}".format(self.root, key) + url = f"{self.root}/i/{key}" extr = text.extract_from(self.request(url).text) data = { diff --git a/gallery_dl/extractor/lexica.py b/gallery_dl/extractor/lexica.py index 7327f087..00a4dac2 100644 --- a/gallery_dl/extractor/lexica.py +++ b/gallery_dl/extractor/lexica.py @@ -43,7 +43,7 @@ class LexicaSearchExtractor(Extractor): url = self.root + "/api/infinite-prompts" headers = { "Accept" : "application/json, text/plain, */*", - "Referer": "{}/?q={}".format(self.root, self.query), + "Referer": f"{self.root}/?q={self.query}", } json = { "text" : self.text, diff --git a/gallery_dl/extractor/livedoor.py b/gallery_dl/extractor/livedoor.py index 91ace16d..94acc6cd 100644 --- a/gallery_dl/extractor/livedoor.py +++ b/gallery_dl/extractor/livedoor.py @@ -87,7 +87,7 @@ class LivedoorBlogExtractor(LivedoorExtractor): example = "http://blog.livedoor.jp/USER/" def posts(self): - url = "{}/{}".format(self.root, self.user) + url = f"{self.root}/{self.user}" while url: extr = text.extract_from(self.request(url).text) while True: @@ -111,8 +111,7 @@ class LivedoorPostExtractor(LivedoorExtractor): self.post_id = match[2] def posts(self): - url = "{}/{}/archives/{}.html".format( - self.root, self.user, self.post_id) + url = f"{self.root}/{self.user}/archives/{self.post_id}.html" extr = text.extract_from(self.request(url).text) data = extr('<rdf:RDF', '</rdf:RDF>') body = extr('class="article-body-inner">', 'class="article-footer">') diff --git a/gallery_dl/extractor/lolisafe.py b/gallery_dl/extractor/lolisafe.py index 861f3a08..6b888468 100644 --- a/gallery_dl/extractor/lolisafe.py +++ b/gallery_dl/extractor/lolisafe.py @@ -63,7 +63,7 @@ class LolisafeAlbumExtractor(LolisafeExtractor): file["filename"] = file["name"] + "-" + fid elif "id" in file: file["name"] = file["filename"] - file["filename"] = "{}-{}".format(file["name"], file["id"]) + file["filename"] = f"{file['name']}-{file['id']}" else: file["name"], sep, file["id"] = \ file["filename"].rpartition("-") @@ -71,7 +71,7 @@ class LolisafeAlbumExtractor(LolisafeExtractor): yield Message.Url, url, file def fetch_album(self, album_id): - url = "{}/api/album/get/{}".format(self.root, album_id) + url = f"{self.root}/api/album/get/{album_id}" data = self.request(url).json() return data["files"], { diff --git a/gallery_dl/extractor/luscious.py b/gallery_dl/extractor/luscious.py index afe07ae4..66f2b6ab 100644 --- a/gallery_dl/extractor/luscious.py +++ b/gallery_dl/extractor/luscious.py @@ -26,7 +26,7 @@ class LusciousExtractor(Extractor): "variables" : variables, } response = self.request( - "{}/graphql/nobatch/?operationName={}".format(self.root, op), + f"{self.root}/graphql/nobatch/?operationName={op}", method="POST", json=data, fatal=False, ) diff --git a/gallery_dl/extractor/mangadex.py b/gallery_dl/extractor/mangadex.py index 1a9f96ea..4392b209 100644 --- a/gallery_dl/extractor/mangadex.py +++ b/gallery_dl/extractor/mangadex.py @@ -44,7 +44,7 @@ class MangadexExtractor(Extractor): def _items_manga(self): data = {"_extractor": MangadexMangaExtractor} for manga in self.manga(): - url = "{}/title/{}".format(self.root, manga["id"]) + url = f"{self.root}/title/{manga['id']}" yield Message.Queue, url, data def _transform(self, chapter): @@ -121,7 +121,7 @@ class MangadexChapterExtractor(MangadexExtractor): server = self.api.athome_server(self.uuid) chapter = server["chapter"] - base = "{}/data/{}/".format(server["baseUrl"], chapter["hash"]) + base = f"{server['baseUrl']}/data/{chapter['hash']}/" enum = util.enumerate_reversed if self.config( "page-reverse") else enumerate @@ -199,7 +199,7 @@ class MangadexAuthorExtractor(MangadexExtractor): def items(self): for manga in self.api.manga_author(self.uuid): manga["_extractor"] = MangadexMangaExtractor - url = "{}/title/{}".format(self.root, manga["id"]) + url = f"{self.root}/title/{manga['id']}" yield Message.Queue, url, manga diff --git a/gallery_dl/extractor/mangafox.py b/gallery_dl/extractor/mangafox.py index 20d9c13c..76f4b7e8 100644 --- a/gallery_dl/extractor/mangafox.py +++ b/gallery_dl/extractor/mangafox.py @@ -54,7 +54,7 @@ class MangafoxChapterExtractor(ChapterExtractor): yield text.ensure_http_scheme(text.unescape(url)), None pnum += 2 - page = self.request("{}/{}.html".format(self.urlbase, pnum)).text + page = self.request(f"{self.urlbase}/{pnum}.html").text class MangafoxMangaExtractor(MangaExtractor): diff --git a/gallery_dl/extractor/mangahere.py b/gallery_dl/extractor/mangahere.py index a96919b3..bc7b683a 100644 --- a/gallery_dl/extractor/mangahere.py +++ b/gallery_dl/extractor/mangahere.py @@ -67,7 +67,7 @@ class MangahereChapterExtractor(MangahereBase, ChapterExtractor): page = self.request(self.url_fmt.format(self.part, pnum)).text def _get_title(self): - url = "{}/manga/{}/".format(self.root, self.part) + url = f"{self.root}/manga/{self.part}/" page = self.request(url).text try: diff --git a/gallery_dl/extractor/mangoxo.py b/gallery_dl/extractor/mangoxo.py index 1744f003..beb13ce5 100644 --- a/gallery_dl/extractor/mangoxo.py +++ b/gallery_dl/extractor/mangoxo.py @@ -86,7 +86,7 @@ class MangoxoAlbumExtractor(MangoxoExtractor): def items(self): self.login() - url = "{}/album/{}/".format(self.root, self.album_id) + url = f"{self.root}/album/{self.album_id}/" page = self.request(url).text data = self.metadata(page) imgs = self.images(url, page) @@ -152,7 +152,7 @@ class MangoxoChannelExtractor(MangoxoExtractor): def items(self): self.login() num = total = 1 - url = "{}/{}/album/".format(self.root, self.user) + url = f"{self.root}/{self.user}/album/" data = {"_extractor": MangoxoAlbumExtractor} while True: diff --git a/gallery_dl/extractor/mastodon.py b/gallery_dl/extractor/mastodon.py index df4d80ae..00e5296b 100644 --- a/gallery_dl/extractor/mastodon.py +++ b/gallery_dl/extractor/mastodon.py @@ -202,7 +202,7 @@ class MastodonStatusExtractor(MastodonExtractor): def statuses(self): if self.groups[-2] is not None: - url = "{}/objects/{}".format(self.root, self.item) + url = f"{self.root}/objects/{self.item}" location = self.request_location(url) self.item = location.rpartition("/")[2] return (MastodonAPI(self).status(self.item),) @@ -243,7 +243,7 @@ class MastodonAPI(): if "@" in username: handle = "@" + username else: - handle = "@{}@{}".format(username, self.extractor.instance) + handle = f"@{username}@{self.extractor.instance}" for account in self.account_search(handle, 1): if account["acct"] == username: @@ -263,7 +263,7 @@ class MastodonAPI(): def account_following(self, account_id): """Accounts which the given account is following""" - endpoint = "/v1/accounts/{}/following".format(account_id) + endpoint = f"/v1/accounts/{account_id}/following" return self._pagination(endpoint, None) def account_lookup(self, username): @@ -281,7 +281,7 @@ class MastodonAPI(): def account_statuses(self, account_id, only_media=True, exclude_replies=False): """Statuses posted to the given account""" - endpoint = "/v1/accounts/{}/statuses".format(account_id) + endpoint = f"/v1/accounts/{account_id}/statuses" params = {"only_media" : "true" if only_media else "false", "exclude_replies": "true" if exclude_replies else "false"} return self._pagination(endpoint, params) diff --git a/gallery_dl/extractor/moebooru.py b/gallery_dl/extractor/moebooru.py index 08d757fd..ba279948 100644 --- a/gallery_dl/extractor/moebooru.py +++ b/gallery_dl/extractor/moebooru.py @@ -161,11 +161,8 @@ class MoebooruPopularExtractor(MoebooruExtractor): self.params = params = text.parse_query(self.query) if "year" in params: - date = "{:>04}-{:>02}-{:>02}".format( - params["year"], - params.get("month", "01"), - params.get("day", "01"), - ) + date = (f"{params['year']:>04}-{params.get('month', '01'):>02}-" + f"{params.get('day', '01'):>02}") else: date = datetime.date.today().isoformat() diff --git a/gallery_dl/extractor/motherless.py b/gallery_dl/extractor/motherless.py index 0ef7e058..35454807 100644 --- a/gallery_dl/extractor/motherless.py +++ b/gallery_dl/extractor/motherless.py @@ -113,7 +113,7 @@ class MotherlessGalleryExtractor(MotherlessExtractor): yield Message.Queue, self.root + "/GV" + gid, data return - url = "{}/G{}{}".format(self.root, type, gid) + url = f"{self.root}/G{type}{gid}" page = self.request(url).text data = self._extract_gallery_data(page) diff --git a/gallery_dl/extractor/myhentaigallery.py b/gallery_dl/extractor/myhentaigallery.py index 6c23f497..2a39dc92 100644 --- a/gallery_dl/extractor/myhentaigallery.py +++ b/gallery_dl/extractor/myhentaigallery.py @@ -21,7 +21,7 @@ class MyhentaigalleryGalleryExtractor(GalleryExtractor): def __init__(self, match): self.gallery_id = match[1] - url = "{}/g/{}".format(self.root, self.gallery_id) + url = f"{self.root}/g/{self.gallery_id}" GalleryExtractor.__init__(self, match, url) def _init(self): diff --git a/gallery_dl/extractor/naver.py b/gallery_dl/extractor/naver.py index 8c8a7d49..9ca0369e 100644 --- a/gallery_dl/extractor/naver.py +++ b/gallery_dl/extractor/naver.py @@ -41,8 +41,8 @@ class NaverPostExtractor(NaverBase, GalleryExtractor): self.blog_id = match[3] self.post_id = match[4] - url = "{}/PostView.nhn?blogId={}&logNo={}".format( - self.root, self.blog_id, self.post_id) + url = (f"{self.root}/PostView.nhn" + f"?blogId={self.blog_id}&logNo={self.post_id}") GalleryExtractor.__init__(self, match, url) def metadata(self, page): @@ -138,13 +138,13 @@ class NaverBlogExtractor(NaverBase, Extractor): def items(self): # fetch first post number - url = "{}/PostList.nhn?blogId={}".format(self.root, self.blog_id) + url = f"{self.root}/PostList.nhn?blogId={self.blog_id}" post_num = text.extr( self.request(url).text, 'gnFirstLogNo = "', '"', ) # setup params for API calls - url = "{}/PostViewBottomTitleListAsync.nhn".format(self.root) + url = f"{self.root}/PostViewBottomTitleListAsync.nhn" params = { "blogId" : self.blog_id, "logNo" : post_num or "0", @@ -163,8 +163,8 @@ class NaverBlogExtractor(NaverBase, Extractor): data = self.request(url, params=params).json() for post in data["postList"]: - post["url"] = "{}/PostView.nhn?blogId={}&logNo={}".format( - self.root, self.blog_id, post["logNo"]) + post["url"] = (f"{self.root}/PostView.nhn?blogId=" + f"{self.blog_id}&logNo={post['logNo']}") post["_extractor"] = NaverPostExtractor yield Message.Queue, post["url"], post diff --git a/gallery_dl/extractor/naverwebtoon.py b/gallery_dl/extractor/naverwebtoon.py index afddb1c0..f70516cc 100644 --- a/gallery_dl/extractor/naverwebtoon.py +++ b/gallery_dl/extractor/naverwebtoon.py @@ -32,7 +32,7 @@ class NaverwebtoonEpisodeExtractor(NaverwebtoonBase, GalleryExtractor): def __init__(self, match): path, query = match.groups() - url = "{}/{}/detail?{}".format(self.root, path, query) + url = f"{self.root}/{path}/detail?{query}" GalleryExtractor.__init__(self, match, url) query = text.parse_query(query) @@ -92,8 +92,7 @@ class NaverwebtoonComicExtractor(NaverwebtoonBase, Extractor): data = self.request(url, headers=headers, params=params).json() path = data["webtoonLevelCode"].lower().replace("_c", "C", 1) - base = "{}/{}/detail?titleId={}&no=".format( - self.root, path, data["titleId"]) + base = f"{self.root}/{path}/detail?titleId={data['titleId']}&no=" for article in data["articleList"]: article["_extractor"] = NaverwebtoonEpisodeExtractor diff --git a/gallery_dl/extractor/nekohouse.py b/gallery_dl/extractor/nekohouse.py index fe9d5126..e6b0461a 100644 --- a/gallery_dl/extractor/nekohouse.py +++ b/gallery_dl/extractor/nekohouse.py @@ -32,8 +32,7 @@ class NekohousePostExtractor(NekohouseExtractor): def items(self): service, user_id, post_id = self.groups - url = "{}/{}/user/{}/post/{}".format( - self.root, service, user_id, post_id) + url = f"{self.root}/{service}/user/{user_id}/post/{post_id}" html = self.request(url).text files = self._extract_files(html) @@ -104,7 +103,7 @@ class NekohouseUserExtractor(NekohouseExtractor): def items(self): service, user_id, _ = self.groups - creator_url = "{}/{}/user/{}".format(self.root, service, user_id) + creator_url = f"{self.root}/{service}/user/{user_id}" params = {"o": 0} data = {"_extractor": NekohousePostExtractor} diff --git a/gallery_dl/extractor/newgrounds.py b/gallery_dl/extractor/newgrounds.py index cceee491..e8228ed7 100644 --- a/gallery_dl/extractor/newgrounds.py +++ b/gallery_dl/extractor/newgrounds.py @@ -31,7 +31,7 @@ class NewgroundsExtractor(Extractor): def __init__(self, match): Extractor.__init__(self, match) self.user = match[1] - self.user_root = "https://{}.newgrounds.com".format(self.user) + self.user_root = f"https://{self.user}.newgrounds.com" def _init(self): self._extract_comment_urls = util.re( @@ -71,8 +71,7 @@ class NewgroundsExtractor(Extractor): if "_multi" in post: for data in post["_multi"]: post["num"] += 1 - post["_index"] = "{}_{:>02}".format( - post["index"], post["num"]) + post["_index"] = f"{post['index']}_{post['num']:>02}" post.update(data) url = data["image"] @@ -84,8 +83,7 @@ class NewgroundsExtractor(Extractor): for url in self._extract_comment_urls(post["_comment"]): post["num"] += 1 - post["_index"] = "{}_{:>02}".format( - post["index"], post["num"]) + post["_index"] = f"{post['index']}_{post['num']:>02}" url = text.ensure_http_scheme(url) text.nameext_from_url(url, post) yield Message.Url, url, post @@ -152,7 +150,7 @@ class NewgroundsExtractor(Extractor): data["codehint"] = " " elif result.get("requiresEmailMfa"): email = result.get("obfuscatedEmail") - prompt = "Email Verification Code ({}): ".format(email) + prompt = f"Email Verification Code ({email}): " data["code"] = self.input(prompt) data["codehint"] = " " @@ -346,7 +344,7 @@ class NewgroundsExtractor(Extractor): yield fmt[1][0]["src"] def _pagination(self, kind, pnum=1): - url = "{}/{}".format(self.user_root, kind) + url = f"{self.user_root}/{kind}" params = { "page": text.parse_int(pnum, 1), "isAjaxRequest": "1", @@ -399,8 +397,7 @@ class NewgroundsImageExtractor(NewgroundsExtractor): NewgroundsExtractor.__init__(self, match) if match[2]: self.user = match[2] - self.post_url = "https://www.newgrounds.com/art/view/{}/{}".format( - self.user, match[3]) + self.post_url = f"{self.root}/art/view/{self.user}/{match[3]}" else: self.post_url = text.ensure_http_scheme(match[0]) @@ -483,7 +480,7 @@ class NewgroundsFavoriteExtractor(NewgroundsExtractor): ) def _pagination_favorites(self, kind, pnum=1): - url = "{}/favorites/{}".format(self.user_root, kind) + url = f"{self.user_root}/favorites/{kind}" params = { "page": text.parse_int(pnum, 1), "isAjaxRequest": "1", @@ -509,8 +506,7 @@ class NewgroundsFavoriteExtractor(NewgroundsExtractor): def _extract_favorites(self, page): return [ self.root + path - for path in text.extract_iter( - page, 'href="https://www.newgrounds.com', '"') + for path in text.extract_iter(page, f'href="{self.root}', '"') ] diff --git a/gallery_dl/extractor/nhentai.py b/gallery_dl/extractor/nhentai.py index 602d96ea..8544d3c0 100644 --- a/gallery_dl/extractor/nhentai.py +++ b/gallery_dl/extractor/nhentai.py @@ -87,7 +87,7 @@ class NhentaiExtractor(Extractor): def items(self): data = {"_extractor": NhentaiGalleryExtractor} for gallery_id in self._pagination(): - url = "{}/g/{}/".format(self.root, gallery_id) + url = f"{self.root}/g/{gallery_id}/" yield Message.Queue, url, data def _pagination(self): diff --git a/gallery_dl/extractor/nijie.py b/gallery_dl/extractor/nijie.py index 486b4370..c6df835f 100644 --- a/gallery_dl/extractor/nijie.py +++ b/gallery_dl/extractor/nijie.py @@ -40,7 +40,7 @@ class NijieExtractor(AsynchronousMixin, BaseExtractor): for image_id in self.image_ids(): - url = "{}/view.php?id={}".format(self.root, image_id) + url = f"{self.root}/view.php?id={image_id}" response = self.request(url, fatal=False) if response.status_code >= 400: continue @@ -109,7 +109,7 @@ class NijieExtractor(AsynchronousMixin, BaseExtractor): def _extract_images(self, image_id, page): if '&#diff_1" ' in page: # multiple images - url = "{}/view_popup.php?id={}".format(self.root, image_id) + url = f"{self.root}/view_popup.php?id={image_id}" page = self.request(url).text return [ text.extr(media, ' src="', '"') @@ -139,7 +139,7 @@ class NijieExtractor(AsynchronousMixin, BaseExtractor): def _login_impl(self, username, password): self.log.info("Logging in as %s", username) - url = "{}/login_int.php".format(self.root) + url = f"{self.root}/login_int.php" data = {"email": username, "password": password, "save": "on"} response = self.request(url, method="POST", data=data) @@ -148,7 +148,7 @@ class NijieExtractor(AsynchronousMixin, BaseExtractor): return self.cookies def _pagination(self, path): - url = "{}/{}.php".format(self.root, path) + url = f"{self.root}/{path}.php" params = {"id": self.user_id, "p": 1} while True: @@ -181,7 +181,7 @@ class NijieUserExtractor(Dispatch, NijieExtractor): example = "https://nijie.info/members.php?id=12345" def items(self): - fmt = "{}/{{}}.php?id={}".format(self.root, self.user_id).format + fmt = f"{self.root}/{{}}.php?id={self.user_id}".format return self._dispatch_extractors(( (NijieIllustrationExtractor, fmt("members_illust")), (NijieDoujinExtractor , fmt("members_dojin")), @@ -280,7 +280,7 @@ class NijieFollowedExtractor(NijieExtractor): for user_id in text.extract_iter( page, '"><a href="/members.php?id=', '"'): - user_url = "{}/members.php?id={}".format(self.root, user_id) + user_url = f"{self.root}/members.php?id={user_id}" yield Message.Queue, user_url, data if '<a rel="next"' not in page: diff --git a/gallery_dl/extractor/nitter.py b/gallery_dl/extractor/nitter.py index 00eab7a4..fbb65050 100644 --- a/gallery_dl/extractor/nitter.py +++ b/gallery_dl/extractor/nitter.py @@ -70,11 +70,8 @@ class NitterExtractor(BaseExtractor): if videos and not files: if ytdl: - append({ - "url": "ytdl:{}/i/status/{}".format( - self.root, tweet["tweet_id"]), - "extension": None, - }) + url = f"ytdl:{self.root}/i/status/{tweet['tweet_id']}" + append({"url": url, "extension": "mp4"}) else: for url in text.extract_iter( attachments, 'data-url="', '"'): @@ -205,10 +202,10 @@ class NitterExtractor(BaseExtractor): if self.user_id: self.user = self.request( - "{}/i/user/{}".format(self.root, self.user_id), + f"{self.root}/i/user/{self.user_id}", allow_redirects=False, ).headers["location"].rpartition("/")[2] - base_url = url = "{}/{}{}".format(self.root, self.user, path) + base_url = url = f"{self.root}/{self.user}{path}" while True: tweets_html = self.request(url).text.split( @@ -284,7 +281,7 @@ class NitterTweetExtractor(NitterExtractor): example = "https://nitter.net/USER/status/12345" def tweets(self): - url = "{}/i/status/{}".format(self.root, self.user) + url = f"{self.root}/i/status/{self.user}" html = text.extr(self.request(url).text, 'class="main-tweet', '''\ </div> </div></div></div>''') diff --git a/gallery_dl/extractor/nozomi.py b/gallery_dl/extractor/nozomi.py index 5c9a0546..21c361cd 100644 --- a/gallery_dl/extractor/nozomi.py +++ b/gallery_dl/extractor/nozomi.py @@ -32,8 +32,8 @@ class NozomiExtractor(Extractor): data = self.metadata() for post_id in map(str, self.posts()): - url = "https://j.{}/post/{}/{}/{}.json".format( - self.domain, post_id[-1], post_id[-3:-1], post_id) + url = (f"https://j.{self.domain}/post" + f"/{post_id[-1]}/{post_id[-3:-1]}/{post_id}.json") response = self.request(url, fatal=False) if response.status_code >= 400: @@ -77,8 +77,8 @@ class NozomiExtractor(Extractor): ext = "webp" post["extension"] = ext - post["url"] = url = "https://{}.{}/{}/{}/{}.{}".format( - subdomain, self.domain, did[-1], did[-3:-1], did, ext) + post["url"] = url = (f"https://{subdomain}.{self.domain}" + f"/{did[-1]}/{did[-3:-1]}/{did}.{ext}") yield Message.Url, url, post def posts(self): @@ -86,7 +86,7 @@ class NozomiExtractor(Extractor): offset = (text.parse_int(self.pnum, 1) - 1) * 256 while True: - headers = {"Range": "bytes={}-{}".format(offset, offset+255)} + headers = {"Range": f"bytes={offset}-{offset + 255}"} response = self.request(url, headers=headers) yield from decode_nozomi(response.content) @@ -126,7 +126,7 @@ class NozomiIndexExtractor(NozomiExtractor): def __init__(self, match): NozomiExtractor.__init__(self, match) index, self.pnum = match.groups() - self.nozomi = "/{}.nozomi".format(index or "index") + self.nozomi = f"/{index or 'index'}.nozomi" class NozomiTagExtractor(NozomiExtractor): @@ -141,7 +141,7 @@ class NozomiTagExtractor(NozomiExtractor): NozomiExtractor.__init__(self, match) tags, self.pnum = match.groups() self.tags = text.unquote(tags) - self.nozomi = "/nozomi/{}.nozomi".format(self.tags) + self.nozomi = f"/nozomi/{self.tags}.nozomi" def metadata(self): return {"search_tags": self.tags} @@ -168,7 +168,7 @@ class NozomiSearchExtractor(NozomiExtractor): negative = [] def nozomi(path): - url = "https://j.{}/{}.nozomi".format(self.domain, path) + url = f"https://j.{self.domain}/{path}.nozomi" return decode_nozomi(self.request(url).content) for tag in self.tags: diff --git a/gallery_dl/extractor/nsfwalbum.py b/gallery_dl/extractor/nsfwalbum.py index d824e48c..0e66d1f4 100644 --- a/gallery_dl/extractor/nsfwalbum.py +++ b/gallery_dl/extractor/nsfwalbum.py @@ -66,8 +66,8 @@ class NsfwalbumAlbumExtractor(GalleryExtractor): "width" : text.parse_int(data[1]), "height": text.parse_int(data[2]), "_http_validate": self._validate_response, - "_fallback": ("{}/imageProxy.php?photoId={}&spirit={}".format( - self.root, image_id, spirit),), + "_fallback": (f"{self.root}/imageProxy.php" + f"?photoId={image_id}&spirit={spirit}",), } def _validate_response(self, response): diff --git a/gallery_dl/extractor/oauth.py b/gallery_dl/extractor/oauth.py index ecc10b37..2d20f689 100644 --- a/gallery_dl/extractor/oauth.py +++ b/gallery_dl/extractor/oauth.py @@ -89,12 +89,12 @@ class OAuthBase(Extractor): else: self.log.info("Please open this URL in your browser:") - stdout_write("\n{}\n\n".format(url)) + stdout_write(f"\n{url}\n\n") return (recv or self.recv)() def error(self, msg): return self.send( - "Remote server reported an error:\n\n{}\n".format(msg)) + f"Remote server reported an error:\n\n{msg}\n") def _oauth1_authorization_flow( self, default_key, default_secret, @@ -151,10 +151,7 @@ class OAuthBase(Extractor): "default" if client_id == default_id else "custom", instance or self.subcategory, client_id) - state = "gallery-dl_{}_{}".format( - self.subcategory, - oauth.nonce(8), - ) + state = f"gallery-dl_{self.subcategory}_{oauth.nonce(8)}" auth_params = { "client_id" : client_id, @@ -170,8 +167,8 @@ class OAuthBase(Extractor): # check authorization response if state != params.get("state"): - self.send("'state' mismatch: expected {}, got {}.\n".format( - state, params.get("state"))) + self.send(f"'state' mismatch: expected {state}, " + f"got {params.get('state')}.\n") return if "error" in params: return self.error(params) @@ -233,11 +230,9 @@ class OAuthBase(Extractor): for n in names ) if self.cache: - msg += ( - "\nor set\n'extractor.{}.{}' to \"cache\"" - .format(self.subcategory, names[0]) - ) - msg += "\nto use {}.\n".format(_it) + msg = (f"{msg}\nor set\n'extractor." + f"{self.subcategory}.{names[0]}' to \"cache\"") + msg = f"{msg}\nto use {_it}.\n" return msg @@ -371,8 +366,8 @@ class OAuthMastodon(OAuthBase): application["client-secret"], application["client-id"], application["client-secret"], - "https://{}/oauth/authorize".format(self.instance), - "https://{}/oauth/token".format(self.instance), + f"https://{self.instance}/oauth/authorize", + f"https://{self.instance}/oauth/token", instance=self.instance, key="access_token", cache=mastodon._access_token_cache, @@ -382,7 +377,7 @@ class OAuthMastodon(OAuthBase): def _register(self, instance): self.log.info("Registering application for '%s'", instance) - url = "https://{}/api/v1/apps".format(instance) + url = f"https://{instance}/api/v1/apps" data = { "client_name": "gdl:" + oauth.nonce(8), "redirect_uris": self.redirect_uri, @@ -447,7 +442,7 @@ class OAuthPixiv(OAuthBase): url, method="POST", headers=headers, data=data).json() if "error" in data: - stdout_write("\n{}\n".format(data)) + stdout_write(f"\n{data}\n") if data["error"] in ("invalid_request", "invalid_grant"): stdout_write("'code' expired, try again\n\n") return diff --git a/gallery_dl/extractor/paheal.py b/gallery_dl/extractor/paheal.py index 3621b49f..5245f314 100644 --- a/gallery_dl/extractor/paheal.py +++ b/gallery_dl/extractor/paheal.py @@ -42,7 +42,7 @@ class PahealExtractor(Extractor): """Return an iterable containing data of all relevant posts""" def _extract_post(self, post_id): - url = "{}/post/view/{}".format(self.root, post_id) + url = f"{self.root}/post/view/{post_id}" extr = text.extract_from(self.request(url).text) post = { @@ -64,7 +64,7 @@ class PahealExtractor(Extractor): post["width"], _, height = dimensions.partition("x") post["height"], _, duration = height.partition(", ") post["duration"] = text.parse_float(duration[:-1]) - post["filename"] = "{} - {}".format(post_id, post["tags"]) + post["filename"] = f"{post_id} - {post['tags']}" post["extension"] = ext return post @@ -94,7 +94,7 @@ class PahealTagExtractor(PahealExtractor): def get_posts(self): pnum = self.page_start - base = "{}/post/list/{}/".format(self.root, self.groups[0]) + base = f"{self.root}/post/list/{self.groups[0]}/" while True: page = self.request(base + str(pnum)).text @@ -129,7 +129,7 @@ class PahealTagExtractor(PahealExtractor): "tags" : text.unescape(tags), "size" : text.parse_bytes(size[:-1]), "date" : text.parse_datetime(date, "%B %d, %Y; %H:%M"), - "filename" : "{} - {}".format(pid, tags), + "filename" : f"{pid} - {tags}", "extension": ext, } diff --git a/gallery_dl/extractor/pexels.py b/gallery_dl/extractor/pexels.py index 804623b8..49aba270 100644 --- a/gallery_dl/extractor/pexels.py +++ b/gallery_dl/extractor/pexels.py @@ -105,7 +105,7 @@ class PexelsImageExtractor(PexelsExtractor): example = "https://www.pexels.com/photo/SLUG-12345/" def posts(self): - url = "{}/photo/{}/".format(self.root, self.groups[0]) + url = f"{self.root}/photo/{self.groups[0]}/" page = self.request(url).text return (self._extract_nextdata(page)["props"]["pageProps"]["medium"],) @@ -132,7 +132,7 @@ class PexelsAPI(): } def collections_media(self, collection_id): - endpoint = "/v3/collections/{}/media".format(collection_id) + endpoint = f"/v3/collections/{collection_id}/media" params = { "page" : "1", "per_page": "24", @@ -153,7 +153,7 @@ class PexelsAPI(): return self._pagination(endpoint, params) def users_media_recent(self, user_id): - endpoint = "/v3/users/{}/media/recent".format(user_id) + endpoint = f"/v3/users/{user_id}/media/recent" params = { "page" : "1", "per_page": "24", diff --git a/gallery_dl/extractor/pictoa.py b/gallery_dl/extractor/pictoa.py index a8008cf8..da252f35 100644 --- a/gallery_dl/extractor/pictoa.py +++ b/gallery_dl/extractor/pictoa.py @@ -30,7 +30,7 @@ class PictoaImageExtractor(PictoaExtractor): def items(self): album_id, image_id = self.groups - url = "{}/albums/{}/{}.html".format(self.root, album_id, image_id) + url = f"{self.root}/albums/{album_id}/{image_id}.html" page = self.request(url).text album_title = text.extr(page, 'property="og:title" content="', '"') image_url = text.extr(page, 'property="og:image" content="', '"') @@ -55,7 +55,7 @@ class PictoaAlbumExtractor(PictoaExtractor): def items(self): album_id = self.groups[0] - url = "{}/albums/{}.html".format(self.root, album_id) + url = f"{self.root}/albums/{album_id}.html" page = self.request(url).text album_data = { diff --git a/gallery_dl/extractor/piczel.py b/gallery_dl/extractor/piczel.py index 8a729f35..b5ba4573 100644 --- a/gallery_dl/extractor/piczel.py +++ b/gallery_dl/extractor/piczel.py @@ -71,7 +71,7 @@ class PiczelUserExtractor(PiczelExtractor): example = "https://piczel.tv/gallery/USER" def posts(self): - url = "{}/api/users/{}/gallery".format(self.root_api, self.groups[0]) + url = f"{self.root_api}/api/users/{self.groups[0]}/gallery" return self._pagination(url) @@ -84,7 +84,7 @@ class PiczelFolderExtractor(PiczelExtractor): example = "https://piczel.tv/gallery/USER/12345" def posts(self): - url = "{}/api/gallery/folder/{}".format(self.root_api, self.groups[0]) + url = f"{self.root_api}/api/gallery/folder/{self.groups[0]}" return self._pagination(url) @@ -95,5 +95,5 @@ class PiczelImageExtractor(PiczelExtractor): example = "https://piczel.tv/gallery/image/12345" def posts(self): - url = "{}/api/gallery/{}".format(self.root_api, self.groups[0]) + url = f"{self.root_api}/api/gallery/{self.groups[0]}" return (self.request(url).json(),) diff --git a/gallery_dl/extractor/pillowfort.py b/gallery_dl/extractor/pillowfort.py index 37b414d2..9944b661 100644 --- a/gallery_dl/extractor/pillowfort.py +++ b/gallery_dl/extractor/pillowfort.py @@ -125,7 +125,7 @@ class PillowfortPostExtractor(PillowfortExtractor): example = "https://www.pillowfort.social/posts/12345" def posts(self): - url = "{}/posts/{}/json/".format(self.root, self.item) + url = f"{self.root}/posts/{self.item}/json/" return (self.request(url).json(),) @@ -136,7 +136,7 @@ class PillowfortUserExtractor(PillowfortExtractor): example = "https://www.pillowfort.social/USER" def posts(self): - url = "{}/{}/json/".format(self.root, self.item) + url = f"{self.root}/{self.item}/json/" params = {"p": 1} while True: diff --git a/gallery_dl/extractor/pinterest.py b/gallery_dl/extractor/pinterest.py index 8531b6eb..af80f80a 100644 --- a/gallery_dl/extractor/pinterest.py +++ b/gallery_dl/extractor/pinterest.py @@ -173,8 +173,8 @@ class PinterestExtractor(Extractor): def _extract_image(self, page, block): sig = block.get("image_signature") or page["image_signature"] - url_base = "https://i.pinimg.com/originals/{}/{}/{}/{}.".format( - sig[0:2], sig[2:4], sig[4:6], sig) + url_base = (f"https://i.pinimg.com/originals" + f"/{sig[0:2]}/{sig[2:4]}/{sig[4:6]}/{sig}.") url_jpg = url_base + "jpg" url_png = url_base + "png" url_webp = url_base + "webp" @@ -249,7 +249,7 @@ class PinterestBoardExtractor(PinterestExtractor): pins = self.api.board_pins(board["id"]) if board["section_count"] and self.config("sections", True): - base = "{}{}id:".format(self.root, board["url"]) + base = f"{self.root}{board['url']}id:" data = {"_extractor": PinterestSectionExtractor} sections = [(base + section["id"], data) for section in self.api.board_sections(board["id"])] @@ -393,8 +393,8 @@ class PinterestPinitExtractor(PinterestExtractor): example = "https://pin.it/abcde" def items(self): - url = "https://api.pinterest.com/url_shortener/{}/redirect/".format( - self.groups[0]) + url = (f"https://api.pinterest.com/url_shortener" + f"/{self.groups[0]}/redirect/") location = self.request_location(url) if not location or not PinterestPinExtractor.pattern.match(location): raise exception.NotFoundError("pin") @@ -520,7 +520,7 @@ class PinterestAPI(): return self._pagination("BaseSearch", options) def _call(self, resource, options): - url = "{}/resource/{}Resource/get/".format(self.root, resource) + url = f"{self.root}/resource/{resource}Resource/get/" params = { "data" : util.json_dumps({"options": options}), "source_url": "", diff --git a/gallery_dl/extractor/pixeldrain.py b/gallery_dl/extractor/pixeldrain.py index a3426e6a..03886bb0 100644 --- a/gallery_dl/extractor/pixeldrain.py +++ b/gallery_dl/extractor/pixeldrain.py @@ -42,7 +42,7 @@ class PixeldrainFileExtractor(PixeldrainExtractor): self.file_id = match[1] def items(self): - url = "{}/api/file/{}".format(self.root, self.file_id) + url = f"{self.root}/api/file/{self.file_id}" file = self.request(url + "/info").json() file["url"] = url + "?download" @@ -68,7 +68,7 @@ class PixeldrainAlbumExtractor(PixeldrainExtractor): self.file_index = match[2] def items(self): - url = "{}/api/list/{}".format(self.root, self.album_id) + url = f"{self.root}/api/list/{self.album_id}" album = self.request(url).json() files = album["files"] @@ -91,8 +91,7 @@ class PixeldrainAlbumExtractor(PixeldrainExtractor): for num, file in enumerate(files, idx+1): file["album"] = album file["num"] = num - file["url"] = url = "{}/api/file/{}?download".format( - self.root, file["id"]) + file["url"] = url = f"{self.root}/api/file/{file['id']}?download" file["date"] = self.parse_datetime(file["date_upload"]) text.nameext_from_url(file["name"], file) yield Message.Url, url, file @@ -120,7 +119,7 @@ class PixeldrainFolderExtractor(PixeldrainExtractor): def items(self): recursive = self.config("recursive") - url = "{}/api/filesystem/{}".format(self.root, self.groups[0]) + url = f"{self.root}/api/filesystem/{self.groups[0]}" stat = self.request(url + "?stat").json() paths = stat["path"] @@ -143,9 +142,8 @@ class PixeldrainFolderExtractor(PixeldrainExtractor): for child in children: if child["type"] == "file": num += 1 - url = "{}/api/filesystem{}?attach".format( - self.root, child["path"]) - share_url = "{}/d{}".format(self.root, child["path"]) + url = f"{self.root}/api/filesystem{child['path']}?attach" + share_url = f"{self.root}/d{child['path']}" data = self.metadata(child) data.update({ "id" : folder["id"], @@ -159,7 +157,7 @@ class PixeldrainFolderExtractor(PixeldrainExtractor): elif child["type"] == "dir": if recursive: - url = "{}/d{}".format(self.root, child["path"]) + url = f"{self.root}/d{child['path']}" child["_extractor"] = PixeldrainFolderExtractor yield Message.Queue, url, child diff --git a/gallery_dl/extractor/pixiv.py b/gallery_dl/extractor/pixiv.py index d1ca0b2a..902910a6 100644 --- a/gallery_dl/extractor/pixiv.py +++ b/gallery_dl/extractor/pixiv.py @@ -120,7 +120,7 @@ class PixivExtractor(Extractor): return [ { "url" : img["image_urls"]["original"], - "suffix": "_p{:02}".format(num), + "suffix": f"_p{num:02}", "_fallback": self._fallback_image(img), } for num, img in enumerate(meta_pages) @@ -203,7 +203,7 @@ class PixivExtractor(Extractor): for ext in ("jpg", "png", "gif"): try: - url = "{}0.{}".format(base, ext) + url = f"{base}0.{ext}" self.request(url, method="HEAD") break except exception.HttpError: @@ -214,8 +214,8 @@ class PixivExtractor(Extractor): return [ { - "url": "{}{}.{}".format(base, num, ext), - "suffix": "_p{:02}".format(num), + "url": f"{base}{num}.{ext}", + "suffix": f"_p{num:02}", "_ugoira_frame_index": num, } for num in range(len(frames)) @@ -231,7 +231,7 @@ class PixivExtractor(Extractor): return ({"url": url},) def _request_ajax(self, endpoint): - url = "{}/ajax{}".format(self.root, endpoint) + url = f"{self.root}/ajax{endpoint}" try: return self.request(url, headers=self.headers_web).json()["body"] except Exception: @@ -285,8 +285,8 @@ class PixivExtractor(Extractor): base, _, ext = url.rpartition("_p0.") return [ { - "url" : "{}_p{}.{}".format(base, num, ext), - "suffix": "_p{:02}".format(num), + "url" : f"{base}_p{num}.{ext}", + "suffix": f"_p{num:02}", } for num in range(count) ] @@ -310,7 +310,7 @@ class PixivExtractor(Extractor): for ext in ("jpg", "png", "gif"): try: - url = "{}_p0.{}".format(base, ext) + url = f"{base}_p0.{ext}" self.request(url, method="HEAD") return url except exception.HttpError: @@ -351,8 +351,8 @@ class PixivExtractor(Extractor): def _make_work(self, kind, url, user): p = url.split("/") return { - "create_date" : "{}-{}-{}T{}:{}:{}+09:00".format( - p[5], p[6], p[7], p[8], p[9], p[10]) if len(p) > 9 else None, + "create_date" : (f"{p[5]}-{p[6]}-{p[7]}T{p[8]}:{p[9]}:{p[10]}" + f"+09:00" if len(p) > 9 else None), "height" : 0, "id" : kind, "image_urls" : None, @@ -384,7 +384,7 @@ class PixivUserExtractor(Dispatch, PixivExtractor): example = "https://www.pixiv.net/en/users/12345" def items(self): - base = "{}/users/{}/".format(self.root, self.groups[0]) + base = f"{self.root}/users/{self.groups[0]}/" return self._dispatch_extractors(( (PixivAvatarExtractor , base + "avatar"), (PixivBackgroundExtractor , base + "background"), @@ -435,7 +435,7 @@ class PixivArtworksExtractor(PixivExtractor): if self.sanity_workaround: body = self._request_ajax( - "/user/{}/profile/all".format(self.user_id)) + f"/user/{self.user_id}/profile/all") try: ajax_ids = list(map(int, body["illusts"])) ajax_ids.extend(map(int, body["manga"])) @@ -643,7 +643,7 @@ class PixivFavoriteExtractor(PixivExtractor): for preview in self.api.user_following(self.user_id, restrict): user = preview["user"] user["_extractor"] = PixivUserExtractor - url = "https://www.pixiv.net/users/{}".format(user["id"]) + url = f"https://www.pixiv.net/users/{user['id']}" yield Message.Queue, url, user @@ -699,7 +699,7 @@ class PixivRankingExtractor(PixivExtractor): date = query.get("date") if date: if len(date) == 8 and date.isdecimal(): - date = "{}-{}-{}".format(date[0:4], date[4:6], date[6:8]) + date = f"{date[0:4]}-{date[4:6]}-{date[6:8]}" else: self.log.warning("invalid date '%s'", date) date = None @@ -929,7 +929,7 @@ class PixivNovelExtractor(PixivExtractor): path.rpartition(".")[0].replace("_master1200", "")) novel["date_url"] = self._date_from_url(url) novel["num"] += 1 - novel["suffix"] = "_p{:02}".format(novel["num"]) + novel["suffix"] = f"_p{novel['num']:02}" novel["_fallback"] = (url + ".png",) url_jpg = url + ".jpg" text.nameext_from_url(url_jpg, novel) @@ -961,7 +961,7 @@ class PixivNovelExtractor(PixivExtractor): novel.update(image) novel["date_url"] = self._date_from_url(url) novel["num"] += 1 - novel["suffix"] = "_p{:02}".format(novel["num"]) + novel["suffix"] = f"_p{novel['num']:02}" text.nameext_from_url(url, novel) yield Message.Url, url, novel @@ -970,8 +970,8 @@ class PixivNovelExtractor(PixivExtractor): novel["date_url"] = None for illust_id in illusts: novel["num"] += 1 - novel["suffix"] = "_p{:02}".format(novel["num"]) - url = "{}/artworks/{}".format(self.root, illust_id) + novel["suffix"] = f"_p{novel['num']:02}" + url = f"{self.root}/artworks/{illust_id}" yield Message.Queue, url, novel def novels(self): @@ -1044,7 +1044,7 @@ class PixivSketchExtractor(Extractor): self.username = match[1] def items(self): - headers = {"Referer": "{}/@{}".format(self.root, self.username)} + headers = {"Referer": f"{self.root}/@{self.username}"} for post in self.posts(): media = post["media"] @@ -1067,11 +1067,10 @@ class PixivSketchExtractor(Extractor): yield Message.Url, url, post def posts(self): - url = "{}/api/walls/@{}/posts/public.json".format( - self.root, self.username) + url = f"{self.root}/api/walls/@{self.username}/posts/public.json" headers = { "Accept": "application/vnd.sketch-v4+json", - "X-Requested-With": "{}/@{}".format(self.root, self.username), + "X-Requested-With": f"{self.root}/@{self.username}", "Referer": self.root + "/", } diff --git a/gallery_dl/extractor/pixnet.py b/gallery_dl/extractor/pixnet.py index eb3edc3f..1fd98cc1 100644 --- a/gallery_dl/extractor/pixnet.py +++ b/gallery_dl/extractor/pixnet.py @@ -24,7 +24,7 @@ class PixnetExtractor(Extractor): def __init__(self, match): Extractor.__init__(self, match) self.blog, self.item_id = match.groups() - self.root = "https://{}.pixnet.net".format(self.blog) + self.root = f"https://{self.blog}.pixnet.net" def items(self): url = self.url_fmt.format(self.root, self.item_id) @@ -72,8 +72,8 @@ class PixnetImageExtractor(PixnetExtractor): def items(self): url = "https://api.pixnet.cc/oembed" params = { - "url": "https://{}.pixnet.net/album/photo/{}".format( - self.blog, self.item_id), + "url": (f"https://{self.blog}.pixnet.net" + f"/album/photo/{self.item_id}"), "format": "json", } diff --git a/gallery_dl/extractor/plurk.py b/gallery_dl/extractor/plurk.py index fb48e581..8a09860b 100644 --- a/gallery_dl/extractor/plurk.py +++ b/gallery_dl/extractor/plurk.py @@ -76,7 +76,7 @@ class PlurkTimelineExtractor(PlurkExtractor): self.user = match[1] def plurks(self): - url = "{}/{}".format(self.root, self.user) + url = f"{self.root}/{self.user}" page = self.request(url).text user_id, pos = text.extract(page, '"page_user": {"id":', ',') plurks = self._load(text.extract(page, "_PLURKS = ", ";\n", pos)[0]) @@ -103,7 +103,7 @@ class PlurkPostExtractor(PlurkExtractor): example = "https://www.plurk.com/p/12345" def plurks(self): - url = "{}/p/{}".format(self.root, self.groups[0]) + url = f"{self.root}/p/{self.groups[0]}" page = self.request(url).text user, pos = text.extract(page, " GLOBAL=", "\n") data, pos = text.extract(page, "plurk =", ";\n", pos) diff --git a/gallery_dl/extractor/poipiku.py b/gallery_dl/extractor/poipiku.py index e371ee26..974b6e84 100644 --- a/gallery_dl/extractor/poipiku.py +++ b/gallery_dl/extractor/poipiku.py @@ -145,4 +145,4 @@ class PoipikuPostExtractor(PoipikuExtractor): self.user_id, self.post_id = match.groups() def posts(self): - return ("/{}/{}.html".format(self.user_id, self.post_id),) + return (f"/{self.user_id}/{self.post_id}.html",) diff --git a/gallery_dl/extractor/poringa.py b/gallery_dl/extractor/poringa.py index 5ea56899..da17eaef 100644 --- a/gallery_dl/extractor/poringa.py +++ b/gallery_dl/extractor/poringa.py @@ -28,7 +28,7 @@ class PoringaExtractor(Extractor): def items(self): for post_id in self.posts(): - url = "{}/posts/imagenes/{}".format(self.root, post_id) + url = f"{self.root}/posts/imagenes/{post_id}" try: response = self.request(url) diff --git a/gallery_dl/extractor/pornhub.py b/gallery_dl/extractor/pornhub.py index 692de5d5..f6cff58b 100644 --- a/gallery_dl/extractor/pornhub.py +++ b/gallery_dl/extractor/pornhub.py @@ -27,7 +27,7 @@ class PornhubExtractor(Extractor): if "/" not in path: path += "/public" - url = "{}/{}/{}/ajax".format(self.root, user, path) + url = f"{self.root}/{user}/{path}/ajax" params = {"page": 1} headers = { "Referer": url[:-5], @@ -40,8 +40,7 @@ class PornhubExtractor(Extractor): allow_redirects=False) if 300 <= response.status_code < 400: - url = "{}{}/{}/ajax".format( - self.root, response.headers["location"], path) + url = f"{self.root}{response.headers['location']}/{path}/ajax" continue yield response.text @@ -82,8 +81,7 @@ class PornhubGalleryExtractor(PornhubExtractor): yield Message.Url, url, text.nameext_from_url(url, image) def metadata(self): - url = "{}/album/{}".format( - self.root, self.gallery_id) + url = f"{self.root}/album/{self.gallery_id}" extr = text.extract_from(self.request(url).text) title = extr("<title>", "") @@ -105,8 +103,7 @@ class PornhubGalleryExtractor(PornhubExtractor): } def images(self): - url = "{}/album/show_album_json?album={}".format( - self.root, self.gallery_id) + url = f"{self.root}/album/show_album_json?album={self.gallery_id}" response = self.request(url) if response.content == b"Permission denied": @@ -144,7 +141,7 @@ class PornhubGifExtractor(PornhubExtractor): self.gallery_id = match[1] def items(self): - url = "{}/gif/{}".format(self.root, self.gallery_id) + url = f"{self.root}/gif/{self.gallery_id}" extr = text.extract_from(self.request(url).text) gif = { @@ -170,7 +167,7 @@ class PornhubUserExtractor(Dispatch, PornhubExtractor): example = "https://www.pornhub.com/model/USER" def items(self): - base = "{}/{}/".format(self.root, self.groups[0]) + base = f"{self.root}/{self.groups[0]}/" return self._dispatch_extractors(( (PornhubPhotosExtractor, base + "photos"), (PornhubGifsExtractor , base + "gifs"), diff --git a/gallery_dl/extractor/pornpics.py b/gallery_dl/extractor/pornpics.py index 36ebd3dc..6f61a2e3 100644 --- a/gallery_dl/extractor/pornpics.py +++ b/gallery_dl/extractor/pornpics.py @@ -62,7 +62,7 @@ class PornpicsGalleryExtractor(PornpicsExtractor, GalleryExtractor): example = "https://www.pornpics.com/galleries/TITLE-12345/" def __init__(self, match): - url = "{}/galleries/{}/".format(self.root, match[1]) + url = f"{self.root}/galleries/{match[1]}/" GalleryExtractor.__init__(self, match, url) items = GalleryExtractor.items @@ -98,7 +98,7 @@ class PornpicsTagExtractor(PornpicsExtractor): example = "https://www.pornpics.com/tags/TAGS/" def galleries(self): - url = "{}/tags/{}/".format(self.root, self.groups[0]) + url = f"{self.root}/tags/{self.groups[0]}/" return self._pagination(url) diff --git a/gallery_dl/extractor/rawkuma.py b/gallery_dl/extractor/rawkuma.py index bc3f042e..242486d7 100644 --- a/gallery_dl/extractor/rawkuma.py +++ b/gallery_dl/extractor/rawkuma.py @@ -25,7 +25,7 @@ class RawkumaChapterExtractor(RawkumaBase, ChapterExtractor): example = "https://rawkuma.net/TITLE-chapter-123/" def __init__(self, match): - url = "{}/{}/".format(self.root, match[1]) + url = f"{self.root}/{match[1]}/" ChapterExtractor.__init__(self, match, url) def metadata(self, page): @@ -61,7 +61,7 @@ class RawkumaMangaExtractor(RawkumaBase, MangaExtractor): example = "https://rawkuma.net/manga/TITLE/" def __init__(self, match): - url = "{}/manga/{}/".format(self.root, match[1]) + url = f"{self.root}/manga/{match[1]}/" MangaExtractor.__init__(self, match, url) def chapters(self, page): diff --git a/gallery_dl/extractor/readcomiconline.py b/gallery_dl/extractor/readcomiconline.py index 71d62059..285c769f 100644 --- a/gallery_dl/extractor/readcomiconline.py +++ b/gallery_dl/extractor/readcomiconline.py @@ -112,7 +112,7 @@ class ReadcomiconlineComicExtractor(ReadcomiconlineBase, MangaExtractor): page , pos = text.extract(page, ' class="listing">', '', pos) comic = comic.rpartition("information")[0].strip() - needle = ' title="Read {} '.format(comic) + needle = f' title="Read {comic} ' comic = text.unescape(comic) for item in text.extract_iter(page, ' href="', ' comic online '): diff --git a/gallery_dl/extractor/realbooru.py b/gallery_dl/extractor/realbooru.py index ec8408f2..cf45578c 100644 --- a/gallery_dl/extractor/realbooru.py +++ b/gallery_dl/extractor/realbooru.py @@ -21,8 +21,7 @@ class RealbooruExtractor(booru.BooruExtractor): root = "https://realbooru.com" def _parse_post(self, post_id): - url = "{}/index.php?page=post&s=view&id={}".format( - self.root, post_id) + url = f"{self.root}/index.php?page=post&s=view&id={post_id}" page = self.request(url).text extr = text.extract_from(page) rating = extr('name="rating" content="', '"') @@ -126,7 +125,7 @@ class RealbooruPoolExtractor(RealbooruExtractor): def metadata(self): pool_id = self.groups[0] - url = "{}/index.php?page=pool&s=show&id={}".format(self.root, pool_id) + url = f"{self.root}/index.php?page=pool&s=show&id={pool_id}" page = self.request(url).text name, pos = text.extract(page, "

Pool: ", "

") diff --git a/gallery_dl/extractor/reddit.py b/gallery_dl/extractor/reddit.py index 76785601..aae4e836 100644 --- a/gallery_dl/extractor/reddit.py +++ b/gallery_dl/extractor/reddit.py @@ -336,7 +336,7 @@ class RedditImageExtractor(Extractor): self.query = match[3] or "" def items(self): - url = "https://{}/{}{}".format(self.domain, self.path, self.query) + url = f"https://{self.domain}/{self.path}{self.query}" data = text.nameext_from_url(url) yield Message.Directory, data yield Message.Url, url, data @@ -355,8 +355,7 @@ class RedditRedirectExtractor(Extractor): sub_type, subreddit, share_url = self.groups if sub_type == "u": sub_type = "user" - url = "https://www.reddit.com/{}/{}/s/{}".format( - sub_type, subreddit, share_url) + url = f"https://www.reddit.com/{sub_type}/{subreddit}/s/{share_url}" location = self.request_location(url, notfound="submission") data = {"_extractor": RedditSubmissionExtractor} yield Message.Queue, location, data @@ -478,8 +477,8 @@ class RedditAPI(): if response.status_code != 200: self.log.debug("Server response: %s", data) - raise exception.AuthenticationError('"{}: {}"'.format( - data.get("error"), data.get("message"))) + raise exception.AuthenticationError( + f"\"{data.get('error')}: {data.get('message')}\"") return "Bearer " + data["access_token"] def _call(self, endpoint, params): diff --git a/gallery_dl/extractor/redgifs.py b/gallery_dl/extractor/redgifs.py index 480485c8..f74d1b6a 100644 --- a/gallery_dl/extractor/redgifs.py +++ b/gallery_dl/extractor/redgifs.py @@ -135,9 +135,9 @@ class RedgifsCollectionsExtractor(RedgifsExtractor): example = "https://www.redgifs.com/users/USER/collections" def items(self): + base = f"{self.root}/users/{self.key}/collections/" for collection in self.api.collections(self.key): - url = "{}/users/{}/collections/{}".format( - self.root, self.key, collection["folderId"]) + url = f"{base}{collection['folderId']}" collection["_extractor"] = RedgifsCollectionExtractor yield Message.Queue, url, collection @@ -223,25 +223,24 @@ class RedgifsAPI(): return self._call(endpoint) def user(self, user, order="new"): - endpoint = "/v2/users/{}/search".format(user.lower()) + endpoint = f"/v2/users/{user.lower()}/search" params = {"order": order} return self._pagination(endpoint, params) def collection(self, user, collection_id): - endpoint = "/v2/users/{}/collections/{}/gifs".format( - user, collection_id) + endpoint = f"/v2/users/{user}/collections/{collection_id}/gifs" return self._pagination(endpoint) def collection_info(self, user, collection_id): - endpoint = "/v2/users/{}/collections/{}".format(user, collection_id) + endpoint = f"/v2/users/{user}/collections/{collection_id}" return self._call(endpoint) def collections(self, user): - endpoint = "/v2/users/{}/collections".format(user) + endpoint = f"/v2/users/{user}/collections" return self._pagination(endpoint, key="collections") def niches(self, niche, order): - endpoint = "/v2/niches/{}/gifs".format(niche) + endpoint = f"/v2/niches/{niche}/gifs" params = {"count": 30, "order": order} return self._pagination(endpoint, params) diff --git a/gallery_dl/extractor/rule34us.py b/gallery_dl/extractor/rule34us.py index a0eb0bf7..a43ea4cc 100644 --- a/gallery_dl/extractor/rule34us.py +++ b/gallery_dl/extractor/rule34us.py @@ -23,7 +23,7 @@ class Rule34usExtractor(BooruExtractor): r'
  • ]*>= 400: return diff --git a/gallery_dl/extractor/schalenetwork.py b/gallery_dl/extractor/schalenetwork.py index 75fdd6b4..49a7d364 100644 --- a/gallery_dl/extractor/schalenetwork.py +++ b/gallery_dl/extractor/schalenetwork.py @@ -49,8 +49,7 @@ class SchalenetworkExtractor(Extractor): return for entry in entries: - url = "{}/g/{}/{}".format( - self.root, entry["id"], entry["public_key"]) + url = f"{self.root}/g/{entry['id']}/{entry['public_key']}" entry["_extractor"] = SchalenetworkGalleryExtractor yield Message.Queue, url, entry @@ -106,8 +105,7 @@ class SchalenetworkGalleryExtractor(SchalenetworkExtractor, GalleryExtractor): self.directory_fmt = ("{category}",) def metadata(self, _): - url = "{}/books/detail/{}/{}".format( - self.root_api, self.groups[1], self.groups[2]) + url = f"{self.root_api}/books/detail/{self.groups[1]}/{self.groups[2]}" self.data = data = self.request(url, headers=self.headers).json() data["date"] = text.parse_timestamp(data["created_at"] // 1000) @@ -142,11 +140,8 @@ class SchalenetworkGalleryExtractor(SchalenetworkExtractor, GalleryExtractor): data = self.data fmt = self._select_format(data["data"]) - url = "{}/books/data/{}/{}/{}/{}".format( - self.root_api, - data["id"], data["public_key"], - fmt["id"], fmt["public_key"], - ) + url = (f"{self.root_api}/books/data/{data['id']}/" + f"{data['public_key']}/{fmt['id']}/{fmt['public_key']}") params = { "v": data["updated_at"], "w": fmt["w"], @@ -157,7 +152,7 @@ class SchalenetworkGalleryExtractor(SchalenetworkExtractor, GalleryExtractor): base = self.request( url, method="POST", params=params, headers=self.headers, ).json()["base"] - url = "{}?v={}&w={}".format(base, data["updated_at"], fmt["w"]) + url = f"{base}?v={data['updated_at']}&w={fmt['w']}" info = text.nameext_from_url(base) if not info["extension"]: info["extension"] = "cbz" diff --git a/gallery_dl/extractor/seiga.py b/gallery_dl/extractor/seiga.py index 350e4d6c..2fda06e3 100644 --- a/gallery_dl/extractor/seiga.py +++ b/gallery_dl/extractor/seiga.py @@ -42,7 +42,7 @@ class SeigaExtractor(Extractor): def get_image_url(self, image_id): """Get url for an image with id 'image_id'""" - url = "{}/image/source/{}".format(self.root, image_id) + url = f"{self.root}/image/source/{image_id}" location = self.request_location(url, notfound="image") if "nicovideo.jp/login" in location: raise exception.StopExtraction( @@ -81,7 +81,7 @@ class SeigaExtractor(Extractor): if "/mfa" in response.url: page = response.text email = text.extr(page, 'class="userAccount">', "<") - code = self.input("Email Confirmation Code ({}): ".format(email)) + code = self.input(f"Email Confirmation Code ({email}): ") data = { "otp": code, @@ -145,7 +145,7 @@ class SeigaUserExtractor(SeigaExtractor): } def get_images(self): - url = "{}/user/illust/{}".format(self.root, self.user_id) + url = f"{self.root}/user/illust/{self.user_id}" params = {"sort": self.order, "page": self.start_page, "target": "illust_all"} @@ -197,7 +197,7 @@ class SeigaImageExtractor(SeigaExtractor): self.cookies.set( "skip_fetish_warning", "1", domain="seiga.nicovideo.jp") - url = "{}/seiga/im{}".format(self.root, self.image_id) + url = f"{self.root}/seiga/im{self.image_id}" page = self.request(url, notfound="image").text data = text.extract_all(page, ( diff --git a/gallery_dl/extractor/sexcom.py b/gallery_dl/extractor/sexcom.py index f7b8098a..e27e8d4f 100644 --- a/gallery_dl/extractor/sexcom.py +++ b/gallery_dl/extractor/sexcom.py @@ -215,8 +215,8 @@ class SexcomRelatedPinExtractor(SexcomPinExtractor): return {"original_pin": pin} def pins(self): - url = "{}/pin/related?pinId={}&limit=24&offset=0".format( - self.root, self.groups[1]) + url = (f"{self.root}/pin/related?pinId={self.groups[1]}" + f"&limit=24&offset=0") return self._pagination(url) @@ -231,7 +231,7 @@ class SexcomPinsExtractor(SexcomExtractor): return {"user": text.unquote(self.groups[0])} def pins(self): - url = "{}/user/{}/pins/".format(self.root, self.groups[0]) + url = f"{self.root}/user/{self.groups[0]}/pins/" return self._pagination(url) @@ -246,7 +246,7 @@ class SexcomLikesExtractor(SexcomExtractor): return {"user": text.unquote(self.groups[0])} def pins(self): - url = "{}/user/{}/likes/".format(self.root, self.groups[0]) + url = f"{self.root}/user/{self.groups[0]}/likes/" return self._pagination(url) @@ -266,7 +266,7 @@ class SexcomBoardExtractor(SexcomExtractor): } def pins(self): - url = "{}/user/{}/{}/".format(self.root, self.user, self.board) + url = f"{self.root}/user/{self.user}/{self.board}/" return self._pagination(url) @@ -291,7 +291,7 @@ class SexcomSearchExtractor(SexcomExtractor): return {"search": self.search} def pins(self): - url = "{}/{}".format(self.root, self.path) + url = f"{self.root}/{self.path}" return self._pagination(url) diff --git a/gallery_dl/extractor/shimmie2.py b/gallery_dl/extractor/shimmie2.py index 01d31b74..936cb4df 100644 --- a/gallery_dl/extractor/shimmie2.py +++ b/gallery_dl/extractor/shimmie2.py @@ -110,7 +110,7 @@ class Shimmie2TagExtractor(Shimmie2Extractor): mime = "" while True: - url = "{}/post/list/{}/{}".format(self.root, self.tags, pnum) + url = f"{self.root}/post/list/{self.tags}/{pnum}" page = self.request(url).text extr = text.extract_from(page) @@ -153,7 +153,7 @@ class Shimmie2TagExtractor(Shimmie2Extractor): pnum += 1 if not extr(">Next<", ">"): - if not extr("/{}'>{}<".format(pnum, pnum), ">"): + if not extr(f"/{pnum}'>{pnum}<", ">"): return def _posts_giantessbooru(self): @@ -161,8 +161,7 @@ class Shimmie2TagExtractor(Shimmie2Extractor): file_url_fmt = (self.root + "/index.php?q=/image/{}.jpg").format while True: - url = "{}/index.php?q=/post/list/{}/{}".format( - self.root, self.tags, pnum) + url = f"{self.root}/index.php?q=/post/list/{self.tags}/{pnum}" extr = text.extract_from(self.request(url).text) while True: @@ -184,7 +183,7 @@ class Shimmie2TagExtractor(Shimmie2Extractor): } pnum += 1 - if not extr("/{0}'>{0}<".format(pnum), ">"): + if not extr(f"/{pnum}'>{pnum}<", ">"): return @@ -196,18 +195,18 @@ class Shimmie2PostExtractor(Shimmie2Extractor): def posts(self): post_id = self.groups[-1] - url = "{}/post/view/{}".format(self.root, post_id) + url = f"{self.root}/post/view/{post_id}" page = self.request(url).text extr = text.extract_from(page) - quote = self._quote_type(page) + qt = self._quote_type(page) post = { "id" : post_id, "tags" : extr(": ", "<").partition(" - ")[0].rstrip(")"), "md5" : extr("/_thumbs/", "/"), "file_url": self.root + ( - extr("id={0}main_image{0} src={0}".format(quote), quote) or - extr("").partition( " ")[0].strip("\"'"), @@ -221,7 +220,7 @@ class Shimmie2PostExtractor(Shimmie2Extractor): def _posts_giantessbooru(self): post_id = self.groups[-1] - url = "{}/index.php?q=/post/view/{}".format(self.root, post_id) + url = f"{self.root}/index.php?q=/post/view/{post_id}" extr = text.extract_from(self.request(url).text) return ({ diff --git a/gallery_dl/extractor/skeb.py b/gallery_dl/extractor/skeb.py index d541bb5d..cd0c47a6 100644 --- a/gallery_dl/extractor/skeb.py +++ b/gallery_dl/extractor/skeb.py @@ -100,7 +100,7 @@ class SkebExtractor(Extractor): params["offset"] += 30 def _pagination_users(self, endpoint, params): - url = "{}/api{}".format(self.root, endpoint) + url = f"{self.root}/api{endpoint}" params["offset"] = 0 params["limit"] = 90 @@ -114,8 +114,7 @@ class SkebExtractor(Extractor): params["offset"] += params["limit"] def _get_post_data(self, user_name, post_num): - url = "{}/api/users/{}/works/{}".format( - self.root, user_name, post_num) + url = f"{self.root}/api/users/{user_name}/works/{post_num}" resp = self.request(url, headers=self.headers).json() creator = resp["creator"] post = { @@ -216,7 +215,7 @@ class SkebUserExtractor(SkebExtractor): example = "https://skeb.jp/@USER" def posts(self): - url = "{}/api/users/{}/works".format(self.root, self.user_name) + url = f"{self.root}/api/users/{self.user_name}/works" params = {"role": "creator", "sort": "date"} posts = self._pagination(url, params) @@ -289,7 +288,7 @@ class SkebFollowingExtractor(SkebExtractor): items = SkebExtractor._items_users def users(self): - endpoint = "/users/{}/following_creators".format(self.user_name) + endpoint = f"/users/{self.user_name}/following_creators" params = {"sort": "date"} return self._pagination_users(endpoint, params) diff --git a/gallery_dl/extractor/slickpic.py b/gallery_dl/extractor/slickpic.py index 64f8a02d..f6bed219 100644 --- a/gallery_dl/extractor/slickpic.py +++ b/gallery_dl/extractor/slickpic.py @@ -22,7 +22,7 @@ class SlickpicExtractor(Extractor): def __init__(self, match): Extractor.__init__(self, match) self.user = match[1] - self.root = "https://{}.slickpic.com".format(self.user) + self.root = f"https://{self.user}.slickpic.com" class SlickpicAlbumExtractor(SlickpicExtractor): @@ -72,7 +72,7 @@ class SlickpicAlbumExtractor(SlickpicExtractor): yield Message.Url, url, img def metadata(self): - url = "{}/albums/{}/?wallpaper".format(self.root, self.album) + url = f"{self.root}/albums/{self.album}/?wallpaper" extr = text.extract_from(self.request(url).text) title = text.unescape(extr("", "")) diff --git a/gallery_dl/extractor/slideshare.py b/gallery_dl/extractor/slideshare.py index 683b40d0..c0f0e360 100644 --- a/gallery_dl/extractor/slideshare.py +++ b/gallery_dl/extractor/slideshare.py @@ -26,8 +26,7 @@ class SlidesharePresentationExtractor(GalleryExtractor): def __init__(self, match): self.user, self.presentation = match.groups() - url = "https://www.slideshare.net/{}/{}".format( - self.user, self.presentation) + url = f"https://www.slideshare.net/{self.user}/{self.presentation}" GalleryExtractor.__init__(self, match, url) def metadata(self, page): @@ -47,11 +46,8 @@ class SlidesharePresentationExtractor(GalleryExtractor): def images(self, page): slides = self.slideshow["slides"] - begin = "{}/{}/95/{}-".format( - slides["host"], - slides["imageLocation"], - slides["title"], - ) + begin = (f"{slides['host']}/{slides['imageLocation']}" + f"/95/{slides['title']}-") end = "-1024.jpg" return [ diff --git a/gallery_dl/extractor/smugmug.py b/gallery_dl/extractor/smugmug.py index d250279e..d5da3306 100644 --- a/gallery_dl/extractor/smugmug.py +++ b/gallery_dl/extractor/smugmug.py @@ -197,7 +197,7 @@ class SmugmugAPI(oauth.OAuth1API): return self._expansion(endpoint, "Node", params) def _call(self, endpoint, params=None, domain=API_DOMAIN): - url = "https://{}/api/v2/{}".format(domain, endpoint) + url = f"https://{domain}/api/v2/{endpoint}" params = params or {} if self.api_key: params["APIKey"] = self.api_key diff --git a/gallery_dl/extractor/soundgasm.py b/gallery_dl/extractor/soundgasm.py index 4632b2ab..79ab74dd 100644 --- a/gallery_dl/extractor/soundgasm.py +++ b/gallery_dl/extractor/soundgasm.py @@ -58,7 +58,7 @@ class SoundgasmAudioExtractor(SoundgasmExtractor): self.user, self.slug = match.groups() def sounds(self): - return ("{}/u/{}/{}".format(self.root, self.user, self.slug),) + return (f"{self.root}/u/{self.user}/{self.slug}",) class SoundgasmUserExtractor(SoundgasmExtractor): diff --git a/gallery_dl/extractor/speakerdeck.py b/gallery_dl/extractor/speakerdeck.py index c4d2984e..342ca319 100644 --- a/gallery_dl/extractor/speakerdeck.py +++ b/gallery_dl/extractor/speakerdeck.py @@ -28,7 +28,7 @@ class SpeakerdeckPresentationExtractor(GalleryExtractor): url = self.root + "/oembed.json" params = { - "url": "{}/{}/{}".format(self.root, user, presentation), + "url": f"{self.root}/{user}/{presentation}", } data = self.request(url, params=params).json() @@ -44,7 +44,7 @@ class SpeakerdeckPresentationExtractor(GalleryExtractor): } def images(self, _): - url = "{}/player/{}".format(self.root, self.presentation_id) + url = f"{self.root}/player/{self.presentation_id}" page = self.request(url).text page = util.re(r"\s+").sub(" ", page) return [ diff --git a/gallery_dl/extractor/steamgriddb.py b/gallery_dl/extractor/steamgriddb.py index ac7b6a51..8844865f 100644 --- a/gallery_dl/extractor/steamgriddb.py +++ b/gallery_dl/extractor/steamgriddb.py @@ -169,8 +169,8 @@ class SteamgriddbAssetExtractor(SteamgriddbExtractor): endpoint = "/api/public/asset/" + self.asset_type + "/" + self.asset_id asset = self._call(endpoint)["asset"] if asset is None: - raise exception.NotFoundError("asset ({}:{})".format( - self.asset_type, self.asset_id)) + raise exception.NotFoundError( + f"asset ({self.asset_type}:{self.asset_id})") return (asset,) @@ -211,7 +211,7 @@ class SteamgriddbIconsExtractor(SteamgriddbAssetsExtractor): asset_type = "icon" pattern = BASE_PATTERN + r"/(game|collection)/(\d+)/icons(?:/(\d+))?" example = "https://www.steamgriddb.com/game/1234/icons" - valid_dimensions = ["{0}x{0}".format(i) for i in (8, 10, 14, 16, 20, 24, + valid_dimensions = [f"{i}x{i}" for i in (8, 10, 14, 16, 20, 24, 28, 32, 35, 40, 48, 54, 56, 57, 60, 64, 72, 76, 80, 90, 96, 100, 114, 120, 128, 144, 150, 152, 160, 180, 192, 194, 256, 310, 512, 768, 1024)] diff --git a/gallery_dl/extractor/subscribestar.py b/gallery_dl/extractor/subscribestar.py index 8ab8f277..d9d6d9e5 100644 --- a/gallery_dl/extractor/subscribestar.py +++ b/gallery_dl/extractor/subscribestar.py @@ -119,7 +119,7 @@ class SubscribestarExtractor(Extractor): if errors: self.log.debug(errors) try: - msg = '"{}"'.format(errors.popitem()[1]) + msg = f'"{errors.popitem()[1]}"' except Exception: msg = None raise exception.AuthenticationError(msg) @@ -222,7 +222,7 @@ class SubscribestarUserExtractor(SubscribestarExtractor): def posts(self): needle_next_page = 'data-role="infinite_scroll-next_page" href="' - page = self.request("{}/{}".format(self.root, self.item)).text + page = self.request(f"{self.root}/{self.item}").text while True: posts = page.split('
    ") diff --git a/gallery_dl/extractor/tiktok.py b/gallery_dl/extractor/tiktok.py index 3af05575..973bd224 100644 --- a/gallery_dl/extractor/tiktok.py +++ b/gallery_dl/extractor/tiktok.py @@ -52,7 +52,7 @@ class TiktokExtractor(Extractor): if "imagePost" in post: if not original_title: - title = "TikTok photo #{}".format(post["id"]) + title = f"TikTok photo #{post['id']}" img_list = post["imagePost"]["images"] for i, img in enumerate(img_list, 1): url = img["imageURL"]["urlList"][0] @@ -83,7 +83,7 @@ class TiktokExtractor(Extractor): if ytdl_media: if not original_title: - title = "TikTok {} #{}".format(ytdl_media, post["id"]) + title = f"TikTok {ytdl_media} #{post['id']}" post.update({ "type" : ytdl_media, "image" : None, @@ -133,7 +133,7 @@ class TiktokExtractor(Extractor): post.update({ "type" : "audio", "image" : None, - "title" : post["desc"] or "TikTok audio #{}".format(post["id"]), + "title" : post["desc"] or f"TikTok audio #{post['id']}", "duration" : audio.get("duration"), "num" : 0, "img_id" : "", @@ -172,7 +172,7 @@ class TiktokPostExtractor(TiktokExtractor): def urls(self): user, post_id = self.groups - url = "{}/@{}/video/{}".format(self.root, user or "", post_id) + url = f"{self.root}/@{user or ''}/video/{post_id}" return (url,) @@ -246,7 +246,7 @@ class TiktokUserExtractor(TiktokExtractor): set_cookie(cookie) user_name = self.groups[0] - profile_url = "{}/@{}".format(self.root, user_name) + profile_url = f"{self.root}/@{user_name}" if self.avatar: try: avatar_url, avatar = self._generate_avatar( diff --git a/gallery_dl/extractor/tmohentai.py b/gallery_dl/extractor/tmohentai.py index ecdc194e..ef441d34 100644 --- a/gallery_dl/extractor/tmohentai.py +++ b/gallery_dl/extractor/tmohentai.py @@ -21,14 +21,13 @@ class TmohentaiGalleryExtractor(GalleryExtractor): def __init__(self, match): self.gallery_id = match[1] - url = "{}/contents/{}".format(self.root, self.gallery_id) + url = f"{self.root}/contents/{self.gallery_id}" GalleryExtractor.__init__(self, match, url) def images(self, page): - fmt = "https://imgrojo.tmohentai.com/contents/{}/{{:>03}}.webp".format( - self.gallery_id).format + base = f"https://imgrojo.tmohentai.com/contents/{self.gallery_id}/" cnt = page.count('class="lanzador') - return [(fmt(i), None) for i in range(0, cnt)] + return [(f"{base}{i:>03}.webp", None) for i in range(0, cnt)] def metadata(self, page): extr = text.extract_from(page) diff --git a/gallery_dl/extractor/toyhouse.py b/gallery_dl/extractor/toyhouse.py index 0b156719..7add79ac 100644 --- a/gallery_dl/extractor/toyhouse.py +++ b/gallery_dl/extractor/toyhouse.py @@ -108,7 +108,7 @@ class ToyhouseArtExtractor(ToyhouseExtractor): example = "https://www.toyhou.se/USER/art" def posts(self): - return self._pagination("/{}/art".format(self.user)) + return self._pagination(f"/{self.user}/art") def metadata(self): return {"user": self.user} @@ -124,6 +124,6 @@ class ToyhouseImageExtractor(ToyhouseExtractor): example = "https://toyhou.se/~images/12345" def posts(self): - url = "{}/~images/{}".format(self.root, self.user) + url = f"{self.root}/~images/{self.user}" return (self._parse_post( self.request(url).text, '= 300: @@ -61,7 +62,7 @@ class TumblrgalleryTumblrblogExtractor(TumblrgalleryExtractor): for url in self._urls_from_page(response.text): yield url, self._data_from_url(url) - page_num += 1 + pnum += 1 class TumblrgalleryPostExtractor(TumblrgalleryExtractor): @@ -112,7 +113,7 @@ class TumblrgallerySearchExtractor(TumblrgalleryExtractor): for gallery_id in text.extract_iter( page, '
    > 22) + 1288834974657) // 1000) @@ -595,7 +591,7 @@ class TwitterUserExtractor(Dispatch, TwitterExtractor): if user_id is not None: user = "id:" + user_id - base = "{}/{}/".format(self.root, user) + base = f"{self.root}/{user}/" return self._dispatch_extractors(( (TwitterInfoExtractor , base + "info"), (TwitterAvatarExtractor , base + "photo"), @@ -661,12 +657,12 @@ class TwitterTimelineExtractor(TwitterExtractor): self.api._user_id_by_screen_name(self.user) # build search query - query = "from:{} max_id:{}".format(self._user["name"], tweet_id) + query = f"from:{self._user['name']} max_id:{tweet_id}" if self.retweets: query += " include:retweets include:nativeretweets" if state <= 2: - self._cursor_prefix = "2_{}/".format(tweet_id) + self._cursor_prefix = f"2_{tweet_id}/" if reset: self._cursor = self._cursor_prefix @@ -682,7 +678,7 @@ class TwitterTimelineExtractor(TwitterExtractor): if state <= 3: # yield unfiltered search results - self._cursor_prefix = "3_{}/".format(tweet_id) + self._cursor_prefix = f"3_{tweet_id}/" if reset: self._cursor = self._cursor_prefix @@ -845,7 +841,7 @@ class TwitterHashtagExtractor(TwitterExtractor): example = "https://x.com/hashtag/NAME" def items(self): - url = "{}/search?q=%23{}".format(self.root, self.user) + url = f"{self.root}/search?q=%23{self.user}" data = {"_extractor": TwitterSearchExtractor} yield Message.Queue, url, data @@ -975,7 +971,7 @@ class TwitterQuotesExtractor(TwitterExtractor): example = "https://x.com/USER/status/12345/quotes" def items(self): - url = "{}/search?q=quoted_tweet_id:{}".format(self.root, self.user) + url = f"{self.root}/search?q=quoted_tweet_id:{self.user}" data = {"_extractor": TwitterSearchExtractor} yield Message.Queue, url, data @@ -1053,8 +1049,7 @@ class TwitterImageExtractor(Extractor): TwitterExtractor._init_sizes(self) def items(self): - base = "https://pbs.twimg.com/media/{}?format={}&name=".format( - self.id, self.fmt) + base = f"https://pbs.twimg.com/media/{self.id}?format={self.fmt}&name=" data = { "filename": self.id, @@ -1389,7 +1384,7 @@ class TwitterAPI(): ("viewer", "communities_timeline", "timeline")) def live_event_timeline(self, event_id): - endpoint = "/2/live_event/timeline/{}.json".format(event_id) + endpoint = f"/2/live_event/timeline/{event_id}.json" params = self.params.copy() params["timeline_id"] = "recap" params["urt"] = "true" @@ -1397,7 +1392,7 @@ class TwitterAPI(): return self._pagination_legacy(endpoint, params) def live_event(self, event_id): - endpoint = "/1.1/live_event/1/{}/timeline.json".format(event_id) + endpoint = f"/1.1/live_event/1/{event_id}/timeline.json" params = self.params.copy() params["count"] = "0" params["urt"] = "true" @@ -1482,9 +1477,9 @@ class TwitterAPI(): return user["rest_id"] except KeyError: if "unavailable_message" in user: - raise exception.NotFoundError("{} ({})".format( - user["unavailable_message"].get("text"), - user.get("reason")), False) + raise exception.NotFoundError( + f"{user['unavailable_message'].get('text')} " + f"({user.get('reason')})", False) else: raise exception.NotFoundError("user") @@ -1782,12 +1777,10 @@ class TwitterAPI(): extr.log.info("Retrying API request as guest") continue raise exception.AuthorizationError( - "{} blocked your account".format( - user["screen_name"])) + f"{user['screen_name']} blocked your account") elif user.get("protected"): raise exception.AuthorizationError( - "{}'s Tweets are protected".format( - user["screen_name"])) + f"{user['screen_name']}'s Tweets are protected") raise exception.StopExtraction( "Unable to retrieve Tweets from this timeline") @@ -2017,7 +2010,7 @@ def _login_impl(extr, username, password): errors = [] for error in data.get("errors") or (): msg = error.get("message") - errors.append('"{}"'.format(msg) if msg else "Unknown error") + errors.append(f'"{msg}"' if msg else "Unknown error") extr.log.debug(response.text) raise exception.AuthenticationError(", ".join(errors)) @@ -2161,7 +2154,7 @@ def _login_impl(extr, username, password): "subtask_inputs": [inputs], } - extr.sleep(random.uniform(1.0, 3.0), "login ({})".format(subtask)) + extr.sleep(random.uniform(1.0, 3.0), f"login ({subtask})") flow_token, subtask = process(data) return { diff --git a/gallery_dl/extractor/unsplash.py b/gallery_dl/extractor/unsplash.py index 16706c91..0821ee83 100644 --- a/gallery_dl/extractor/unsplash.py +++ b/gallery_dl/extractor/unsplash.py @@ -78,7 +78,7 @@ class UnsplashImageExtractor(UnsplashExtractor): example = "https://unsplash.com/photos/ID" def photos(self): - url = "{}/napi/photos/{}".format(self.root, self.item) + url = f"{self.root}/napi/photos/{self.item}" return (self.request(url).json(),) @@ -89,7 +89,7 @@ class UnsplashUserExtractor(UnsplashExtractor): example = "https://unsplash.com/@USER" def photos(self): - url = "{}/napi/users/{}/photos".format(self.root, self.item) + url = f"{self.root}/napi/users/{self.item}/photos" params = {"order_by": "latest"} return self._pagination(url, params) @@ -101,7 +101,7 @@ class UnsplashFavoriteExtractor(UnsplashExtractor): example = "https://unsplash.com/@USER/likes" def photos(self): - url = "{}/napi/users/{}/likes".format(self.root, self.item) + url = f"{self.root}/napi/users/{self.item}/likes" params = {"order_by": "latest"} return self._pagination(url, params) @@ -120,7 +120,7 @@ class UnsplashCollectionExtractor(UnsplashExtractor): return {"collection_id": self.item, "collection_title": self.title} def photos(self): - url = "{}/napi/collections/{}/photos".format(self.root, self.item) + url = f"{self.root}/napi/collections/{self.item}/photos" params = {"order_by": "latest"} return self._pagination(url, params) diff --git a/gallery_dl/extractor/uploadir.py b/gallery_dl/extractor/uploadir.py index b6e482b2..d06c2ad3 100644 --- a/gallery_dl/extractor/uploadir.py +++ b/gallery_dl/extractor/uploadir.py @@ -27,7 +27,7 @@ class UploadirFileExtractor(Extractor): self.file_id = match[1] def items(self): - url = "{}/u/{}".format(self.root, self.file_id) + url = f"{self.root}/u/{self.file_id}" response = self.request(url, method="HEAD", allow_redirects=False) if 300 <= response.status_code < 400: diff --git a/gallery_dl/extractor/urlgalleries.py b/gallery_dl/extractor/urlgalleries.py index ebfeb9df..1aa43096 100644 --- a/gallery_dl/extractor/urlgalleries.py +++ b/gallery_dl/extractor/urlgalleries.py @@ -23,8 +23,7 @@ class UrlgalleriesGalleryExtractor(GalleryExtractor): _, blog_alt, blog, self.gallery_id = self.groups if not blog: blog = blog_alt - url = "https://urlgalleries.net/b/{}/porn-gallery-{}/?a=10000".format( - blog, self.gallery_id) + url = f"{self.root}/b/{blog}/porn-gallery-{self.gallery_id}/?a=10000" with self.request(url, allow_redirects=False, fatal=...) as response: if 300 <= response.status_code < 500: diff --git a/gallery_dl/extractor/vipergirls.py b/gallery_dl/extractor/vipergirls.py index 1bbe06d2..58ec70bd 100644 --- a/gallery_dl/extractor/vipergirls.py +++ b/gallery_dl/extractor/vipergirls.py @@ -88,7 +88,7 @@ class VipergirlsExtractor(Extractor): def _login_impl(self, username, password): self.log.info("Logging in as %s", username) - url = "{}/login.php?do=login".format(self.root) + url = f"{self.root}/login.php?do=login" data = { "vb_login_username": username, "vb_login_password": password, @@ -127,7 +127,7 @@ class VipergirlsThreadExtractor(VipergirlsExtractor): self.thread_id, self.page = match.groups() def posts(self): - url = "{}/vr.php?t={}".format(self.root, self.thread_id) + url = f"{self.root}/vr.php?t={self.thread_id}" return self.request_xml(url) @@ -144,5 +144,5 @@ class VipergirlsPostExtractor(VipergirlsExtractor): self.page = 0 def posts(self): - url = "{}/vr.php?p={}".format(self.root, self.post_id) + url = f"{self.root}/vr.php?p={self.post_id}" return self.request_xml(url) diff --git a/gallery_dl/extractor/vk.py b/gallery_dl/extractor/vk.py index 3218bd05..4a34e4f0 100644 --- a/gallery_dl/extractor/vk.py +++ b/gallery_dl/extractor/vk.py @@ -143,10 +143,10 @@ class VkPhotosExtractor(VkExtractor): if self.user_id: user_id = self.user_id prefix = "public" if user_id[0] == "-" else "id" - url = "{}/{}{}".format(self.root, prefix, user_id.lstrip("-")) + url = f"{self.root}/{prefix}{user_id.lstrip('-')}" data = self._extract_profile(url) else: - url = "{}/{}".format(self.root, self.user_name) + url = f"{self.root}/{self.user_name}" data = self._extract_profile(url) self.user_id = data["user"]["id"] return data @@ -185,8 +185,7 @@ class VkAlbumExtractor(VkExtractor): self.user_id, self.album_id = match.groups() def photos(self): - return self._pagination("album{}_{}".format( - self.user_id, self.album_id)) + return self._pagination(f"album{self.user_id}_{self.album_id}") def metadata(self): return { @@ -207,7 +206,7 @@ class VkTaggedExtractor(VkExtractor): self.user_id = match[1] def photos(self): - return self._pagination("tag{}".format(self.user_id)) + return self._pagination(f"tag{self.user_id}") def metadata(self): return {"user": {"id": self.user_id}} diff --git a/gallery_dl/extractor/vsco.py b/gallery_dl/extractor/vsco.py index 0496be06..d2adb13f 100644 --- a/gallery_dl/extractor/vsco.py +++ b/gallery_dl/extractor/vsco.py @@ -47,7 +47,7 @@ class VscoExtractor(Extractor): base = img["responsive_url"].partition("/")[2] cdn, _, path = base.partition("/") if cdn.startswith("aws"): - url = "https://image-{}.vsco.co/{}".format(cdn, path) + url = f"https://image-{cdn}.vsco.co/{path}" elif cdn.isdecimal(): url = "https://image.vsco.co/" + base elif img["responsive_url"].startswith("http"): @@ -83,7 +83,7 @@ class VscoExtractor(Extractor): def _pagination(self, url, params, token, key, extra=None): headers = { - "Referer" : "{}/{}".format(self.root, self.user), + "Referer" : f"{self.root}/{self.user}", "Authorization" : "Bearer " + token, "X-Client-Platform": "web", "X-Client-Build" : "1", @@ -136,7 +136,7 @@ class VscoUserExtractor(Dispatch, VscoExtractor): example = "https://vsco.co/USER" def items(self): - base = "{}/{}/".format(self.root, self.user) + base = f"{self.root}/{self.user}/" return self._dispatch_extractors(( (VscoAvatarExtractor , base + "avatar"), (VscoGalleryExtractor , base + "gallery"), @@ -152,12 +152,12 @@ class VscoGalleryExtractor(VscoExtractor): example = "https://vsco.co/USER/gallery" def images(self): - url = "{}/{}/gallery".format(self.root, self.user) + url = f"{self.root}/{self.user}/gallery" data = self._extract_preload_state(url) tkn = data["users"]["currentUser"]["tkn"] sid = str(data["sites"]["siteByUsername"][self.user]["site"]["id"]) - url = "{}/api/3.0/medias/profile".format(self.root) + url = f"{self.root}/api/3.0/medias/profile" params = { "site_id" : sid, "limit" : "14", @@ -176,14 +176,14 @@ class VscoCollectionExtractor(VscoExtractor): example = "https://vsco.co/USER/collection/1" def images(self): - url = "{}/{}/collection/1".format(self.root, self.user) + url = f"{self.root}/{self.user}/collection/1" data = self._extract_preload_state(url) tkn = data["users"]["currentUser"]["tkn"] cid = (data["sites"]["siteByUsername"][self.user] ["site"]["siteCollectionId"]) - url = "{}/api/2.0/collections/{}/medias".format(self.root, cid) + url = f"{self.root}/api/2.0/collections/{cid}/medias" params = {"page": 2, "size": "20"} return self._pagination(url, params, tkn, "medias", ( data["medias"]["byId"][mid["id"]]["media"] @@ -201,7 +201,7 @@ class VscoSpaceExtractor(VscoExtractor): example = "https://vsco.co/spaces/a1b2c3d4e5f" def images(self): - url = "{}/spaces/{}".format(self.root, self.user) + url = f"{self.root}/spaces/{self.user}" data = self._extract_preload_state(url) tkn = data["users"]["currentUser"]["tkn"] @@ -215,14 +215,14 @@ class VscoSpaceExtractor(VscoExtractor): space = data["spaces"]["byId"][sid] space["postsList"] = [posts[pid] for pid in space["postsList"]] - url = "{}/grpc/spaces/{}/posts".format(self.root, sid) + url = f"{self.root}/grpc/spaces/{sid}/posts" params = {} return self._pagination(url, params, tkn, space) def _pagination(self, url, params, token, data): headers = { "Accept" : "application/json", - "Referer" : "{}/spaces/{}".format(self.root, self.user), + "Referer" : f"{self.root}/spaces/{self.user}", "Content-Type" : "application/json", "Authorization": "Bearer " + token, } @@ -248,7 +248,7 @@ class VscoSpacesExtractor(VscoExtractor): example = "https://vsco.co/USER/spaces" def items(self): - url = "{}/{}/spaces".format(self.root, self.user) + url = f"{self.root}/{self.user}/spaces" data = self._extract_preload_state(url) tkn = data["users"]["currentUser"]["tkn"] @@ -261,12 +261,12 @@ class VscoSpacesExtractor(VscoExtractor): "Authorization": "Bearer " + tkn, } # this would theoretically need to be paginated - url = "{}/grpc/spaces/user/{}".format(self.root, uid) + url = f"{self.root}/grpc/spaces/user/{uid}" data = self.request(url, headers=headers).json() for space in data["spacesWithRoleList"]: space = space["space"] - url = "{}/spaces/{}".format(self.root, space["id"]) + url = f"{self.root}/spaces/{space['id']}" space["_extractor"] = VscoSpaceExtractor yield Message.Queue, url, space @@ -278,7 +278,7 @@ class VscoAvatarExtractor(VscoExtractor): example = "https://vsco.co/USER/avatar" def images(self): - url = "{}/{}/gallery".format(self.root, self.user) + url = f"{self.root}/{self.user}/gallery" page = self.request(url).text piid = text.extr(page, '"profileImageId":"', '"') @@ -306,7 +306,7 @@ class VscoImageExtractor(VscoExtractor): example = "https://vsco.co/USER/media/0123456789abcdef" def images(self): - url = "{}/{}/media/{}".format(self.root, self.user, self.groups[1]) + url = f"{self.root}/{self.user}/media/{self.groups[1]}" data = self._extract_preload_state(url) media = data["medias"]["byId"].popitem()[1]["media"] return (self._transform_media(media),) @@ -319,7 +319,7 @@ class VscoVideoExtractor(VscoExtractor): example = "https://vsco.co/USER/video/012345678-9abc-def0" def images(self): - url = "{}/{}/video/{}".format(self.root, self.user, self.groups[1]) + url = f"{self.root}/{self.user}/video/{self.groups[1]}" data = self._extract_preload_state(url) media = data["medias"]["byId"].popitem()[1]["media"] diff --git a/gallery_dl/extractor/wallhaven.py b/gallery_dl/extractor/wallhaven.py index 5272b53e..2871043f 100644 --- a/gallery_dl/extractor/wallhaven.py +++ b/gallery_dl/extractor/wallhaven.py @@ -93,7 +93,7 @@ class WallhavenUserExtractor(Dispatch, WallhavenExtractor): example = "https://wallhaven.cc/user/USER" def items(self): - base = "{}/user/{}/".format(self.root, self.groups[0]) + base = f"{self.root}/user/{self.groups[0]}/" return self._dispatch_extractors(( (WallhavenUploadsExtractor , base + "uploads"), (WallhavenCollectionsExtractor, base + "favorites"), @@ -111,10 +111,10 @@ class WallhavenCollectionsExtractor(WallhavenExtractor): self.username = match[1] def items(self): + base = f"{self.root}/user/{self.username}/favorites/" for collection in self.api.collections(self.username): collection["_extractor"] = WallhavenCollectionExtractor - url = "https://wallhaven.cc/user/{}/favorites/{}".format( - self.username, collection["id"]) + url = f"{base}{collection['id']}" yield Message.Queue, url, collection @@ -175,7 +175,7 @@ class WallhavenAPI(): return self._call(endpoint)["data"] def collection(self, username, collection_id): - endpoint = "/v1/collections/{}/{}".format(username, collection_id) + endpoint = f"/v1/collections/{username}/{collection_id}" return self._pagination(endpoint) def collections(self, username): diff --git a/gallery_dl/extractor/warosu.py b/gallery_dl/extractor/warosu.py index 677f8994..a80d4c41 100644 --- a/gallery_dl/extractor/warosu.py +++ b/gallery_dl/extractor/warosu.py @@ -28,7 +28,7 @@ class WarosuThreadExtractor(Extractor): self.board, self.thread = match.groups() def items(self): - url = "{}/{}/thread/{}".format(self.root, self.board, self.thread) + url = f"{self.root}/{self.board}/thread/{self.thread}" page = self.request(url).text data = self.metadata(page) posts = self.posts(page) diff --git a/gallery_dl/extractor/weasyl.py b/gallery_dl/extractor/weasyl.py index 0a2a835f..7bc7be7f 100644 --- a/gallery_dl/extractor/weasyl.py +++ b/gallery_dl/extractor/weasyl.py @@ -35,11 +35,11 @@ class WeasylExtractor(Extractor): def request_submission(self, submitid): return self.request( - "{}/api/submissions/{}/view".format(self.root, submitid)).json() + f"{self.root}/api/submissions/{submitid}/view").json() def retrieve_journal(self, journalid): data = self.request( - "{}/api/journals/{}/view".format(self.root, journalid)).json() + f"{self.root}/api/journals/{journalid}/view").json() data["extension"] = "html" data["html"] = "text:" + data["content"] data["date"] = text.parse_datetime(data["posted_at"]) @@ -47,7 +47,7 @@ class WeasylExtractor(Extractor): def submissions(self, owner_login, folderid=None): metadata = self.config("metadata") - url = "{}/api/users/{}/gallery".format(self.root, owner_login) + url = f"{self.root}/api/users/{owner_login}/gallery" params = { "nextid" : None, "folderid": folderid, @@ -150,7 +150,7 @@ class WeasylJournalsExtractor(WeasylExtractor): def items(self): yield Message.Directory, {"owner_login": self.owner_login} - url = "{}/journals/{}".format(self.root, self.owner_login) + url = f"{self.root}/journals/{self.owner_login}" page = self.request(url).text for journalid in text.extract_iter(page, 'href="/journal/', '/'): data = self.retrieve_journal(journalid) diff --git a/gallery_dl/extractor/webmshare.py b/gallery_dl/extractor/webmshare.py index 5ec6fc13..cc41b039 100644 --- a/gallery_dl/extractor/webmshare.py +++ b/gallery_dl/extractor/webmshare.py @@ -28,7 +28,7 @@ class WebmshareVideoExtractor(Extractor): self.video_id = match[1] def items(self): - url = "{}/{}".format(self.root, self.video_id) + url = f"{self.root}/{self.video_id}" extr = text.extract_from(self.request(url).text) data = { diff --git a/gallery_dl/extractor/weebcentral.py b/gallery_dl/extractor/weebcentral.py index b1364799..03cbf293 100644 --- a/gallery_dl/extractor/weebcentral.py +++ b/gallery_dl/extractor/weebcentral.py @@ -22,7 +22,7 @@ class WeebcentralBase(): @memcache(keyarg=1) def _extract_manga_data(self, manga_id): - url = "{}/series/{}".format(self.root, manga_id) + url = f"{self.root}/series/{manga_id}" page = self.request(url).text extr = text.extract_from(page) @@ -100,7 +100,7 @@ class WeebcentralMangaExtractor(WeebcentralBase, MangaExtractor): def chapters(self, _): manga_id = self.groups[0] - referer = "{}/series/{}".format(self.root, manga_id) + referer = f"{self.root}/series/{manga_id}" url = referer + "/full-chapter-list" headers = { "Accept" : "*/*", diff --git a/gallery_dl/extractor/weibo.py b/gallery_dl/extractor/weibo.py index c121865c..b878025a 100644 --- a/gallery_dl/extractor/weibo.py +++ b/gallery_dl/extractor/weibo.py @@ -151,17 +151,16 @@ class WeiboExtractor(Extractor): return media["play_info"].copy() def _status_by_id(self, status_id): - url = "{}/ajax/statuses/show?id={}".format(self.root, status_id) + url = f"{self.root}/ajax/statuses/show?id={status_id}" return self.request(url).json() def _user_id(self): if len(self.user) >= 10 and self.user.isdecimal(): return self.user[-10:] else: - url = "{}/ajax/profile/info?{}={}".format( - self.root, - "screen_name" if self._prefix == "n" else "custom", - self.user) + url = (f"{self.root}/ajax/profile/info?" + f"{'screen_name' if self._prefix == 'n' else 'custom'}=" + f"{self.user}") return self.request(url).json()["data"]["user"]["idstr"] def _pagination(self, endpoint, params): @@ -169,7 +168,7 @@ class WeiboExtractor(Extractor): headers = { "X-Requested-With": "XMLHttpRequest", "X-XSRF-TOKEN": None, - "Referer": "{}/u/{}".format(self.root, params["uid"]), + "Referer": f"{self.root}/u/{params['uid']}", } while True: @@ -235,7 +234,7 @@ class WeiboExtractor(Extractor): "a" : "incarnate", "t" : data["tid"], "w" : "3" if data.get("new_tid") else "2", - "c" : "{:>03}".format(data.get("confidence") or 100), + "c" : f"{data.get('confidence') or 100:>03}", "gc" : "", "cb" : "cross_domain", "from" : "weibo", @@ -257,7 +256,7 @@ class WeiboUserExtractor(WeiboExtractor): # pass def items(self): - base = "{}/u/{}?tabtype=".format(self.root, self._user_id()) + base = f"{self.root}/u/{self._user_id()}?tabtype=" return Dispatch._dispatch_extractors(self, ( (WeiboHomeExtractor , base + "home"), (WeiboFeedExtractor , base + "feed"), diff --git a/gallery_dl/extractor/wikiart.py b/gallery_dl/extractor/wikiart.py index 6a6d98a8..b45d551d 100644 --- a/gallery_dl/extractor/wikiart.py +++ b/gallery_dl/extractor/wikiart.py @@ -77,13 +77,12 @@ class WikiartArtistExtractor(WikiartExtractor): self.artist = None def metadata(self): - url = "{}/{}/{}?json=2".format(self.root, self.lang, self.artist_name) + url = f"{self.root}/{self.lang}/{self.artist_name}?json=2" self.artist = self.request(url).json() return {"artist": self.artist} def paintings(self): - url = "{}/{}/{}/mode/all-paintings".format( - self.root, self.lang, self.artist_name) + url = f"{self.root}/{self.lang}/{self.artist_name}/mode/all-paintings" return self._pagination(url) @@ -101,10 +100,8 @@ class WikiartImageExtractor(WikiartArtistExtractor): title, sep, year = self.title.rpartition("-") if not sep or not year.isdecimal(): title = self.title - url = "{}/{}/Search/{} {}".format( - self.root, self.lang, - self.artist.get("artistName") or self.artist_name, title, - ) + url = (f"{self.root}/{self.lang}/Search/" + f"{self.artist.get('artistName') or self.artist_name} {title}") return self._pagination(url, stop=True) @@ -124,8 +121,7 @@ class WikiartArtworksExtractor(WikiartExtractor): return {"group": self.group, "type": self.type} def paintings(self): - url = "{}/{}/paintings-by-{}/{}".format( - self.root, self.lang, self.group, self.type) + url = f"{self.root}/{self.lang}/paintings-by-{self.group}/{self.type}" return self._pagination(url) @@ -141,8 +137,7 @@ class WikiartArtistsExtractor(WikiartExtractor): self.type = match[3] def items(self): - url = "{}/{}/App/Search/Artists-by-{}".format( - self.root, self.lang, self.group) + url = f"{self.root}/{self.lang}/App/Search/Artists-by-{self.group}" params = {"json": "3", "searchterm": self.type} for artist in self._pagination(url, params, "Artists"): diff --git a/gallery_dl/extractor/wikimedia.py b/gallery_dl/extractor/wikimedia.py index c95feb51..a6b3d4a0 100644 --- a/gallery_dl/extractor/wikimedia.py +++ b/gallery_dl/extractor/wikimedia.py @@ -27,8 +27,9 @@ class WikimediaExtractor(BaseExtractor): if self.category == "wikimedia": self.category = self.root.split(".")[-2] elif self.category in ("fandom", "wikigg"): - self.category = "{}-{}".format( - self.category, self.root.partition(".")[0].rpartition("/")[2]) + self.category = ( + f"{self.category}-" + f"{self.root.partition('.')[0].rpartition('/')[2]}") self.per_page = self.config("limit", 50) diff --git a/gallery_dl/extractor/xfolio.py b/gallery_dl/extractor/xfolio.py index a1a5be3c..21d57ec3 100644 --- a/gallery_dl/extractor/xfolio.py +++ b/gallery_dl/extractor/xfolio.py @@ -53,7 +53,7 @@ class XfolioWorkExtractor(XfolioExtractor): def items(self): creator, work_id = self.groups - url = "{}/portfolio/{}/works/{}".format(self.root, creator, work_id) + url = f"{self.root}/portfolio/{creator}/works/{work_id}" html = self.request(url).text work = self._extract_data(html) @@ -113,7 +113,7 @@ class XfolioUserExtractor(XfolioExtractor): example = "https://xfolio.jp/portfolio/USER" def works(self): - url = "{}/portfolio/{}/works".format(self.root, self.groups[0]) + url = f"{self.root}/portfolio/{self.groups[0]}/works" while True: html = self.request(url).text @@ -136,7 +136,7 @@ class XfolioSeriesExtractor(XfolioExtractor): def works(self): creator, series_id = self.groups - url = "{}/portfolio/{}/series/{}".format(self.root, creator, series_id) + url = f"{self.root}/portfolio/{creator}/series/{series_id}" html = self.request(url).text return [ diff --git a/gallery_dl/extractor/xhamster.py b/gallery_dl/extractor/xhamster.py index 1c08854d..6c971754 100644 --- a/gallery_dl/extractor/xhamster.py +++ b/gallery_dl/extractor/xhamster.py @@ -106,7 +106,7 @@ class XhamsterUserExtractor(XhamsterExtractor): example = "https://xhamster.com/users/USER/photos" def items(self): - url = "{}/users/{}/photos".format(self.root, self.groups[1]) + url = f"{self.root}/users/{self.groups[1]}/photos" data = {"_extractor": XhamsterGalleryExtractor} while url: diff --git a/gallery_dl/extractor/xvideos.py b/gallery_dl/extractor/xvideos.py index e275beec..6c016ecf 100644 --- a/gallery_dl/extractor/xvideos.py +++ b/gallery_dl/extractor/xvideos.py @@ -33,8 +33,7 @@ class XvideosGalleryExtractor(XvideosBase, GalleryExtractor): def __init__(self, match): self.user, self.gallery_id = match.groups() - url = "{}/profiles/{}/photos/{}".format( - self.root, self.user, self.gallery_id) + url = f"{self.root}/profiles/{self.user}/photos/{self.gallery_id}" GalleryExtractor.__init__(self, match, url) def metadata(self, page): @@ -95,7 +94,7 @@ class XvideosUserExtractor(XvideosBase, Extractor): self.user = match[1] def items(self): - url = "{}/profiles/{}".format(self.root, self.user) + url = f"{self.root}/profiles/{self.user}" page = self.request(url, notfound=self.subcategory).text data = util.json_loads(text.extr( page, "xv.conf=", ";"))["data"] @@ -116,7 +115,7 @@ class XvideosUserExtractor(XvideosBase, Extractor): ] galleries.sort(key=lambda x: x["id"]) + base = f"{self.root}/profiles/{self.user}/photos/" for gallery in galleries: - url = "https://www.xvideos.com/profiles/{}/photos/{}".format( - self.user, gallery["id"]) + url = f"{base}{gallery['id']}" yield Message.Queue, url, gallery diff --git a/gallery_dl/extractor/yiffverse.py b/gallery_dl/extractor/yiffverse.py index 2b143419..37c1efac 100644 --- a/gallery_dl/extractor/yiffverse.py +++ b/gallery_dl/extractor/yiffverse.py @@ -46,8 +46,8 @@ class YiffverseExtractor(BooruExtractor): post_id = post["id"] root = self.root_cdn if files[fmt][0] else self.root - post["file_url"] = url = "{}/posts/{}/{}/{}.{}".format( - root, post_id // 1000, post_id, post_id, extension) + post["file_url"] = url = \ + f"{root}/posts/{post_id // 1000}/{post_id}/{post_id}.{extension}" post["format_id"] = fmt post["format"] = extension.partition(".")[0] @@ -73,11 +73,11 @@ class YiffverseExtractor(BooruExtractor): post["tags_" + types[type]] = values def _fetch_post(self, post_id): - url = "{}/api/v2/post/{}".format(self.root, post_id) + url = f"{self.root}/api/v2/post/{post_id}" return self.request(url).json() def _pagination(self, endpoint, params=None): - url = "{}/api{}".format(self.root, endpoint) + url = f"{self.root}/api{endpoint}" if params is None: params = {} diff --git a/gallery_dl/extractor/zerochan.py b/gallery_dl/extractor/zerochan.py index ba1ac858..0b768f01 100644 --- a/gallery_dl/extractor/zerochan.py +++ b/gallery_dl/extractor/zerochan.py @@ -62,7 +62,7 @@ class ZerochanExtractor(BooruExtractor): return response.cookies def _parse_entry_html(self, entry_id): - url = "{}/{}".format(self.root, entry_id) + url = f"{self.root}/{entry_id}" page = self.request(url).text try: @@ -101,7 +101,7 @@ class ZerochanExtractor(BooruExtractor): return data def _parse_entry_api(self, entry_id): - url = "{}/{}?json".format(self.root, entry_id) + url = f"{self.root}/{entry_id}?json" txt = self.request(url).text try: item = util.json_loads(txt) diff --git a/gallery_dl/extractor/zzup.py b/gallery_dl/extractor/zzup.py index 9508c571..73939316 100644 --- a/gallery_dl/extractor/zzup.py +++ b/gallery_dl/extractor/zzup.py @@ -25,7 +25,7 @@ class ZzupGalleryExtractor(GalleryExtractor): if subdomain == "up.": self.root = "https://up.zzup.com" self.images = self.images_v2 - url = "{}{}/index.html".format(self.root, path) + url = f"{self.root}{path}/index.html" GalleryExtractor.__init__(self, match, url) def metadata(self, page): @@ -41,17 +41,18 @@ class ZzupGalleryExtractor(GalleryExtractor): page = self.request(self.root + path).text url = self.root + text.extr(page, '\n05}" + p2[4:] - return [(ufmt.format(num), None) for num in range(1, count + 1)] + p2 = p2[4:] + return [(f"{p1}/image{i:>05}{p2}", None) for i in range(1, count + 1)] def images_v2(self, page): + base = f"{self.root}/showimage/" results = [] while True: for path in text.extract_iter( page, ' class="picbox">{extr.category}" cfgpath.append((cat, sub)) cfgpath.append((category + ">*", sub)) cfgpath.append((extr.category, sub)) @@ -779,7 +779,7 @@ class KeywordJob(Job): if markers is None: markers = {markerid} elif markerid in markers: - write("{}\n \n".format(prefix[:-2])) + write(f"{prefix[:-2]}\n \n") return # ignore circular reference else: markers.add(markerid) @@ -805,7 +805,7 @@ class KeywordJob(Job): else: # string or number - write("{}\n {}\n".format(key, value)) + write(f"{key}\n {value}\n") markers.remove(markerid) @@ -864,20 +864,18 @@ class InfoJob(Job): return 0 def _print_multi(self, title, *values): - stdout_write("{}\n {}\n\n".format( - title, " / ".join(map(util.json_dumps, values)))) + stdout_write( + f"{title}\n {' / '.join(map(util.json_dumps, values))}\n\n") def _print_config(self, title, optname, value): optval = self.extractor.config(optname, util.SENTINEL) if optval is not util.SENTINEL: stdout_write( - "{} (custom):\n {}\n{} (default):\n {}\n\n".format( - title, util.json_dumps(optval), - title, util.json_dumps(value))) + f"{title} (custom):\n {util.json_dumps(optval)}\n" + f"{title} (default):\n {util.json_dumps(value)}\n\n") elif value: stdout_write( - "{} (default):\n {}\n\n".format( - title, util.json_dumps(value))) + f"{title} (default):\n {util.json_dumps(value)}\n\n") class DataJob(Job): diff --git a/gallery_dl/option.py b/gallery_dl/option.py index ed52343d..7aa70d2f 100644 --- a/gallery_dl/option.py +++ b/gallery_dl/option.py @@ -40,8 +40,8 @@ class DeprecatedConfigConstAction(argparse.Action): """Set argparse const values as config values + deprecation warning""" def __call__(self, parser, namespace, values, option_string=None): sys.stderr.write( - "warning: {} is deprecated. Use {} instead.\n".format( - "/".join(self.option_strings), self.choices)) + f"Warning: {'/'.join(self.option_strings)} is deprecated. " + f"Use {self.choices} instead.\n") namespace.options.append(((), self.dest, self.const)) @@ -144,7 +144,7 @@ class UgoiraAction(argparse.Action): } namespace.options.append(((), "ugoira", "original")) else: - parser.error("Unsupported Ugoira format '{}'".format(value)) + parser.error(f"Unsupported Ugoira format '{value}'") pp["name"] = "ugoira" pp["whitelist"] = ("pixiv", "danbooru") diff --git a/gallery_dl/output.py b/gallery_dl/output.py index 446ea792..a31f9d30 100644 --- a/gallery_dl/output.py +++ b/gallery_dl/output.py @@ -416,10 +416,10 @@ class TerminalOutput(): bdl = util.format_value(bytes_downloaded) bps = util.format_value(bytes_per_second) if bytes_total is None: - stderr_write("\r{:>7}B {:>7}B/s ".format(bdl, bps)) + stderr_write(f"\r{bdl:>7}B {bps:>7}B/s ") else: - stderr_write("\r{:>3}% {:>7}B {:>7}B/s ".format( - bytes_downloaded * 100 // bytes_total, bdl, bps)) + stderr_write(f"\r{bytes_downloaded * 100 // bytes_total:>3}% " + f"{bdl:>7}B {bps:>7}B/s ") class ColorOutput(TerminalOutput): @@ -431,10 +431,8 @@ class ColorOutput(TerminalOutput): if colors is None: colors = COLORS_DEFAULT - self.color_skip = "\033[{}m".format( - colors.get("skip", "2")) - self.color_success = "\r\033[{}m".format( - colors.get("success", "1;32")) + self.color_skip = f"\x1b[{colors.get('skip', '2')}m" + self.color_success = f"\r\x1b[{colors.get('success', '1;32')}m" def start(self, path): stdout_write_flush(self.shorten(path)) diff --git a/gallery_dl/postprocessor/ugoira.py b/gallery_dl/postprocessor/ugoira.py index eed3ce75..edf06235 100644 --- a/gallery_dl/postprocessor/ugoira.py +++ b/gallery_dl/postprocessor/ugoira.py @@ -170,8 +170,8 @@ class UgoiraPP(PostProcessor): for frame in self._files: # update frame filename extension - frame["file"] = name = "{}.{}".format( - frame["file"].partition(".")[0], frame["ext"]) + frame["file"] = name = \ + f"{frame['file'].partition('.')[0]}.{frame['ext']}" if tempdir: # move frame into tempdir @@ -332,7 +332,7 @@ class UgoiraPP(PostProcessor): last_copy = last.copy() frames.append(last_copy) name, _, ext = last_copy["file"].rpartition(".") - last_copy["file"] = "{:>06}.{}".format(int(name)+1, ext) + last_copy["file"] = f"{int(name) + 1:>06}.{ext}" shutil.copyfile(tempdir + last["file"], tempdir + last_copy["file"]) @@ -347,10 +347,8 @@ class UgoiraPP(PostProcessor): "-f", "image2", "-ts_from_file", "2", "-pattern_type", "sequence", - "-i", "{}%06d.{}".format( - tempdir.replace("%", "%%"), - frame["file"].rpartition(".")[2] - ), + "-i", (f"{tempdir.replace('%', '%%')}%06d." + f"{frame['file'].rpartition('.')[2]}"), ] def _process_mkvmerge(self, pathfmt, tempdir): @@ -361,10 +359,8 @@ class UgoiraPP(PostProcessor): self.ffmpeg, "-f", "image2", "-pattern_type", "sequence", - "-i", "{}/%06d.{}".format( - tempdir.replace("%", "%%"), - self._frames[0]["file"].rpartition(".")[2] - ), + "-i", (f"{tempdir.replace('%', '%%')}/%06d." + f"{self._frames[0]['file'].rpartition('.')[2]}"), ] def _finalize_mkvmerge(self, pathfmt, tempdir): @@ -385,10 +381,9 @@ class UgoiraPP(PostProcessor): append = content.append for frame in self._frames: - append("file '{}'\nduration {}".format( - frame["file"], frame["delay"] / 1000)) + append(f"file '{frame['file']}'\nduration {frame['delay'] / 1000}") if self.repeat: - append("file '{}'".format(frame["file"])) + append(f"file '{frame['file']}'") append("") ffconcat = tempdir + "/ffconcat.txt" @@ -414,12 +409,12 @@ class UgoiraPP(PostProcessor): def calculate_framerate(self, frames): if self._delay_is_uniform(frames): - return ("1000/{}".format(frames[0]["delay"]), None) + return (f"1000/{frames[0]['delay']}", None) if not self.uniform: gcd = self._delay_gcd(frames) if gcd >= 10: - return (None, "1000/{}".format(gcd)) + return (None, f"1000/{gcd}") return (None, None) diff --git a/gallery_dl/transaction_id.py b/gallery_dl/transaction_id.py index 89e3d5b5..915b7b3f 100644 --- a/gallery_dl/transaction_id.py +++ b/gallery_dl/transaction_id.py @@ -139,8 +139,7 @@ class ClientTransaction(): (now >> 24) & 0xFF, ) - payload = "{}!{}!{}{}{}".format( - method, path, now, keyword, self.animation_key) + payload = f"{method}!{path}!{now}{keyword}{self.animation_key}" bytes_hash = hashlib.sha256(payload.encode()).digest()[:16] num = (random.randrange(16) << 4) + int((nowf - nowi) * 16.0) diff --git a/gallery_dl/update.py b/gallery_dl/update.py index 4cc607fe..73da5265 100644 --- a/gallery_dl/update.py +++ b/gallery_dl/update.py @@ -97,7 +97,7 @@ class UpdateJob(DownloadJob): import atexit import subprocess - cmd = 'ping 127.0.0.1 -n 5 -w 1000 & del /F "{}"'.format(path_old) + cmd = f'ping 127.0.0.1 -n 5 -w 1000 & del /F "{path_old}"' atexit.register( util.Popen, cmd, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, @@ -192,8 +192,7 @@ class UpdateExtractor(Extractor): raise exception.StopExtraction("Invalid channel '%s'", repo) path_tag = tag if tag == "latest" else "tags/" + tag - url = "{}/repos/{}/releases/{}".format( - self.root_api, path_repo, path_tag) + url = f"{self.root_api}/repos/{path_repo}/releases/{path_tag}" headers = { "Accept": "application/vnd.github+json", "User-Agent": util.USERAGENT, @@ -210,8 +209,8 @@ class UpdateExtractor(Extractor): else: binary_name = BINARIES[repo][binary] - url = "{}/{}/releases/download/{}/{}".format( - self.root, path_repo, data["tag_name"], binary_name) + url = (f"{self.root}/{path_repo}/releases/download" + f"/{data['tag_name']}/{binary_name}") yield Message.Directory, data yield Message.Url, url, data diff --git a/gallery_dl/ytdl.py b/gallery_dl/ytdl.py index 8cd6501a..fa948f2c 100644 --- a/gallery_dl/ytdl.py +++ b/gallery_dl/ytdl.py @@ -146,7 +146,7 @@ def parse_command_line(module, argv): if name not in compat_opts: return False compat_opts.discard(name) - compat_opts.update(["*%s" % name]) + compat_opts.update([f"*{name}"]) return True def set_default_compat( @@ -211,7 +211,7 @@ def parse_command_line(module, argv): if "pre_process" not in parse_metadata: parse_metadata["pre_process"] = [] parse_metadata["pre_process"].append( - "title:%s" % opts.metafromtitle) + f"title:{opts.metafromtitle}") opts.parse_metadata = { k: list(itertools.chain.from_iterable(map( metadataparser_actions, v))) @@ -221,7 +221,7 @@ def parse_command_line(module, argv): if parse_metadata is None: parse_metadata = [] if opts.metafromtitle is not None: - parse_metadata.append("title:%s" % opts.metafromtitle) + parse_metadata.append(f"title:{opts.metafromtitle}") opts.parse_metadata = list(itertools.chain.from_iterable(map( metadataparser_actions, parse_metadata)))