Skip to content

Commit 1d01e07

Browse files
authored
Merge pull request #608 from ethanwharris/fix/localfs_links
Fix support for symbolic links in `LocalFileSystem`
2 parents 490857e + 81c2d22 commit 1d01e07

File tree

2 files changed

+45
-11
lines changed

2 files changed

+45
-11
lines changed

fsspec/implementations/local.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,21 +59,23 @@ def glob(self, path, **kwargs):
5959
def info(self, path, **kwargs):
6060
path = self._strip_protocol(path)
6161
out = os.stat(path, follow_symlinks=False)
62-
dest = False
63-
if os.path.islink(path):
64-
t = "link"
65-
dest = os.readlink(path)
66-
elif os.path.isdir(path):
62+
if os.path.isdir(path):
6763
t = "directory"
6864
elif os.path.isfile(path):
6965
t = "file"
7066
else:
7167
t = "other"
72-
result = {"name": path, "size": out.st_size, "type": t, "created": out.st_ctime}
68+
result = {
69+
"name": path,
70+
"size": out.st_size,
71+
"type": t,
72+
"created": out.st_ctime,
73+
"islink": os.path.islink(path),
74+
}
7375
for field in ["mode", "uid", "gid", "mtime"]:
7476
result[field] = getattr(out, "st_" + field)
75-
if dest:
76-
result["destination"] = dest
77+
if result["islink"]:
78+
result["destination"] = os.readlink(path)
7779
try:
7880
out2 = os.stat(path, follow_symlinks=True)
7981
result["size"] = out2.st_size

fsspec/implementations/tests/test_local.py

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ def test_make_path_posix():
450450
assert "/" in make_path_posix("rel\\path", sep="\\")
451451

452452

453-
def test_links(tmpdir):
453+
def test_linked_files(tmpdir):
454454
tmpdir = str(tmpdir)
455455
fn0 = os.path.join(tmpdir, "target")
456456
fn1 = os.path.join(tmpdir, "link1")
@@ -469,8 +469,12 @@ def test_links(tmpdir):
469469

470470
fs = LocalFileSystem()
471471
assert fs.info(fn0)["type"] == "file"
472-
assert fs.info(fn1)["type"] == "link"
473-
assert fs.info(fn2)["type"] == "link"
472+
assert fs.info(fn1)["type"] == "file"
473+
assert fs.info(fn2)["type"] == "file"
474+
475+
assert not fs.info(fn0)["islink"]
476+
assert fs.info(fn1)["islink"]
477+
assert fs.info(fn2)["islink"]
474478

475479
assert fs.info(fn0)["size"] == len(data)
476480
assert fs.info(fn1)["size"] == len(data)
@@ -485,6 +489,34 @@ def test_links(tmpdir):
485489
assert f.read() == data
486490

487491

492+
def test_linked_directories(tmpdir):
493+
tmpdir = str(tmpdir)
494+
495+
subdir0 = os.path.join(tmpdir, "target")
496+
subdir1 = os.path.join(tmpdir, "link1")
497+
subdir2 = os.path.join(tmpdir, "link2")
498+
499+
os.makedirs(subdir0)
500+
501+
try:
502+
os.symlink(subdir0, subdir1)
503+
os.symlink(subdir0, subdir2)
504+
except OSError:
505+
if WIN:
506+
pytest.xfail("Ran on win without admin permissions")
507+
else:
508+
raise
509+
510+
fs = LocalFileSystem()
511+
assert fs.info(subdir0)["type"] == "directory"
512+
assert fs.info(subdir1)["type"] == "directory"
513+
assert fs.info(subdir2)["type"] == "directory"
514+
515+
assert not fs.info(subdir0)["islink"]
516+
assert fs.info(subdir1)["islink"]
517+
assert fs.info(subdir2)["islink"]
518+
519+
488520
def test_isfilestore():
489521
fs = LocalFileSystem(auto_mkdir=False)
490522
assert fs._isfilestore()

0 commit comments

Comments
 (0)