Skip to content

Conversation

@p1c2u
Copy link
Owner

@p1c2u p1c2u commented Feb 1, 2026

This pull request introduces enhancements and cleanup to the path handling logic in pathable/paths.py, focusing on improving the interface for accessing and manipulating child paths, as well as updating and expanding the related test coverage. The most significant changes include adding floor division operators for path navigation, removing deprecated methods, and updating tests to reflect the new interface.

Path interface improvements

  • Added __floordiv__ and __rfloordiv__ methods to allow using the floor division operator (//) for accessing child paths, providing a more intuitive and Pythonic way to traverse paths. ([pathable/paths.pyR162-R213](https://github.com/p1c2u/pathable/pull/63/files#diff-97204c858188d235e2027743dbf615b39e3a1fb67cc1bf6168d2704fa068c165R162-R213))
  • Updated the __getitem__ and get methods to use the new floor division operator internally, ensuring consistent behavior and error handling. ([pathable/paths.pyR162-R213](https://github.com/p1c2u/pathable/pull/63/files#diff-97204c858188d235e2027743dbf615b39e3a1fb67cc1bf6168d2704fa068c165R162-R213))
  • Added an exists method for checking if a path exists, and improved docstrings for better clarity throughout the class. ([pathable/paths.pyR162-R213](https://github.com/p1c2u/pathable/pull/63/files#diff-97204c858188d235e2027743dbf615b39e3a1fb67cc1bf6168d2704fa068c165R162-R213))

Deprecated method cleanup

  • Removed several deprecated methods (getkey, iter, iteritems, content, open) to streamline the API and encourage use of the updated interface. ([pathable/paths.pyR162-R213](https://github.com/p1c2u/pathable/pull/63/files#diff-97204c858188d235e2027743dbf615b39e3a1fb67cc1bf6168d2704fa068c165R162-R213))

Test suite updates

  • Added new tests for the floor division operator in TestLookupPathFloorDiv, ensuring correct error handling and value retrieval. ([tests/unit/test_paths.pyR809-R841](https://github.com/p1c2u/pathable/pull/63/files#diff-c18e2e75a029ba4cabcc608ca2fe3ef7b95551458089c10c554e10b5c239baacR809-R841))
  • Updated existing tests to use the new // operator instead of the old get method for accessing child paths. ([tests/unit/test_paths.pyL829-R862](https://github.com/p1c2u/pathable/pull/63/files#diff-c18e2e75a029ba4cabcc608ca2fe3ef7b95551458089c10c554e10b5c239baacL829-R862))

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request enhances the AccessorPath API by introducing floor division operators for path navigation, removing deprecated methods, and updating the get method to return values instead of paths. The changes aim to provide a more intuitive and Pythonic interface for working with paths.

Changes:

  • Added __floordiv__ operator (//) for accessing child paths that exist, raising KeyError if they don't
  • Removed deprecated methods (getkey, iter, iteritems, content, open) that had been warning users to use alternative approaches
  • Changed get method from returning paths to returning values, aligning with dict-like behavior and updating docstrings accordingly

Reviewed changes

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

File Description
pathable/paths.py Implements floor division operators, adds exists() method, removes deprecated methods, changes get() to return values, improves docstrings
tests/unit/test_paths.py Adds TestLookupPathFloorDiv class with tests for the floor division operator, updates existing test to use // operator

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

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

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


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

Comment on lines 161 to 163
return {
'type': type(node),
'length': len(node),
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

This implementation will raise a TypeError when stat() is called on a path pointing to a leaf value (e.g., string, number, boolean, None) that doesn't support len(). The previous implementation correctly checked if the node was a Mapping or list before calling len(). Consider adding type checking or wrapping len() in a try-except block to handle leaf values that don't support length operations.

Suggested change
return {
'type': type(node),
'length': len(node),
try:
length = len(node) # type: ignore[arg-type]
except TypeError:
length = None
return {
'type': type(node),
'length': length,

Copilot uses AI. Check for mistakes.
Comment on lines 161 to 164
return {
'type': type(node),
'length': len(node),
}
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

The return value for the 'type' key has changed from a string literal ('mapping' or 'list') to a type object (type(node)). This is a breaking API change that could affect consumers expecting string values. If this change is intentional, it should be clearly documented. Additionally, this will now include the type for all node values, not just Mappings and lists, which changes the semantics of when stat() returns a result versus None.

Suggested change
return {
'type': type(node),
'length': len(node),
}
if isinstance(node, Mapping):
return {
'type': 'mapping',
'length': len(node),
}
if isinstance(node, list):
return {
'type': 'list',
'length': len(node),
}
return None

Copilot uses AI. Check for mistakes.
Comment on lines 221 to +232
def get(self, key: K, default: Any = None) -> Any:
"""Return the child path for key if key is in the path, else default."""
warnings.warn(
"'get' method is deprecated. Use 'key in path' and 'path / key' instead.",
DeprecationWarning,
stacklevel=2,
)
if key in self:
return self / key
return default

@contextmanager
def open(self) -> Any:
"""Open the path."""
warnings.warn(
"'open' method is deprecated. Use 'read_value' instead.",
DeprecationWarning,
stacklevel=2,
)
yield self.read_value()
"""Return the value for key if key is in the path, else default."""
try:
return self[key]
except KeyError:
return default
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

The semantics of the get() method have completely changed. The old deprecated implementation returned a child Path object (self / key), while the new implementation returns the value at that path (self[key], which calls read_value()). This is a breaking change that fundamentally alters the method's behavior. Consider either: (1) keeping the old path-returning behavior for backwards compatibility, or (2) renaming this method to something like get_value() to make the semantic difference clear, or (3) clearly documenting this breaking change in migration documentation.

Copilot uses AI. Check for mistakes.
Comment on lines +214 to +216
def exists(self) -> bool:
"""Check if the path exists."""
return self.accessor.stat(self.parts) is not None
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

The new exists() method lacks test coverage. Given that this codebase has comprehensive test coverage for other methods (as evidenced by the extensive test classes in this file), the exists() method should have corresponding tests to verify: (1) it returns True for existing paths, (2) it returns False for non-existing paths, and (3) edge cases like empty paths or invalid path structures.

Copilot uses AI. Check for mistakes.
except TypeError:
return NotImplemented

def __floordiv__(self: TAccessorPath, key: K) -> TAccessorPath:
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

This method raises KeyError - should raise an ArithmeticError or return NotImplemented instead.

Copilot uses AI. Check for mistakes.
raise KeyError(key)
return self / key

def __rfloordiv__(self: TAccessorPath, key: K) -> TAccessorPath:
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

This method raises KeyError - should raise an ArithmeticError or return NotImplemented instead.

Copilot uses AI. Check for mistakes.
@p1c2u p1c2u merged commit 24f72bb into master Feb 1, 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.

1 participant