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.
- objpath/AGENTS.md +311 -0
- objpath/README.md +153 -0
- objpath/__init__.py +68 -0
- objpath/_az.py +547 -0
- objpath/_az_backend.py +130 -0
- objpath/_az_errors.py +110 -0
- objpath/_clients.py +108 -0
- objpath/_digests.py +10 -0
- objpath/_failures.py +84 -0
- objpath/_gs.py +447 -0
- objpath/_gs_backend.py +95 -0
- objpath/_gs_errors.py +112 -0
- objpath/_keys.py +119 -0
- objpath/_optional.py +60 -0
- objpath/_places.py +26 -0
- objpath/_reader.py +83 -0
- objpath/_s3.py +489 -0
- objpath/_s3_backend.py +68 -0
- objpath/_s3_errors.py +106 -0
- objpath/_storepath.py +579 -0
- objpath/_uri_store.py +162 -0
- objpath/_version.py +11 -0
- objpath/_writer.py +113 -0
- objpath/exceptions.py +31 -0
- objpath/py.typed +0 -0
- objpath/uri.py +213 -0
- objpath-0.1.0.dist-info/METADATA +204 -0
- objpath-0.1.0.dist-info/RECORD +31 -0
- objpath-0.1.0.dist-info/WHEEL +4 -0
- objpath-0.1.0.dist-info/entry_points.txt +4 -0
- objpath-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -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
|
+
[](https://pypi.org/project/objpath/)
|
|
55
|
+
[](https://pypi.org/project/objpath/)
|
|
56
|
+
[](https://github.com/jose-pr/objpath/blob/main/LICENSE)
|
|
57
|
+
[](https://jose-pr.github.io/objpath/)
|
|
58
|
+
[](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,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.
|