Skip to content

Commit 2735215

Browse files
authored
fix for tarfs '.' exception (#281)
* fix for tarfs '.' exception * fix py27 tarfs decoding * version bump, docstrings
1 parent 5f0a475 commit 2735215

File tree

5 files changed

+49
-5
lines changed

5 files changed

+49
-5
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1010
### Fixed
1111

1212
- Restored deprecated `setfile` method with deprecation warning to change to `writefile`
13+
- Fixed exception when a tarfile contains a path called '.' https://github.com/PyFilesystem/pyfilesystem2/issues/275
14+
- Made TarFS directory loading lazy
15+
16+
### Changed
17+
18+
- Removed case_insensitive meta value from OSFS meta on OSX. normcase check doesn't work on OSX (https://stackoverflow.com/questions/7870041/check-if-file-system-is-case-insensitive-in-python)
1319

1420
## [2.4.4] - 2019-02-23
1521

fs/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""Version, used in module and setup.py.
22
"""
3-
__version__ = "2.4.5a0"
3+
__version__ = "2.4.5"

fs/osfs.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@ def __init__(
143143
"virtual": False,
144144
}
145145

146+
if platform.system() == "Darwin":
147+
# Standard test doesn't work on OSX.
148+
# Best we can say is we don't know.
149+
del _meta["case_insensitive"]
150+
146151
if _WINDOWS_PLATFORM: # pragma: no cover
147152
_meta["invalid_path_chars"] = (
148153
"".join(six.unichr(n) for n in range(31)) + '\\:*?"<>|'

fs/tarfs.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from .info import Info
2121
from .iotools import RawWrapper
2222
from .opener import open_fs
23-
from .path import dirname, relpath, basename, isbase, parts, frombase
23+
from .path import dirname, relpath, basename, isbase, normpath, parts, frombase
2424
from .wrapfs import WrapFS
2525
from .permissions import Permissions
2626

@@ -272,9 +272,18 @@ def __init__(self, file, encoding="utf-8"):
272272
else:
273273
self._tar = tarfile.open(fileobj=file, mode="r")
274274

275-
self._directory = OrderedDict(
276-
(relpath(self._decode(info.name)).rstrip("/"), info) for info in self._tar
277-
)
275+
self._directory_cache = None
276+
277+
@property
278+
def _directory(self):
279+
"""Lazy directory cache."""
280+
if self._directory_cache is None:
281+
_decode = self._decode
282+
_directory = ((_decode(info.name).strip("/"), info) for info in self._tar)
283+
self._directory_cache = OrderedDict(
284+
(name, info) for name, info in _directory if normpath(name)
285+
)
286+
return self._directory_cache
278287

279288
def __repr__(self):
280289
# type: () -> Text

tests/test_tarfs.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,30 @@ def test_getinfo(self):
188188
self.assertTrue(top.get("tar", "is_file"))
189189

190190

191+
class TestBrokenDir(unittest.TestCase):
192+
@classmethod
193+
def setUpClass(cls):
194+
cls.tmpfs = open_fs("temp://tarfstest")
195+
196+
@classmethod
197+
def tearDownClass(cls):
198+
cls.tmpfs.close()
199+
200+
def setUp(self):
201+
self.tempfile = self.tmpfs.open("test.tar", "wb+")
202+
with tarfile.open(mode="w", fileobj=self.tempfile) as tf:
203+
tf.addfile(tarfile.TarInfo("."), io.StringIO)
204+
self.tempfile.seek(0)
205+
self.fs = tarfs.TarFS(self.tempfile)
206+
207+
def tearDown(self):
208+
self.fs.close()
209+
self.tempfile.close()
210+
211+
def test_listdir(self):
212+
self.assertEqual(self.fs.listdir("/"), [])
213+
214+
191215
class TestImplicitDirectories(unittest.TestCase):
192216
"""Regression tests for #160.
193217
"""

0 commit comments

Comments
 (0)