chuk-artifacts 0.4__py3-none-any.whl → 0.4.1__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.
- chuk_artifacts/__init__.py +5 -1
- chuk_artifacts/core.py +75 -58
- chuk_artifacts/store.py +6 -3
- {chuk_artifacts-0.4.dist-info → chuk_artifacts-0.4.1.dist-info}/METADATA +1 -1
- {chuk_artifacts-0.4.dist-info → chuk_artifacts-0.4.1.dist-info}/RECORD +7 -7
- {chuk_artifacts-0.4.dist-info → chuk_artifacts-0.4.1.dist-info}/WHEEL +0 -0
- {chuk_artifacts-0.4.dist-info → chuk_artifacts-0.4.1.dist-info}/top_level.txt +0 -0
chuk_artifacts/__init__.py
CHANGED
@@ -12,6 +12,7 @@ from dotenv import load_dotenv
|
|
12
12
|
|
13
13
|
# Core classes
|
14
14
|
from .store import ArtifactStore
|
15
|
+
from .models import ArtifactEnvelope
|
15
16
|
|
16
17
|
# Exception classes
|
17
18
|
from .exceptions import (
|
@@ -42,6 +43,9 @@ __all__ = [
|
|
42
43
|
# Main class
|
43
44
|
"ArtifactStore",
|
44
45
|
|
46
|
+
# Models
|
47
|
+
"ArtifactEnvelope",
|
48
|
+
|
45
49
|
# Exceptions
|
46
50
|
"ArtifactStoreError",
|
47
51
|
"ArtifactNotFoundError",
|
@@ -146,4 +150,4 @@ def configure_logging(level: str = "INFO"):
|
|
146
150
|
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
147
151
|
)
|
148
152
|
handler.setFormatter(formatter)
|
149
|
-
logger.addHandler(handler)
|
153
|
+
logger.addHandler(handler)
|
chuk_artifacts/core.py
CHANGED
@@ -19,7 +19,7 @@ from typing import Any, Dict, Optional, TYPE_CHECKING
|
|
19
19
|
if TYPE_CHECKING:
|
20
20
|
from .store import ArtifactStore
|
21
21
|
|
22
|
-
from .exceptions import ArtifactStoreError, ProviderError, SessionError
|
22
|
+
from .exceptions import ArtifactStoreError, ProviderError, SessionError, ArtifactNotFoundError
|
23
23
|
|
24
24
|
logger = logging.getLogger(__name__)
|
25
25
|
|
@@ -102,44 +102,55 @@ class CoreStorageOperations:
|
|
102
102
|
raise ProviderError(f"Storage failed: {e}") from e
|
103
103
|
|
104
104
|
async def update_file(
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
105
|
+
self,
|
106
|
+
artifact_id: str,
|
107
|
+
new_data: Optional[bytes] = None,
|
108
|
+
*,
|
109
|
+
mime: Optional[str] = None,
|
110
|
+
summary: Optional[str] = None,
|
111
|
+
meta: Optional[Dict[str, Any]] = None,
|
112
|
+
filename: Optional[str] = None,
|
113
|
+
ttl: Optional[int] = None,
|
114
|
+
) -> bool:
|
115
|
+
"""
|
116
|
+
Update an artifact's content, metadata, filename, summary, or mime type.
|
117
|
+
|
118
|
+
Parameters
|
119
|
+
----------
|
120
|
+
artifact_id : str
|
121
|
+
ID of the artifact to update
|
122
|
+
new_data : bytes, optional
|
123
|
+
New data to overwrite the existing artifact
|
124
|
+
mime : str, optional
|
125
|
+
New MIME type
|
126
|
+
summary : str, optional
|
127
|
+
New summary
|
128
|
+
meta : dict, optional
|
129
|
+
Updated metadata
|
130
|
+
filename : str, optional
|
131
|
+
New filename
|
132
|
+
ttl : int, optional
|
133
|
+
New TTL
|
134
|
+
|
135
|
+
Returns
|
136
|
+
-------
|
137
|
+
bool
|
138
|
+
True if update was successful
|
139
|
+
"""
|
140
|
+
if self.artifact_store._closed:
|
141
|
+
raise ArtifactStoreError("Store is closed")
|
117
142
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
ID of the artifact to update.
|
122
|
-
new_data : bytes
|
123
|
-
New data to overwrite the existing artifact.
|
124
|
-
mime : Optional[str]
|
125
|
-
Optional new MIME type.
|
126
|
-
summary : Optional[str]
|
127
|
-
Optional new summary.
|
128
|
-
meta : Optional[Dict[str, Any]]
|
129
|
-
Optional updated metadata.
|
130
|
-
filename : Optional[str]
|
131
|
-
Optional new filename.
|
132
|
-
ttl : Optional[int]
|
133
|
-
Optional TTL to reset (if provided).
|
134
|
-
"""
|
135
|
-
if self.artifact_store._closed:
|
136
|
-
raise ArtifactStoreError("Store is closed")
|
143
|
+
if not any([new_data is not None, meta is not None, filename is not None,
|
144
|
+
summary is not None, mime is not None, ttl is not None]):
|
145
|
+
raise ValueError("At least one update parameter must be provided.")
|
137
146
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
147
|
+
try:
|
148
|
+
record = await self._get_record(artifact_id)
|
149
|
+
key = record["key"]
|
150
|
+
session_id = record["session_id"]
|
142
151
|
|
152
|
+
# Update data if provided
|
153
|
+
if new_data is not None:
|
143
154
|
# Overwrite in object storage
|
144
155
|
await self._store_with_retry(
|
145
156
|
new_data,
|
@@ -148,31 +159,37 @@ class CoreStorageOperations:
|
|
148
159
|
filename or record.get("filename"),
|
149
160
|
session_id,
|
150
161
|
)
|
162
|
+
|
163
|
+
# Update size and hash in metadata
|
164
|
+
record["bytes"] = len(new_data)
|
165
|
+
record["sha256"] = hashlib.sha256(new_data).hexdigest()
|
151
166
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
167
|
+
# Update metadata fields
|
168
|
+
if mime is not None:
|
169
|
+
record["mime"] = mime
|
170
|
+
if summary is not None:
|
171
|
+
record["summary"] = summary
|
172
|
+
if filename is not None:
|
173
|
+
record["filename"] = filename
|
174
|
+
if meta is not None:
|
175
|
+
record["meta"] = meta
|
176
|
+
if ttl is not None:
|
177
|
+
record["ttl"] = ttl
|
163
178
|
|
164
|
-
|
165
|
-
|
179
|
+
# Add update timestamp
|
180
|
+
record["updated_at"] = datetime.utcnow().isoformat() + "Z"
|
166
181
|
|
167
|
-
|
168
|
-
|
169
|
-
|
182
|
+
# Store updated metadata
|
183
|
+
session_ctx_mgr = self.artifact_store._session_factory()
|
184
|
+
async with session_ctx_mgr as session:
|
185
|
+
await session.setex(artifact_id, record["ttl"], json.dumps(record))
|
170
186
|
|
171
|
-
|
187
|
+
logger.info("Artifact updated successfully", extra={"artifact_id": artifact_id})
|
188
|
+
return True
|
172
189
|
|
173
|
-
|
174
|
-
|
175
|
-
|
190
|
+
except Exception as e:
|
191
|
+
logger.error(f"Update failed for artifact {artifact_id}: {e}")
|
192
|
+
raise ProviderError(f"Artifact update failed: {e}") from e
|
176
193
|
|
177
194
|
async def retrieve(self, artifact_id: str) -> bytes:
|
178
195
|
"""Retrieve artifact data."""
|
@@ -246,7 +263,7 @@ class CoreStorageOperations:
|
|
246
263
|
raise last_exception
|
247
264
|
|
248
265
|
async def _get_record(self, artifact_id: str) -> Dict[str, Any]:
|
249
|
-
"""Get artifact metadata."""
|
266
|
+
"""Get artifact metadata record from session provider."""
|
250
267
|
try:
|
251
268
|
session_ctx_mgr = self.artifact_store._session_factory()
|
252
269
|
async with session_ctx_mgr as session:
|
@@ -255,7 +272,7 @@ class CoreStorageOperations:
|
|
255
272
|
raise SessionError(f"Session error for {artifact_id}: {e}") from e
|
256
273
|
|
257
274
|
if raw is None:
|
258
|
-
raise
|
275
|
+
raise ArtifactNotFoundError(f"Artifact {artifact_id} not found")
|
259
276
|
|
260
277
|
try:
|
261
278
|
return json.loads(raw)
|
chuk_artifacts/store.py
CHANGED
@@ -172,21 +172,24 @@ class ArtifactStore:
|
|
172
172
|
filename: Optional[str] = None,
|
173
173
|
summary: Optional[str] = None,
|
174
174
|
mime: Optional[str] = None,
|
175
|
+
ttl: Optional[int] = None,
|
175
176
|
) -> bool:
|
176
177
|
"""
|
177
178
|
Update an artifact's content, metadata, filename, summary, or mime type.
|
178
179
|
All parameters are optional. At least one must be provided.
|
179
180
|
"""
|
180
|
-
if not any([data, meta, filename
|
181
|
+
if not any([data is not None, meta is not None, filename is not None,
|
182
|
+
summary is not None, mime is not None, ttl is not None]):
|
181
183
|
raise ValueError("At least one update parameter must be provided.")
|
182
184
|
|
183
185
|
return await self._core.update_file(
|
184
186
|
artifact_id=artifact_id,
|
185
187
|
new_data=data,
|
188
|
+
mime=mime,
|
189
|
+
summary=summary,
|
186
190
|
meta=meta,
|
187
191
|
filename=filename,
|
188
|
-
|
189
|
-
mime=mime,
|
192
|
+
ttl=ttl,
|
190
193
|
)
|
191
194
|
|
192
195
|
async def retrieve(self, artifact_id: str) -> bytes:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: chuk-artifacts
|
3
|
-
Version: 0.4
|
3
|
+
Version: 0.4.1
|
4
4
|
Summary: Chuk Artifacts provides a production-ready, modular artifact storage system that works seamlessly across multiple storage backends (memory, filesystem, AWS S3, IBM Cloud Object Storage) with Redis or memory-based metadata caching and strict session-based security.
|
5
5
|
Requires-Python: >=3.11
|
6
6
|
Description-Content-Type: text/markdown
|
@@ -1,23 +1,23 @@
|
|
1
|
-
chuk_artifacts/__init__.py,sha256
|
1
|
+
chuk_artifacts/__init__.py,sha256=9HIUqLd14M4CGcQvTsa4XEd8SBCjYRIqoKfTh_GEG4w,3683
|
2
2
|
chuk_artifacts/admin.py,sha256=lUgmKBPxJh-0FYrGWjkACXQOl8lbVEDPJaeGVsWZmC4,6071
|
3
3
|
chuk_artifacts/base.py,sha256=BtuVnC9M8QI1znyTdBxjZ6knIKP_k0yUfLfh7inGJUc,2559
|
4
4
|
chuk_artifacts/batch.py,sha256=x8ARrWJ24I9fAXXodzvh31uMxYrvwZCGGJhUCM4vMJ4,5099
|
5
5
|
chuk_artifacts/config.py,sha256=MaUzHzKPoBUyERviEpv8JVvPybMzSksgLyj0b7AO3Sc,7664
|
6
|
-
chuk_artifacts/core.py,sha256=
|
6
|
+
chuk_artifacts/core.py,sha256=K23Z9WtbHXCaacWV5mVRPYYCF13qfB0cnG-x3wxXyDs,9893
|
7
7
|
chuk_artifacts/exceptions.py,sha256=f-s7Mg7c8vMXsbgqO2B6lMHdXcJQNvsESAY4GhJaV4g,814
|
8
8
|
chuk_artifacts/grid.py,sha256=PqDQGPSyxzDkQp7X-JKJvUmVmrmjdVv1wbzQ6Ysj6gg,4328
|
9
9
|
chuk_artifacts/metadata.py,sha256=KSWZxaIxpOP_SdxUVXLttQ65aXJGx9ylqkW4n3997fI,7845
|
10
10
|
chuk_artifacts/models.py,sha256=XlI-PATNO67vlGVEOnphCx78mfmofcBRAiVU79Ohs9o,881
|
11
11
|
chuk_artifacts/presigned.py,sha256=-GE8r0CfUZuPNA_jnSGTfX7kuws6kYCPe7C4y6FItdo,11491
|
12
12
|
chuk_artifacts/provider_factory.py,sha256=T0IXx1C8gygJzp417oB44_DxEaZoZR7jcdwQy8FghRE,3398
|
13
|
-
chuk_artifacts/store.py,sha256=
|
13
|
+
chuk_artifacts/store.py,sha256=IAXRQbtvR5jw4GVZKOT_P9_g1B5Kr912NLlESQXUUQI,27533
|
14
14
|
chuk_artifacts/providers/__init__.py,sha256=3lN1lAy1ETT1mQslJo1f22PPR1W4CyxmsqJBclzH4NE,317
|
15
15
|
chuk_artifacts/providers/filesystem.py,sha256=fj8p2SVq8V8GQCnqId77Fkwn_PgOquIj6UEaGTiqUe0,15949
|
16
16
|
chuk_artifacts/providers/ibm_cos.py,sha256=Kf4ZqxP7aHeYKm6gM03aponMzx-lIyWn2_TL8_X4A_U,3677
|
17
17
|
chuk_artifacts/providers/ibm_cos_iam.py,sha256=7mDs0VvVh1OOUmSc-fgghbTa_euongazwZ0QG3wjdJo,5068
|
18
18
|
chuk_artifacts/providers/memory.py,sha256=QpJFxJuZGf548ulctmNGtUpHlRzyx1_PW5F1XNVIKrE,12002
|
19
19
|
chuk_artifacts/providers/s3.py,sha256=QSSiYjNENQfwxJ2-Yw-CJrO8lNZcIrsfdn2Vo_DD-b4,2931
|
20
|
-
chuk_artifacts-0.4.dist-info/METADATA,sha256=
|
21
|
-
chuk_artifacts-0.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
22
|
-
chuk_artifacts-0.4.dist-info/top_level.txt,sha256=1_PVMtWXR0A-ZmeH6apF9mPaMtU0i23JE6wmN4GBRDI,15
|
23
|
-
chuk_artifacts-0.4.dist-info/RECORD,,
|
20
|
+
chuk_artifacts-0.4.1.dist-info/METADATA,sha256=sDw8-dWWFBngeUNzXYD3s7t7D-5_Pa5szsh5clfucPA,18708
|
21
|
+
chuk_artifacts-0.4.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
22
|
+
chuk_artifacts-0.4.1.dist-info/top_level.txt,sha256=1_PVMtWXR0A-ZmeH6apF9mPaMtU0i23JE6wmN4GBRDI,15
|
23
|
+
chuk_artifacts-0.4.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|