| @@ -4,4 +4,5 @@ venv | |||||
| build | build | ||||
| libarchive/__libarchive.so | libarchive/__libarchive.so | ||||
| libarchive/_libarchive_wrap.o | |||||
| python_libarchive.egg-info | python_libarchive.egg-info | ||||
| @@ -1,14 +1,16 @@ | |||||
| language: python | language: python | ||||
| python: | |||||
| - "2.7" | |||||
| env: | |||||
| - DJANGO=1.3 | |||||
| - DJANGO=1.4 | |||||
| jobs: | |||||
| include: | |||||
| - python: "2.7" | |||||
| env: PYVER=2.7 | |||||
| - python: "3.6" | |||||
| env: PYVER=3.6 | |||||
| before_install: | before_install: | ||||
| - sudo apt-get update -qq | - sudo apt-get update -qq | ||||
| - sudo apt-get install -qq libarchive-dev | - sudo apt-get install -qq libarchive-dev | ||||
| - pyenv shell $(python -c 'import platform; print(platform.python_version())') | |||||
| install: | install: | ||||
| - pip install . | |||||
| - make build | |||||
| script: | script: | ||||
| - make test | - make test | ||||
| notifications: | notifications: | ||||
| @@ -1,3 +1,6 @@ | |||||
| build: | |||||
| make -C libarchive | |||||
| test: | test: | ||||
| python tests.py | python tests.py | ||||
| @@ -11,3 +14,6 @@ install: | |||||
| publish: | publish: | ||||
| python setup.py register | python setup.py register | ||||
| python setup.py sdist upload | python setup.py sdist upload | ||||
| clean: | |||||
| make -C libarchive clean | |||||
| @@ -40,8 +40,8 @@ source_suffix = '.rst' | |||||
| master_doc = 'index' | master_doc = 'index' | ||||
| # General information about the project. | # General information about the project. | ||||
| project = u'python-libarchive' | |||||
| copyright = u'2012, Ben Timby' | |||||
| project = 'python-libarchive' | |||||
| copyright = '2012, Ben Timby' | |||||
| # The version info for the project you're documenting, acts as replacement for | # The version info for the project you're documenting, acts as replacement for | ||||
| # |version| and |release|, also used in various other places throughout the | # |version| and |release|, also used in various other places throughout the | ||||
| @@ -178,8 +178,8 @@ htmlhelp_basename = 'python-libarchivedoc' | |||||
| # Grouping the document tree into LaTeX files. List of tuples | # Grouping the document tree into LaTeX files. List of tuples | ||||
| # (source start file, target name, title, author, documentclass [howto/manual]). | # (source start file, target name, title, author, documentclass [howto/manual]). | ||||
| latex_documents = [ | latex_documents = [ | ||||
| ('index', 'python-libarchive.tex', u'python-libarchive Documentation', | |||||
| u'Ben Timby', 'manual'), | |||||
| ('index', 'python-libarchive.tex', 'python-libarchive Documentation', | |||||
| 'Ben Timby', 'manual'), | |||||
| ] | ] | ||||
| # The name of an image file (relative to this directory) to place at the top of | # The name of an image file (relative to this directory) to place at the top of | ||||
| @@ -211,6 +211,6 @@ latex_documents = [ | |||||
| # One entry per manual page. List of tuples | # One entry per manual page. List of tuples | ||||
| # (source start file, name, description, authors, manual section). | # (source start file, name, description, authors, manual section). | ||||
| man_pages = [ | man_pages = [ | ||||
| ('index', 'python-libarchive', u'python-libarchive Documentation', | |||||
| [u'Ben Timby'], 1) | |||||
| ('index', 'python-libarchive', 'python-libarchive Documentation', | |||||
| ['Ben Timby'], 1) | |||||
| ] | ] | ||||
| @@ -1,12 +1,8 @@ | |||||
| CFLAGS = -g | CFLAGS = -g | ||||
| INCLUDE = -I/usr/include -I. | INCLUDE = -I/usr/include -I. | ||||
| LIBS = -L/usr/local/lib -l:libarchive.so.13.1.2 | |||||
| LIBS = -larchive | |||||
| #if PYTHON_VERSION | |||||
| PYVER = $(PYTHON_VERSION) | |||||
| #else | |||||
| PYVER = 2.7 | |||||
| #endif | |||||
| PYVER ?= 2.7 | |||||
| all: __libarchive.so | all: __libarchive.so | ||||
| @@ -30,10 +30,9 @@ import time | |||||
| import warnings | import warnings | ||||
| from libarchive import _libarchive | from libarchive import _libarchive | ||||
| try: | |||||
| from cStringIO import StringIO | |||||
| except ImportError: | |||||
| from StringIO import StringIO | |||||
| from io import StringIO | |||||
| PY3 = sys.version_info[0] == 3 | |||||
| # Suggested block size for libarchive. Libarchive may adjust it. | # Suggested block size for libarchive. Libarchive may adjust it. | ||||
| BLOCK_SIZE = 10240 | BLOCK_SIZE = 10240 | ||||
| @@ -134,7 +133,7 @@ def is_archive_name(filename, formats=None): | |||||
| This function will return the name of the most likely archive format, None if the file is | This function will return the name of the most likely archive format, None if the file is | ||||
| unlikely to be an archive.''' | unlikely to be an archive.''' | ||||
| if formats is None: | if formats is None: | ||||
| formats = FORMAT_EXTENSIONS.values() | |||||
| formats = list(FORMAT_EXTENSIONS.values()) | |||||
| format, filter = guess_format(filename) | format, filter = guess_format(filename) | ||||
| if format in formats: | if format in formats: | ||||
| return format | return format | ||||
| @@ -153,8 +152,8 @@ def is_archive(f, formats=(None, ), filters=(None, )): | |||||
| This function will return True if the file can be opened as an archive using the given | This function will return True if the file can be opened as an archive using the given | ||||
| format(s)/filter(s).''' | format(s)/filter(s).''' | ||||
| if isinstance(f, basestring): | |||||
| f = file(f, 'r') | |||||
| if isinstance(f, str): | |||||
| f = open(f, 'r') | |||||
| a = _libarchive.archive_read_new() | a = _libarchive.archive_read_new() | ||||
| for format in formats: | for format in formats: | ||||
| format = get_func(format, FORMATS, 0) | format = get_func(format, FORMATS, 0) | ||||
| @@ -175,6 +174,7 @@ def is_archive(f, formats=(None, ), filters=(None, )): | |||||
| finally: | finally: | ||||
| _libarchive.archive_read_close(a) | _libarchive.archive_read_close(a) | ||||
| _libarchive.archive_read_free(a) | _libarchive.archive_read_free(a) | ||||
| f.close() | |||||
| class EntryReadStream(object): | class EntryReadStream(object): | ||||
| @@ -271,7 +271,7 @@ class EntryWriteStream(object): | |||||
| if self.buffer: | if self.buffer: | ||||
| self.buffer.write(data) | self.buffer.write(data) | ||||
| else: | else: | ||||
| _libarchive.archive_write_data_from_str(self.archive._a, data) | |||||
| _libarchive.archive_write_data_from_str(self.archive._a, data.encode('utf-8')) | |||||
| self.bytes += len(data) | self.bytes += len(data) | ||||
| def close(self): | def close(self): | ||||
| @@ -280,7 +280,7 @@ class EntryWriteStream(object): | |||||
| if self.buffer: | if self.buffer: | ||||
| self.entry.size = self.buffer.tell() | self.entry.size = self.buffer.tell() | ||||
| self.entry.to_archive(self.archive) | self.entry.to_archive(self.archive) | ||||
| _libarchive.archive_write_data_from_str(self.archive._a, self.buffer.getvalue()) | |||||
| _libarchive.archive_write_data_from_str(self.archive._a, self.buffer.getvalue().encode('utf-8')) | |||||
| _libarchive.archive_write_finish_entry(self.archive._a) | _libarchive.archive_write_finish_entry(self.archive._a) | ||||
| # Call archive.close() with _defer True to let it know we have been | # Call archive.close() with _defer True to let it know we have been | ||||
| @@ -312,8 +312,13 @@ class Entry(object): | |||||
| call_and_check(_libarchive.archive_read_next_header2, archive._a, archive._a, e) | call_and_check(_libarchive.archive_read_next_header2, archive._a, archive._a, e) | ||||
| mode = _libarchive.archive_entry_filetype(e) | mode = _libarchive.archive_entry_filetype(e) | ||||
| mode |= _libarchive.archive_entry_perm(e) | mode |= _libarchive.archive_entry_perm(e) | ||||
| entry = cls( | |||||
| if PY3: | |||||
| pathname=_libarchive.archive_entry_pathname(e) | |||||
| else: | |||||
| pathname=_libarchive.archive_entry_pathname(e).decode(encoding), | pathname=_libarchive.archive_entry_pathname(e).decode(encoding), | ||||
| entry = cls( | |||||
| pathname=pathname, | |||||
| size=_libarchive.archive_entry_size(e), | size=_libarchive.archive_entry_size(e), | ||||
| mtime=_libarchive.archive_entry_mtime(e), | mtime=_libarchive.archive_entry_mtime(e), | ||||
| mode=mode, | mode=mode, | ||||
| @@ -330,7 +335,7 @@ class Entry(object): | |||||
| if entry is None: | if entry is None: | ||||
| entry = cls(encoding=encoding) | entry = cls(encoding=encoding) | ||||
| if entry.pathname is None: | if entry.pathname is None: | ||||
| if isinstance(f, basestring): | |||||
| if isinstance(f, str): | |||||
| st = os.stat(f) | st = os.stat(f) | ||||
| entry.pathname = f | entry.pathname = f | ||||
| entry.size = st.st_size | entry.size = st.st_size | ||||
| @@ -353,7 +358,10 @@ class Entry(object): | |||||
| '''Creates an archive header and writes it to the given archive.''' | '''Creates an archive header and writes it to the given archive.''' | ||||
| e = _libarchive.archive_entry_new() | e = _libarchive.archive_entry_new() | ||||
| try: | try: | ||||
| _libarchive.archive_entry_set_pathname(e, self.pathname.encode(self.encoding)) | |||||
| if PY3: | |||||
| _libarchive.archive_entry_set_pathname(e, self.pathname) | |||||
| else: | |||||
| _libarchive.archive_entry_set_pathname(e, self.pathname.encode(self.encoding)) | |||||
| _libarchive.archive_entry_set_filetype(e, stat.S_IFMT(self.mode)) | _libarchive.archive_entry_set_filetype(e, stat.S_IFMT(self.mode)) | ||||
| _libarchive.archive_entry_set_perm(e, stat.S_IMODE(self.mode)) | _libarchive.archive_entry_set_perm(e, stat.S_IMODE(self.mode)) | ||||
| _libarchive.archive_entry_set_size(e, self.size) | _libarchive.archive_entry_set_size(e, self.size) | ||||
| @@ -390,9 +398,9 @@ class Archive(object): | |||||
| self._stream = None | self._stream = None | ||||
| self.encoding = encoding | self.encoding = encoding | ||||
| self.blocksize = blocksize | self.blocksize = blocksize | ||||
| if isinstance(f, basestring): | |||||
| if isinstance(f, str): | |||||
| self.filename = f | self.filename = f | ||||
| f = file(f, mode) | |||||
| f = open(f, mode) | |||||
| # Only close it if we opened it... | # Only close it if we opened it... | ||||
| self._defer_close = True | self._defer_close = True | ||||
| elif hasattr(f, 'fileno'): | elif hasattr(f, 'fileno'): | ||||
| @@ -520,11 +528,11 @@ class Archive(object): | |||||
| def readpath(self, f): | def readpath(self, f): | ||||
| '''Write current archive entry contents to file. f can be a file-like object or | '''Write current archive entry contents to file. f can be a file-like object or | ||||
| a path.''' | a path.''' | ||||
| if isinstance(f, basestring): | |||||
| if isinstance(f, str): | |||||
| basedir = os.path.basename(f) | basedir = os.path.basename(f) | ||||
| if not os.path.exists(basedir): | if not os.path.exists(basedir): | ||||
| os.makedirs(basedir) | os.makedirs(basedir) | ||||
| f = file(f, 'w') | |||||
| f = open(f, 'w') | |||||
| return _libarchive.archive_read_data_into_fd(self._a, f.fileno()) | return _libarchive.archive_read_data_into_fd(self._a, f.fileno()) | ||||
| def readstream(self, size): | def readstream(self, size): | ||||
| @@ -534,23 +542,26 @@ class Archive(object): | |||||
| def write(self, member, data=None): | def write(self, member, data=None): | ||||
| '''Writes a string buffer to the archive as the given entry.''' | '''Writes a string buffer to the archive as the given entry.''' | ||||
| if isinstance(member, basestring): | |||||
| if isinstance(member, str): | |||||
| member = self.entry_class(pathname=member, encoding=self.encoding) | member = self.entry_class(pathname=member, encoding=self.encoding) | ||||
| if data: | if data: | ||||
| member.size = len(data) | member.size = len(data) | ||||
| member.to_archive(self) | member.to_archive(self) | ||||
| if data: | if data: | ||||
| _libarchive.archive_write_data_from_str(self._a, data) | |||||
| if PY3: | |||||
| result = _libarchive.archive_write_data_from_str(self._a, data.encode('utf8')) | |||||
| else: | |||||
| result = _libarchive.archive_write_data_from_str(self._a, data) | |||||
| _libarchive.archive_write_finish_entry(self._a) | _libarchive.archive_write_finish_entry(self._a) | ||||
| def writepath(self, f, pathname=None, folder=False): | def writepath(self, f, pathname=None, folder=False): | ||||
| '''Writes a file to the archive. f can be a file-like object or a path. Uses | '''Writes a file to the archive. f can be a file-like object or a path. Uses | ||||
| write() to do the actual writing.''' | write() to do the actual writing.''' | ||||
| member = self.entry_class.from_file(f, encoding=self.encoding) | member = self.entry_class.from_file(f, encoding=self.encoding) | ||||
| if isinstance(f, basestring): | |||||
| if isinstance(f, str): | |||||
| if os.path.isfile(f): | if os.path.isfile(f): | ||||
| f = file(f, 'r') | |||||
| f = open(f, 'r') | |||||
| if pathname: | if pathname: | ||||
| member.pathname = pathname | member.pathname = pathname | ||||
| if folder and not member.isdir(): | if folder and not member.isdir(): | ||||
| @@ -587,8 +598,8 @@ class SeekableArchive(Archive): | |||||
| self._stream = None | self._stream = None | ||||
| # Convert file to open file. We need this to reopen the archive. | # Convert file to open file. We need this to reopen the archive. | ||||
| mode = kwargs.setdefault('mode', 'r') | mode = kwargs.setdefault('mode', 'r') | ||||
| if isinstance(f, basestring): | |||||
| f = file(f, mode) | |||||
| if isinstance(f, str): | |||||
| f = open(f, mode) | |||||
| super(SeekableArchive, self).__init__(f, **kwargs) | super(SeekableArchive, self).__init__(f, **kwargs) | ||||
| self.entries = [] | self.entries = [] | ||||
| self.eof = False | self.eof = False | ||||
| @@ -614,7 +625,11 @@ class SeekableArchive(Archive): | |||||
| def getentry(self, pathname): | def getentry(self, pathname): | ||||
| '''Take a name or entry object and returns an entry object.''' | '''Take a name or entry object and returns an entry object.''' | ||||
| for entry in self: | for entry in self: | ||||
| if entry.pathname == pathname: | |||||
| if PY3: | |||||
| entry_pathname = entry.pathname | |||||
| if not PY3: | |||||
| entry_pathname = entry.pathname[0] | |||||
| if entry_pathname == pathname: | |||||
| return entry | return entry | ||||
| raise KeyError(pathname) | raise KeyError(pathname) | ||||
| @@ -360,7 +360,7 @@ extern const char *archive_error_string(struct archive *); | |||||
| %inline %{ | %inline %{ | ||||
| PyObject *archive_read_data_into_str(struct archive *archive, int len) { | PyObject *archive_read_data_into_str(struct archive *archive, int len) { | ||||
| PyObject *str = NULL; | PyObject *str = NULL; | ||||
| if (!(str = PyString_FromStringAndSize(NULL, len))) { | |||||
| if (!(str = PyUnicode_FromStringAndSize(NULL, len))) { | |||||
| PyErr_SetString(PyExc_MemoryError, "could not allocate string."); | PyErr_SetString(PyExc_MemoryError, "could not allocate string."); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| @@ -739,7 +739,7 @@ SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) { | |||||
| #define PyString_Size(str) PyBytes_Size(str) | #define PyString_Size(str) PyBytes_Size(str) | ||||
| #define PyString_InternFromString(key) PyUnicode_InternFromString(key) | #define PyString_InternFromString(key) PyUnicode_InternFromString(key) | ||||
| #define Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_BASETYPE | #define Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_BASETYPE | ||||
| #define PyString_AS_STRING(x) PyUnicode_AS_STRING(x) | |||||
| #define PyString_AS_STRING(x) PyBytes_AsString(x) | |||||
| #define _PyLong_FromSsize_t(x) PyLong_FromSsize_t(x) | #define _PyLong_FromSsize_t(x) PyLong_FromSsize_t(x) | ||||
| #endif | #endif | ||||
| @@ -3342,10 +3342,17 @@ SWIG_AsVal_unsigned_SS_short (PyObject * obj, unsigned short *val) | |||||
| PyObject *archive_read_data_into_str(struct archive *archive, int len) { | PyObject *archive_read_data_into_str(struct archive *archive, int len) { | ||||
| PyObject *str = NULL; | PyObject *str = NULL; | ||||
| if (!(str = PyString_FromStringAndSize(NULL, len))) { | |||||
| #if PY_VERSION_HEX >= 0x03000000 | |||||
| if (!(str = PyBytes_FromStringAndSize(NULL, len))) { | |||||
| PyErr_SetString(PyExc_MemoryError, "could not allocate string."); | PyErr_SetString(PyExc_MemoryError, "could not allocate string."); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| #else | |||||
| if (!(str = PyString_FromStringAndSize(NULL, len))) { | |||||
| PyErr_SetString(PyExc_MemoryError, "could not allocate string."); | |||||
| return NULL; | |||||
| } | |||||
| #endif | |||||
| if (len != archive_read_data(archive, PyString_AS_STRING(str), len)) { | if (len != archive_read_data(archive, PyString_AS_STRING(str), len)) { | ||||
| PyErr_SetString(PyExc_RuntimeError, "could not read requested data."); | PyErr_SetString(PyExc_RuntimeError, "could not read requested data."); | ||||
| return NULL; | return NULL; | ||||
| @@ -76,14 +76,14 @@ class TarFile(SeekableArchive): | |||||
| def getnames(self): | def getnames(self): | ||||
| return list(self.iterpaths) | return list(self.iterpaths) | ||||
| def next(self): | |||||
| def __next__(self): | |||||
| raise NotImplementedError | raise NotImplementedError | ||||
| pass # TODO: how to do this? | pass # TODO: how to do this? | ||||
| def extract(self, member, path=None): | def extract(self, member, path=None): | ||||
| if path is None: | if path is None: | ||||
| path = os.getcwd() | path = os.getcwd() | ||||
| if isinstance(member, basestring): | |||||
| if isinstance(member, str): | |||||
| f = os.path.join(path, member) | f = os.path.join(path, member) | ||||
| else: | else: | ||||
| f = os.path.join(path, member.pathname) | f = os.path.join(path, member.pathname) | ||||
| @@ -23,7 +23,7 @@ class ZipEntry(Entry): | |||||
| return self.size | return self.size | ||||
| def set_file_size(self, value): | def set_file_size(self, value): | ||||
| assert isinstance(value, (int, long)), 'Please provide size as int or long.' | |||||
| assert isinstance(value, int), 'Please provide size as int or long.' | |||||
| self.size = value | self.size = value | ||||
| file_size = property(get_file_size, set_file_size) | file_size = property(get_file_size, set_file_size) | ||||
| @@ -42,7 +42,7 @@ versrel = version + '-' + release | |||||
| readme = 'README.rst' | readme = 'README.rst' | ||||
| download_url = "http://" + name + ".googlecode.com/files/" + name + "-" + \ | download_url = "http://" + name + ".googlecode.com/files/" + name + "-" + \ | ||||
| versrel + ".tar.gz" | versrel + ".tar.gz" | ||||
| long_description = file(readme).read() | |||||
| long_description = open(readme).read() | |||||
| class build_ext_extra(build_ext, object): | class build_ext_extra(build_ext, object): | ||||
| """ | """ | ||||
| @@ -26,11 +26,13 @@ | |||||
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
| # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| import os, unittest, tempfile, random, string, subprocess | |||||
| import os, unittest, tempfile, random, string, subprocess, sys | |||||
| from libarchive import is_archive_name, is_archive | from libarchive import is_archive_name, is_archive | ||||
| from libarchive.zip import is_zipfile, ZipFile, ZipEntry | from libarchive.zip import is_zipfile, ZipFile, ZipEntry | ||||
| PY3 = sys.version_info[0] == 3 | |||||
| TMPDIR = tempfile.mkdtemp() | TMPDIR = tempfile.mkdtemp() | ||||
| ZIPCMD = '/usr/bin/zip' | ZIPCMD = '/usr/bin/zip' | ||||
| ZIPFILE = 'test.zip' | ZIPFILE = 'test.zip' | ||||
| @@ -47,7 +49,8 @@ FILENAMES = [ | |||||
| def make_temp_files(): | def make_temp_files(): | ||||
| if not os.path.exists(ZIPPATH): | if not os.path.exists(ZIPPATH): | ||||
| for name in FILENAMES: | for name in FILENAMES: | ||||
| file(os.path.join(TMPDIR, name), 'w').write(''.join(random.sample(string.printable, 10))) | |||||
| with open(os.path.join(TMPDIR, name), 'w') as f: | |||||
| f.write(''.join(random.sample(string.ascii_letters, 10))) | |||||
| def make_temp_archive(): | def make_temp_archive(): | ||||
| @@ -93,14 +96,17 @@ class TestIsArchiveTar(unittest.TestCase): | |||||
| class TestZipRead(unittest.TestCase): | class TestZipRead(unittest.TestCase): | ||||
| def setUp(self): | def setUp(self): | ||||
| make_temp_archive() | make_temp_archive() | ||||
| self.f = open(ZIPPATH, mode='r') | |||||
| def tearDown(self): | |||||
| self.f.close() | |||||
| def test_iszipfile(self): | def test_iszipfile(self): | ||||
| self.assertEqual(is_zipfile('/dev/null'), False) | self.assertEqual(is_zipfile('/dev/null'), False) | ||||
| self.assertEqual(is_zipfile(ZIPPATH), True) | self.assertEqual(is_zipfile(ZIPPATH), True) | ||||
| def test_iterate(self): | def test_iterate(self): | ||||
| f = file(ZIPPATH, mode='r') | |||||
| z = ZipFile(f, 'r') | |||||
| z = ZipFile(self.f, 'r') | |||||
| count = 0 | count = 0 | ||||
| for e in z: | for e in z: | ||||
| count += 1 | count += 1 | ||||
| @@ -108,8 +114,7 @@ class TestZipRead(unittest.TestCase): | |||||
| def test_deferred_close_by_archive(self): | def test_deferred_close_by_archive(self): | ||||
| """ Test archive deferred close without a stream. """ | """ Test archive deferred close without a stream. """ | ||||
| f = file(ZIPPATH, mode='r') | |||||
| z = ZipFile(f, 'r') | |||||
| z = ZipFile(self.f, 'r') | |||||
| self.assertIsNotNone(z._a) | self.assertIsNotNone(z._a) | ||||
| self.assertIsNone(z._stream) | self.assertIsNone(z._stream) | ||||
| z.close() | z.close() | ||||
| @@ -117,8 +122,7 @@ class TestZipRead(unittest.TestCase): | |||||
| def test_deferred_close_by_stream(self): | def test_deferred_close_by_stream(self): | ||||
| """ Ensure archive closes self if stream is closed first. """ | """ Ensure archive closes self if stream is closed first. """ | ||||
| f = file(ZIPPATH, mode='r') | |||||
| z = ZipFile(f, 'r') | |||||
| z = ZipFile(self.f, 'r') | |||||
| stream = z.readstream(FILENAMES[0]) | stream = z.readstream(FILENAMES[0]) | ||||
| stream.close() | stream.close() | ||||
| # Make sure archive stays open after stream is closed. | # Make sure archive stays open after stream is closed. | ||||
| @@ -131,8 +135,7 @@ class TestZipRead(unittest.TestCase): | |||||
| def test_close_stream_first(self): | def test_close_stream_first(self): | ||||
| """ Ensure that archive stays open after being closed if a stream is | """ Ensure that archive stays open after being closed if a stream is | ||||
| open. Further, ensure closing the stream closes the archive. """ | open. Further, ensure closing the stream closes the archive. """ | ||||
| f = file(ZIPPATH, mode='r') | |||||
| z = ZipFile(f, 'r') | |||||
| z = ZipFile(self.f, 'r') | |||||
| stream = z.readstream(FILENAMES[0]) | stream = z.readstream(FILENAMES[0]) | ||||
| z.close() | z.close() | ||||
| try: | try: | ||||
| @@ -146,11 +149,13 @@ class TestZipRead(unittest.TestCase): | |||||
| self.assertIsNone(z._stream) | self.assertIsNone(z._stream) | ||||
| def test_filenames(self): | def test_filenames(self): | ||||
| f = file(ZIPPATH, mode='r') | |||||
| z = ZipFile(f, 'r') | |||||
| z = ZipFile(self.f, 'r') | |||||
| names = [] | names = [] | ||||
| for e in z: | for e in z: | ||||
| names.append(e.filename) | |||||
| if PY3: | |||||
| names.append(e.filename) | |||||
| else: | |||||
| names.append(e.filename[0]) | |||||
| self.assertEqual(names, FILENAMES, 'File names differ in archive.') | self.assertEqual(names, FILENAMES, 'File names differ in archive.') | ||||
| #~ def test_non_ascii(self): | #~ def test_non_ascii(self): | ||||
| @@ -163,25 +168,27 @@ class TestZipRead(unittest.TestCase): | |||||
| class TestZipWrite(unittest.TestCase): | class TestZipWrite(unittest.TestCase): | ||||
| def setUp(self): | def setUp(self): | ||||
| make_temp_files() | make_temp_files() | ||||
| self.f = open(ZIPPATH, mode='w') | |||||
| def tearDown(self): | |||||
| self.f.close() | |||||
| def test_writepath(self): | def test_writepath(self): | ||||
| f = file(ZIPPATH, mode='w') | |||||
| z = ZipFile(f, 'w') | |||||
| z = ZipFile(self.f, 'w') | |||||
| for fname in FILENAMES: | for fname in FILENAMES: | ||||
| z.writepath(file(os.path.join(TMPDIR, fname), 'r')) | |||||
| with open(os.path.join(TMPDIR, fname), 'r') as f: | |||||
| z.writepath(f) | |||||
| z.close() | z.close() | ||||
| def test_writepath_directory(self): | def test_writepath_directory(self): | ||||
| """ Test writing a directory. """ | """ Test writing a directory. """ | ||||
| f = file(ZIPPATH, mode='w') | |||||
| z = ZipFile(f, 'w') | |||||
| z = ZipFile(self.f, 'w') | |||||
| z.writepath(None, pathname='/testdir', folder=True) | z.writepath(None, pathname='/testdir', folder=True) | ||||
| z.writepath(None, pathname='/testdir/testinside', folder=True) | z.writepath(None, pathname='/testdir/testinside', folder=True) | ||||
| z.close() | z.close() | ||||
| f.close() | |||||
| self.f.close() | |||||
| f = file(ZIPPATH, mode='r') | |||||
| f = open(ZIPPATH, mode='r') | |||||
| z = ZipFile(f, 'r') | z = ZipFile(f, 'r') | ||||
| entries = z.infolist() | entries = z.infolist() | ||||
| @@ -192,46 +199,52 @@ class TestZipWrite(unittest.TestCase): | |||||
| f.close() | f.close() | ||||
| def test_writestream(self): | def test_writestream(self): | ||||
| f = file(ZIPPATH, mode='w') | |||||
| z = ZipFile(f, 'w') | |||||
| z = ZipFile(self.f, 'w') | |||||
| for fname in FILENAMES: | for fname in FILENAMES: | ||||
| full_path = os.path.join(TMPDIR, fname) | full_path = os.path.join(TMPDIR, fname) | ||||
| i = file(full_path) | |||||
| i = open(full_path) | |||||
| o = z.writestream(fname) | o = z.writestream(fname) | ||||
| while True: | while True: | ||||
| data = i.read(1) | data = i.read(1) | ||||
| if not data: | if not data: | ||||
| break | break | ||||
| o.write(data) | |||||
| if PY3: | |||||
| o.write(data) | |||||
| else: | |||||
| o.write(unicode(data)) | |||||
| o.close() | o.close() | ||||
| i.close() | i.close() | ||||
| z.close() | z.close() | ||||
| def test_writestream_unbuffered(self): | def test_writestream_unbuffered(self): | ||||
| f = file(ZIPPATH, mode='w') | |||||
| z = ZipFile(f, 'w') | |||||
| z = ZipFile(self.f, 'w') | |||||
| for fname in FILENAMES: | for fname in FILENAMES: | ||||
| full_path = os.path.join(TMPDIR, fname) | full_path = os.path.join(TMPDIR, fname) | ||||
| i = file(full_path) | |||||
| i = open(full_path) | |||||
| o = z.writestream(fname, os.path.getsize(full_path)) | o = z.writestream(fname, os.path.getsize(full_path)) | ||||
| while True: | while True: | ||||
| data = i.read(1) | data = i.read(1) | ||||
| if not data: | if not data: | ||||
| break | break | ||||
| o.write(data) | |||||
| if PY3: | |||||
| o.write(data) | |||||
| else: | |||||
| o.write(unicode(data)) | |||||
| o.close() | o.close() | ||||
| i.close() | i.close() | ||||
| z.close() | z.close() | ||||
| def test_deferred_close_by_archive(self): | def test_deferred_close_by_archive(self): | ||||
| """ Test archive deferred close without a stream. """ | """ Test archive deferred close without a stream. """ | ||||
| f = file(ZIPPATH, mode='w') | |||||
| z = ZipFile(f, 'w') | |||||
| z = ZipFile(self.f, 'w') | |||||
| o = z.writestream(FILENAMES[0]) | o = z.writestream(FILENAMES[0]) | ||||
| z.close() | z.close() | ||||
| self.assertIsNotNone(z._a) | self.assertIsNotNone(z._a) | ||||
| self.assertIsNotNone(z._stream) | self.assertIsNotNone(z._stream) | ||||
| o.write('testdata') | |||||
| if PY3: | |||||
| o.write('testdata') | |||||
| else: | |||||
| o.write(unicode('testdata')) | |||||
| o.close() | o.close() | ||||
| self.assertIsNone(z._a) | self.assertIsNone(z._a) | ||||
| self.assertIsNone(z._stream) | self.assertIsNone(z._stream) | ||||