diff options
Diffstat (limited to 'youtube_dl/utils.py')
| -rw-r--r-- | youtube_dl/utils.py | 101 | 
1 files changed, 101 insertions, 0 deletions
| diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py index 69ca88c85..d2dfa8013 100644 --- a/youtube_dl/utils.py +++ b/youtube_dl/utils.py @@ -42,6 +42,7 @@ from .compat import (      compat_html_entities_html5,      compat_http_client,      compat_kwargs, +    compat_os_name,      compat_parse_qs,      compat_shlex_quote,      compat_socket_create_connection, @@ -141,6 +142,8 @@ DATE_FORMATS = (      '%Y-%m-%dT%H:%M:%S',      '%Y-%m-%dT%H:%M:%S.%f',      '%Y-%m-%dT%H:%M', +    '%b %d %Y at %H:%M', +    '%b %d %Y at %H:%M:%S',  )  DATE_FORMATS_DAY_FIRST = list(DATE_FORMATS) @@ -775,6 +778,25 @@ class ContentTooShortError(Exception):          self.expected = expected +class XAttrMetadataError(Exception): +    def __init__(self, code=None, msg='Unknown error'): +        super(XAttrMetadataError, self).__init__(msg) +        self.code = code + +        # Parsing code and msg +        if (self.code in (errno.ENOSPC, errno.EDQUOT) or +                'No space left' in self.msg or 'Disk quota excedded' in self.msg): +            self.reason = 'NO_SPACE' +        elif self.code == errno.E2BIG or 'Argument list too long' in self.msg: +            self.reason = 'VALUE_TOO_LONG' +        else: +            self.reason = 'NOT_SUPPORTED' + + +class XAttrUnavailableError(Exception): +    pass + +  def _create_http_connection(ydl_handler, http_class, is_https, *args, **kwargs):      # Working around python 2 bug (see http://bugs.python.org/issue17849) by limiting      # expected HTTP responses to meet HTTP/1.0 or later (see also @@ -3131,3 +3153,82 @@ def decode_png(png_data):              current_row.append(color)      return width, height, pixels + + +def write_xattr(path, key, value): +    # This mess below finds the best xattr tool for the job +    try: +        # try the pyxattr module... +        import xattr + +        # Unicode arguments are not supported in python-pyxattr until +        # version 0.5.0 +        # See https://github.com/rg3/youtube-dl/issues/5498 +        pyxattr_required_version = '0.5.0' +        if version_tuple(xattr.__version__) < version_tuple(pyxattr_required_version): +            # TODO: fallback to CLI tools +            raise XAttrUnavailableError( +                'python-pyxattr is detected but is too old. ' +                'youtube-dl requires %s or above while your version is %s. ' +                'Falling back to other xattr implementations' % ( +                    pyxattr_required_version, xattr.__version__)) + +        try: +            xattr.set(path, key, value) +        except EnvironmentError as e: +            raise XAttrMetadataError(e.errno, e.strerror) + +    except ImportError: +        if compat_os_name == 'nt': +            # Write xattrs to NTFS Alternate Data Streams: +            # http://en.wikipedia.org/wiki/NTFS#Alternate_data_streams_.28ADS.29 +            assert ':' not in key +            assert os.path.exists(path) + +            ads_fn = path + ':' + key +            try: +                with open(ads_fn, 'wb') as f: +                    f.write(value) +            except EnvironmentError as e: +                raise XAttrMetadataError(e.errno, e.strerror) +        else: +            user_has_setfattr = check_executable('setfattr', ['--version']) +            user_has_xattr = check_executable('xattr', ['-h']) + +            if user_has_setfattr or user_has_xattr: + +                value = value.decode('utf-8') +                if user_has_setfattr: +                    executable = 'setfattr' +                    opts = ['-n', key, '-v', value] +                elif user_has_xattr: +                    executable = 'xattr' +                    opts = ['-w', key, value] + +                cmd = ([encodeFilename(executable, True)] + +                       [encodeArgument(o) for o in opts] + +                       [encodeFilename(path, True)]) + +                try: +                    p = subprocess.Popen( +                        cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) +                except EnvironmentError as e: +                    raise XAttrMetadataError(e.errno, e.strerror) +                stdout, stderr = p.communicate() +                stderr = stderr.decode('utf-8', 'replace') +                if p.returncode != 0: +                    raise XAttrMetadataError(p.returncode, stderr) + +            else: +                # On Unix, and can't find pyxattr, setfattr, or xattr. +                if sys.platform.startswith('linux'): +                    raise XAttrUnavailableError( +                        "Couldn't find a tool to set the xattrs. " +                        "Install either the python 'pyxattr' or 'xattr' " +                        "modules, or the GNU 'attr' package " +                        "(which contains the 'setfattr' tool).") +                else: +                    raise XAttrUnavailableError( +                        "Couldn't find a tool to set the xattrs. " +                        "Install either the python 'xattr' module, " +                        "or the 'xattr' binary.") | 
