mirror of
https://github.com/python/cpython.git
synced 2025-08-08 10:58:51 +00:00
110 lines
No EOL
2.6 KiB
Python
110 lines
No EOL
2.6 KiB
Python
"""
|
|
>>> root = Path(getfixture('zipfile_abcde'))
|
|
>>> a, b = root.iterdir()
|
|
>>> a
|
|
Path('abcde.zip', 'a.txt')
|
|
>>> b
|
|
Path('abcde.zip', 'b/')
|
|
>>> b.name
|
|
'b'
|
|
>>> c = b / 'c.txt'
|
|
>>> c
|
|
Path('abcde.zip', 'b/c.txt')
|
|
>>> c.name
|
|
'c.txt'
|
|
>>> c.read_text()
|
|
'content of c'
|
|
>>> c.exists()
|
|
True
|
|
>>> (b / 'missing.txt').exists()
|
|
False
|
|
>>> str(c)
|
|
'abcde.zip/b/c.txt'
|
|
"""
|
|
|
|
from __future__ import division
|
|
|
|
import io
|
|
import sys
|
|
import posixpath
|
|
import zipfile
|
|
import operator
|
|
import functools
|
|
|
|
__metaclass__ = type
|
|
|
|
|
|
class Path:
|
|
__repr = '{self.__class__.__name__}({self.root.filename!r}, {self.at!r})'
|
|
|
|
def __init__(self, root, at=''):
|
|
self.root = root if isinstance(root, zipfile.ZipFile) \
|
|
else zipfile.ZipFile(self._pathlib_compat(root))
|
|
self.at = at
|
|
|
|
@staticmethod
|
|
def _pathlib_compat(path):
|
|
"""
|
|
For path-like objects, convert to a filename for compatibility
|
|
on Python 3.6.1 and earlier.
|
|
"""
|
|
try:
|
|
return path.__fspath__()
|
|
except AttributeError:
|
|
return str(path)
|
|
|
|
@property
|
|
def open(self):
|
|
return functools.partial(self.root.open, self.at)
|
|
|
|
@property
|
|
def name(self):
|
|
return posixpath.basename(self.at.rstrip('/'))
|
|
|
|
def read_text(self, *args, **kwargs):
|
|
with self.open() as strm:
|
|
return io.TextIOWrapper(strm, *args, **kwargs).read()
|
|
|
|
def read_bytes(self):
|
|
with self.open() as strm:
|
|
return strm.read()
|
|
|
|
def _is_child(self, path):
|
|
return posixpath.dirname(path.at.rstrip('/')) == self.at.rstrip('/')
|
|
|
|
def _next(self, at):
|
|
return Path(self.root, at)
|
|
|
|
def is_dir(self):
|
|
return not self.at or self.at.endswith('/')
|
|
|
|
def is_file(self):
|
|
return not self.is_dir()
|
|
|
|
def exists(self):
|
|
return self.at in self.root.namelist()
|
|
|
|
def iterdir(self):
|
|
if not self.is_dir():
|
|
raise ValueError("Can't listdir a file")
|
|
names = map(operator.attrgetter('filename'), self.root.infolist())
|
|
subs = map(self._next, names)
|
|
return filter(self._is_child, subs)
|
|
|
|
def __str__(self):
|
|
return posixpath.join(self.root.filename, self.at)
|
|
|
|
def __repr__(self):
|
|
return self.__repr.format(self=self)
|
|
|
|
def __truediv__(self, add):
|
|
add = self._pathlib_compat(add)
|
|
next = posixpath.join(self.at, add)
|
|
next_dir = posixpath.join(self.at, add, '')
|
|
names = self.root.namelist()
|
|
return self._next(
|
|
next_dir if next not in names and next_dir in names else next
|
|
)
|
|
|
|
if sys.version_info < (3,):
|
|
__div__ = __truediv__ |