diff options
Diffstat (limited to 'youtube_dl/utils.py')
| -rw-r--r-- | youtube_dl/utils.py | 99 | 
1 files changed, 82 insertions, 17 deletions
| diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py index 29c9b1a4c..9c9320934 100644 --- a/youtube_dl/utils.py +++ b/youtube_dl/utils.py @@ -2,6 +2,7 @@  # -*- coding: utf-8 -*-  import calendar +import codecs  import contextlib  import ctypes  import datetime @@ -539,7 +540,6 @@ def encodeFilename(s, for_subprocess=False):          encoding = 'utf-8'      return s.encode(encoding, 'ignore') -  def decodeOption(optval):      if optval is None:          return optval @@ -910,25 +910,84 @@ def platform_name():      return res -def write_string(s, out=None): +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, +    } + +    def ucs2_len(s): +        return sum((2 if ord(c) > 0xffff else 1) for c in s) + +    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 = ucs2_len(s) +    while remaining > 0: +        ret = WriteConsoleW( +            h, s, min(remaining, 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 -        s = s.encode(preferredencoding(), 'ignore') -    try: +        byt = s.encode(encoding or preferredencoding(), 'ignore') +        out.write(byt) +    elif hasattr(out, 'buffer'): +        enc = encoding or getattr(out, 'encoding', None) or preferredencoding() +        byt = s.encode(enc, 'ignore') +        out.buffer.write(byt) +    else:          out.write(s) -    except UnicodeEncodeError: -        # In Windows shells, this can fail even when the codec is just charmap!? -        # See https://wiki.python.org/moin/PrintFails#Issue -        if sys.platform == 'win32' and hasattr(out, 'encoding'): -            s = s.encode(out.encoding, 'ignore').decode(out.encoding) -            out.write(s) -        else: -            raise -      out.flush() @@ -1177,8 +1236,12 @@ class HEADRequest(compat_urllib_request.Request):          return "HEAD" -def int_or_none(v, scale=1): -    return v if v is None else (int(v) // scale) +def int_or_none(v, scale=1, default=None): +    return default if v is None else (int(v) // scale) + + +def float_or_none(v, scale=1, default=None): +    return default if v is None else (float(v) / scale)  def parse_duration(s): @@ -1260,9 +1323,11 @@ class PagedList(object):  def uppercase_escape(s): +    unicode_escape = codecs.getdecoder('unicode_escape')      return re.sub( -        r'\\U([0-9a-fA-F]{8})', -        lambda m: compat_chr(int(m.group(1), base=16)), s) +        r'\\U[0-9a-fA-F]{8}', +        lambda m: unicode_escape(m.group(0))[0], +        s)  try:      struct.pack(u'!I', 0) | 
