Skip to content

[SYNPY-1882] preserve file name casing when uploading/downloading data #1431

Draft
danlu1 wants to merge 2 commits into
developfrom
SYNPY-1882-file-name-casing
Draft

[SYNPY-1882] preserve file name casing when uploading/downloading data #1431
danlu1 wants to merge 2 commits into
developfrom
SYNPY-1882-file-name-casing

Conversation

@danlu1

@danlu1 danlu1 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Problem:

The current normalize_path function lowercases the entire file path on Windows during data transfer, which alters the original path casing.

#Solution

Update normalize_path to preserve the original path casing instead of converting it to lowercase.
Continue using lowercase paths for the download cache to avoid duplicate file downloads on Windows, where file paths are case-insensitive.

#Testing
Unit and integration test suites are added.

os.path.normcase() in normalize_path() lowercases the entire path on
Windows (a no-op on POSIX), which cascaded into guess_file_name() and
corrupted the derived entity name (e.g. File_Name.tsv -> file_name.tsv)
while the FileHandle fileName kept its case. It also lowercased
downloaded files on disk.

Remove normcase() from normalize_path() so casing is preserved on every
platform, and move case-insensitive cache matching into a dedicated
_match_cache_map_key() helper in cache.py. The helper prefers an exact
(case-sensitive) match -- correct for case-sensitive NTFS directories --
and falls back to an os.path.normcase() comparison so cache entries
written by older clients with lowercased keys still resolve. This avoids
forcing Windows users to re-download already-cached files. Cache.add()
now migrates a legacy lowercased key to the case-preserving key instead
of accumulating duplicates.

Adds regression tests for case-preserving normalize_path/guess_file_name
and for the case-tolerant cache matching, add-migration, and legacy
lowercased key lookup.
…g-v1bujx-wbf2ka

[SYNR-1534] Preserve file name casing on Windows uploads/downloads
Copilot AI review requested due to automatic review settings July 22, 2026 18:20
@danlu1
danlu1 requested a review from a team as a code owner July 22, 2026 18:20
@danlu1
danlu1 marked this pull request as draft July 22, 2026 18:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the Synapse Python Client’s path normalization to preserve original path casing (notably on Windows) so derived entity names and downloaded filenames are not unintentionally lowercased, while updating cache lookup behavior to remain compatible with legacy (lowercased) cache keys.

Changes:

  • Updated utils.normalize_path() to stop using os.path.normcase() so path casing is preserved.
  • Added cache-key matching logic in core/cache.py that prefers exact matches and falls back to os.path.normcase matching to support legacy Windows cache maps.
  • Added unit tests to validate case preservation and legacy cache-key compatibility.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
synapseclient/core/utils.py Preserves path casing by removing os.path.normcase() from normalize_path().
synapseclient/core/cache.py Adds _match_cache_map_key() and updates cache operations to tolerate legacy lowercased keys.
tests/unit/synapseclient/core/unit_test_utils.py Adds coverage ensuring normalize_path() and guess_file_name() preserve case.
tests/unit/synapseclient/core/unit_test_Cache.py Adds tests for legacy lowercased cache keys and key migration behavior.
synapseclient/core/CLAUDE.md Updates internal documentation to reflect the new normalize_path()/cache behavior contract.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +326 to +331
# Compare case-insensitively via os.path.normcase (a
# no-op on POSIX) so directories cached by older clients
# with lowercased keys on Windows are still matched.
if os.path.normcase(path) == os.path.normcase(
os.path.dirname(cached_file_path)
):
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.

3 participants