Skip to content

feat(extension_types): add os.PathLike conformance to op.File and op.Directory (ITL-493)#209

Merged
eywalker merged 6 commits into
mainfrom
eywalker/itl-493-make-opfile-opdirectory-subclass-ospathlike
Jul 3, 2026
Merged

feat(extension_types): add os.PathLike conformance to op.File and op.Directory (ITL-493)#209
eywalker merged 6 commits into
mainfrom
eywalker/itl-493-make-opfile-opdirectory-subclass-ospathlike

Conversation

@kurodo3

@kurodo3 kurodo3 Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds __fspath__ to File and Directory, delegating to os.fspath(self.__wrapped__).
  • isinstance(f, os.PathLike) now returns True for both classes via the os.PathLike ABC's __subclasshook__.
  • Local-backed instances work with open(), pathlib.Path(), and shutil directly.
  • Remote-backed instances (S3, GCS, engm, …) raise TypeError on os.fspath(), mirroring UPath's own behaviour.
  • UPathProxy is unchanged.

Closes ITL-493

Test plan

  • uv run pytest tests/test_extension_types/test_file_type.py -v — all pass
  • uv run pytest tests/test_extension_types/test_directory_type.py -v — all pass
  • uv run pytest tests/ -v — no regressions (4063 tests passed)

@codecov

codecov Bot commented Jul 3, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

f"File: path is not a regular file: {self.__wrapped__!r}"
)

def __fspath__(self) -> str:

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.

if os.fspath first performs hasattr(obj, "__fspath__") this will cause the instance of our file type to always register as os.PathLike -- is that the desired behavior?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, this is the intended behavior — it was an explicit design decision made before implementation.

The reasoning: File is semantically path-like as a class, so all instances register as os.PathLike via the ABC's __subclasshook__. Whether os.fspath() actually succeeds at runtime is a separate question that depends on the backing: local-backed instances (PosixUPath) return the path string; remote-backed instances (S3Path etc.) raise TypeError — the same failure mode you'd get calling os.fspath() on a remote UPath directly.

This is documented in the __fspath__ docstring and in the design spec (superpowers/specs/2026-07-03-itl-493-pathlike-conformance-design.md, section isinstance behaviour). There's no clean alternative: isinstance() checks the class, not the instance, so there's no way to make remote-backed File instances opt out while keeping local-backed ones opted in.

@kurodo3 kurodo3 Bot force-pushed the eywalker/itl-493-make-opfile-opdirectory-subclass-ospathlike branch from 5169562 to 76a6c75 Compare July 3, 2026 22:33
@eywalker eywalker requested a review from Copilot July 3, 2026 22:34

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 adds os.PathLike conformance to orcapod.extension_types.File and Directory by implementing __fspath__ and validating the expected behavior via new tests. This improves interoperability with stdlib APIs (e.g., open(), os.listdir(), pathlib.Path()) for local-backed instances while preserving the existing UPath behavior for remote-backed instances (raising TypeError on os.fspath()).

Changes:

  • Add File.__fspath__ and Directory.__fspath__, delegating to os.fspath(self.__wrapped__).
  • Add test coverage ensuring local-backed instances work with stdlib path consumers and remote-backed instances raise TypeError.
  • Add design/spec + implementation plan documentation for ITL-493.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/orcapod/extension_types/file_type.py Implements File.__fspath__ via delegation to the wrapped UPath.
src/orcapod/extension_types/directory_type.py Implements Directory.__fspath__ via delegation to the wrapped UPath.
tests/test_extension_types/test_file_type.py Adds TestFilePathLike verifying os.PathLike/os.fspath/open/pathlib.Path behavior.
tests/test_extension_types/test_directory_type.py Adds TestDirectoryPathLike verifying os.PathLike/os.fspath/os.listdir/pathlib.Path behavior.
superpowers/specs/2026-07-03-itl-493-pathlike-conformance-design.md Captures the approved design decisions and behavioral contract for path-like conformance.
superpowers/plans/2026-07-03-itl-493-pathlike-conformance.md Documents the implementation plan and verification steps for the change.

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

@kurodo3

kurodo3 Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

Review round summary

No code changes in this round.

The one open comment questioned whether isinstance(f, os.PathLike) returning True for all File/Directory instances (including remote-backed ones) is intended. It is — this was an explicit pre-implementation design decision. Replied inline with the reasoning and a pointer to the design spec.

The branch was also rebased onto main (which had gained one commit, ITL-489 #208) and force-pushed.

@eywalker eywalker merged commit da8e106 into main Jul 3, 2026
12 checks passed
@eywalker eywalker deleted the eywalker/itl-493-make-opfile-opdirectory-subclass-ospathlike branch July 3, 2026 22:38
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