pathlib-next 0.9.7__tar.gz → 0.9.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/CHANGELOG.md +14 -1
  2. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/PKG-INFO +1 -1
  3. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/pyproject.toml +1 -1
  4. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/__init__.py +7 -1
  5. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_routing.py +7 -1
  6. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_uri_path.py +26 -0
  7. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/.gitignore +0 -0
  8. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/AGENTS.md +0 -0
  9. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/LICENSE +0 -0
  10. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/README.md +0 -0
  11. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/docs/api/cli.md +0 -0
  12. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/docs/api/mempath.md +0 -0
  13. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/docs/api/path.md +0 -0
  14. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/docs/api/protocols.md +0 -0
  15. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/docs/api/schemes/archive.md +0 -0
  16. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/docs/api/schemes/ftp.md +0 -0
  17. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/docs/api/schemes/git.md +0 -0
  18. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/docs/api/schemes/http.md +0 -0
  19. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/docs/api/schemes/local.md +0 -0
  20. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/docs/api/schemes/objstore.md +0 -0
  21. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/docs/api/schemes/sftp.md +0 -0
  22. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/docs/api/testing.md +0 -0
  23. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/docs/api/uri.md +0 -0
  24. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/docs/api/utils.md +0 -0
  25. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/docs/benchmarks.md +0 -0
  26. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/docs/changelog.md +0 -0
  27. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/docs/divergences.md +0 -0
  28. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/docs/guides/cli.md +0 -0
  29. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/docs/guides/extending.md +0 -0
  30. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/docs/guides/schemes.md +0 -0
  31. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/docs/index.md +0 -0
  32. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/examples/az_listing.py +0 -0
  33. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/examples/data_and_archive.py +0 -0
  34. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/examples/ftp_listing.py +0 -0
  35. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/examples/github_listing.py +0 -0
  36. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/examples/gitlab_listing.py +0 -0
  37. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/examples/gs_listing.py +0 -0
  38. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/examples/http_listing.py +0 -0
  39. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/examples/local_and_mem.py +0 -0
  40. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/examples/s3_listing.py +0 -0
  41. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/examples/sftp_sync.py +0 -0
  42. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/examples/webdav_roundtrip.py +0 -0
  43. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/mkdocs.yml +0 -0
  44. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/AGENTS.md +0 -0
  45. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/__init__.py +0 -0
  46. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/fspath.py +0 -0
  47. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/mempath.py +0 -0
  48. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/path.py +0 -0
  49. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/protocols/__init__.py +0 -0
  50. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/protocols/checksum.py +0 -0
  51. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/protocols/fs.py +0 -0
  52. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/protocols/io.py +0 -0
  53. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/py.typed +0 -0
  54. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/testing.py +0 -0
  55. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/tools/__init__.py +0 -0
  56. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/tools/uripath.py +0 -0
  57. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/query.py +0 -0
  58. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/__init__.py +0 -0
  59. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/_gitrepo.py +0 -0
  60. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/archive/__init__.py +0 -0
  61. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/archive/_base.py +0 -0
  62. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/archive/tar.py +0 -0
  63. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/archive/zip.py +0 -0
  64. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/az.py +0 -0
  65. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/data.py +0 -0
  66. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/dav.py +0 -0
  67. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/file.py +0 -0
  68. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/ftp.py +0 -0
  69. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/git/__init__.py +0 -0
  70. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/git/_base.py +0 -0
  71. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/git/github.py +0 -0
  72. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/git/gitlab.py +0 -0
  73. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/github.py +0 -0
  74. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/gitlab.py +0 -0
  75. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/gs.py +0 -0
  76. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/http.py +0 -0
  77. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/s3.py +0 -0
  78. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/sftp/__init__.py +0 -0
  79. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/sftp/_asyncssh.py +0 -0
  80. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/sftp/_paramiko.py +0 -0
  81. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/schemes/sftp/_sshconfig.py +0 -0
  82. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/uri/source.py +0 -0
  83. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/utils/__init__.py +0 -0
  84. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/utils/archive.py +0 -0
  85. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/utils/checksum.py +0 -0
  86. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/utils/glob.py +0 -0
  87. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/utils/stat.py +0 -0
  88. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/src/pathlib_next/utils/sync.py +0 -0
  89. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/conftest.py +0 -0
  90. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_archive_parity.py +0 -0
  91. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_archive_safety.py +0 -0
  92. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_archive_uri.py +0 -0
  93. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_az.py +0 -0
  94. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_az_fake.py +0 -0
  95. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_checksum.py +0 -0
  96. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_contract.py +0 -0
  97. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_contract_helpers.py +0 -0
  98. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_data_uri.py +0 -0
  99. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_dav.py +0 -0
  100. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_destructive_safety.py +0 -0
  101. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_ftp.py +0 -0
  102. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_ftp_objstore_parity.py +0 -0
  103. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_gitrepo.py +0 -0
  104. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_glob.py +0 -0
  105. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_glob_parity.py +0 -0
  106. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_gs.py +0 -0
  107. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_gs_fake.py +0 -0
  108. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_http.py +0 -0
  109. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_http_live.py +0 -0
  110. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_http_parser.py +0 -0
  111. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_httpdav_safety.py +0 -0
  112. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_io_parity.py +0 -0
  113. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_local.py +0 -0
  114. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_low_core.py +0 -0
  115. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_low_schemes.py +0 -0
  116. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_low_sync.py +0 -0
  117. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_mempath.py +0 -0
  118. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_mro_precedence.py +0 -0
  119. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_parity_io.py +0 -0
  120. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_parity_pure.py +0 -0
  121. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_path_gaps.py +0 -0
  122. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_pathname.py +0 -0
  123. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_plugins.py +0 -0
  124. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_properties.py +0 -0
  125. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_pure_parity.py +0 -0
  126. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_query.py +0 -0
  127. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_s3.py +0 -0
  128. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_sftp.py +0 -0
  129. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_sftp_asyncssh.py +0 -0
  130. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_sftp_transport.py +0 -0
  131. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_smoke.py +0 -0
  132. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_source.py +0 -0
  133. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_sync.py +0 -0
  134. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_sync_safety.py +0 -0
  135. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_sync_sftp.py +0 -0
  136. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_sync_sftp_parity.py +0 -0
  137. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_transport_security.py +0 -0
  138. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_uri_core_parity.py +0 -0
  139. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_uri_parse.py +0 -0
  140. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_uripath_tool.py +0 -0
  141. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_utils.py +0 -0
  142. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_walk.py +0 -0
  143. {pathlib_next-0.9.7 → pathlib_next-0.9.8}/tests/test_webdav.py +0 -0
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.9.8] - 2026-09-17
11
+
12
+ ### Fixed
13
+ - **Joining a URI path no longer builds a backend.** 0.9.7 routed `/` and
14
+ `joinpath()` through the child builder a listing uses, which reads the
15
+ `backend` property -- and that property CREATES one, so spelling
16
+ `UriPath("sftp://h/x") / "y"` imported paramiko and raised `ImportError`
17
+ without the extra (`http:` wanted `requests`, `s3:` `botocore`). A join
18
+ is a pure-path operation and is lazy again; a child still shares its
19
+ parent's connection when one already exists, which is all the sharing was
20
+ ever for.
21
+
10
22
  ## [0.9.7] - 2026-09-17
11
23
 
12
24
  ### Added
@@ -1450,7 +1462,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
1450
1462
  - Sync error handling.
1451
1463
  - Generic Path Protocol based pathlib implementation for URI paths with file access support for sftp, http, file schemes.
1452
1464
 
1453
- [Unreleased]: https://github.com/jose-pr/pathlib-next/compare/v0.9.7...HEAD
1465
+ [Unreleased]: https://github.com/jose-pr/pathlib-next/compare/v0.9.8...HEAD
1466
+ [0.9.8]: https://github.com/jose-pr/pathlib-next/compare/v0.9.7...v0.9.8
1454
1467
  [0.9.7]: https://github.com/jose-pr/pathlib-next/compare/v0.9.6...v0.9.7
1455
1468
  [0.9.6]: https://github.com/jose-pr/pathlib-next/compare/v0.9.5...v0.9.6
1456
1469
  [0.9.5]: https://github.com/jose-pr/pathlib-next/compare/v0.9.4...v0.9.5
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pathlib-next
3
- Version: 0.9.7
3
+ Version: 0.9.8
4
4
  Summary: Generic Path Protocol based pathlib
5
5
  Project-URL: Homepage, https://github.com/jose-pr/pathlib-next/
6
6
  Project-URL: Documentation, https://jose-pr.github.io/pathlib-next/
@@ -13,7 +13,7 @@ build-backend = "hatchling.build"
13
13
  # `import pathlib_next`) -- a hyphen is not legal in a Python identifier.
14
14
  # Distribution name and import name differing is ordinary and intended.
15
15
  name = "pathlib-next"
16
- version = "0.9.7"
16
+ version = "0.9.8"
17
17
  authors = [{ name = "Jose A" }]
18
18
  description = "Generic Path Protocol based pathlib"
19
19
  readme = "README.md"
@@ -1149,7 +1149,13 @@ class UriPath(Uri, Path):
1149
1149
  def _make_child_relpath(
1150
1150
  self, name: str, stat_hint: "FileStat" = None, **kwargs
1151
1151
  ) -> _ty.Self:
1152
- inst = super()._make_child_relpath(name, backend=self.backend, **kwargs)
1152
+ # The backend ALREADY BUILT, never `self.backend` -- that property
1153
+ # creates one, and naming a child is a pure-path operation: since
1154
+ # `/` walks segments through here, reading the property made
1155
+ # `UriPath("sftp://h/x") / "y"` import paramiko (and `http:` import
1156
+ # requests) just to spell a path. A listing has one by the time it
1157
+ # gets here, so its children still share the instance.
1158
+ inst = super()._make_child_relpath(name, backend=self._backend, **kwargs)
1153
1159
  inst._stat_hint = stat_hint
1154
1160
  return inst
1155
1161
 
@@ -74,7 +74,13 @@ def test_github_token_backend_does_not_follow_join_to_another_host():
74
74
  # A str join stays on the original host, so the token goes nowhere new.
75
75
  literal = root / "github://evil.invalid/x/y"
76
76
  assert literal.source.host == "github.com"
77
- assert literal.backend is root.backend
77
+ assert literal.backend.token == "ghp_SECRET"
78
+ # Identity is only promised when the parent already HAS a backend: a
79
+ # join must not build one (it is a pure-path operation), so a child of a
80
+ # connectionless parent makes its own on first use.
81
+ assert root._backend is None
82
+ root.backend # now it exists, and the next child shares it
83
+ assert (root / "docs").backend is root.backend
78
84
 
79
85
  # Crossing hosts needs a Uri argument, and that drops the token.
80
86
  evil = root / GitHubPath("github://evil.invalid/x/y")
@@ -357,3 +357,29 @@ def test_a_same_endpoint_uri_destination_keeps_the_configured_backend():
357
357
  base._coerce_target("http://trusted.invalid/api/b.txt").backend is base.backend
358
358
  )
359
359
  assert base._coerce_target("http://other.invalid/b.txt").backend is not base.backend
360
+
361
+
362
+ def test_joining_a_path_never_builds_a_backend():
363
+ """A join is a PURE-PATH operation. 0.9.7 routed `/` through
364
+ `_make_child_relpath()`, which read the `backend` property -- and that
365
+ property builds one, so spelling `UriPath("sftp://h/x") / "y"` imported
366
+ paramiko and raised ImportError without the extra. Every scheme, not
367
+ just the ones whose client happens to be installed."""
368
+ for uri in ("sftp://h/mnt", "http://h/a", "s3://b/k", "file:///tmp/x"):
369
+ base = UriPath(uri)
370
+ child = base / "child"
371
+ assert child.path.endswith("/child")
372
+ assert child._backend is None, uri
373
+ assert base._backend is None, uri
374
+ assert base.joinpath("a", "b")._backend is None, uri
375
+
376
+
377
+ def test_joining_shares_a_backend_that_already_exists():
378
+ """What the property read was there for: children of a listing share the
379
+ parent's live connection. That still holds -- by then it exists."""
380
+ base = UriPath("http://h/a")
381
+ sentinel = object()
382
+ base._backend = sentinel
383
+ assert (base / "c")._backend is sentinel
384
+ assert base.joinpath("c", "d")._backend is sentinel
385
+ assert base._make_child_relpath("c")._backend is sentinel
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes