replace calls to print() with stdout_write() (#2529)
This commit is contained in:
@@ -12,7 +12,7 @@ import logging
|
|||||||
from . import version, config, option, output, extractor, job, util, exception
|
from . import version, config, option, output, extractor, job, util, exception
|
||||||
|
|
||||||
__author__ = "Mike Fährmann"
|
__author__ = "Mike Fährmann"
|
||||||
__copyright__ = "Copyright 2014-2021 Mike Fährmann"
|
__copyright__ = "Copyright 2014-2022 Mike Fährmann"
|
||||||
__license__ = "GPLv2"
|
__license__ = "GPLv2"
|
||||||
__maintainer__ = "Mike Fährmann"
|
__maintainer__ = "Mike Fährmann"
|
||||||
__email__ = "mike_faehrmann@web.de"
|
__email__ = "mike_faehrmann@web.de"
|
||||||
@@ -22,10 +22,13 @@ __version__ = version.__version__
|
|||||||
def progress(urls, pformat):
|
def progress(urls, pformat):
|
||||||
"""Wrapper around urls to output a simple progress indicator"""
|
"""Wrapper around urls to output a simple progress indicator"""
|
||||||
if pformat is True:
|
if pformat is True:
|
||||||
pformat = "[{current}/{total}] {url}"
|
pformat = "[{current}/{total}] {url}\n"
|
||||||
|
else:
|
||||||
|
pformat += "\n"
|
||||||
|
|
||||||
pinfo = {"total": len(urls)}
|
pinfo = {"total": len(urls)}
|
||||||
for pinfo["current"], pinfo["url"] in enumerate(urls, 1):
|
for pinfo["current"], pinfo["url"] in enumerate(urls, 1):
|
||||||
print(pformat.format_map(pinfo), file=sys.stderr)
|
output.stderr_write(pformat.format_map(pinfo))
|
||||||
yield pinfo["url"]
|
yield pinfo["url"]
|
||||||
|
|
||||||
|
|
||||||
@@ -196,20 +199,23 @@ def main():
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
if args.list_modules:
|
if args.list_modules:
|
||||||
for module_name in extractor.modules:
|
extractor.modules.append("")
|
||||||
print(module_name)
|
sys.stdout.write("\n".join(extractor.modules))
|
||||||
|
|
||||||
elif args.list_extractors:
|
elif args.list_extractors:
|
||||||
|
write = sys.stdout.write
|
||||||
|
fmt = "{}\n{}\nCategory: {} - Subcategory: {}{}\n\n".format
|
||||||
|
|
||||||
for extr in extractor.extractors():
|
for extr in extractor.extractors():
|
||||||
if not extr.__doc__:
|
if not extr.__doc__:
|
||||||
continue
|
continue
|
||||||
print(extr.__name__)
|
|
||||||
print(extr.__doc__)
|
|
||||||
print("Category:", extr.category,
|
|
||||||
"- Subcategory:", extr.subcategory)
|
|
||||||
test = next(extr._get_tests(), None)
|
test = next(extr._get_tests(), None)
|
||||||
if test:
|
write(fmt(
|
||||||
print("Example :", test[0])
|
extr.__name__, extr.__doc__,
|
||||||
print()
|
extr.category, extr.subcategory,
|
||||||
|
"\nExample : " + test[0] if test else "",
|
||||||
|
))
|
||||||
|
|
||||||
elif args.clear_cache:
|
elif args.clear_cache:
|
||||||
from . import cache
|
from . import cache
|
||||||
log = logging.getLogger("cache")
|
log = logging.getLogger("cache")
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
from .common import Extractor, Message
|
from .common import Extractor, Message
|
||||||
from . import deviantart, flickr, mastodon, pixiv, reddit, smugmug, tumblr
|
from . import deviantart, flickr, mastodon, pixiv, reddit, smugmug, tumblr
|
||||||
from .. import text, oauth, util, config, exception
|
from .. import text, oauth, util, config, exception
|
||||||
|
from ..output import stdout_write
|
||||||
from ..cache import cache
|
from ..cache import cache
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import hashlib
|
import hashlib
|
||||||
@@ -37,7 +38,7 @@ class OAuthBase(Extractor):
|
|||||||
def recv(self):
|
def recv(self):
|
||||||
"""Open local HTTP server and recv callback parameters"""
|
"""Open local HTTP server and recv callback parameters"""
|
||||||
import socket
|
import socket
|
||||||
print("Waiting for response. (Cancel with Ctrl+c)")
|
stdout_write("Waiting for response. (Cancel with Ctrl+c)\n")
|
||||||
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
server.bind(("localhost", self.config("port", 6414)))
|
server.bind(("localhost", self.config("port", 6414)))
|
||||||
@@ -60,7 +61,7 @@ class OAuthBase(Extractor):
|
|||||||
|
|
||||||
def send(self, msg):
|
def send(self, msg):
|
||||||
"""Send 'msg' to the socket opened in 'recv()'"""
|
"""Send 'msg' to the socket opened in 'recv()'"""
|
||||||
print(msg)
|
stdout_write(msg)
|
||||||
self.client.send(b"HTTP/1.1 200 OK\r\n\r\n" + msg.encode())
|
self.client.send(b"HTTP/1.1 200 OK\r\n\r\n" + msg.encode())
|
||||||
self.client.close()
|
self.client.close()
|
||||||
|
|
||||||
@@ -69,12 +70,13 @@ class OAuthBase(Extractor):
|
|||||||
import webbrowser
|
import webbrowser
|
||||||
url += "?" + urllib.parse.urlencode(params)
|
url += "?" + urllib.parse.urlencode(params)
|
||||||
if not self.config("browser", True) or not webbrowser.open(url):
|
if not self.config("browser", True) or not webbrowser.open(url):
|
||||||
print("Please open this URL in your browser:")
|
stdout_write(
|
||||||
print(url, end="\n\n", flush=True)
|
"Please open this URL in your browser:\n\n" + url + "\n\n")
|
||||||
return (recv or self.recv)()
|
return (recv or self.recv)()
|
||||||
|
|
||||||
def error(self, msg):
|
def error(self, msg):
|
||||||
return self.send("Remote server reported an error:\n\n" + str(msg))
|
return self.send(
|
||||||
|
"Remote server reported an error:\n\n{}\n".format(msg))
|
||||||
|
|
||||||
def _oauth1_authorization_flow(
|
def _oauth1_authorization_flow(
|
||||||
self, request_token_url, authorize_url, access_token_url):
|
self, request_token_url, authorize_url, access_token_url):
|
||||||
@@ -133,7 +135,7 @@ class OAuthBase(Extractor):
|
|||||||
|
|
||||||
# check authorization response
|
# check authorization response
|
||||||
if state != params.get("state"):
|
if state != params.get("state"):
|
||||||
self.send("'state' mismatch: expected {}, got {}.".format(
|
self.send("'state' mismatch: expected {}, got {}.\n".format(
|
||||||
state, params.get("state")
|
state, params.get("state")
|
||||||
))
|
))
|
||||||
return
|
return
|
||||||
@@ -188,7 +190,7 @@ class OAuthBase(Extractor):
|
|||||||
|
|
||||||
opt = self.oauth_config(names[0])
|
opt = self.oauth_config(names[0])
|
||||||
if self.cache and (opt is None or opt == "cache"):
|
if self.cache and (opt is None or opt == "cache"):
|
||||||
msg += _vh + " been cached and will automatically be used."
|
msg += _vh + " been cached and will automatically be used.\n"
|
||||||
else:
|
else:
|
||||||
msg += "Put " + _va + " into your configuration file as \n"
|
msg += "Put " + _va + " into your configuration file as \n"
|
||||||
msg += " and\n".join(
|
msg += " and\n".join(
|
||||||
@@ -200,7 +202,7 @@ class OAuthBase(Extractor):
|
|||||||
"\nor set\n'extractor.{}.{}' to \"cache\""
|
"\nor set\n'extractor.{}.{}' to \"cache\""
|
||||||
.format(self.subcategory, names[0])
|
.format(self.subcategory, names[0])
|
||||||
)
|
)
|
||||||
msg += "\nto use {}.".format(_it)
|
msg += "\nto use {}.\n".format(_it)
|
||||||
|
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
@@ -398,9 +400,9 @@ class OAuthPixiv(OAuthBase):
|
|||||||
data = self.session.post(url, headers=headers, data=data).json()
|
data = self.session.post(url, headers=headers, data=data).json()
|
||||||
|
|
||||||
if "error" in data:
|
if "error" in data:
|
||||||
print(data)
|
stdout_write("\n{}\n".format(data))
|
||||||
if data["error"] in ("invalid_request", "invalid_grant"):
|
if data["error"] in ("invalid_request", "invalid_grant"):
|
||||||
print("'code' expired, try again")
|
stdout_write("'code' expired, try again\n\n")
|
||||||
return
|
return
|
||||||
|
|
||||||
token = data["refresh_token"]
|
token = data["refresh_token"]
|
||||||
@@ -409,10 +411,10 @@ class OAuthPixiv(OAuthBase):
|
|||||||
pixiv._refresh_token_cache.update(username, token)
|
pixiv._refresh_token_cache.update(username, token)
|
||||||
self.log.info("Writing 'refresh-token' to cache")
|
self.log.info("Writing 'refresh-token' to cache")
|
||||||
|
|
||||||
print(self._generate_message(("refresh-token",), (token,)))
|
stdout_write(self._generate_message(("refresh-token",), (token,)))
|
||||||
|
|
||||||
def _input(self):
|
def _input(self):
|
||||||
print("""
|
stdout_write("""\
|
||||||
1) Open your browser's Developer Tools (F12) and switch to the Network tab
|
1) Open your browser's Developer Tools (F12) and switch to the Network tab
|
||||||
2) Login
|
2) Login
|
||||||
3) Select the last network monitor entry ('callback?state=...')
|
3) Select the last network monitor entry ('callback?state=...')
|
||||||
@@ -421,6 +423,7 @@ class OAuthPixiv(OAuthBase):
|
|||||||
- This 'code' will expire 30 seconds after logging in.
|
- This 'code' will expire 30 seconds after logging in.
|
||||||
- Copy-pasting more than just the 'code' value will work as well,
|
- Copy-pasting more than just the 'code' value will work as well,
|
||||||
like the entire URL or several query parameters.
|
like the entire URL or several query parameters.
|
||||||
|
|
||||||
""")
|
""")
|
||||||
code = input("code: ")
|
code = input("code: ")
|
||||||
return code.rpartition("=")[2].strip()
|
return code.rpartition("=")[2].strip()
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import collections
|
|||||||
from . import extractor, downloader, postprocessor
|
from . import extractor, downloader, postprocessor
|
||||||
from . import config, text, util, path, formatter, output, exception
|
from . import config, text, util, path, formatter, output, exception
|
||||||
from .extractor.message import Message
|
from .extractor.message import Message
|
||||||
|
from .output import stdout_write
|
||||||
|
|
||||||
|
|
||||||
class Job():
|
class Job():
|
||||||
@@ -537,14 +538,14 @@ class KeywordJob(Job):
|
|||||||
self.private = config.get(("output",), "private")
|
self.private = config.get(("output",), "private")
|
||||||
|
|
||||||
def handle_url(self, url, kwdict):
|
def handle_url(self, url, kwdict):
|
||||||
print("\nKeywords for filenames and --filter:")
|
stdout_write("\nKeywords for filenames and --filter:\n"
|
||||||
print("------------------------------------")
|
"------------------------------------\n")
|
||||||
self.print_kwdict(kwdict)
|
self.print_kwdict(kwdict)
|
||||||
raise exception.StopExtraction()
|
raise exception.StopExtraction()
|
||||||
|
|
||||||
def handle_directory(self, kwdict):
|
def handle_directory(self, kwdict):
|
||||||
print("Keywords for directory names:")
|
stdout_write("Keywords for directory names:\n"
|
||||||
print("-----------------------------")
|
"-----------------------------\n")
|
||||||
self.print_kwdict(kwdict)
|
self.print_kwdict(kwdict)
|
||||||
|
|
||||||
def handle_queue(self, url, kwdict):
|
def handle_queue(self, url, kwdict):
|
||||||
@@ -565,16 +566,17 @@ class KeywordJob(Job):
|
|||||||
self.extractor.log.info(
|
self.extractor.log.info(
|
||||||
"Try 'gallery-dl -K \"%s\"' instead.", url)
|
"Try 'gallery-dl -K \"%s\"' instead.", url)
|
||||||
else:
|
else:
|
||||||
print("Keywords for --chapter-filter:")
|
stdout_write("Keywords for --chapter-filter:\n"
|
||||||
print("------------------------------")
|
"------------------------------\n")
|
||||||
self.print_kwdict(kwdict)
|
self.print_kwdict(kwdict)
|
||||||
if extr or self.extractor.categorytransfer:
|
if extr or self.extractor.categorytransfer:
|
||||||
print()
|
stdout_write("\n")
|
||||||
KeywordJob(extr or url, self).run()
|
KeywordJob(extr or url, self).run()
|
||||||
raise exception.StopExtraction()
|
raise exception.StopExtraction()
|
||||||
|
|
||||||
def print_kwdict(self, kwdict, prefix=""):
|
def print_kwdict(self, kwdict, prefix=""):
|
||||||
"""Print key-value pairs in 'kwdict' with formatting"""
|
"""Print key-value pairs in 'kwdict' with formatting"""
|
||||||
|
write = sys.stdout.write
|
||||||
suffix = "]" if prefix else ""
|
suffix = "]" if prefix else ""
|
||||||
for key, value in sorted(kwdict.items()):
|
for key, value in sorted(kwdict.items()):
|
||||||
if key[0] == "_" and not self.private:
|
if key[0] == "_" and not self.private:
|
||||||
@@ -588,13 +590,13 @@ class KeywordJob(Job):
|
|||||||
if value and isinstance(value[0], dict):
|
if value and isinstance(value[0], dict):
|
||||||
self.print_kwdict(value[0], key + "[][")
|
self.print_kwdict(value[0], key + "[][")
|
||||||
else:
|
else:
|
||||||
print(key, "[]", sep="")
|
write(key + "[]\n")
|
||||||
for val in value:
|
for val in value:
|
||||||
print(" -", val)
|
write(" - " + str(val) + "\n")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# string or number
|
# string or number
|
||||||
print(key, "\n ", value, sep="")
|
write("{}\n {}\n".format(key, value))
|
||||||
|
|
||||||
|
|
||||||
class UrlJob(Job):
|
class UrlJob(Job):
|
||||||
@@ -609,14 +611,14 @@ class UrlJob(Job):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def handle_url(url, _):
|
def handle_url(url, _):
|
||||||
print(url)
|
stdout_write(url + "\n")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def handle_url_fallback(url, kwdict):
|
def handle_url_fallback(url, kwdict):
|
||||||
print(url)
|
stdout_write(url + "\n")
|
||||||
if "_fallback" in kwdict:
|
if "_fallback" in kwdict:
|
||||||
for url in kwdict["_fallback"]:
|
for url in kwdict["_fallback"]:
|
||||||
print("|", url)
|
stdout_write("| " + url + "\n")
|
||||||
|
|
||||||
def handle_queue(self, url, kwdict):
|
def handle_queue(self, url, kwdict):
|
||||||
cls = kwdict.get("_extractor")
|
cls = kwdict.get("_extractor")
|
||||||
@@ -653,15 +655,18 @@ class InfoJob(Job):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
def _print_multi(self, title, *values):
|
def _print_multi(self, title, *values):
|
||||||
print(title, "\n ", " / ".join(json.dumps(v) for v in values), sep="")
|
stdout_write("{}\n {}\n\n".format(
|
||||||
|
title, " / ".join(json.dumps(v) for v in values)))
|
||||||
|
|
||||||
def _print_config(self, title, optname, value):
|
def _print_config(self, title, optname, value):
|
||||||
optval = self.extractor.config(optname, util.SENTINEL)
|
optval = self.extractor.config(optname, util.SENTINEL)
|
||||||
if optval is not util.SENTINEL:
|
if optval is not util.SENTINEL:
|
||||||
print(title, "(custom):\n ", json.dumps(optval))
|
stdout_write(
|
||||||
print(title, "(default):\n ", json.dumps(value))
|
"{} (custom):\n {}\n{} (default):\n {}\n\n".format(
|
||||||
|
title, json.dumps(optval), title, json.dumps(value)))
|
||||||
elif value:
|
elif value:
|
||||||
print(title, "(default):\n ", json.dumps(value))
|
stdout_write(
|
||||||
|
"{} (default):\n {}\n\n".format(title, json.dumps(value)))
|
||||||
|
|
||||||
|
|
||||||
class DataJob(Job):
|
class DataJob(Job):
|
||||||
|
|||||||
@@ -39,8 +39,9 @@ class AppendCommandAction(argparse.Action):
|
|||||||
class DeprecatedConfigConstAction(argparse.Action):
|
class DeprecatedConfigConstAction(argparse.Action):
|
||||||
"""Set argparse const values as config values + deprecation warning"""
|
"""Set argparse const values as config values + deprecation warning"""
|
||||||
def __call__(self, parser, namespace, values, option_string=None):
|
def __call__(self, parser, namespace, values, option_string=None):
|
||||||
print("warning: {} is deprecated. Use {} instead.".format(
|
sys.stderr.write(
|
||||||
"/".join(self.option_strings), self.choices), file=sys.stderr)
|
"warning: {} is deprecated. Use {} instead.\n".format(
|
||||||
|
"/".join(self.option_strings), self.choices))
|
||||||
namespace.options.append(((), self.dest, self.const))
|
namespace.options.append(((), self.dest, self.const))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -149,10 +149,13 @@ class TestInfoJob(TestJob):
|
|||||||
self.assertEqual(self._capture_stdout(extr), """\
|
self.assertEqual(self._capture_stdout(extr), """\
|
||||||
Category / Subcategory
|
Category / Subcategory
|
||||||
"test_category" / "test_subcategory"
|
"test_category" / "test_subcategory"
|
||||||
|
|
||||||
Filename format (default):
|
Filename format (default):
|
||||||
"test_{filename}.{extension}"
|
"test_{filename}.{extension}"
|
||||||
|
|
||||||
Directory format (default):
|
Directory format (default):
|
||||||
["{category}"]
|
["{category}"]
|
||||||
|
|
||||||
""")
|
""")
|
||||||
|
|
||||||
def test_custom(self):
|
def test_custom(self):
|
||||||
@@ -165,18 +168,22 @@ Directory format (default):
|
|||||||
self.assertEqual(self._capture_stdout(extr), """\
|
self.assertEqual(self._capture_stdout(extr), """\
|
||||||
Category / Subcategory
|
Category / Subcategory
|
||||||
"test_category" / "test_subcategory"
|
"test_category" / "test_subcategory"
|
||||||
|
|
||||||
Filename format (custom):
|
Filename format (custom):
|
||||||
"custom"
|
"custom"
|
||||||
Filename format (default):
|
Filename format (default):
|
||||||
"test_{filename}.{extension}"
|
"test_{filename}.{extension}"
|
||||||
|
|
||||||
Directory format (custom):
|
Directory format (custom):
|
||||||
["custom"]
|
["custom"]
|
||||||
Directory format (default):
|
Directory format (default):
|
||||||
["{category}"]
|
["{category}"]
|
||||||
|
|
||||||
Request interval (custom):
|
Request interval (custom):
|
||||||
321
|
321
|
||||||
Request interval (default):
|
Request interval (default):
|
||||||
123.456
|
123.456
|
||||||
|
|
||||||
""")
|
""")
|
||||||
|
|
||||||
def test_base_category(self):
|
def test_base_category(self):
|
||||||
@@ -186,10 +193,13 @@ Request interval (default):
|
|||||||
self.assertEqual(self._capture_stdout(extr), """\
|
self.assertEqual(self._capture_stdout(extr), """\
|
||||||
Category / Subcategory / Basecategory
|
Category / Subcategory / Basecategory
|
||||||
"test_category" / "test_subcategory" / "test_basecategory"
|
"test_category" / "test_subcategory" / "test_basecategory"
|
||||||
|
|
||||||
Filename format (default):
|
Filename format (default):
|
||||||
"test_{filename}.{extension}"
|
"test_{filename}.{extension}"
|
||||||
|
|
||||||
Directory format (default):
|
Directory format (default):
|
||||||
["{category}"]
|
["{category}"]
|
||||||
|
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user