diff --git a/upath/core.py b/upath/core.py index df567e07..d315364a 100644 --- a/upath/core.py +++ b/upath/core.py @@ -125,8 +125,26 @@ class UPath(pathlib.Path, PureUPath, metaclass=UPathMeta): def __new__(cls, *args, **kwargs): if issubclass(cls, UPath): args_list = list(args) - url = args_list.pop(0) - url = stringify_path(url) + first = args_list.pop(0) + if isinstance(first, pathlib.PurePath): + # Create a (modified) copy, if first arg is a Path object + other = first + parts = args_list + drv, root, parts = other._parse_args(parts) + drv, root, parts = other._flavour.join_parsed_parts( + other._drv, other._root, other._parts, drv, root, parts + ) + + new_kwargs = getattr(other, "_kwargs", {}).copy() + new_kwargs.pop("_url", None) + new_kwargs.update(kwargs) + + return other.__class__( + other._format_parsed_parts(drv, root, parts), + **new_kwargs, + ) + + url = stringify_path(first) parsed_url = urllib.parse.urlparse(url) for key in ["scheme", "netloc"]: val = kwargs.get(key) diff --git a/upath/tests/cases.py b/upath/tests/cases.py index 6968d88b..9ee6a5ff 100644 --- a/upath/tests/cases.py +++ b/upath/tests/cases.py @@ -259,3 +259,14 @@ def test_child_path(self): assert path_a._drv == path_b._drv assert path_a._parts == path_b._parts assert path_a._url == path_b._url + + def test_copy_path(self): + path = self.path + copy_path = UPath(path) + + assert type(path) == type(copy_path) + assert str(path) == str(copy_path) + assert path._drv == copy_path._drv + assert path._root == copy_path._root + assert path._parts == copy_path._parts + assert path.fs.storage_options == copy_path.fs.storage_options diff --git a/upath/tests/test_core.py b/upath/tests/test_core.py index 7a9b7e05..8de66dd8 100644 --- a/upath/tests/test_core.py +++ b/upath/tests/test_core.py @@ -176,3 +176,51 @@ def test_pickling_child_path(): assert path._root == recovered_path._root assert path._parts == recovered_path._parts assert path.fs.storage_options == recovered_path.fs.storage_options + + +def test_copy_path(): + path = UPath("gcs://bucket/folder", anon=True) + copy_path = UPath(path) + + print(type(path), type(copy_path)) + + assert type(path) == type(copy_path) + assert str(path) == str(copy_path) + assert path._drv == copy_path._drv + assert path._root == copy_path._root + assert path._parts == copy_path._parts + assert path.fs.storage_options == copy_path.fs.storage_options + + +def test_copy_path_posix(): + path = UPath("/tmp/folder") + copy_path = UPath(path) + + assert type(path) == type(copy_path) == type(pathlib.Path("")) + assert str(path) == str(copy_path) + assert path._drv == copy_path._drv + assert path._root == copy_path._root + assert path._parts == copy_path._parts + + +def test_copy_path_append(): + path = UPath("/tmp/folder") + copy_path = UPath(path, "folder2") + + assert type(path) == type(copy_path) == type(pathlib.Path("")) + assert str(path / "folder2") == str(copy_path) + + path = UPath("/tmp/folder") + copy_path = UPath(path, "folder2/folder3") + + assert str(path / "folder2" / "folder3") == str(copy_path) + + +def test_copy_path_append_kwargs(): + path = UPath("gcs://bucket/folder", anon=True) + copy_path = UPath(path, anon=False) + + assert type(path) == type(copy_path) + assert str(path) == str(copy_path) + assert not copy_path._kwargs["anon"] + assert path._kwargs["anon"]