Skip to content

refactor copy files method. if there is a top level directory, remove it but keep the structure inside - #174

Merged
HaneenT merged 2 commits into
developfrom
KPMP-6726_fix-dlu-watcher-on-FIleNotFound
Jul 17, 2026
Merged

refactor copy files method. if there is a top level directory, remove it but keep the structure inside#174
HaneenT merged 2 commits into
developfrom
KPMP-6726_fix-dlu-watcher-on-FIleNotFound

Conversation

@Dert1129

@Dert1129 Dert1129 commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • Bug Fixes

    • Improved file and directory copying for data packages, including nested directory structures.
    • Prevented duplicate copies and preserved existing destination files.
    • Enhanced source-file resolution and error details when files cannot be found.
  • New Features

    • Added support for copying complete directory contents.
    • Copy operations now report the total number of files copied.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

DLUFileHandler gains recursive directory copying and a rewritten package-copy flow. The implementation now creates destination trees, skips existing files, avoids duplicate wrapper copies, resolves fallback source paths, reports detailed missing-source errors, and returns the cumulative copied-file count.

Changes

Filesystem Copy Behavior

Layer / File(s) Summary
Recursive directory-copy helper
data_management/services/dlu_filesystem.py
Adds copy_directory_contents to recursively copy files, create destination directories including empty directories, skip existing files, and return the number of copied files.
Package copy resolution and orchestration
data_management/services/dlu_filesystem.py
Reworks copy_files to clear the destination package directory, resolve primary and fallback source paths, copy files or directories through internal helpers, deduplicate wrapper directories, and accumulate copied-file counts.

Sequence Diagram(s)

sequenceDiagram
  participant DLUFileHandler
  participant SourceFilesystem
  participant DestinationFilesystem
  DLUFileHandler->>SourceFilesystem: Resolve package and fallback source paths
  DLUFileHandler->>DestinationFilesystem: Clear destination package directory
  DLUFileHandler->>SourceFilesystem: Read files and directory contents
  DLUFileHandler->>DestinationFilesystem: Create directories and copy missing files
  DLUFileHandler-->>DLUFileHandler: Return files_copied
Loading
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch KPMP-6726_fix-dlu-watcher-on-FIleNotFound

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fa75b297-a3f3-4c6d-bad7-d23081754a73

📥 Commits

Reviewing files that changed from the base of the PR and between 2a3bbaa and 1e97648.

📒 Files selected for processing (1)
  • data_management/services/dlu_filesystem.py

Comment on lines +186 to +191
if os.path.exists(base_dest_package_directory):
logger.info(
"Removing existing destination directory %s",
base_dest_package_directory,
)
shutil.rmtree(base_dest_package_directory)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🔴 Critical | 🏗️ Heavy lift

Do not destroy the existing package before the replacement succeeds.

The destination is removed before validating all sources. An empty file_list, missing source, or mid-copy failure leaves the prior package deleted or partially rebuilt.

Copy into a temporary sibling directory and replace the destination only after the entire operation succeeds.

Comment on lines +303 to +310
if preserve_path:
dest_package_directory = os.path.join(dest_package_directory,
file.get_short_path())

subdirs = [os.path.join(source_package_directory, o)
for o in os.listdir(source_package_directory)
if os.path.isdir(os.path.join(source_package_directory, o))]
dir = "".join(subdirs)
if len(os.listdir(source_package_directory)) == 1 and os.path.isdir(source_package_directory) and os.path.isdir(dir):
os.chdir(dir)
allfiles = os.listdir(dir)
for f in allfiles:
src_path = os.path.join(dir, f)
dst_path = os.path.join(dest_package_directory, f)
if not os.path.isdir(dest_package_directory):
os.mkdir(dest_package_directory)
if os.path.isfile(f):
logger.info("Copying file " + f + " to " + dst_path)
shutil.copy(src_path, dst_path)
files_copied += 1
short_path = file.get_short_path()

if short_path:
dest_package_directory = os.path.join(
dest_package_directory,
short_path,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Flatten the wrapper into the base destination, not each file’s preserved path.

With preserve_path=True, dest_package_directory includes file.get_short_path(). Copying the complete wrapper there duplicates the path hierarchy and may copy the tree repeatedly for different files.

Proposed fix
+                    wrapper_destination = base_dest_package_directory
                     wrapper_key = (
                         os.path.abspath(only_item_path),
-                        os.path.abspath(dest_package_directory),
+                        os.path.abspath(wrapper_destination),
                     )
...
                         files_copied += self.copy_directory_contents(
                             src_dir=only_item_path,
-                            dst_dir=dest_package_directory,
+                            dst_dir=wrapper_destination,
                         )

Also applies to: 340-358

Comment on lines +327 to +333
try:
top_level_items = os.listdir(source_package_directory)
except FileNotFoundError:
raise FileNotFoundError(
f"Cannot list source package directory because it does not exist: "
f"{source_package_directory}"
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Preserve the original FileNotFoundError as the exception cause.

Proposed fix
-            except FileNotFoundError:
+            except FileNotFoundError as err:
                 raise FileNotFoundError(
                     f"Cannot list source package directory because it does not exist: "
                     f"{source_package_directory}"
-                )
+                ) from err
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try:
top_level_items = os.listdir(source_package_directory)
except FileNotFoundError:
raise FileNotFoundError(
f"Cannot list source package directory because it does not exist: "
f"{source_package_directory}"
)
try:
top_level_items = os.listdir(source_package_directory)
except FileNotFoundError as err:
raise FileNotFoundError(
f"Cannot list source package directory because it does not exist: "
f"{source_package_directory}"
) from err
🧰 Tools
🪛 Ruff (0.15.21)

[warning] 330-333: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

Source: Linters/SAST tools

@HaneenT
HaneenT merged commit 3d7f0f6 into develop Jul 17, 2026
1 check passed
@HaneenT
HaneenT deleted the KPMP-6726_fix-dlu-watcher-on-FIleNotFound branch July 17, 2026 20:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants