From f9471b7aa717d29836da11a0736d950f70deca3e Mon Sep 17 00:00:00 2001 From: Norman Rzepka Date: Mon, 8 Aug 2022 13:07:27 +0200 Subject: [PATCH 01/14] Add Python 3.11 testing --- .github/workflows/python.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 5d68c53a..f89cf9e7 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -7,7 +7,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.7, 3.8, 3.9, "3.10"] + python-version: [3.7, 3.8, 3.9, "3.10", "3.11"] os: [ubuntu-latest, windows-latest] steps: From 20b54f1d8cf85533c5d62e9adf73ccbed7fdbe75 Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Sun, 7 Aug 2022 21:56:57 +0200 Subject: [PATCH 02/14] upath.core: fix python3.11 compatibility mkdir was the one method broken by moving away from _accessors in Python3.11 --- upath/core.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/upath/core.py b/upath/core.py index 058643d4..b52c0650 100644 --- a/upath/core.py +++ b/upath/core.py @@ -342,6 +342,19 @@ def readlink(self): def touch(self, truncate=True, **kwargs): self._accessor.touch(self, truncate=truncate, **kwargs) + def mkdir(self, mode=0o777, parents=False, exist_ok=False): + """ + Create a new directory at this given path. + """ + if parents: + self._accessor.mkdir(self, create_parents=parents, exist_ok=exist_ok, permissions=mode) + else: + try: + self._accessor.mkdir(self, create_parents=False) + except OSError: + if not exist_ok or not self.is_dir(): + raise + @classmethod def _from_parts(cls, args, url=None, **kwargs): obj = object.__new__(cls) From b1c5680739b820a1d29b2de7e3cfa87003a33ab3 Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Sun, 7 Aug 2022 21:59:36 +0200 Subject: [PATCH 03/14] upath.core: explictly disable more methods broken by Python3.11 --- upath/core.py | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/upath/core.py b/upath/core.py index b52c0650..4b0764a4 100644 --- a/upath/core.py +++ b/upath/core.py @@ -29,7 +29,7 @@ def __init__(self, parsed_url: ParseResult, **kwargs): def _format_path(self, path: "UPath") -> str: return path.path - def open(self, path, mode='r', *args, **kwargs): + def open(self, path, mode="r", *args, **kwargs): return self._fs.open(self._format_path(path), mode, *args, **kwargs) def stat(self, path, **kwargs): @@ -185,6 +185,9 @@ def parent(self): def stat(self): return self._accessor.stat(self) + def samefile(self, other_path): + raise NotImplementedError + def iterdir(self): """Iterate over the files in this directory. Does not yield any result for the special paths '.' and '..'. @@ -223,6 +226,10 @@ def relative_to(self, *other): output._kwargs = self._kwargs return output + def _scandir(self): + # provided in Python3.11 but not required in fsspec glob implementation + raise NotImplementedError + def glob(self, pattern): path_pattern = self.joinpath(pattern) for name in self._accessor.glob(self, path_pattern): @@ -230,11 +237,25 @@ def glob(self, pattern): name = name.split(self._flavour.sep) yield self._make_child(name) + def rglob(self, pattern): + path_pattern = self.joinpath("**", pattern) + for name in self._accessor.glob(self, path_pattern): + name = self._sub_path(name) + name = name.split(self._flavour.sep) + yield self._make_child(name) + def _sub_path(self, name): # only want the path name with iterdir sp = self.path return re.sub(f"^({sp}|{sp[1:]})/", "", name) + def absolute(self): + # fsspec paths are always absolute + return self + + def resolve(self, strict=False): + raise NotImplementedError + def exists(self): """ Whether this path exists. @@ -290,6 +311,9 @@ def is_block_device(self): def is_char_device(self): return False + def is_absolute(self): + return True + def unlink(self, missing_ok=False): if not self.exists(): if not missing_ok: @@ -308,13 +332,25 @@ def rmdir(self, recursive=True): raise NotDirectoryError self._accessor.rm(self, recursive=recursive) - def chmod(self, mod): + def chmod(self, mode, *, follow_symlinks=True): raise NotImplementedError def rename(self, target): # can be implemented, but may be tricky raise NotImplementedError + def replace(self, target): + raise NotImplementedError + + def symlink_to(self, target, target_is_directory=False): + raise NotImplementedError + + def hardlink_to(self, target): + raise NotImplementedError + + def link_to(self, target): + raise NotImplementedError + def cwd(self): raise NotImplementedError @@ -347,7 +383,12 @@ def mkdir(self, mode=0o777, parents=False, exist_ok=False): Create a new directory at this given path. """ if parents: - self._accessor.mkdir(self, create_parents=parents, exist_ok=exist_ok, permissions=mode) + self._accessor.mkdir( + self, + create_parents=parents, + exist_ok=exist_ok, + permissions=mode, + ) else: try: self._accessor.mkdir(self, create_parents=False) From 0ca10006bdbf9e1ad80adfe8674b3c027d7c05ac Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Tue, 9 Aug 2022 08:19:55 +0200 Subject: [PATCH 04/14] tests: add tests for mkdir exist_ok --- upath/tests/cases.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/upath/tests/cases.py b/upath/tests/cases.py index ffd90117..26dcf28a 100644 --- a/upath/tests/cases.py +++ b/upath/tests/cases.py @@ -126,6 +126,17 @@ def test_mkdir(self): new_dir.mkdir() assert new_dir.exists() + def test_mkdir_exists_ok_true(self): + new_dir = self.path.joinpath("new_dir_may_exists") + new_dir.mkdir() + new_dir.mkdir(exist_ok=True) + + def test_mkdir_exists_ok_false(self): + new_dir = self.path.joinpath("new_dir_may_not_exists") + new_dir.mkdir() + with pytest.raises(FileExistsError): + new_dir.mkdir(exist_ok=False) + def test_open(self): pass From 3d95df33e1cbbfa03db3d3b5912f446a92a800ea Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Tue, 9 Aug 2022 08:21:44 +0200 Subject: [PATCH 05/14] tests: cloud filesystems require a file for dirs --- upath/tests/cases.py | 8 ++++++++ upath/tests/implementations/test_azure.py | 10 +++------- upath/tests/implementations/test_gcs.py | 7 ++----- upath/tests/implementations/test_s3.py | 10 ++-------- 4 files changed, 15 insertions(+), 20 deletions(-) diff --git a/upath/tests/cases.py b/upath/tests/cases.py index 26dcf28a..2777d76d 100644 --- a/upath/tests/cases.py +++ b/upath/tests/cases.py @@ -9,6 +9,8 @@ class BaseTests: + MKDIR_REQUIRES_FILE = False + def test_cwd(self): with pytest.raises(NotImplementedError): self.path.cwd() @@ -124,16 +126,22 @@ def test_lstat(self): def test_mkdir(self): new_dir = self.path.joinpath("new_dir") new_dir.mkdir() + if self.MKDIR_REQUIRES_FILE: + new_dir.joinpath(".file").touch() assert new_dir.exists() def test_mkdir_exists_ok_true(self): new_dir = self.path.joinpath("new_dir_may_exists") new_dir.mkdir() + if self.MKDIR_REQUIRES_FILE: + new_dir.joinpath(".file").touch() new_dir.mkdir(exist_ok=True) def test_mkdir_exists_ok_false(self): new_dir = self.path.joinpath("new_dir_may_not_exists") new_dir.mkdir() + if self.MKDIR_REQUIRES_FILE: + new_dir.joinpath(".file").touch() with pytest.raises(FileExistsError): new_dir.mkdir(exist_ok=False) diff --git a/upath/tests/implementations/test_azure.py b/upath/tests/implementations/test_azure.py index f5fd293f..1c89c55e 100644 --- a/upath/tests/implementations/test_azure.py +++ b/upath/tests/implementations/test_azure.py @@ -10,6 +10,8 @@ @skip_on_windows @pytest.mark.usefixtures("path") class TestAzurePath(BaseTests): + MKDIR_REQUIRES_FILE = True + @pytest.fixture(autouse=True, scope="function") def path(self, azurite_credentials, azure_fixture): account_name, connection_string = azurite_credentials @@ -24,14 +26,8 @@ def path(self, azurite_credentials, azure_fixture): def test_is_AzurePath(self): assert isinstance(self.path, AzurePath) - def test_mkdir(self): - new_dir = self.path / "new_dir" - new_dir.mkdir() - (new_dir / "test.txt").touch() - assert new_dir.exists() - def test_rmdir(self): - new_dir = self.path / "new_dir" + new_dir = self.path / "new_dir_rmdir" new_dir.mkdir() path = new_dir / "test.txt" path.write_text("hello") diff --git a/upath/tests/implementations/test_gcs.py b/upath/tests/implementations/test_gcs.py index e14ecb5f..28a41a90 100644 --- a/upath/tests/implementations/test_gcs.py +++ b/upath/tests/implementations/test_gcs.py @@ -10,6 +10,8 @@ @skip_on_windows @pytest.mark.usefixtures("path") class TestGCSPath(BaseTests): + MKDIR_REQUIRES_FILE = True + @pytest.fixture(autouse=True, scope="function") def path(self, gcs_fixture): path, endpoint_url = gcs_fixture @@ -19,11 +21,6 @@ def path(self, gcs_fixture): def test_is_GCSPath(self): assert isinstance(self.path, GCSPath) - def test_mkdir(self): - new_dir = self.path.joinpath("new_dir") - new_dir.joinpath("test.txt").touch() - assert new_dir.exists() - def test_rmdir(self): dirname = "rmdir_test" mock_dir = self.path.joinpath(dirname) diff --git a/upath/tests/implementations/test_s3.py b/upath/tests/implementations/test_s3.py index e24360eb..11d1ca92 100644 --- a/upath/tests/implementations/test_s3.py +++ b/upath/tests/implementations/test_s3.py @@ -9,6 +9,8 @@ class TestUPathS3(BaseTests): + MKDIR_REQUIRES_FILE = True + @pytest.fixture(autouse=True) def path(self, s3_fixture): path, anon, s3so = s3_fixture @@ -23,14 +25,6 @@ def test_chmod(self): # todo pass - def test_mkdir(self): - new_dir = self.path.joinpath("new_dir") - # new_dir.mkdir() - # mkdir doesn't really do anything. A directory only exists in s3 - # if some file or something is written to it - new_dir.joinpath("test.txt").touch() - assert new_dir.exists() - def test_rmdir(self): dirname = "rmdir_test" mock_dir = self.path.joinpath(dirname) From ade3203b690fb34d985cce87c42e60aba2df7a75 Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Tue, 9 Aug 2022 08:23:12 +0200 Subject: [PATCH 06/14] tests: mark unsupported http tests as skipped --- upath/tests/implementations/test_http.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/upath/tests/implementations/test_http.py b/upath/tests/implementations/test_http.py index 8c7a217c..ed370145 100644 --- a/upath/tests/implementations/test_http.py +++ b/upath/tests/implementations/test_http.py @@ -34,15 +34,27 @@ def path(self, http_fixture): def test_work_at_root(self): assert "folder" in (f.name for f in self.path.parent.iterdir()) + @pytest.mark.skip def test_mkdir(self): pass + @pytest.mark.skip + def test_mkdir_exists_ok_false(self): + pass + + @pytest.mark.skip + def test_mkdir_exists_ok_true(self): + pass + + @pytest.mark.skip def test_touch_unlink(self): pass + @pytest.mark.skip def test_write_bytes(self, pathlib_base): pass + @pytest.mark.skip def test_write_text(self, pathlib_base): pass From 8ee5c4c6a9fec7c70b9c5f2d85f5a33986cd6ed1 Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Tue, 9 Aug 2022 08:24:01 +0200 Subject: [PATCH 07/14] upath.implementations.hdfs: fix mkdir to correctly handle exist_ok --- upath/implementations/hdfs.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/upath/implementations/hdfs.py b/upath/implementations/hdfs.py index 84b29bd5..01b45c6f 100644 --- a/upath/implementations/hdfs.py +++ b/upath/implementations/hdfs.py @@ -10,6 +10,19 @@ def touch(self, path, **kwargs): kwargs.pop("truncate", None) super().touch(path, **kwargs) + def mkdir(self, path, create_parents=True, **kwargs): + pth = self._format_path(path) + if create_parents: + return self._fs.makedirs( + pth, **kwargs + ) + else: + if not kwargs.get("exist_ok", False) and self._fs.exists(pth): + raise FileExistsError + return self._fs.mkdir( + pth, create_parents=create_parents, **kwargs + ) + class HDFSPath(upath.core.UPath): _default_accessor = _HDFSAccessor From 1a259ae3bc500a2f2e9df663f7455c2a9001fabd Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Tue, 9 Aug 2022 08:25:06 +0200 Subject: [PATCH 08/14] upath.core: catch FileExistsError in mkdir and fix mode kwarg --- upath/core.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/upath/core.py b/upath/core.py index 4b0764a4..7cda5991 100644 --- a/upath/core.py +++ b/upath/core.py @@ -385,14 +385,18 @@ def mkdir(self, mode=0o777, parents=False, exist_ok=False): if parents: self._accessor.mkdir( self, - create_parents=parents, + create_parents=True, exist_ok=exist_ok, - permissions=mode, + mode=mode, ) else: try: - self._accessor.mkdir(self, create_parents=False) - except OSError: + self._accessor.mkdir( + self, + create_parents=False, + mode=mode, + ) + except FileExistsError: if not exist_ok or not self.is_dir(): raise From b565cf915ea1724d9c39df00cc425be73050f237 Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Tue, 9 Aug 2022 08:36:35 +0200 Subject: [PATCH 09/14] upath.implementations.cloud: fix exist_ok=False for mkdir --- .github/workflows/python.yml | 2 +- upath/implementations/cloud.py | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index f89cf9e7..b9fb3fdc 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -7,7 +7,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.7, 3.8, 3.9, "3.10", "3.11"] + python-version: [3.7, 3.8, 3.9, "3.10", "3.11-dev"] os: [ubuntu-latest, windows-latest] steps: diff --git a/upath/implementations/cloud.py b/upath/implementations/cloud.py index c482e18a..825df8f2 100644 --- a/upath/implementations/cloud.py +++ b/upath/implementations/cloud.py @@ -3,12 +3,22 @@ class _CloudAccessor(upath.core._FSSpecAccessor): + def _format_path(self, path): """ netloc has already been set to project via `CloudPath._from_parts` """ return f"{path._url.netloc}/{path.path.lstrip('/')}" + def mkdir(self, path, create_parents=True, **kwargs): + if ( + not create_parents + and not kwargs.get("exist_ok", False) + and self._fs.exists(self._format_path(path)) + ): + raise FileExistsError + return super().mkdir(path, create_parents=create_parents, **kwargs) + # project is not part of the path, but is part of the credentials class CloudPath(upath.core.UPath): From acbde351c49ae4d307f6d3a5f7fabd329505b1ad Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Tue, 9 Aug 2022 09:00:54 +0200 Subject: [PATCH 10/14] ci: use newest setup-python and checkout actions --- .github/workflows/python.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index b9fb3fdc..f4bd16d4 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -11,9 +11,9 @@ jobs: os: [ubuntu-latest, windows-latest] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Install dependencies From e40c8e6823b3431314fbe8dace5d213dce1ecea4 Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Sun, 28 Aug 2022 11:09:38 +0200 Subject: [PATCH 11/14] black formatting --- setup.py | 2 +- upath/core.py | 23 +++++++++++++++-------- upath/implementations/cloud.py | 1 - upath/implementations/hdfs.py | 8 ++------ 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/setup.py b/setup.py index e8d9bdb8..485fed85 100644 --- a/setup.py +++ b/setup.py @@ -16,5 +16,5 @@ description="pathlib api extended to use fsspec backends", long_description=long_description, long_description_content_type="text/markdown", - license="MIT" + license="MIT", ) diff --git a/upath/core.py b/upath/core.py index 7cda5991..34af7243 100644 --- a/upath/core.py +++ b/upath/core.py @@ -484,7 +484,7 @@ def with_suffix(self, suffix): f = self._flavour if f.sep in suffix or f.altsep and f.altsep in suffix: raise ValueError("Invalid suffix %r" % (suffix,)) - if suffix and not suffix.startswith('.') or suffix == '.': + if suffix and not suffix.startswith(".") or suffix == ".": raise ValueError("Invalid suffix %r" % (suffix)) name = self.name if not name: @@ -493,17 +493,24 @@ def with_suffix(self, suffix): if not old_suffix: name = name + suffix else: - name = name[:-len(old_suffix)] + suffix - return self._from_parsed_parts(self._drv, self._root, - self._parts[:-1] + [name], url=self._url) + name = name[: -len(old_suffix)] + suffix + return self._from_parsed_parts( + self._drv, self._root, self._parts[:-1] + [name], url=self._url + ) def with_name(self, name): """Return a new path with the file name changed.""" if not self.name: raise ValueError("%r has an empty name" % (self,)) drv, root, parts = self._flavour.parse_parts((name,)) - if (not name or name[-1] in [self._flavour.sep, self._flavour.altsep] - or drv or root or len(parts) != 1): + if ( + not name + or name[-1] in [self._flavour.sep, self._flavour.altsep] + or drv + or root + or len(parts) != 1 + ): raise ValueError("Invalid name %r" % (name)) - return self._from_parsed_parts(self._drv, self._root, - self._parts[:-1] + [name], url=self._url) + return self._from_parsed_parts( + self._drv, self._root, self._parts[:-1] + [name], url=self._url + ) diff --git a/upath/implementations/cloud.py b/upath/implementations/cloud.py index 825df8f2..f4ac26bc 100644 --- a/upath/implementations/cloud.py +++ b/upath/implementations/cloud.py @@ -3,7 +3,6 @@ class _CloudAccessor(upath.core._FSSpecAccessor): - def _format_path(self, path): """ netloc has already been set to project via `CloudPath._from_parts` diff --git a/upath/implementations/hdfs.py b/upath/implementations/hdfs.py index 01b45c6f..eeda435b 100644 --- a/upath/implementations/hdfs.py +++ b/upath/implementations/hdfs.py @@ -13,15 +13,11 @@ def touch(self, path, **kwargs): def mkdir(self, path, create_parents=True, **kwargs): pth = self._format_path(path) if create_parents: - return self._fs.makedirs( - pth, **kwargs - ) + return self._fs.makedirs(pth, **kwargs) else: if not kwargs.get("exist_ok", False) and self._fs.exists(pth): raise FileExistsError - return self._fs.mkdir( - pth, create_parents=create_parents, **kwargs - ) + return self._fs.mkdir(pth, create_parents=create_parents, **kwargs) class HDFSPath(upath.core.UPath): From 4366b97b75d00bd6ed224b1bc7e8f46294b441f5 Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Sun, 28 Aug 2022 11:10:19 +0200 Subject: [PATCH 12/14] nox: add workaround for missing py311 aiohttp wheels --- noxfile.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/noxfile.py b/noxfile.py index cee93c14..97f95d7c 100644 --- a/noxfile.py +++ b/noxfile.py @@ -1,3 +1,6 @@ +import os +import sys + import nox from pathlib import Path @@ -27,6 +30,12 @@ def install(session): @nox.session() def smoke(session): + if (3, 10) < sys.version_info <= (3, 11, 0, "final"): + # workaround for missing aiohttp wheels for py3.11 + session.install("aiohttp", "--no-binary", "aiohttp", env={ + "AIOHTTP_NO_EXTENSIONS": "1" + }) + session.install( "pytest", "adlfs", From 203cda7ac26dbc98c25b1a7281d1511abbcf02fa Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Sun, 28 Aug 2022 11:26:05 +0200 Subject: [PATCH 13/14] noxfile: lint only the upath package --- noxfile.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/noxfile.py b/noxfile.py index 97f95d7c..7be17355 100644 --- a/noxfile.py +++ b/noxfile.py @@ -1,4 +1,3 @@ -import os import sys import nox @@ -20,7 +19,7 @@ def black(session): @nox.session() def lint(session): session.install("flake8") - session.run(*"flake8".split()) + session.run("flake8", "upath") @nox.session() From 7f4cb5df2ea130ae25324568c67737533fc652a6 Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Sun, 28 Aug 2022 11:44:03 +0200 Subject: [PATCH 14/14] tests: better name for empty dir support flag --- upath/tests/cases.py | 8 ++++---- upath/tests/implementations/test_azure.py | 2 +- upath/tests/implementations/test_gcs.py | 2 +- upath/tests/implementations/test_s3.py | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/upath/tests/cases.py b/upath/tests/cases.py index 2777d76d..0ddb22cf 100644 --- a/upath/tests/cases.py +++ b/upath/tests/cases.py @@ -9,7 +9,7 @@ class BaseTests: - MKDIR_REQUIRES_FILE = False + SUPPORTS_EMPTY_DIRS = True def test_cwd(self): with pytest.raises(NotImplementedError): @@ -126,21 +126,21 @@ def test_lstat(self): def test_mkdir(self): new_dir = self.path.joinpath("new_dir") new_dir.mkdir() - if self.MKDIR_REQUIRES_FILE: + if not self.SUPPORTS_EMPTY_DIRS: new_dir.joinpath(".file").touch() assert new_dir.exists() def test_mkdir_exists_ok_true(self): new_dir = self.path.joinpath("new_dir_may_exists") new_dir.mkdir() - if self.MKDIR_REQUIRES_FILE: + if not self.SUPPORTS_EMPTY_DIRS: new_dir.joinpath(".file").touch() new_dir.mkdir(exist_ok=True) def test_mkdir_exists_ok_false(self): new_dir = self.path.joinpath("new_dir_may_not_exists") new_dir.mkdir() - if self.MKDIR_REQUIRES_FILE: + if not self.SUPPORTS_EMPTY_DIRS: new_dir.joinpath(".file").touch() with pytest.raises(FileExistsError): new_dir.mkdir(exist_ok=False) diff --git a/upath/tests/implementations/test_azure.py b/upath/tests/implementations/test_azure.py index 1c89c55e..f4c33307 100644 --- a/upath/tests/implementations/test_azure.py +++ b/upath/tests/implementations/test_azure.py @@ -10,7 +10,7 @@ @skip_on_windows @pytest.mark.usefixtures("path") class TestAzurePath(BaseTests): - MKDIR_REQUIRES_FILE = True + SUPPORTS_EMPTY_DIRS = False @pytest.fixture(autouse=True, scope="function") def path(self, azurite_credentials, azure_fixture): diff --git a/upath/tests/implementations/test_gcs.py b/upath/tests/implementations/test_gcs.py index 28a41a90..99e189ed 100644 --- a/upath/tests/implementations/test_gcs.py +++ b/upath/tests/implementations/test_gcs.py @@ -10,7 +10,7 @@ @skip_on_windows @pytest.mark.usefixtures("path") class TestGCSPath(BaseTests): - MKDIR_REQUIRES_FILE = True + SUPPORTS_EMPTY_DIRS = False @pytest.fixture(autouse=True, scope="function") def path(self, gcs_fixture): diff --git a/upath/tests/implementations/test_s3.py b/upath/tests/implementations/test_s3.py index 11d1ca92..8e10bcf0 100644 --- a/upath/tests/implementations/test_s3.py +++ b/upath/tests/implementations/test_s3.py @@ -9,7 +9,7 @@ class TestUPathS3(BaseTests): - MKDIR_REQUIRES_FILE = True + SUPPORTS_EMPTY_DIRS = False @pytest.fixture(autouse=True) def path(self, s3_fixture):