Skip to content

Fix symlink handling in OSFS #431

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
8 changes: 5 additions & 3 deletions fs/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import six

from . import copy, errors, fsencode, iotools, move, tools, walk, wildcard
from .enums import ResourceType
from .glob import BoundGlobber
from .mode import validate_open_mode
from .path import abspath, join, normpath
Expand Down Expand Up @@ -49,7 +50,6 @@
Union,
)
from types import TracebackType
from .enums import ResourceType
from .info import Info, RawInfo
from .subfs import SubFS
from .permissions import Permissions
Expand Down Expand Up @@ -981,8 +981,10 @@ def islink(self, path):
bool: `True` if ``path`` maps to a symlink.

"""
self.getinfo(path)
return False
try:
return self.gettype(path) == ResourceType.symlink
except errors.ResourceNotFound:
return False

def lock(self):
# type: () -> RLock
Expand Down
4 changes: 1 addition & 3 deletions fs/osfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ def gettype(self, path):
self.check()
sys_path = self._to_sys_path(path)
with convert_os_errors("gettype", path):
stat = os.stat(sys_path)
stat = os.lstat(sys_path)
resource_type = self._get_type_from_stat(stat)
return resource_type

Expand All @@ -608,8 +608,6 @@ def islink(self, path):
self.check()
_path = self.validatepath(path)
sys_path = self._to_sys_path(_path)
if not self.exists(path):
raise errors.ResourceNotFound(path)
with convert_os_errors("islink", path):
return os.path.islink(sys_path)

Expand Down
3 changes: 1 addition & 2 deletions fs/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,7 @@ def test_isdir(self):
def test_islink(self):
self.fs.touch("foo")
self.assertFalse(self.fs.islink("foo"))
with self.assertRaises(errors.ResourceNotFound):
self.fs.islink("bar")
self.assertFalse(self.fs.islink("bar"))

def test_getsize(self):
self.fs.writebytes("empty", b"")
Expand Down
17 changes: 17 additions & 0 deletions tests/test_osfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import pytest

from fs import osfs, open_fs
from fs.enums import ResourceType
from fs.path import relpath, dirname
from fs import errors
from fs.test import FSTestCases
Expand Down Expand Up @@ -203,3 +204,19 @@ def test_complex_geturl(self):

def test_geturl_return_no_url(self):
self.assertRaises(errors.NoURL, self.fs.geturl, "test/path", "upload")

@pytest.mark.skipif(not hasattr(os, "symlink"), reason="No symlink support")
def test_symlinks_dangling(self):
self.fs.create("a")
os.symlink(self.fs.getsyspath("a"), self.fs.getsyspath("b"))

self.assertTrue(self.fs.exists("a"))
self.assertFalse(self.fs.islink("a"))
self.assertEqual(self.fs.gettype("a"), ResourceType.file)
self.assertTrue(self.fs.exists("b"))
self.assertTrue(self.fs.islink("b"))
self.assertEqual(self.fs.gettype("b"), ResourceType.symlink)

self.fs.remove("a")
self.assertTrue(self.fs.islink("b"))
self.assertEqual(self.fs.gettype("b"), ResourceType.symlink)