Path: blob/master/ invest-robot-contest_TinkoffBotTwitch-main/venv/lib/python3.8/site-packages/setuptools/archive_util.py
7763 views
"""Utilities for extracting common archive formats"""12import zipfile3import tarfile4import os5import shutil6import posixpath7import contextlib8from distutils.errors import DistutilsError910from pkg_resources import ensure_directory1112__all__ = [13"unpack_archive", "unpack_zipfile", "unpack_tarfile", "default_filter",14"UnrecognizedFormat", "extraction_drivers", "unpack_directory",15]161718class UnrecognizedFormat(DistutilsError):19"""Couldn't recognize the archive type"""202122def default_filter(src, dst):23"""The default progress/filter callback; returns True for all files"""24return dst252627def unpack_archive(28filename, extract_dir, progress_filter=default_filter,29drivers=None):30"""Unpack `filename` to `extract_dir`, or raise ``UnrecognizedFormat``3132`progress_filter` is a function taking two arguments: a source path33internal to the archive ('/'-separated), and a filesystem path where it34will be extracted. The callback must return the desired extract path35(which may be the same as the one passed in), or else ``None`` to skip36that file or directory. The callback can thus be used to report on the37progress of the extraction, as well as to filter the items extracted or38alter their extraction paths.3940`drivers`, if supplied, must be a non-empty sequence of functions with the41same signature as this function (minus the `drivers` argument), that raise42``UnrecognizedFormat`` if they do not support extracting the designated43archive type. The `drivers` are tried in sequence until one is found that44does not raise an error, or until all are exhausted (in which case45``UnrecognizedFormat`` is raised). If you do not supply a sequence of46drivers, the module's ``extraction_drivers`` constant will be used, which47means that ``unpack_zipfile`` and ``unpack_tarfile`` will be tried, in that48order.49"""50for driver in drivers or extraction_drivers:51try:52driver(filename, extract_dir, progress_filter)53except UnrecognizedFormat:54continue55else:56return57else:58raise UnrecognizedFormat(59"Not a recognized archive type: %s" % filename60)616263def unpack_directory(filename, extract_dir, progress_filter=default_filter):64""""Unpack" a directory, using the same interface as for archives6566Raises ``UnrecognizedFormat`` if `filename` is not a directory67"""68if not os.path.isdir(filename):69raise UnrecognizedFormat("%s is not a directory" % filename)7071paths = {72filename: ('', extract_dir),73}74for base, dirs, files in os.walk(filename):75src, dst = paths[base]76for d in dirs:77paths[os.path.join(base, d)] = src + d + '/', os.path.join(dst, d)78for f in files:79target = os.path.join(dst, f)80target = progress_filter(src + f, target)81if not target:82# skip non-files83continue84ensure_directory(target)85f = os.path.join(base, f)86shutil.copyfile(f, target)87shutil.copystat(f, target)888990def unpack_zipfile(filename, extract_dir, progress_filter=default_filter):91"""Unpack zip `filename` to `extract_dir`9293Raises ``UnrecognizedFormat`` if `filename` is not a zipfile (as determined94by ``zipfile.is_zipfile()``). See ``unpack_archive()`` for an explanation95of the `progress_filter` argument.96"""9798if not zipfile.is_zipfile(filename):99raise UnrecognizedFormat("%s is not a zip file" % (filename,))100101with zipfile.ZipFile(filename) as z:102for info in z.infolist():103name = info.filename104105# don't extract absolute paths or ones with .. in them106if name.startswith('/') or '..' in name.split('/'):107continue108109target = os.path.join(extract_dir, *name.split('/'))110target = progress_filter(name, target)111if not target:112continue113if name.endswith('/'):114# directory115ensure_directory(target)116else:117# file118ensure_directory(target)119data = z.read(info.filename)120with open(target, 'wb') as f:121f.write(data)122unix_attributes = info.external_attr >> 16123if unix_attributes:124os.chmod(target, unix_attributes)125126127def unpack_tarfile(filename, extract_dir, progress_filter=default_filter):128"""Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir`129130Raises ``UnrecognizedFormat`` if `filename` is not a tarfile (as determined131by ``tarfile.open()``). See ``unpack_archive()`` for an explanation132of the `progress_filter` argument.133"""134try:135tarobj = tarfile.open(filename)136except tarfile.TarError as e:137raise UnrecognizedFormat(138"%s is not a compressed or uncompressed tar file" % (filename,)139) from e140with contextlib.closing(tarobj):141# don't do any chowning!142tarobj.chown = lambda *args: None143for member in tarobj:144name = member.name145# don't extract absolute paths or ones with .. in them146if not name.startswith('/') and '..' not in name.split('/'):147prelim_dst = os.path.join(extract_dir, *name.split('/'))148149# resolve any links and to extract the link targets as normal150# files151while member is not None and (152member.islnk() or member.issym()):153linkpath = member.linkname154if member.issym():155base = posixpath.dirname(member.name)156linkpath = posixpath.join(base, linkpath)157linkpath = posixpath.normpath(linkpath)158member = tarobj._getmember(linkpath)159160if member is not None and (member.isfile() or member.isdir()):161final_dst = progress_filter(name, prelim_dst)162if final_dst:163if final_dst.endswith(os.sep):164final_dst = final_dst[:-1]165try:166# XXX Ugh167tarobj._extract_member(member, final_dst)168except tarfile.ExtractError:169# chown/chmod/mkfifo/mknode/makedev failed170pass171return True172173174extraction_drivers = unpack_directory, unpack_zipfile, unpack_tarfile175176177