Skip to content

copy_into isn't recursive despite is_dir() being True #528

@hutch3232

Description

@hutch3232

The docs for copy_into say:

Copy this file or directory tree into the given existing directory.

I took that to mean if the instance of UPath is a directory, its directory tree would be copied recursively into target_dir but that doesn't seem to be the case for my S3 path.

# /// script
# requires-python = ">=3.13"
# dependencies = [
#     "dotenv>=0.9.9",
#     "s3fs>=2025.12.0",
#     "universal-pathlib>=0.3.7",
# ]
# ///
import tempfile

from dotenv import load_dotenv
from upath import UPath

load_dotenv()

path = UPath("s3://my-bucket/my-dir")

assert path.is_dir()

with tempfile.TemporaryDirectory() as tmpdir:
    path.copy_into(UPath(tmpdir))

# Traceback (most recent call last):
#   File "/mnt/code/upath_copy.py", line 44, in <module>
#     path.copy_into(UPath(tmpdir))
#     ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
#   File "/mnt/imported/data/mewtwo/uv/environments-v2/upath-copy-f6a8fa3cfa21e199/lib/python3.13/site-packages/upath/core.py", line 1238, in copy_into
#     return super().copy_into(target_dir, **kwargs)
#            ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
#   File "/mnt/imported/data/mewtwo/uv/environments-v2/upath-copy-f6a8fa3cfa21e199/lib/python3.13/site-packages/pathlib_abc/__init__.py", line 403, in copy_into
#     return self.copy(target_dir / name, **kwargs)
#            ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#   File "/mnt/imported/data/mewtwo/uv/environments-v2/upath-copy-f6a8fa3cfa21e199/lib/python3.13/site-packages/upath/core.py", line 1221, in copy
#     return super().copy(target, **kwargs)
#            ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
#   File "/mnt/imported/data/mewtwo/uv/environments-v2/upath-copy-f6a8fa3cfa21e199/lib/python3.13/site-packages/pathlib_abc/__init__.py", line 393, in copy
#     target._copy_from(self, **kwargs)
#     ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
#   File "/mnt/imported/data/mewtwo/uv/environments-v2/upath-copy-f6a8fa3cfa21e199/lib/python3.13/site-packages/upath/implementations/local.py", line 712, in _copy_from
#     _copy_from(source, follow_symlinks=follow_symlinks)
#     ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#   File "/mnt/imported/data/mewtwo/uv/environments-v2/upath-copy-f6a8fa3cfa21e199/lib/python3.13/site-packages/pathlib_abc/__init__.py", line 476, in _copy_from
#     with vfsopen(src, 'rb') as source_f:
#          ~~~~~~~^^^^^^^^^^^
#   File "/mnt/imported/data/mewtwo/uv/environments-v2/upath-copy-f6a8fa3cfa21e199/lib/python3.13/site-packages/pathlib_abc/_os.py", line 243, in vfsopen
#     stream = _open_reader(obj)
#   File "/mnt/imported/data/mewtwo/uv/environments-v2/upath-copy-f6a8fa3cfa21e199/lib/python3.13/site-packages/pathlib_abc/_os.py", line 181, in _open_reader
#     return open_reader(obj)
#   File "/mnt/imported/data/mewtwo/uv/environments-v2/upath-copy-f6a8fa3cfa21e199/lib/python3.13/site-packages/upath/core.py", line 1198, in __open_reader__
#     return self.fs.open(self.path, mode="rb")
#            ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
#   File "/mnt/imported/data/mewtwo/uv/environments-v2/upath-copy-f6a8fa3cfa21e199/lib/python3.13/site-packages/fsspec/spec.py", line 1349, in open
#     f = self._open(
#         path,
#     ...<4 lines>...
#         **kwargs,
#     )
#   File "/mnt/imported/data/mewtwo/uv/environments-v2/upath-copy-f6a8fa3cfa21e199/lib/python3.13/site-packages/s3fs/core.py", line 733, in _open
#     return S3File(
#         self,
#     ...<11 lines>...
#         size=size,
#     )
#   File "/mnt/imported/data/mewtwo/uv/environments-v2/upath-copy-f6a8fa3cfa21e199/lib/python3.13/site-packages/s3fs/core.py", line 2295, in __init__
#     super().__init__(
#     ~~~~~~~~~~~~~~~~^
#         s3,
#         ^^^
#     ...<6 lines>...
#         size=size,
#         ^^^^^^^^^^
#     )
#     ^
#   File "/mnt/imported/data/mewtwo/uv/environments-v2/upath-copy-f6a8fa3cfa21e199/lib/python3.13/site-packages/fsspec/spec.py", line 1923, in __init__
#     self.size = self.details["size"]
#                 ^^^^^^^^^^^^
#   File "/mnt/imported/data/mewtwo/uv/environments-v2/upath-copy-f6a8fa3cfa21e199/lib/python3.13/site-packages/fsspec/spec.py", line 1936, in details
#     self._details = [self.fs.info](http://self.fs.info/)(self.path)
#                     ~~~~~~~~~~~~^^^^^^^^^^^
#   File "/mnt/imported/data/mewtwo/uv/environments-v2/upath-copy-f6a8fa3cfa21e199/lib/python3.13/site-packages/fsspec/asyn.py", line 118, in wrapper
#     return sync(self.loop, func, *args, **kwargs)
#   File "/mnt/imported/data/mewtwo/uv/environments-v2/upath-copy-f6a8fa3cfa21e199/lib/python3.13/site-packages/fsspec/asyn.py", line 103, in sync
#     raise return_result
#   File "/mnt/imported/data/mewtwo/uv/environments-v2/upath-copy-f6a8fa3cfa21e199/lib/python3.13/site-packages/fsspec/asyn.py", line 56, in _runner
#     result[0] = await coro
#                 ^^^^^^^^^^
#   File "/mnt/imported/data/mewtwo/uv/environments-v2/upath-copy-f6a8fa3cfa21e199/lib/python3.13/site-packages/s3fs/core.py", line 1452, in _info
#     out = self._ls_from_cache(fullpath)
#   File "/mnt/imported/data/mewtwo/uv/environments-v2/upath-copy-f6a8fa3cfa21e199/lib/python3.13/site-packages/fsspec/spec.py", line 384, in _ls_from_cache
#     raise FileNotFoundError(path)
# FileNotFoundError: my-bucket/my-dir/my-dir

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions