objpath 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,204 @@
1
+ Metadata-Version: 2.5
2
+ Name: objpath
3
+ Version: 0.1.0
4
+ Summary: pathlib-style paths for S3, Google Cloud Storage and Azure Blob Storage, and the s3:, gs: and az: schemes for uripath
5
+ Project-URL: Homepage, https://github.com/jose-pr/objpath/
6
+ Project-URL: Documentation, https://jose-pr.github.io/objpath/
7
+ Project-URL: Issues, https://github.com/jose-pr/objpath/issues
8
+ Author: Jose A
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.9
22
+ Requires-Dist: pathapi<0.2,>=0.1.0
23
+ Provides-Extra: all
24
+ Requires-Dist: azure-identity<2,>=1.0; extra == 'all'
25
+ Requires-Dist: azure-storage-blob<13,>=12.4.0; extra == 'all'
26
+ Requires-Dist: boto3<2,>=1.36.0; extra == 'all'
27
+ Requires-Dist: google-cloud-storage<4,>=3.0; extra == 'all'
28
+ Requires-Dist: pathapi-uri<0.2,>=0.1.0; extra == 'all'
29
+ Provides-Extra: az
30
+ Requires-Dist: azure-identity<2,>=1.0; extra == 'az'
31
+ Requires-Dist: azure-storage-blob<13,>=12.4.0; extra == 'az'
32
+ Provides-Extra: dev
33
+ Requires-Dist: black; extra == 'dev'
34
+ Requires-Dist: build; extra == 'dev'
35
+ Requires-Dist: hatchling; extra == 'dev'
36
+ Requires-Dist: moto[s3]; extra == 'dev'
37
+ Requires-Dist: pytest; extra == 'dev'
38
+ Requires-Dist: pytest-cov; extra == 'dev'
39
+ Requires-Dist: twine; extra == 'dev'
40
+ Provides-Extra: docs
41
+ Requires-Dist: mkdocs; extra == 'docs'
42
+ Requires-Dist: mkdocs-material; extra == 'docs'
43
+ Requires-Dist: mkdocstrings[python]; extra == 'docs'
44
+ Provides-Extra: gs
45
+ Requires-Dist: google-cloud-storage<4,>=3.0; extra == 'gs'
46
+ Provides-Extra: s3
47
+ Requires-Dist: boto3<2,>=1.36.0; extra == 's3'
48
+ Provides-Extra: uri
49
+ Requires-Dist: pathapi-uri<0.2,>=0.1.0; extra == 'uri'
50
+ Description-Content-Type: text/markdown
51
+
52
+ # objpath
53
+
54
+ [![Version](https://img.shields.io/pypi/v/objpath.svg)](https://pypi.org/project/objpath/)
55
+ [![Python versions](https://img.shields.io/pypi/pyversions/objpath.svg)](https://pypi.org/project/objpath/)
56
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/jose-pr/objpath/blob/main/LICENSE)
57
+ [![Docs](https://img.shields.io/badge/docs-latest-blue.svg)](https://jose-pr.github.io/objpath/)
58
+ [![CI](https://img.shields.io/github/actions/workflow/status/jose-pr/objpath/test.yml)](https://github.com/jose-pr/objpath/actions/workflows/test.yml)
59
+
60
+ **`pathlib` for S3, Google Cloud Storage and Azure Blob buckets.**
61
+ `S3Path("reports/2026.csv", bucket="data")` has the method names, signatures and
62
+ exception types of `pathlib.Path`, and `GSPath` and `AZPath` do the same for the
63
+ other two stores; none needs a URI. They build on
64
+ [`pathapi`](https://github.com/jose-pr/pathapi) alone; with
65
+ [`uripath`](https://github.com/jose-pr/uripath) installed the same package also
66
+ provides the `s3:`, `gs:` and `az:` schemes. It is documented at
67
+ <https://jose-pr.github.io/objpath/>.
68
+
69
+ ## Features
70
+
71
+ | Store | Class | Extra | Directories | Server-side copy | Checksum | Append |
72
+ | --- | --- | --- | --- | --- | --- | --- |
73
+ | Amazon S3 and S3-compatible | `S3Path` | `s3` | key prefixes, `mkdir()` writes a marker object | `CopyObject`, same client | ETag MD5, `crc32`, `crc32c`, `crc64nvme`, `sha1`, `sha256` | no |
74
+ | Google Cloud Storage | `GSPath` | `gs` | key prefixes, `mkdir()` writes a marker object | `copy_blob`, same client | `md5`, `crc32c` | no |
75
+ | Azure Blob Storage | `AZPath` | `az` | key prefixes, `mkdir()` writes a marker blob | service copy, same container and client | `Content-MD5` | no |
76
+
77
+ - **A `pathlib` path on a bucket**: `open`, `read_text`, `iterdir`, `glob`, `stat`,
78
+ `mkdir`, `rename` and the rest, plus `walk`, `copy`, `move`, `rm` and `PathSyncer` from
79
+ `pathapi`. Nothing connects until the first request.
80
+ - **Directories without directories**: `is_dir()` is a prefix test, listings use a
81
+ delimiter and carry the size and time of each object, and the keys a walk cannot reach
82
+ (an empty segment, a name that is both an object and a prefix) are named and refused
83
+ instead of copied or removed half way.
84
+ - **Batch deletes and server-side copies**: `rm(recursive=True)` deletes a thousand keys a
85
+ request, and a copy within a store moves no byte through your process.
86
+ - **Safe writes**: uploads are spooled and sent on `close()`; a `with` block that raised
87
+ uploads nothing. A read is one version of the object, and an object replaced meanwhile
88
+ is an error, not a mix.
89
+ - **The SDKs stay out of the way**: `import objpath` loads no SDK and not `uripath`; a
90
+ store used without its extra raises an `ImportError` naming it. No SDK exception crosses
91
+ the API: errors are the `OSError` types `pathlib` raises, `TimeoutError` and
92
+ `ConnectionError`.
93
+ - **The `s3:`, `gs:` and `az:` schemes** for `uripath`: `URIPath("s3://data/reports")` is
94
+ an `S3URIPath` that delegates to an `S3Path`.
95
+
96
+ ## Installation
97
+
98
+ ```bash
99
+ pip install "objpath[s3]"
100
+ ```
101
+
102
+ Requires `pathapi`, which pip installs with it, and Python 3.9 or newer.
103
+
104
+ | Install | Adds |
105
+ | --- | --- |
106
+ | `pip install objpath` | the paths and the backend contracts; no SDK |
107
+ | `pip install "objpath[s3]"` | `boto3>=1.36.0,<2` for `S3Path` |
108
+ | `pip install "objpath[gs]"` | `google-cloud-storage>=3.0,<4` for `GSPath` |
109
+ | `pip install "objpath[az]"` | `azure-storage-blob` and `azure-identity` for `AZPath` |
110
+ | `pip install "objpath[uri]"` | `uripath` and with it the `s3:`, `gs:` and `az:` schemes |
111
+ | `pip install "objpath[all]"` | all of the above |
112
+
113
+ ## Quick start
114
+
115
+ **A path in a bucket**: the bucket is a keyword, the segments are the key, and the
116
+ credentials are the ones boto3 finds:
117
+
118
+ <!-- example: skip: connects to S3 -->
119
+ ```python
120
+ from objpath import S3Path
121
+
122
+ report = S3Path("reports/2026.csv", bucket="data")
123
+ print(report.read_text())
124
+ for child in report.parent.iterdir():
125
+ print(child.name, child.stat().st_size)
126
+ ```
127
+
128
+ **Another store, or another endpoint**: client options build the path's own backend, and a
129
+ backend shared between paths is one client and one connection pool:
130
+
131
+ <!-- example: skip: connects to a store -->
132
+ ```python
133
+ from objpath import AZPath, GSPath, S3Backend, S3Path
134
+
135
+ blob = AZPath("logs/app.log", container="ops", account="mycompany")
136
+ gcs = GSPath("models/latest", bucket="ml", project="my-project")
137
+
138
+ with S3Backend(endpoint_url="https://minio.example.org", region_name="us-east-1") as backend:
139
+ root = S3Path(bucket="backups", backend=backend)
140
+ (root / "2026").mkdir(exist_ok=True)
141
+ (root / "2026" / "n.txt").write_text("1")
142
+ root.copy(S3Path("mirror", bucket="backups", backend=backend), recursive=True)
143
+ ```
144
+
145
+ **Mirror a tree** with `PathSyncer`, onto a local directory:
146
+
147
+ <!-- example: skip: connects to S3 -->
148
+ ```python
149
+ from pathapi import LocalPath
150
+ from pathapi.sync import PathSyncer
151
+ from objpath import S3Path
152
+
153
+ PathSyncer(remove_missing=True).sync(S3Path("logs", bucket="data"), LocalPath("mirror"))
154
+ ```
155
+
156
+ **The schemes**, with `uripath` installed:
157
+
158
+ <!-- example: skip: connects to S3 -->
159
+ ```python
160
+ from uripath import URIPath
161
+
162
+ print(URIPath("s3://data/reports/2026.csv").read_text())
163
+ ```
164
+
165
+ ## API overview
166
+
167
+ | Module | Purpose |
168
+ | --- | --- |
169
+ | `objpath` | `S3Path`, `GSPath`, `AZPath`, the backends `S3Backend`, `GSBackend`, `AZBackend` and the contracts `BaseS3Backend`, `BaseGSBackend`, `BaseAZBackend`, the exceptions and `__version__` |
170
+ | `objpath.exceptions` | `ObjPathError`, `ObjectChangedError` and `UnreachableKeysError` |
171
+ | `objpath.uri` | `S3URIPath`, `GSURIPath` and `AZURIPath`, the schemes of `uripath` (needs the `uri` extra) |
172
+
173
+ The full reference is on the [documentation site](https://jose-pr.github.io/objpath/);
174
+ an agent-oriented API summary ships inside the package as `objpath/AGENTS.md`.
175
+
176
+ ## Development
177
+
178
+ ```bash
179
+ pip install -e ".[dev,all]"
180
+ python -m pytest -q -rs
181
+ ```
182
+
183
+ The S3 tests run against `moto` in the test process, and the Google Cloud Storage and
184
+ Azure tests against fake servers on the loopback interface; none reaches another host. A
185
+ test for an extra that is not installed is skipped, so check the skip list (`-rs`).
186
+ Contributor notes (virtual environments, formatting, CI, releases) are in the repository's
187
+ [`AGENTS.md`](https://github.com/jose-pr/objpath/blob/main/AGENTS.md). To preview the
188
+ documentation: `pip install -e ".[all,docs]"` then `mkdocs serve`.
189
+
190
+ Changes are recorded in the
191
+ [changelog](https://github.com/jose-pr/objpath/blob/main/CHANGELOG.md).
192
+
193
+ ### Releasing
194
+
195
+ This project follows [Semantic Versioning](https://semver.org/) and keeps a
196
+ [`CHANGELOG.md`](https://github.com/jose-pr/objpath/blob/main/CHANGELOG.md). Pushing a tag matching `v*` triggers the release
197
+ workflow: test gate → build (checking the tag names the version built) → a strict
198
+ docs build as a gate → GitHub release → publish. The release workflow never deploys
199
+ the docs site itself: for a final release its last job dispatches the docs workflow
200
+ at the tag, which owns every Pages deploy.
201
+
202
+ ## License
203
+
204
+ MIT — see [LICENSE](https://github.com/jose-pr/objpath/blob/main/LICENSE).
@@ -0,0 +1,31 @@
1
+ objpath/AGENTS.md,sha256=nS4tBJ-ozc_iG2YuOzpDPpCU_iAAoJYf0_4M4jRjkv4,18565
2
+ objpath/__init__.py,sha256=GnK1zSHe3O8KgsGuTrTOVwN_zAESaUh_Gy-gyHDMMmI,2013
3
+ objpath/_az.py,sha256=5qCioOcDojMFwa0d3hmOC5laZd3hcXaK5BluZXZWYSQ,21975
4
+ objpath/_az_backend.py,sha256=Dy7qkKGnFt_gv11qbPDHMXALrcjl5O8NmaDdpbxjhw8,5435
5
+ objpath/_az_errors.py,sha256=tlS2zP3pyWKa-9dx07H-mrqZr3YdxTGm8McnfTw6szo,4226
6
+ objpath/_clients.py,sha256=4UlpMr6KxNM-MauehWq7NESv3Pz7q-vj-oP-9tbePK8,3686
7
+ objpath/_digests.py,sha256=im-yEzmzzUwt0Gu8SHxAJFxkgBXpy1PIQKc1j7yisGA,259
8
+ objpath/_failures.py,sha256=YJJNF40Xmi4SQxv3JxPdvcmOO26MlluheLlm01pf2_w,3309
9
+ objpath/_gs.py,sha256=4cEGIR5Rog_Cknmz9jf7Zs5Gp3oLSO9y_rc3UCP1FjU,18450
10
+ objpath/_gs_backend.py,sha256=WgnVYpCaL0Qy5Q5q5kjn0l9EQNZNzT40QtD8V644_fU,3556
11
+ objpath/_gs_errors.py,sha256=QCkBwLXtXhBgbwbYVIlU4Ds_yKDtdn_gJJ7UZRLzXsc,4551
12
+ objpath/_keys.py,sha256=Eh9i5vpRJJQFdam0jxVns8U1MOuaoFhfP2Qj9_wat0I,4423
13
+ objpath/_optional.py,sha256=jBbIdrp3dA15_D2JKA_CiSzoprGvkrD6UQkRM4eVOuM,2159
14
+ objpath/_places.py,sha256=vtDR5Kh3_H_2qqs0BoSZGDGdSGDXhj9VRi7PNqDdjYk,1055
15
+ objpath/_reader.py,sha256=8NDZy5AUEr4HFm0vCtPUFmNCYGRPA3_5yRI3XEvPkRE,2893
16
+ objpath/_s3.py,sha256=PA3jpHZfwtsgWMF5LzThYsMu8m3_z8WUCUm3XESH13A,19523
17
+ objpath/_s3_backend.py,sha256=RR1vTAQLFaTXiW47tn6Y4exMQVFn9TZbcbjGX4SSU_E,2250
18
+ objpath/_s3_errors.py,sha256=MSqThOnyzSbnJkP1ysAhHwxdjdWNdG9vHWwm84zH1Ik,4278
19
+ objpath/_storepath.py,sha256=TiNXbH9ZwlCTbfJUBZxCwyZshw3_sVJbT6pb1rDUa3A,22637
20
+ objpath/_uri_store.py,sha256=GwLHPqIEL7_FfN1Ym7SRyN7y3qGR94jof6N83OQBinc,6273
21
+ objpath/_version.py,sha256=hcDoVXoHoOHn8E5oO2MSjjLQkA0eBxQFd6fM-olPsms,307
22
+ objpath/_writer.py,sha256=Pzge-9HkNLyb49Xm-6OWGeL8VGljm4grglI3cbEvhfk,3425
23
+ objpath/exceptions.py,sha256=EH9LRqsKeNrZU11FPLBzOyD4bqgWP3W7Uri3rFTKGQY,1164
24
+ objpath/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
+ objpath/uri.py,sha256=LbwBSvPPPIUixkZLoZ9rpNEwUxYbS4WyD7vD1Ni4MHo,7631
26
+ objpath/README.md,sha256=sr0xiNtPreB948zLBirXEuSe2Kfw8VgSF0xnwRlQO2Q,7157
27
+ objpath-0.1.0.dist-info/METADATA,sha256=VxiH7aupz1yZcgWzxivtOclkzk2DRit_jYJ8IYHlNNs,9255
28
+ objpath-0.1.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
29
+ objpath-0.1.0.dist-info/entry_points.txt,sha256=fJRzVbr7g-wZY-cRB0k5mS6Pah3xcszthQZMZMxSQQc,99
30
+ objpath-0.1.0.dist-info/licenses/LICENSE,sha256=bBY0SeXglEP0yGEOZbyqRTbNfXD0DVpkr-3mBq7-BPQ,1063
31
+ objpath-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.4
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,4 @@
1
+ [uripath.schemes]
2
+ az = objpath.uri:AZURIPath
3
+ gs = objpath.uri:GSURIPath
4
+ s3 = objpath.uri:S3URIPath
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Jose A
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.