Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(292)

Unified Diff: venv/Lib/site-packages/django/utils/archive.py

Issue 554060043: testMe
Patch Set: Created 2 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « venv/Lib/site-packages/django/utils/_os.py ('k') | venv/Lib/site-packages/django/utils/autoreload.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: venv/Lib/site-packages/django/utils/archive.py
===================================================================
new file mode 100644
--- /dev/null
+++ b/venv/Lib/site-packages/django/utils/archive.py
@@ -0,0 +1,229 @@
+"""
+Based on "python-archive" -- http://pypi.python.org/pypi/python-archive/
+
+Copyright (c) 2010 Gary Wilson Jr. <gary.wilson@gmail.com> and contributors.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+"""
+import os
+import shutil
+import stat
+import tarfile
+import zipfile
+
+from django.utils import six
+
+
+class ArchiveException(Exception):
+ """
+ Base exception class for all archive errors.
+ """
+
+
+class UnrecognizedArchiveFormat(ArchiveException):
+ """
+ Error raised when passed file is not a recognized archive format.
+ """
+
+
+def extract(path, to_path=''):
+ """
+ Unpack the tar or zip file at the specified path to the directory
+ specified by to_path.
+ """
+ with Archive(path) as archive:
+ archive.extract(to_path)
+
+
+class Archive(object):
+ """
+ The external API class that encapsulates an archive implementation.
+ """
+ def __init__(self, file):
+ self._archive = self._archive_cls(file)(file)
+
+ @staticmethod
+ def _archive_cls(file):
+ cls = None
+ if isinstance(file, six.string_types):
+ filename = file
+ else:
+ try:
+ filename = file.name
+ except AttributeError:
+ raise UnrecognizedArchiveFormat(
+ "File object not a recognized archive format.")
+ base, tail_ext = os.path.splitext(filename.lower())
+ cls = extension_map.get(tail_ext)
+ if not cls:
+ base, ext = os.path.splitext(base)
+ cls = extension_map.get(ext)
+ if not cls:
+ raise UnrecognizedArchiveFormat(
+ "Path not a recognized archive format: %s" % filename)
+ return cls
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ self.close()
+
+ def extract(self, to_path=''):
+ self._archive.extract(to_path)
+
+ def list(self):
+ self._archive.list()
+
+ def close(self):
+ self._archive.close()
+
+
+class BaseArchive(object):
+ """
+ Base Archive class. Implementations should inherit this class.
+ """
+ @staticmethod
+ def _copy_permissions(mode, filename):
+ """
+ If the file in the archive has some permissions (this assumes a file
+ won't be writable/executable without being readable), apply those
+ permissions to the unarchived file.
+ """
+ if mode & stat.S_IROTH:
+ os.chmod(filename, mode)
+
+ def split_leading_dir(self, path):
+ path = str(path)
+ path = path.lstrip('/').lstrip('\\')
+ if '/' in path and (('\\' in path and path.find('/') < path.find('\\')) or '\\' not in path):
+ return path.split('/', 1)
+ elif '\\' in path:
+ return path.split('\\', 1)
+ else:
+ return path, ''
+
+ def has_leading_dir(self, paths):
+ """
+ Returns true if all the paths have the same leading path name
+ (i.e., everything is in one subdirectory in an archive)
+ """
+ common_prefix = None
+ for path in paths:
+ prefix, rest = self.split_leading_dir(path)
+ if not prefix:
+ return False
+ elif common_prefix is None:
+ common_prefix = prefix
+ elif prefix != common_prefix:
+ return False
+ return True
+
+ def extract(self):
+ raise NotImplementedError('subclasses of BaseArchive must provide an extract() method')
+
+ def list(self):
+ raise NotImplementedError('subclasses of BaseArchive must provide a list() method')
+
+
+class TarArchive(BaseArchive):
+
+ def __init__(self, file):
+ self._archive = tarfile.open(file)
+
+ def list(self, *args, **kwargs):
+ self._archive.list(*args, **kwargs)
+
+ def extract(self, to_path):
+ members = self._archive.getmembers()
+ leading = self.has_leading_dir(x.name for x in members)
+ for member in members:
+ name = member.name
+ if leading:
+ name = self.split_leading_dir(name)[1]
+ filename = os.path.join(to_path, name)
+ if member.isdir():
+ if filename and not os.path.exists(filename):
+ os.makedirs(filename)
+ else:
+ try:
+ extracted = self._archive.extractfile(member)
+ except (KeyError, AttributeError) as exc:
+ # Some corrupt tar files seem to produce this
+ # (specifically bad symlinks)
+ print("In the tar file %s the member %s is invalid: %s" %
+ (name, member.name, exc))
+ else:
+ dirname = os.path.dirname(filename)
+ if dirname and not os.path.exists(dirname):
+ os.makedirs(dirname)
+ with open(filename, 'wb') as outfile:
+ shutil.copyfileobj(extracted, outfile)
+ self._copy_permissions(member.mode, filename)
+ finally:
+ if extracted:
+ extracted.close()
+
+ def close(self):
+ self._archive.close()
+
+
+class ZipArchive(BaseArchive):
+
+ def __init__(self, file):
+ self._archive = zipfile.ZipFile(file)
+
+ def list(self, *args, **kwargs):
+ self._archive.printdir(*args, **kwargs)
+
+ def extract(self, to_path):
+ namelist = self._archive.namelist()
+ leading = self.has_leading_dir(namelist)
+ for name in namelist:
+ data = self._archive.read(name)
+ info = self._archive.getinfo(name)
+ if leading:
+ name = self.split_leading_dir(name)[1]
+ filename = os.path.join(to_path, name)
+ dirname = os.path.dirname(filename)
+ if dirname and not os.path.exists(dirname):
+ os.makedirs(dirname)
+ if filename.endswith(('/', '\\')):
+ # A directory
+ if not os.path.exists(filename):
+ os.makedirs(filename)
+ else:
+ with open(filename, 'wb') as outfile:
+ outfile.write(data)
+ # Convert ZipInfo.external_attr to mode
+ mode = info.external_attr >> 16
+ self._copy_permissions(mode, filename)
+
+ def close(self):
+ self._archive.close()
+
+
+extension_map = {
+ '.tar': TarArchive,
+ '.tar.bz2': TarArchive,
+ '.tar.gz': TarArchive,
+ '.tgz': TarArchive,
+ '.tz2': TarArchive,
+ '.zip': ZipArchive,
+}
« no previous file with comments | « venv/Lib/site-packages/django/utils/_os.py ('k') | venv/Lib/site-packages/django/utils/autoreload.py » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b