@@ -287,53 +287,84 @@ def ZipFile(*args, **kwargs):
287287 ZipFile = zipfile .ZipFile
288288
289289
290- def _get_handle (path , mode , encoding = None , compression = None , memory_map = False ):
290+ def _get_handle (source , mode , encoding = None , compression = None , memory_map = False ):
291291 """Gets file handle for given path and mode.
292292 """
293- if compression is not None :
294- if encoding is not None and not compat .PY3 :
293+
294+ f = source
295+ is_path = isinstance (source , compat .string_types )
296+
297+ # in Python 3, convert BytesIO or fileobjects passed with an encoding
298+ if compat .PY3 and isinstance (source , compat .BytesIO ):
299+ from io import TextIOWrapper
300+
301+ return TextIOWrapper (source , encoding = encoding )
302+
303+ elif compression is not None :
304+ compression = compression .lower ()
305+ if encoding is not None and not compat .PY3 and not is_path :
295306 msg = 'encoding + compression not yet supported in Python 2'
296307 raise ValueError (msg )
297308
309+ # GZ Compression
298310 if compression == 'gzip' :
299311 import gzip
300- f = gzip .GzipFile (path , mode )
312+
313+ f = gzip .GzipFile (source , mode ) \
314+ if is_path else gzip .GzipFile (fileobj = source )
315+
316+ # BZ Compression
301317 elif compression == 'bz2' :
302318 import bz2
303- f = bz2 .BZ2File (path , mode )
319+
320+ if is_path :
321+ f = bz2 .BZ2File (source , mode )
322+
323+ else :
324+ f = bz2 .BZ2File (source ) if compat .PY3 else StringIO (
325+ bz2 .decompress (source .read ()))
326+ # Python 2's bz2 module can't take file objects, so have to
327+ # run through decompress manually
328+
329+ # ZIP Compression
304330 elif compression == 'zip' :
305331 import zipfile
306- zip_file = zipfile .ZipFile (path )
332+ zip_file = zipfile .ZipFile (source )
307333 zip_names = zip_file .namelist ()
308334
309335 if len (zip_names ) == 1 :
310- file_name = zip_names .pop ()
311- f = zip_file .open (file_name )
336+ f = zip_file .open (zip_names .pop ())
312337 elif len (zip_names ) == 0 :
313338 raise ValueError ('Zero files found in ZIP file {}'
314- .format (path ))
339+ .format (source ))
315340 else :
316341 raise ValueError ('Multiple files found in ZIP file.'
317342 ' Only one file per ZIP :{}'
318343 .format (zip_names ))
344+
345+ # XZ Compression
319346 elif compression == 'xz' :
320347 lzma = compat .import_lzma ()
321- f = lzma .LZMAFile (path , mode )
348+ f = lzma .LZMAFile (source , mode )
349+
322350 else :
323- raise ValueError ('Unrecognized compression type : %s' %
324- compression )
351+ raise ValueError ('Unrecognized compression: %s' % compression )
352+
325353 if compat .PY3 :
326354 from io import TextIOWrapper
355+
327356 f = TextIOWrapper (f , encoding = encoding )
357+
328358 return f
329- else :
359+
360+ elif is_path :
330361 if compat .PY3 :
331362 if encoding :
332- f = open (path , mode , encoding = encoding )
363+ f = open (source , mode , encoding = encoding )
333364 else :
334- f = open (path , mode , errors = 'replace' )
365+ f = open (source , mode , errors = 'replace' )
335366 else :
336- f = open (path , mode )
367+ f = open (source , mode )
337368
338369 if memory_map and hasattr (f , 'fileno' ):
339370 try :
0 commit comments