From 711303f6fba5d93f035c71e61133ff97ee14ec1f Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Fri, 3 Oct 2025 19:58:54 +0200 Subject: [PATCH 1/3] readme: update wording regarding pathlib-abc ABC classes and pathlib --- README.md | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a28e1c16..a2b64761 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,11 @@ And of course, contributions for new filesystems are welcome! The class hierarchy for `UPath` implementations and their relation to base classes in `pathlib_abc` and the stdlib `pathlib` classes are visualized in the following -diagram: +diagram. Please be aware that the `pathlib_abc.JoinablePath`, +`pathlib_abc.ReadablePath`, and `pathlib_abc.WritablePath` classes are currently +not actual parent classes of the stdlib pathlib classes. This might occur in +later Python releases, but for now, the mental model you should keep is represented +by the diagram. ```mermaid flowchart TB @@ -122,14 +126,14 @@ flowchart TB end subgraph s0[pathlib] - X --> A + X -.-> A A----> B A--> AP A--> AW - Y --> B - Z --> B + Y -.-> B + Z -.-> B B--> BP AP----> BP @@ -184,6 +188,19 @@ flowchart TB style s1 fill:none,stroke:#d02,stroke-width:3px,stroke-dasharray:3,color:#d02 ``` +To be concrete this currently means: + +```python +# for all supported Python versions: +from pathlib import Path +from upath import UPath +from upath.types import JoinablePath + +assert isinstance(Path(), JoinablePath) is False +assert isinstance(UPath(), JoinablePath) is True +``` + + When instantiating `UPath` the returned instance type is determined by the path, or better said, the "protocol" that was provided to the constructor. The `UPath` class will return a registered implementation for the protocol, if available. If From bcf44992e752f8f9e66b21c9088ea32d31f39623 Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Fri, 3 Oct 2025 19:59:15 +0200 Subject: [PATCH 2/3] readme: add method implementation table --- README.md | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/README.md b/README.md index a2b64761..9864d9b9 100644 --- a/README.md +++ b/README.md @@ -272,6 +272,113 @@ with fs.open(p.path) as f: data = f.read() ``` +## Supported Interface + +Universal Pathlib provides an implementation of the `pathlib.Path` interface +across different Python versions. The following table shows the compatibility +matrix for stdlib pathlib.Path attributes and methods. Methods supported in +UPath should correctly work for all supported Python versions. If not, we consider +it a bug. + +| Method/Attribute | py3.9 | py3.10 | py3.11 | py3.12 | py3.13 | py3.14 | UPath | +|---------------------------|-------|--------|--------|--------|--------|--------|-------| +| **Pure Paths** | | | | | | | | +| _Operators_ | | | | | | | | +| `__truediv__` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `__rtruediv__` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| _Access individual Parts_ | | | | | | | | +| `parts` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| _Methods and Properties_ | | | | | | | | +| `parser` | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | +| `drive` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `root` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `anchor` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `parents` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `parent` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `name` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `suffix` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `suffixes` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `stem` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `as_posix()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `is_absolute()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `is_relative_to()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `is_reserved()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `joinpath()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `full_match()` | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | +| `match()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `relative_to()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `with_name()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `with_stem()` | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `with_suffix()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `with_segments()` | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | +| **Concrete Paths** | | | | | | | | +| _Parsing URIs_ | | | | | | | | +| `from_uri()` | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | +| `as_uri()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| _Expanding Paths_ | | | | | | | | +| `home()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `expanduser()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `cwd()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `absolute()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `resolve()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `readlink()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ | +| _Querying File status_ | | | | | | | | +| `stat()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `lstat()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `exists()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `is_file()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `is_dir()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `is_symlink()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `is_junction()` | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | +| `is_mount()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `is_socket()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `is_fifo()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `is_block_device()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `is_char_device()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `samefile()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `info` | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | +| _Reading & Writing Files_ | | | | | | | | +| `open()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `read_text()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `read_bytes()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `write_text()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `write_bytes()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| _Reading Directories_ | | | | | | | | +| `iterdir()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `glob()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `rglob()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `walk()` | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | +| _Creating Files & Dirs_ | | | | | | | | +| `touch()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `mkdir()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `symlink_to()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ | +| `hardlink_to()` | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ | +| _Copying & Moving_ | | | | | | | | +| `copy()` | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | +| `copy_into()` | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | +| `rename()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `replace()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ | +| `move()` | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | +| `move_into()` | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | +| `unlink()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| `rmdir()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| _Permission & Owner_ | | | | | | | | +| `owner()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ | +| `group()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ | +| `chmod()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ | +| `lchmod()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ | +| **UPath interface** | | | | | | | | +| `protocol` | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | +| `storage_options` | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | +| `path` | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | +| `fs` | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | +| `joinuri()` | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | + +**Key:** +- ✅ = Available/Supported +- ❌ = Not available in this version +- ⚠️ = Currently raises unsupported error for UPath implementations + ## Advanced Usage If you want to create your own UPath implementations, there are multiple ways to From c2f8c774779a1189c47c97c17c6a387bbfe3b3c1 Mon Sep 17 00:00:00 2001 From: Andreas Poehlmann Date: Fri, 3 Oct 2025 20:09:42 +0200 Subject: [PATCH 3/3] update changelog --- CHANGELOG.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1a976ef..f71efc1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ... +## [0.3.1] - 2025-10-03 +### Added +- upath: add `UPath.from_uri()` classmethod (#423) +- upath: add `UPath.move_into()` method (#422) +- upath: implement `.info` property (#416) +- typesafety: add thorough typechecks to UPath interface (#414) + +### Fixed +- upath: fix type annotations for upath.core, upath.extensions and upath.implementations (#420) +- upath: backport types and methods to local implementations (#421) +- upath: stricter upath types and remove Compat* protocol (#417) + +### Changed +- maintenance: update license identifier and restrict ci permissions (#424) + ## [0.3.0] - 2025-09-29 ### Fixed - upath: support relative paths (#405) @@ -211,7 +226,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - started a changelog to keep track of significant changes -[Unreleased]: https://github.com/fsspec/universal_pathlib/compare/v0.3.0...HEAD +[Unreleased]: https://github.com/fsspec/universal_pathlib/compare/v0.3.1...HEAD +[0.3.1]: https://github.com/fsspec/universal_pathlib/compare/v0.3.0...v0.3.1 [0.3.0]: https://github.com/fsspec/universal_pathlib/compare/v0.2.6...v0.3.0 [0.2.6]: https://github.com/fsspec/universal_pathlib/compare/v0.2.5...v0.2.6 [0.2.5]: https://github.com/fsspec/universal_pathlib/compare/v0.2.4...v0.2.5