Browse Source

Merge pull request #9 from smartfile/python3

Python 3
test_fixup
Jessica Hair 5 years ago
committed by GitHub
parent
commit
59030cb6bf
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 121 additions and 81 deletions
  1. +1
    -0
      .gitignore
  2. +8
    -6
      .travis.yml
  3. +6
    -0
      Makefile
  4. +6
    -6
      docs/conf.py
  5. +2
    -6
      libarchive/Makefile
  6. +39
    -24
      libarchive/__init__.py
  7. +1
    -1
      libarchive/_libarchive.i
  8. +9
    -2
      libarchive/_libarchive_wrap.c
  9. +2
    -2
      libarchive/tar.py
  10. +1
    -1
      libarchive/zip.py
  11. +1
    -1
      setup.py
  12. +45
    -32
      tests.py

+ 1
- 0
.gitignore View File

@@ -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

+ 8
- 6
.travis.yml View File

@@ -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:


+ 6
- 0
Makefile View File

@@ -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

+ 6
- 6
docs/conf.py View File

@@ -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)
] ]

+ 2
- 6
libarchive/Makefile View File

@@ -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




+ 39
- 24
libarchive/__init__.py View File

@@ -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)




+ 1
- 1
libarchive/_libarchive.i View File

@@ -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;
} }


+ 9
- 2
libarchive/_libarchive_wrap.c View File

@@ -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;


+ 2
- 2
libarchive/tar.py View File

@@ -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)


+ 1
- 1
libarchive/zip.py View File

@@ -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)


+ 1
- 1
setup.py View File

@@ -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):
""" """


+ 45
- 32
tests.py View File

@@ -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)


Loading…
Cancel
Save