feat: add file_utils module - #35
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SummaryIntroduces a new The functions use straightforward standard library calls ( What reviewers should knowReview focus areas:
Start with
|
SonarQube reviewer guide
|
There was a problem hiding this comment.
The module is simple and mostly straightforward, but there is one bug in list_files and a logic duplication issue worth fixing before merge.
SonarQube Cloud quality gate is failing — coverage on new code is 0% against an 80% threshold. See the reviewer guide above for details.
| files = [] | ||
| for entry in os.listdir(directory): | ||
| full_path = os.path.join(directory, entry) | ||
| if os.path.isfile(full_path): |
There was a problem hiding this comment.
Bug: If a caller passes extension with a leading dot (e.g. list_files(dir, '.txt')), the check becomes entry.endswith('..txt'), which will never match anything. The function silently returns an empty list with no indication of the mistake.
Given that get_extension already strips the leading dot, normalizing here is safer than expecting callers to know the convention:
| if os.path.isfile(full_path): | |
| if extension is None or entry.endswith(f'.{extension.lstrip(".")}'): |
- Mark as noise
| files = [] | ||
| for entry in os.listdir(directory): | ||
| full_path = os.path.join(directory, entry) | ||
| if os.path.isfile(full_path): |
There was a problem hiding this comment.
Logic duplication: list_files reimplements extension matching via str.endswith(f'.{extension}'), while get_extension uses os.path.splitext for the same concept. These will diverge if extension handling changes (e.g. case normalization, compound extensions like .tar.gz). list_files should delegate to get_extension to stay consistent:
if extension is None or get_extension(entry) == extension.lstrip('.'):- Mark as noise
|
|
||
|
|
||
| def list_files(directory: str, extension: str = None) -> list[str]: | ||
| files = [] |
There was a problem hiding this comment.
Missing test coverage: list_files has three distinct branches — no extension filter, extension filter matching, and extension filter not matching — plus the os.path.isfile guard that silently skips subdirectories. None of these paths are tested. A unit test using pytest's tmp_path fixture would catch regressions in the filtering logic, including the leading-dot bug noted above.
- Mark as noise



Summary
file_utils.pywith helpers:read_file,write_file,file_exists,get_extension,list_filesTest plan
🤖 Generated with Claude Code