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