From 7cebc69bfc88b1a522defdce1637f5159c37def6 Mon Sep 17 00:00:00 2001 From: justindujardin Date: Wed, 8 Apr 2020 16:17:32 -0700 Subject: [PATCH] feat: add `resolve` method - converts path to absolute and removes relative parts --- gcspath/api.py | 21 ++++++++++++--------- tests/test_not_supported.py | 6 ------ tests/test_path_operations.py | 8 ++++++++ 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/gcspath/api.py b/gcspath/api.py index addb3a6..ae966b6 100644 --- a/gcspath/api.py +++ b/gcspath/api.py @@ -3,7 +3,7 @@ from io import DEFAULT_BUFFER_SIZE from pathlib import Path, PurePath, _Accessor, _PosixFlavour from typing import Generator, Iterable, List, Optional, Union - +import os import smart_open from google.api_core import exceptions as gcs_errors from google.cloud import storage @@ -160,6 +160,9 @@ def owner(self, path: "GCSPath") -> Optional[str]: blob: Optional[ClientBlob] = self.get_blob(path) return blob.owner if blob is not None else None + def resolve(self, path: "GCSPath", strict=False): + return GCSPath(os.path.abspath(str(path))) + def rename(self, path: "GCSPath", target: "GCSPath"): bucket: ClientBucket = self.client.get_bucket(path) target_bucket: ClientBucket = self.client.get_bucket(target) @@ -283,14 +286,6 @@ def lstat(self): message = self._NOT_SUPPORTED_MESSAGE.format(method=self.lstat.__qualname__) raise NotImplementedError(message) - def resolve(self, strict=False): - """ - resolve method is unsupported on GCS service - GCS don't have this file system action concept - """ - message = self._NOT_SUPPORTED_MESSAGE.format(method=self.resolve.__qualname__) - raise NotImplementedError(message) - def symlink_to(self, *args, **kwargs): """ symlink_to method is unsupported on GCS service @@ -431,6 +426,14 @@ def owner(self): raise FileNotFoundError(str(self)) return self._accessor.owner(self) + def resolve(self): + """ + Return a copy of this path. All paths are absolute in buckets, so no + transformation is applied. + """ + self._absolute_path_validation() + return self._accessor.resolve(self) + def rename(self, target): """ Renames this file or Bucket / key prefix / key to the given target. diff --git a/tests/test_not_supported.py b/tests/test_not_supported.py index d7585dd..1d61b17 100644 --- a/tests/test_not_supported.py +++ b/tests/test_not_supported.py @@ -70,12 +70,6 @@ def test_lstat(): path.lstat() -def test_resolve(): - path = GCSPath("/fake-bucket/fake-key") - with pytest.raises(NotImplementedError): - path.resolve() - - def test_symlink_to(): path = GCSPath("/fake-bucket/fake-key") with pytest.raises(NotImplementedError): diff --git a/tests/test_path_operations.py b/tests/test_path_operations.py index 132692b..8d1cb3f 100644 --- a/tests/test_path_operations.py +++ b/tests/test_path_operations.py @@ -82,6 +82,14 @@ def test_stat(with_adapter): assert GCSPath("/test-bucket").stat() is None +@pytest.mark.parametrize("adapter", TEST_ADAPTERS) +def test_resolve(with_adapter): + path = GCSPath("/fake-bucket/fake-key") + assert path.resolve() == path + path = GCSPath("/fake-bucket/dir/../fake-key") + assert path.resolve() == GCSPath("/fake-bucket/fake-key") + + @pytest.mark.parametrize("adapter", TEST_ADAPTERS) def test_exists(with_adapter): path = GCSPath("./fake-key")