Skip to content

Add copy_safe action to FileHandler - #76

Merged
DavidHuber-NOAA merged 6 commits into
NOAA-EMC:developfrom
AntonMFernando-NOAA:feature/cpsafe
Jul 16, 2026
Merged

Add copy_safe action to FileHandler#76
DavidHuber-NOAA merged 6 commits into
NOAA-EMC:developfrom
AntonMFernando-NOAA:feature/cpsafe

Conversation

@AntonMFernando-NOAA

@AntonMFernando-NOAA AntonMFernando-NOAA commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Description

  • Adds a copy_safe action to FileHandler, a third copy operation alongside copy_req and copy_opt. It mirrors prod_util cpfs for staging files from DATA to COM: copy to a temp file in the destination folder, fsync it, then atomically rename it onto the final name (overwriting if needed), with error checking at each step and temp-file cleanup on failure.

Type of change

  • New feature (non-breaking change which adds functionality)

  • Bug fix (non-breaking change which fixes an issue)

  • New feature (non-breaking change which adds functionality)

  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

  • This change requires a documentation update

How Has This Been Tested?

  • Ran pynorms (pycodestyle + isort) and pytest locally on Linux (Python 3.12); all pass. Added test_copy_safe covering the nominal copy, overwrite, directory target, and the missing-source / missing-dir / directory-source error paths.

  • pynorms

  • pytests

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes need updates to the documentation. I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • New and existing tests pass with my changes
  • Any dependent changes have been merged and published

- Add cpfs() function to fsutils that copies files via temporary file with fsync and atomic rename
- Implement copy_safe action in FileHandler to leverage cpfs for durable file operations
- Update FileHandler._copy_files() to accept optional copy_fn parameter for customizable copy behavior
- Export cpfs from wxflow package __init__
- Add comprehensive test coverage for copy_safe operation including overwrite and temp file cleanup scenarios
- Mirror prod_util cpfs behavior for safe staging of files from DATA to COM directories
- Remove cpfs function from fsutils module and update __all__ export
- Move atomic copy logic to FileHandler._safe_cp static method in file_utils
- Update FileHandler.copy_safe to use new _safe_cp method instead of cpfs
- Remove cpfs from module imports in __init__.py
- Add tempfile import to file_utils and rm_p import for cleanup
- Consolidate file copy utilities within FileHandler class for better encapsulation
- Maintains identical atomic copy behavior with fsync and atomic rename semantics
- Remove test_copy_safe function that tested safe atomic file copy operations
- Test coverage for copy_safe functionality is now handled by FileHandler._safe_cp tests
- Simplify test suite by consolidating copy operation tests
- Add check to raise IsADirectoryError when source is a directory
- Update docstring to clarify that directory sources are not supported
- Prevents silent failures when attempting to copy directories with _safe_cp
- Add test_copy_safe function covering nominal file copy with overwrite
- Validate that copied content matches source file contents
- Verify no temporary .tmp files remain after successful copy
- Test directory target handling to ensure source basename is retained
- Verify FileNotFoundError raised when source file does not exist
- Verify OSError raised when destination directory does not exist
- Verify IsADirectoryError raised when attempting to copy directory source
- Ensures copy_safe operation behaves as specified in atomic file copy contract
@AntonMFernando-NOAA
AntonMFernando-NOAA marked this pull request as draft July 9, 2026 19:32
@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 75.00000% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 60.90%. Comparing base (293d5f4) to head (846d0ba).

Files with missing lines Patch % Lines
src/wxflow/file_utils.py 74.28% 9 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop      #76      +/-   ##
===========================================
+ Coverage    60.72%   60.90%   +0.17%     
===========================================
  Files           24       24              
  Lines         1986     2018      +32     
  Branches       374      377       +3     
===========================================
+ Hits          1206     1229      +23     
- Misses         723      735      +12     
+ Partials        57       54       -3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@AntonMFernando-NOAA AntonMFernando-NOAA self-assigned this Jul 9, 2026

@DavidHuber-NOAA DavidHuber-NOAA left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good. Thanks for this utility @AntonMFernando-NOAA!

@AntonMFernando-NOAA
AntonMFernando-NOAA marked this pull request as ready for review July 10, 2026 15:57
@DavidHuber-NOAA

Copy link
Copy Markdown
Member

@AntonMFernando-NOAA can you bump the version to 0.4.2 here, please. After that, I will merge.

__version__ = "0.4.1"

@AntonMFernando-NOAA

Copy link
Copy Markdown
Contributor Author

@AntonMFernando-NOAA can you bump the version to 0.4.2 here, please. After that, I will merge.

__version__ = "0.4.1"

@DavidHuber-NOAA Done.

@DavidHuber-NOAA

Copy link
Copy Markdown
Member

Thanks! Merging.

@DavidHuber-NOAA
DavidHuber-NOAA merged commit ce11982 into NOAA-EMC:develop Jul 16, 2026
10 checks passed
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