Skip to content

fix(geometry): accept path-like filenames in PLY point-cloud I/O - #5092

Merged
ducha-aiki merged 3 commits into
kornia:mainfrom
INo-xious:fix/ply-pathlike
Sep 29, 2026
Merged

ducha-aiki merged 3 commits into
kornia:mainfrom
INo-xious:fix/ply-pathlike

Conversation

@INo-xious

@INo-xious INo-xious commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

What does this pull request do?

The four PLY save/load functions reject valid pathlib.Path objects because their filename checks only accept strings. Normalize filenames with os.fspath and accept str | os.PathLike[str], keeping the existing extension and missing-file checks. Parsing, serialization, and tensor handling are unchanged.

Regression tests cover strings, Path, custom string-backed path objects, .ply/.PLY, Path saving with string loading and the reverse, known coordinates, byte-identical serialization, invalid inputs, and missing files. Updates the filename docstrings and adds changelog.d/5092.fixed.md.

Related issue or discussion

Fixes #5072.

Checked #5069: it remains unmerged, so its Path-rejection warning and test have not landed on main. Those need reconciliation if it merges first.

What did you check?

Python 3.12.13 / PyTorch 2.14.0 on macOS arm64, importing this checkout. The new regression class failed before the implementation change: 52 failed, 52 passed.

# Before the fix: 52 failed, 52 passed.
~/.pixi/bin/pixi run test-module tests/geometry/test_pointcloud_io.py::TestPointCloudFilenames --device=cpu --dtype=float32 --tb=line -q

# After the fix: 369 passed.
~/.pixi/bin/pixi run test-module tests/geometry/test_pointcloud_io.py --device=cpu --dtype=all -q

# 297 passed.
~/.pixi/bin/pixi run test-module tests/geometry/test_pointcloud_io.py --device=mps --dtype=float32,float16,bfloat16 -q --color=no

# 194 passed, two deprecation warnings.
~/.pixi/bin/pixi run test-module tests/test_api_surface.py tests/utils/test_deprecated.py -q --color=no

# Passed.
~/.pixi/bin/pixi run pre-commit-all
~/.pixi/bin/pixi run typecheck
~/.pixi/bin/pixi run changelog-preview
.venv/bin/python .github/scripts/check_changelog.py --base-ref origin/main --pr-number 5092
git diff --check

CUDA was unavailable. The full test suite and documentation build were not run. Gradient/compilation checks were not run because this change only handles filenames in file-I/O functions.

How did AI help?

Codex investigated the issue and related PR, implemented the fix and regression tests, reviewed the diff, and ran the checks above.

INo-xious and others added 3 commits September 29, 2026 13:22
The PLY savers and loaders now accept os.PathLike[str], so the message
'must be a string with the .ply extension' misdescribes the contract
when a Path with another suffix is passed. Pin the new wording in
test_invalid_filename_extension, and say in the changelog fragment what
used to happen and that the case-insensitive suffix check is not new.

@ducha-aiki ducha-aiki 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.

Thanks. This fixes #5072 as the issue proposed: os.fspath first, then the same suffix and missing-file checks. I checked it on main a30540a with torch 2.14.0 (macOS arm64, CPU and MPS). I pushed one small commit on top, 0f7867b, which changes the error message and the changelog wording. Please pull before you push again. Details below; I'm approving with it.

What I verified

  • The issue's repro passes. A pathlib.Path and a custom os.PathLike[str] now save and load in all four functions. On main they raised TypeError.
  • Rejected inputs still raise TypeError, for every input I tried, in all four functions:
    • 1234, None and a list: the exception type is unchanged, but the message is now Python's own expected str, bytes or os.PathLike object, not int. That's fine.
    • bytes and a bytes PathLike: os.fspath returns bytes, the isinstance(filename, str) check rejects it, and the message is kornia's, as on main.
    • a __fspath__ that returns an int: os.fspath raises TypeError.
    • a Path ending in .txt.
    • A Path naming a missing .ply file still raises ValueError in the loaders.
  • .PLY is not a behaviour change. Main already accepted "x.PLY" as a str (.lower()), and the PR keeps that.
  • The output bytes are unchanged. For the same points, the ASCII and binary files have the same SHA-256 on main and here. A file saved through a Path or a custom PathLike is byte-identical to the same save through a str. The writers are untouched, so nothing new happens with line endings on Windows. Your byte comparison checks two outputs of the same writer, and the Windows leg passes.
  • Tests. Your new class fails on main (52 failed: 48 test_pathlike_filename_5072 and 4 test_missing_file) and passes here. The two tests you removed from TestSaveLoadPointCloud (1234 and "pointcloud.txt" to the ASCII saver) are covered by the new parametrized ones, which run all four functions. The file passes on CPU float32/float64, float16/bfloat16 under their known-failure profiles, and MPS float32. The half-precision RNG audit passes too.
  • Mutants. Each of the four new os.fspath lines, when dropped, fails 12–14 tests, and str(filename) in its place fails 6–7. Dropping .lower() or the isfile check fails 6–42 tests. Dropping isinstance(filename, str) survives, but the mutant is equivalent: after os.fspath it only sees bytes, and bytes.lower().endswith(".ply") raises TypeError anyway.

What I changed (0f7867b)

  • Error message. It said Input filename must be a string with the .ply extension, so save_pointcloud_ply(Path("points.txt"), ...) told the caller to pass a string. It now reads Input filename must be a str or os.PathLike[str] with the .ply extension, in both savers and _check_ply_filename. test_invalid_filename_extension matches that wording instead of "extension".
  • Changelog. The fragment now says these filenames raised TypeError before. It also says the case-insensitive .ply check is the one strings already had, so "including case-insensitive .ply extensions" doesn't read as a new feature.

Our docs PR #5069

#5069 documents this defect, so it conflicts in kornia/geometry/pointcloud.py. This PR merges first, and we'll update #5069 afterwards; nothing for you to do.

Posted on behalf of @ducha-aiki by Claude (Opus 5.5).

@ducha-aiki
ducha-aiki enabled auto-merge (squash) September 29, 2026 13:53
@ducha-aiki
ducha-aiki merged commit 5ff50fa into kornia:main Sep 29, 2026
19 checks passed
ducha-aiki added a commit that referenced this pull request Sep 30, 2026
Resolve keypoints.py (keep the #5122 NotImplementedError messages under the
batch-10b docstrings) and pointcloud.py (keep os.PathLike from #5092 under the
Convention block). Drop the wart pins and prose that main fixed: #5072 (PLY
path-like filenames, #5092) and #5062 (float16 zero vector, #5084); 13 pins.
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.

PLY point-cloud I/O rejects pathlib.Path, unlike kornia.io (save/load_pointcloud_ply*, TypeError)

2 participants