Skip to content

Commit ab1e39c

Browse files
authored
Merge pull request fsspec#662 from martindurant/after_release
Feedback after release
2 parents 0f700d4 + 2c2d202 commit ab1e39c

File tree

4 files changed

+42
-44
lines changed

4 files changed

+42
-44
lines changed

fsspec/implementations/local.py

+16-12
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,7 @@ def glob(self, path, **kwargs):
5858
return super().glob(path, **kwargs)
5959

6060
def info(self, path, **kwargs):
61-
if isinstance(path, str):
62-
path = self._strip_protocol(path)
63-
out = os.stat(path, follow_symlinks=False)
64-
link = os.path.islink(path)
65-
if os.path.isdir(path):
66-
t = "directory"
67-
elif os.path.isfile(path):
68-
t = "file"
69-
else:
70-
t = "other"
71-
else:
61+
if hasattr(path, "stat"):
7262
# scandir DirEntry
7363
out = path.stat(follow_symlinks=False)
7464
link = path.is_symlink()
@@ -79,6 +69,17 @@ def info(self, path, **kwargs):
7969
else:
8070
t = "other"
8171
path = self._strip_protocol(path.path)
72+
else:
73+
# str or path-like
74+
path = self._strip_protocol(path)
75+
out = os.stat(path, follow_symlinks=False)
76+
link = os.path.islink(path)
77+
if os.path.isdir(path):
78+
t = "directory"
79+
elif os.path.isfile(path):
80+
t = "file"
81+
else:
82+
t = "other"
8283
result = {
8384
"name": path,
8485
"size": out.st_size,
@@ -123,6 +124,9 @@ def mv_file(self, path1, path2, **kwargs):
123124
def rm(self, path, recursive=False, maxdepth=None):
124125
path = self._strip_protocol(path).rstrip("/")
125126
if recursive and self.isdir(path):
127+
128+
if os.path.abspath(path) == os.getcwd():
129+
raise ValueError("Cannot delete current working directory")
126130
shutil.rmtree(path)
127131
else:
128132
os.remove(path)
@@ -163,7 +167,7 @@ def _strip_protocol(cls, path):
163167
path = stringify_path(path)
164168
if path.startswith("file://"):
165169
path = path[7:]
166-
return make_path_posix(path)
170+
return make_path_posix(path).rstrip("/")
167171

168172
def _isfilestore(self):
169173
# Inheriting from DaskFileSystem makes this False (S3, etc. were)

fsspec/implementations/tests/test_local.py

+12
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,7 @@ def test_strip_protocol_expanduser():
567567
assert path != stripped
568568
assert "file://" not in stripped
569569
assert stripped.startswith(os.path.expanduser("~").replace("\\", "/"))
570+
assert not LocalFileSystem._strip_protocol("./").endswith("/")
570571

571572

572573
def test_iterable(tmpdir):
@@ -665,6 +666,17 @@ def test_transaction(tmpdir):
665666
assert content == read_content
666667

667668

669+
def test_delete_cwd(tmpdir):
670+
cwd = os.getcwd()
671+
fs = LocalFileSystem()
672+
try:
673+
os.chdir(tmpdir)
674+
with pytest.raises(ValueError):
675+
fs.rm(".", recursive=True)
676+
finally:
677+
os.chdir(cwd)
678+
679+
668680
@pytest.mark.parametrize(
669681
"opener, ext", [(bz2.open, ".bz2"), (gzip.open, ".gz"), (open, "")]
670682
)

fsspec/registry.py

+14-16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import importlib
2-
from distutils.version import LooseVersion
32

43
__all__ = ["registry", "get_filesystem_class", "default"]
54

@@ -187,8 +186,6 @@ def register_implementation(name, cls, clobber=True, errtxt=None):
187186
"reference": {"class": "fsspec.implementations.reference.ReferenceFileSystem"},
188187
}
189188

190-
minversions = {"s3fs": LooseVersion("0.3.0"), "gcsfs": LooseVersion("0.3.0")}
191-
192189

193190
def get_filesystem_class(protocol):
194191
"""Fetch named protocol implementation from the registry
@@ -221,19 +218,20 @@ def get_filesystem_class(protocol):
221218

222219

223220
def _import_class(cls, minv=None):
224-
mod, name = cls.rsplit(".", 1)
225-
minv = minv or minversions
226-
minversion = minv.get(mod, None)
227-
228-
mod = importlib.import_module(mod)
229-
if minversion:
230-
version = getattr(mod, "__version__", None)
231-
if version and LooseVersion(version) < minversion:
232-
raise RuntimeError(
233-
"'{}={}' is installed, but version '{}' or "
234-
"higher is required".format(mod.__name__, version, minversion)
235-
)
236-
return getattr(mod, name)
221+
"""Take a string FQP and return the imported class or identifier
222+
223+
clas is of the form "package.module.klass" or "package.module:subobject.klass"
224+
"""
225+
if ":" in cls:
226+
mod, name = cls.rsplit(":", 1)
227+
mod = importlib.import_module(mod)
228+
for part in name.split("."):
229+
mod = getattr(mod, part)
230+
return mod
231+
else:
232+
mod, name = cls.rsplit(".", 1)
233+
mod = importlib.import_module(mod)
234+
return getattr(mod, name)
237235

238236

239237
def filesystem(protocol, **storage_options):

fsspec/tests/test_registry.py

-16
Original file line numberDiff line numberDiff line change
@@ -38,22 +38,6 @@ def clean_imports():
3838
sys.modules["fsspec"] = real_module
3939

4040

41-
@pytest.mark.parametrize(
42-
"protocol,module,minversion,oldversion",
43-
[("s3", "s3fs", "0.3.0", "0.1.0"), ("gs", "gcsfs", "0.3.0", "0.1.0")],
44-
)
45-
def test_minversion_s3fs(protocol, module, minversion, oldversion, monkeypatch):
46-
_registry.clear()
47-
mod = pytest.importorskip(module, minversion)
48-
49-
assert get_filesystem_class("s3") is not None
50-
_registry.clear()
51-
52-
monkeypatch.setattr(mod, "__version__", oldversion)
53-
with pytest.raises(RuntimeError, match=minversion):
54-
get_filesystem_class(protocol)
55-
56-
5741
def test_registry_readonly():
5842
get_filesystem_class("file")
5943
assert "file" in registry

0 commit comments

Comments
 (0)