Skip to content

Commit 59a2d64

Browse files
uermelmartindurant
andauthored
Add auto_mkdir argument to SMBFileSystem (#1604)
Co-authored-by: Martin Durant <[email protected]>
1 parent 0a37adc commit 59a2d64

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

fsspec/implementations/smb.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ def __init__(
6868
encrypt=None,
6969
share_access=None,
7070
register_session_retries=5,
71+
auto_mkdir=False,
7172
**kwargs,
7273
):
7374
"""
@@ -102,6 +103,10 @@ def __init__(
102103
- 'r': Allow other handles to be opened with read access.
103104
- 'w': Allow other handles to be opened with write access.
104105
- 'd': Allow other handles to be opened with delete access.
106+
auto_mkdir: bool
107+
Whether, when opening a file, the directory containing it should
108+
be created (if it doesn't already exist). This is assumed by pyarrow
109+
and zarr-python code.
105110
"""
106111
super().__init__(**kwargs)
107112
self.host = host
@@ -113,6 +118,7 @@ def __init__(
113118
self.temppath = kwargs.pop("temppath", "")
114119
self.share_access = share_access
115120
self.register_session_retries = register_session_retries
121+
self.auto_mkdir = auto_mkdir
116122
self._connect()
117123

118124
@property
@@ -224,6 +230,8 @@ def _open(
224230
By specifying 'share_access' in 'kwargs' it is possible to override the
225231
default shared access setting applied in the constructor of this object.
226232
"""
233+
if self.auto_mkdir and "w" in mode:
234+
self.makedirs(self._parent(path), exist_ok=True)
227235
bls = block_size if block_size is not None and block_size >= 0 else -1
228236
wpath = _as_unc_path(self.host, path)
229237
share_access = kwargs.pop("share_access", self.share_access)
@@ -245,6 +253,8 @@ def copy(self, path1, path2, **kwargs):
245253
"""Copy within two locations in the same filesystem"""
246254
wpath1 = _as_unc_path(self.host, path1)
247255
wpath2 = _as_unc_path(self.host, path2)
256+
if self.auto_mkdir:
257+
self.makedirs(self._parent(path2), exist_ok=True)
248258
smbclient.copyfile(wpath1, wpath2, port=self._port, **kwargs)
249259

250260
def _rm(self, path):

fsspec/implementations/tests/test_smb.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,33 @@ def test_simple(smb_params):
8989
assert not fsmb.exists(adir)
9090

9191

92+
@pytest.mark.flaky(reruns=2, reruns_delay=2)
93+
def test_auto_mkdir(smb_params):
94+
adir = "/home/adir"
95+
adir2 = "/home/adir/otherdir/"
96+
afile = "/home/adir/otherdir/afile"
97+
fsmb = fsspec.get_filesystem_class("smb")(**smb_params, auto_mkdir=True)
98+
fsmb.touch(afile)
99+
assert fsmb.exists(adir)
100+
assert fsmb.exists(adir2)
101+
assert fsmb.exists(afile)
102+
assert fsmb.info(afile)["type"] == "file"
103+
104+
another_dir = "/home/another_dir"
105+
another_dir2 = "/home/another_dir/another_nested_dir/"
106+
another_file = "/home/another_dir/another_nested_dir/another_file"
107+
fsmb.copy(afile, another_file)
108+
assert fsmb.exists(another_dir)
109+
assert fsmb.exists(another_dir2)
110+
assert fsmb.exists(another_file)
111+
assert fsmb.info(another_file)["type"] == "file"
112+
113+
fsmb.rm(adir, recursive=True)
114+
fsmb.rm(another_dir, recursive=True)
115+
assert not fsmb.exists(adir)
116+
assert not fsmb.exists(another_dir)
117+
118+
92119
@pytest.mark.flaky(reruns=2, reruns_delay=2)
93120
def test_with_url(smb_params):
94121
if smb_params["port"] is None:

0 commit comments

Comments
 (0)