From 9f8cc863fbbbb8bcda7b4a874c5b2c7a806bbf2a Mon Sep 17 00:00:00 2001 From: Gabriel Lesperance <611342+glesperance@users.noreply.github.com> Date: Thu, 25 Jan 2024 08:59:22 -0500 Subject: [PATCH] Implementation of 'local://' URI Scheme Support (#150) * Update test_local.py * Update registry.py * Linting via nox * upath: add local to registry tests, skip local on old fsspec version * tests: xfail https test on ssl errors * tests: xfail http glob test for fsspec>2023.10.0 --------- Co-authored-by: Andreas Poehlmann --- upath/registry.py | 1 + upath/tests/implementations/test_http.py | 25 +++++++++++++++++++++++ upath/tests/implementations/test_local.py | 13 ++++++++++++ upath/tests/test_registry.py | 1 + upath/tests/utils.py | 11 ++++++++++ 5 files changed, 51 insertions(+) diff --git a/upath/registry.py b/upath/registry.py index 085b2274..1953caa3 100644 --- a/upath/registry.py +++ b/upath/registry.py @@ -64,6 +64,7 @@ class _Registry(MutableMapping[str, "type[upath.core.UPath]"]): "adl": "upath.implementations.cloud.AzurePath", "az": "upath.implementations.cloud.AzurePath", "file": "upath.implementations.local.LocalPath", + "local": "upath.implementations.local.LocalPath", "gcs": "upath.implementations.cloud.GCSPath", "gs": "upath.implementations.cloud.GCSPath", "hdfs": "upath.implementations.hdfs.HDFSPath", diff --git a/upath/tests/implementations/test_http.py b/upath/tests/implementations/test_http.py index 8bcc5ccb..c585437e 100644 --- a/upath/tests/implementations/test_http.py +++ b/upath/tests/implementations/test_http.py @@ -1,11 +1,14 @@ import pytest # noqa: F401 +from fsspec import __version__ as fsspec_version from fsspec import get_filesystem_class +from packaging.version import Version from upath import UPath from upath.implementations.http import HTTPPath from ..cases import BaseTests from ..utils import skip_on_windows +from ..utils import xfail_if_no_ssl_connection try: get_filesystem_class("http") @@ -19,6 +22,7 @@ def test_httppath(): assert path.exists() +@xfail_if_no_ssl_connection def test_httpspath(): path = UPath("https://example.com") assert isinstance(path, HTTPPath) @@ -38,6 +42,27 @@ def test_work_at_root(self): def test_mkdir(self): pass + @pytest.mark.parametrize( + "pattern", + ( + "*.txt", + pytest.param( + "*", + marks=pytest.mark.xfail(reason="requires fsspec<=2023.10.0") + if Version(fsspec_version) > Version("2023.10.0") + else (), + ), + pytest.param( + "**/*.txt", + marks=pytest.mark.xfail(reason="requires fsspec>=2023.9.0") + if Version(fsspec_version) < Version("2023.9.0") + else (), + ), + ), + ) + def test_glob(self, pathlib_base, pattern): + super().test_glob(pathlib_base, pattern) + @pytest.mark.skip def test_mkdir_exists_ok_false(self): pass diff --git a/upath/tests/implementations/test_local.py b/upath/tests/implementations/test_local.py index cb60cd03..437c6f55 100644 --- a/upath/tests/implementations/test_local.py +++ b/upath/tests/implementations/test_local.py @@ -4,6 +4,7 @@ from upath.implementations.local import LocalPath from upath.tests.cases import BaseTests from upath.tests.utils import skip_on_windows +from upath.tests.utils import xfail_if_version @skip_on_windows @@ -15,3 +16,15 @@ def path(self, local_testdir): def test_is_LocalPath(self): assert isinstance(self.path, LocalPath) + + +@skip_on_windows +@xfail_if_version("fsspec", lt="2023.10.0", reason="requires fsspec>=2023.10.0") +class TestRayIOFSSpecLocal(BaseTests): + @pytest.fixture(autouse=True) + def path(self, local_testdir): + path = f"local://{local_testdir}" + self.path = UPath(path) + + def test_is_LocalPath(self): + assert isinstance(self.path, LocalPath) diff --git a/upath/tests/test_registry.py b/upath/tests/test_registry.py index 93388f11..19f38d4e 100644 --- a/upath/tests/test_registry.py +++ b/upath/tests/test_registry.py @@ -17,6 +17,7 @@ "hdfs", "http", "https", + "local", "memory", "s3", "s3a", diff --git a/upath/tests/utils.py b/upath/tests/utils.py index bb73141a..d25df0c1 100644 --- a/upath/tests/utils.py +++ b/upath/tests/utils.py @@ -33,3 +33,14 @@ def xfail_if_version(module, *, reason, **conditions): for op, val in conditions.items(): cond &= getattr(operator, op)(ver, Version(val)) return pytest.mark.xfail(cond, reason=reason) + + +def xfail_if_no_ssl_connection(func): + try: + import requests + + requests.get("https://example.com") + except (ImportError, requests.exceptions.SSLError): + return pytest.mark.xfail(reason="No SSL connection")(func) + else: + return func