]>
Raphaƫl G. Git Repositories - youtubedl/blob - youtube_dl/postprocessor/xattrpp.py
e39ca60aa08326b6f05814ff800bb09c75755e48
   1 from __future__ 
import unicode_literals
 
   8 from .common 
import PostProcessor
 
   9 from ..compat 
import compat_os_name
 
  20 class XAttrMetadataError(PostProcessingError
): 
  21     def __init__(self
, code
=None, msg
='Unknown error'): 
  22         super(XAttrMetadataError
, self
).__init
__(msg
) 
  25         # Parsing code and msg 
  26         if (self
.code 
in (errno
.ENOSPC
, errno
.EDQUOT
) or 
  27                 'No space left' in self
.msg 
or 'Disk quota excedded' in self
.msg
): 
  28             self
.reason 
= 'NO_SPACE' 
  29         elif self
.code 
== errno
.E2BIG 
or 'Argument list too long' in self
.msg
: 
  30             self
.reason 
= 'VALUE_TOO_LONG' 
  32             self
.reason 
= 'NOT_SUPPORTED' 
  35 class XAttrMetadataPP(PostProcessor
): 
  38     # More info about extended attributes for media: 
  39     #   http://freedesktop.org/wiki/CommonExtendedAttributes/ 
  40     #   http://www.freedesktop.org/wiki/PhreedomDraft/ 
  41     #   http://dublincore.org/documents/usageguide/elements.shtml 
  44     #  * capture youtube keywords and put them in 'user.dublincore.subject' (comma-separated) 
  45     #  * figure out which xattrs can be used for 'duration', 'thumbnail', 'resolution' 
  49         """ Set extended attributes on downloaded file (if xattr support is found). """ 
  51         # This mess below finds the best xattr tool for the job and creates a 
  52         # "write_xattr" function. 
  54             # try the pyxattr module... 
  57             # Unicode arguments are not supported in python-pyxattr until 
  59             # See https://github.com/rg3/youtube-dl/issues/5498 
  60             pyxattr_required_version 
= '0.5.0' 
  61             if version_tuple(xattr
.__version
__) < version_tuple(pyxattr_required_version
): 
  62                 self
._downloader
.report_warning( 
  63                     'python-pyxattr is detected but is too old. ' 
  64                     'youtube-dl requires %s or above while your version is %s. ' 
  65                     'Falling back to other xattr implementations' % ( 
  66                         pyxattr_required_version
, xattr
.__version
__)) 
  70             def write_xattr(path
, key
, value
): 
  72                     xattr
.set(path
, key
, value
) 
  73                 except EnvironmentError as e
: 
  74                     raise XAttrMetadataError(e
.errno
, e
.strerror
) 
  77             if compat_os_name 
== 'nt': 
  78                 # Write xattrs to NTFS Alternate Data Streams: 
  79                 # http://en.wikipedia.org/wiki/NTFS#Alternate_data_streams_.28ADS.29 
  80                 def write_xattr(path
, key
, value
): 
  82                     assert os
.path
.exists(path
) 
  84                     ads_fn 
= path 
+ ':' + key
 
  86                         with open(ads_fn
, 'wb') as f
: 
  88                     except EnvironmentError as e
: 
  89                         raise XAttrMetadataError(e
.errno
, e
.strerror
) 
  91                 user_has_setfattr 
= check_executable('setfattr', ['--version']) 
  92                 user_has_xattr 
= check_executable('xattr', ['-h']) 
  94                 if user_has_setfattr 
or user_has_xattr
: 
  96                     def write_xattr(path
, key
, value
): 
  97                         value 
= value
.decode('utf-8') 
  99                             executable 
= 'setfattr' 
 100                             opts 
= ['-n', key
, '-v', value
] 
 103                             opts 
= ['-w', key
, value
] 
 105                         cmd 
= ([encodeFilename(executable
, True)] + 
 106                                [encodeArgument(o
) for o 
in opts
] + 
 107                                [encodeFilename(path
, True)]) 
 110                             p 
= subprocess
.Popen( 
 111                                 cmd
, stdout
=subprocess
.PIPE
, stderr
=subprocess
.PIPE
, stdin
=subprocess
.PIPE
) 
 112                         except EnvironmentError as e
: 
 113                             raise XAttrMetadataError(e
.errno
, e
.strerror
) 
 114                         stdout
, stderr 
= p
.communicate() 
 115                         stderr 
= stderr
.decode('utf-8', 'replace') 
 116                         if p
.returncode 
!= 0: 
 117                             raise XAttrMetadataError(p
.returncode
, stderr
) 
 120                     # On Unix, and can't find pyxattr, setfattr, or xattr. 
 121                     if sys
.platform
.startswith('linux'): 
 122                         self
._downloader
.report_error( 
 123                             "Couldn't find a tool to set the xattrs. " 
 124                             "Install either the python 'pyxattr' or 'xattr' " 
 125                             "modules, or the GNU 'attr' package " 
 126                             "(which contains the 'setfattr' tool).") 
 128                         self
._downloader
.report_error( 
 129                             "Couldn't find a tool to set the xattrs. " 
 130                             "Install either the python 'xattr' module, " 
 131                             "or the 'xattr' binary.") 
 133         # Write the metadata to the file's xattrs 
 134         self
._downloader
.to_screen('[metadata] Writing metadata to file\'s xattrs') 
 136         filename 
= info
['filepath'] 
 140                 'user.xdg.referrer.url': 'webpage_url', 
 141                 # 'user.xdg.comment':            'description', 
 142                 'user.dublincore.title': 'title', 
 143                 'user.dublincore.date': 'upload_date', 
 144                 'user.dublincore.description': 'description', 
 145                 'user.dublincore.contributor': 'uploader', 
 146                 'user.dublincore.format': 'format', 
 149             for xattrname
, infoname 
in xattr_mapping
.items(): 
 151                 value 
= info
.get(infoname
) 
 154                     if infoname 
== 'upload_date': 
 155                         value 
= hyphenate_date(value
) 
 157                     byte_value 
= value
.encode('utf-8') 
 158                     write_xattr(filename
, xattrname
, byte_value
) 
 162         except XAttrMetadataError 
as e
: 
 163             if e
.reason 
== 'NO_SPACE': 
 164                 self
._downloader
.report_warning( 
 165                     'There\'s no disk space left or disk quota exceeded. ' + 
 166                     'Extended attributes are not written.') 
 167             elif e
.reason 
== 'VALUE_TOO_LONG': 
 168                 self
._downloader
.report_warning( 
 169                     'Unable to write extended attributes due to too long values.') 
 171                 msg 
= 'This filesystem doesn\'t support extended attributes. ' 
 172                 if compat_os_name 
== 'nt': 
 173                     msg 
+= 'You need to use NTFS.' 
 175                     msg 
+= '(You may have to enable them in your /etc/fstab)' 
 176                 self
._downloader
.report_error(msg
)