Skip to content

Commit

Permalink
Merge pull request markokr#49 from WouldYouKindly/support-path
Browse files Browse the repository at this point in the history
Added support for passing filenames as pathlib.Path objects to Rarfile
  • Loading branch information
markokr authored Sep 15, 2019
2 parents 2704344 + f59ea9d commit 260c476
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 3 deletions.
25 changes: 23 additions & 2 deletions rarfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@ def tohex(data):
if sys.hexversion < 0x2070000:
memoryview = lambda x: x # noqa

try:
from pathlib import Path
_have_pathlib = True
except ImportError:
_have_pathlib = False

__version__ = '3.0'

# export only interesting items
Expand Down Expand Up @@ -655,7 +661,11 @@ def __init__(self, rarfile, mode="r", charset=None, info_callback=None,
Either "stop" to quietly stop parsing on errors,
or "strict" to raise errors. Default is "stop".
"""
self._rarfile = rarfile
if _have_pathlib and isinstance(rarfile, Path):
self._rarfile = str(rarfile)
else:
self._rarfile = rarfile

self._charset = charset or DEFAULT_CHARSET
self._info_callback = info_callback
self._crc_check = crc_check
Expand Down Expand Up @@ -803,6 +813,8 @@ def extract(self, member, path=None, pwd=None):
"""
if isinstance(member, RarInfo):
fname = member.filename
elif _have_pathlib and isinstance(member, Path):
fname = str(member)
else:
fname = member
self._extract([fname], path, pwd)
Expand Down Expand Up @@ -888,6 +900,8 @@ def _extract(self, fnlist, path=None, psw=None):

# destination path
if path is not None:
if _have_pathlib and isinstance(path, Path):
path = str(path)
cmd.append(path + os.sep)

# call
Expand Down Expand Up @@ -957,6 +971,8 @@ def getinfo(self, member):
"""
if isinstance(member, RarInfo):
fname = member.filename
elif _have_pathlib and isinstance(member, Path):
fname = str(member)
else:
fname = member

Expand Down Expand Up @@ -2728,7 +2744,12 @@ def _parse_xtime(flag, data, pos, basetime=None):
def is_filelike(obj):
"""Filename or file object?
"""
if isinstance(obj, (bytes, unicode)):
if _have_pathlib:
filename_types = (bytes, unicode, Path)
else:
filename_types = (bytes, unicode)

if isinstance(obj, filename_types):
return False
res = True
for a in ('read', 'tell', 'seek'):
Expand Down
25 changes: 24 additions & 1 deletion test/test_api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""API tests.
"""

import sys
import io
import os
Expand All @@ -9,6 +8,9 @@

import rarfile

if rarfile._have_pathlib:
from pathlib import Path

#
# test start
#
Expand Down Expand Up @@ -49,6 +51,11 @@ def test_open_psw_late_rar5():
rf.open('stest1.txt', 'r', 'password').read()
rf.open('stest1.txt', 'r', u'password').read()

if rarfile._have_pathlib:
def test_open_pathlib_path():
rf = rarfile.RarFile('test/files/rar5-psw.rar')
rf.open(Path('stest1.txt'), 'r', 'password').read()

def test_read_psw_late_rar3():
rf = rarfile.RarFile('test/files/rar3-comment-psw.rar')
rf.read('file1.txt', 'password')
Expand All @@ -64,11 +71,21 @@ def test_open_psw_late():
rf = rarfile.RarFile('test/files/rar5-psw.rar')
rf.read('stest1.txt', 'password222')

if rarfile._have_pathlib:
def test_create_from_pathlib_path():
# Make sure we can open both relative and absolute Paths
rarfile.RarFile(Path('test/files/rar5-psw.rar'))
rarfile.RarFile(Path('test/files/rar5-psw.rar').resolve())

def test_detection():
eq_(rarfile.is_rarfile('test/files/ctime4.rar.exp'), False)
eq_(rarfile.is_rarfile('test/files/ctime4.rar'), True)
eq_(rarfile.is_rarfile('test/files/rar5-crc.rar'), True)

if rarfile._have_pathlib:
eq_(rarfile.is_rarfile(Path('test/files/rar5-crc.rar')), True)


@raises(rarfile.BadRarFile)
def test_signature_error():
rarfile.RarFile('test/files/ctime4.rar.exp')
Expand Down Expand Up @@ -169,6 +186,12 @@ def test_extract():
rf.extractall('tmp/extract3', [rf.getinfo('stest2.txt')])
assert_true(os.path.isfile('tmp/extract3/stest2.txt'))

if rarfile._have_pathlib:
os.makedirs('tmp/extract1_pathlib')
rf.extractall(Path('tmp/extract1'))
assert_true(os.path.isfile('tmp/extract1/stest1.txt'))
assert_true(os.path.isfile('tmp/extract1/stest2.txt'))

@with_setup(clean_extract_dirs, clean_extract_dirs)
def test_extract_mem():
os.makedirs('tmp/extract1')
Expand Down

0 comments on commit 260c476

Please sign in to comment.