aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Hagemeister <phihag@phihag.de>2014-04-07 22:48:13 +0200
committerPhilipp Hagemeister <phihag@phihag.de>2014-04-07 22:48:13 +0200
commitb58ddb32bae180dfad240ded5d247cab9a1f2215 (patch)
treeddce4b33f4ffb91745c8d98c792838fc8405403b
parentb9e12a814096c9225cedde8e0c7ce2a977e8a668 (diff)
downloadyoutube-dl-b58ddb32bae180dfad240ded5d247cab9a1f2215.tar.xz
[utils] Completely rewrite Windows output (Fixes #2672)
-rw-r--r--youtube_dl/YoutubeDL.py2
-rw-r--r--youtube_dl/utils.py60
2 files changed, 61 insertions, 1 deletions
diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py
index d011ddeb5..bd7497f85 100644
--- a/youtube_dl/YoutubeDL.py
+++ b/youtube_dl/YoutubeDL.py
@@ -287,7 +287,7 @@ class YoutubeDL(object):
return self.to_stdout(message, skip_eol, check_quiet=True)
def _write_string(self, s, out=None):
- write_string(s, out=out, encoding=self.get_encoding())
+ write_string(s, out=out, encoding=self.params.get('encoding'))
def to_stdout(self, message, skip_eol=False, check_quiet=False):
"""Print message to stdout if not in quiet mode."""
diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py
index 68424aeb6..b57fd7a33 100644
--- a/youtube_dl/utils.py
+++ b/youtube_dl/utils.py
@@ -910,11 +910,71 @@ def platform_name():
return res
+def _windows_write_string(s, out):
+ """ Returns True if the string was written using special methods,
+ False if it has yet to be written out."""
+ # Adapted from http://stackoverflow.com/a/3259271/35070
+
+ import ctypes
+ import ctypes.wintypes
+
+ WIN_OUTPUT_IDS = {
+ 1: -11,
+ 2: -12,
+ }
+
+ fileno = out.fileno()
+ if fileno not in WIN_OUTPUT_IDS:
+ return False
+
+ GetStdHandle = ctypes.WINFUNCTYPE(
+ ctypes.wintypes.HANDLE, ctypes.wintypes.DWORD)(
+ ("GetStdHandle", ctypes.windll.kernel32))
+ h = GetStdHandle(WIN_OUTPUT_IDS[fileno])
+
+ WriteConsoleW = ctypes.WINFUNCTYPE(
+ ctypes.wintypes.BOOL, ctypes.wintypes.HANDLE, ctypes.wintypes.LPWSTR,
+ ctypes.wintypes.DWORD, ctypes.POINTER(ctypes.wintypes.DWORD),
+ ctypes.wintypes.LPVOID)(("WriteConsoleW", ctypes.windll.kernel32))
+ written = ctypes.wintypes.DWORD(0)
+
+ GetFileType = ctypes.WINFUNCTYPE(ctypes.wintypes.DWORD, ctypes.wintypes.DWORD)(("GetFileType", ctypes.windll.kernel32))
+ FILE_TYPE_CHAR = 0x0002
+ FILE_TYPE_REMOTE = 0x8000
+ GetConsoleMode = ctypes.WINFUNCTYPE(
+ ctypes.wintypes.BOOL, ctypes.wintypes.HANDLE,
+ ctypes.POINTER(ctypes.wintypes.DWORD))(
+ ("GetConsoleMode", ctypes.windll.kernel32))
+ INVALID_HANDLE_VALUE = ctypes.wintypes.DWORD(-1).value
+
+ def not_a_console(handle):
+ if handle == INVALID_HANDLE_VALUE or handle is None:
+ return True
+ return ((GetFileType(handle) & ~FILE_TYPE_REMOTE) != FILE_TYPE_CHAR
+ or GetConsoleMode(handle, ctypes.byref(ctypes.wintypes.DWORD())) == 0)
+
+ if not_a_console(h):
+ return False
+
+ remaining = len(s)
+ while remaining > 0:
+ ret = WriteConsoleW(
+ h, s, min(len(s), 1024), ctypes.byref(written), None)
+ if ret == 0:
+ raise OSError('Failed to write string')
+ remaining -= written.value
+ return True
+
+
def write_string(s, out=None, encoding=None):
if out is None:
out = sys.stderr
assert type(s) == compat_str
+ if sys.platform == 'win32' and encoding is None and hasattr(out, 'fileno'):
+ if _windows_write_string(s, out):
+ return
+
if ('b' in getattr(out, 'mode', '') or
sys.version_info[0] < 3): # Python 2 lies about mode of sys.stderr
byt = s.encode(encoding or preferredencoding(), 'ignore')