chuk-artifacts 0.1.1__py3-none-any.whl → 0.1.2__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/session_operations.py +39 -117
- {chuk_artifacts-0.1.1.dist-info → chuk_artifacts-0.1.2.dist-info}/METADATA +1 -1
- {chuk_artifacts-0.1.1.dist-info → chuk_artifacts-0.1.2.dist-info}/RECORD +6 -6
- {chuk_artifacts-0.1.1.dist-info → chuk_artifacts-0.1.2.dist-info}/WHEEL +0 -0
- {chuk_artifacts-0.1.1.dist-info → chuk_artifacts-0.1.2.dist-info}/licenses/LICENSE +0 -0
- {chuk_artifacts-0.1.1.dist-info → chuk_artifacts-0.1.2.dist-info}/top_level.txt +0 -0
@@ -1,8 +1,8 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
-
# chuk_artifacts/session_operations.py (
|
2
|
+
# chuk_artifacts/session_operations.py (LOGGING FIX)
|
3
3
|
"""
|
4
4
|
Session-based file operations with strict session isolation.
|
5
|
-
|
5
|
+
FIXED: Resolved logging conflict with 'filename' parameter.
|
6
6
|
"""
|
7
7
|
|
8
8
|
from __future__ import annotations
|
@@ -36,27 +36,6 @@ class SessionOperations(BaseOperations):
|
|
36
36
|
) -> Dict[str, Any]:
|
37
37
|
"""
|
38
38
|
Move a file within the SAME session or rename it.
|
39
|
-
|
40
|
-
Parameters
|
41
|
-
----------
|
42
|
-
artifact_id : str
|
43
|
-
Source artifact ID
|
44
|
-
new_filename : str, optional
|
45
|
-
New filename (renames the file)
|
46
|
-
new_session_id : str, optional
|
47
|
-
Target session (BLOCKED - always raises error if different)
|
48
|
-
new_meta : dict, optional
|
49
|
-
Additional metadata to merge
|
50
|
-
|
51
|
-
Returns
|
52
|
-
-------
|
53
|
-
dict
|
54
|
-
Updated artifact metadata
|
55
|
-
|
56
|
-
Raises
|
57
|
-
------
|
58
|
-
ArtifactStoreError
|
59
|
-
If trying to move across sessions (always blocked)
|
60
39
|
"""
|
61
40
|
self._check_closed()
|
62
41
|
|
@@ -96,12 +75,14 @@ class SessionOperations(BaseOperations):
|
|
96
75
|
raise
|
97
76
|
except Exception as e:
|
98
77
|
logger.error(
|
99
|
-
"File move failed",
|
78
|
+
"File move failed for artifact %s: %s",
|
79
|
+
artifact_id,
|
80
|
+
str(e),
|
100
81
|
extra={
|
101
82
|
"artifact_id": artifact_id,
|
102
|
-
"
|
83
|
+
"new_file_name": new_filename, # FIXED: Renamed from 'new_filename'
|
103
84
|
"new_session_id": new_session_id,
|
104
|
-
"
|
85
|
+
"operation": "move_file"
|
105
86
|
}
|
106
87
|
)
|
107
88
|
raise ProviderError(f"Move operation failed: {e}") from e
|
@@ -117,29 +98,6 @@ class SessionOperations(BaseOperations):
|
|
117
98
|
) -> str:
|
118
99
|
"""
|
119
100
|
Copy a file WITHIN THE SAME SESSION only.
|
120
|
-
|
121
|
-
Parameters
|
122
|
-
----------
|
123
|
-
artifact_id : str
|
124
|
-
Source artifact ID
|
125
|
-
new_filename : str, optional
|
126
|
-
Filename for the copy (defaults to original + "_copy")
|
127
|
-
target_session_id : str, optional
|
128
|
-
Target session (BLOCKED - must be same as source session)
|
129
|
-
new_meta : dict, optional
|
130
|
-
Additional metadata to merge
|
131
|
-
summary : str, optional
|
132
|
-
New summary for the copy
|
133
|
-
|
134
|
-
Returns
|
135
|
-
-------
|
136
|
-
str
|
137
|
-
New artifact ID of the copy
|
138
|
-
|
139
|
-
Raises
|
140
|
-
------
|
141
|
-
ArtifactStoreError
|
142
|
-
If trying to copy across sessions (always blocked)
|
143
101
|
"""
|
144
102
|
self._check_closed()
|
145
103
|
|
@@ -193,12 +151,15 @@ class SessionOperations(BaseOperations):
|
|
193
151
|
)
|
194
152
|
|
195
153
|
logger.info(
|
196
|
-
"File copied within session",
|
154
|
+
"File copied within session: %s -> %s",
|
155
|
+
artifact_id,
|
156
|
+
new_artifact_id,
|
197
157
|
extra={
|
198
158
|
"source_artifact_id": artifact_id,
|
199
159
|
"new_artifact_id": new_artifact_id,
|
200
160
|
"session": copy_session,
|
201
|
-
"security_level": "same_session_only"
|
161
|
+
"security_level": "same_session_only",
|
162
|
+
"operation": "copy_file"
|
202
163
|
}
|
203
164
|
)
|
204
165
|
|
@@ -208,12 +169,14 @@ class SessionOperations(BaseOperations):
|
|
208
169
|
raise
|
209
170
|
except Exception as e:
|
210
171
|
logger.error(
|
211
|
-
"File copy failed",
|
172
|
+
"File copy failed for artifact %s: %s",
|
173
|
+
artifact_id,
|
174
|
+
str(e),
|
212
175
|
extra={
|
213
176
|
"artifact_id": artifact_id,
|
214
|
-
"
|
177
|
+
"new_file_name": new_filename, # FIXED: Renamed from 'new_filename'
|
215
178
|
"target_session_id": target_session_id,
|
216
|
-
"
|
179
|
+
"operation": "copy_file"
|
217
180
|
}
|
218
181
|
)
|
219
182
|
raise ProviderError(f"Copy operation failed: {e}") from e
|
@@ -227,9 +190,6 @@ class SessionOperations(BaseOperations):
|
|
227
190
|
) -> Union[str, bytes]:
|
228
191
|
"""
|
229
192
|
Read file content directly.
|
230
|
-
|
231
|
-
Note: This operation inherently respects session boundaries since
|
232
|
-
you can only read files you have artifact IDs for.
|
233
193
|
"""
|
234
194
|
self._check_closed()
|
235
195
|
|
@@ -249,8 +209,10 @@ class SessionOperations(BaseOperations):
|
|
249
209
|
raise
|
250
210
|
except Exception as e:
|
251
211
|
logger.error(
|
252
|
-
"File read failed",
|
253
|
-
|
212
|
+
"File read failed for artifact %s: %s",
|
213
|
+
artifact_id,
|
214
|
+
str(e),
|
215
|
+
extra={"artifact_id": artifact_id, "operation": "read_file"}
|
254
216
|
)
|
255
217
|
raise ProviderError(f"Read operation failed: {e}") from e
|
256
218
|
|
@@ -268,35 +230,6 @@ class SessionOperations(BaseOperations):
|
|
268
230
|
) -> str:
|
269
231
|
"""
|
270
232
|
Write content to a new file or overwrite existing WITHIN THE SAME SESSION.
|
271
|
-
|
272
|
-
Parameters
|
273
|
-
----------
|
274
|
-
content : str or bytes
|
275
|
-
Content to write
|
276
|
-
filename : str
|
277
|
-
Filename for the new file
|
278
|
-
mime : str, optional
|
279
|
-
MIME type (default: text/plain)
|
280
|
-
summary : str, optional
|
281
|
-
File summary
|
282
|
-
session_id : str, optional
|
283
|
-
Session for the file
|
284
|
-
meta : dict, optional
|
285
|
-
Additional metadata
|
286
|
-
encoding : str, optional
|
287
|
-
Text encoding for string content (default: utf-8)
|
288
|
-
overwrite_artifact_id : str, optional
|
289
|
-
If provided, overwrite this existing artifact (must be in same session)
|
290
|
-
|
291
|
-
Returns
|
292
|
-
-------
|
293
|
-
str
|
294
|
-
Artifact ID of the written file
|
295
|
-
|
296
|
-
Raises
|
297
|
-
------
|
298
|
-
ArtifactStoreError
|
299
|
-
If trying to overwrite a file in a different session
|
300
233
|
"""
|
301
234
|
self._check_closed()
|
302
235
|
|
@@ -351,28 +284,35 @@ class SessionOperations(BaseOperations):
|
|
351
284
|
meta=write_meta
|
352
285
|
)
|
353
286
|
|
287
|
+
# FIXED: Use separate variables for logging to avoid 'filename' conflict
|
354
288
|
logger.info(
|
355
|
-
"File written successfully",
|
289
|
+
"File written successfully: %s (artifact_id: %s)",
|
290
|
+
filename,
|
291
|
+
artifact_id,
|
356
292
|
extra={
|
357
293
|
"artifact_id": artifact_id,
|
358
|
-
"
|
294
|
+
"file_name": filename, # FIXED: Renamed from 'filename'
|
359
295
|
"bytes": len(data),
|
360
296
|
"overwrite": bool(overwrite_artifact_id),
|
361
297
|
"session_id": session_id,
|
362
|
-
"security_level": "session_isolated"
|
298
|
+
"security_level": "session_isolated",
|
299
|
+
"operation": "write_file"
|
363
300
|
}
|
364
301
|
)
|
365
302
|
|
366
303
|
return artifact_id
|
367
304
|
|
368
305
|
except Exception as e:
|
306
|
+
# FIXED: Use separate variables for logging to avoid 'filename' conflict
|
369
307
|
logger.error(
|
370
|
-
"File write failed",
|
308
|
+
"File write failed for %s: %s",
|
309
|
+
filename,
|
310
|
+
str(e),
|
371
311
|
extra={
|
372
|
-
"
|
312
|
+
"file_name": filename, # FIXED: Renamed from 'filename'
|
373
313
|
"overwrite_artifact_id": overwrite_artifact_id,
|
374
314
|
"session_id": session_id,
|
375
|
-
"
|
315
|
+
"operation": "write_file"
|
376
316
|
}
|
377
317
|
)
|
378
318
|
raise ProviderError(f"Write operation failed: {e}") from e
|
@@ -385,9 +325,6 @@ class SessionOperations(BaseOperations):
|
|
385
325
|
) -> List[Dict[str, Any]]:
|
386
326
|
"""
|
387
327
|
List files in a directory-like structure within a session.
|
388
|
-
|
389
|
-
This operation is inherently session-safe since it requires
|
390
|
-
explicit session_id parameter.
|
391
328
|
"""
|
392
329
|
try:
|
393
330
|
from .metadata import MetadataOperations
|
@@ -395,11 +332,13 @@ class SessionOperations(BaseOperations):
|
|
395
332
|
return await metadata_ops.list_by_prefix(session_id, directory_prefix, limit)
|
396
333
|
except Exception as e:
|
397
334
|
logger.error(
|
398
|
-
"Directory listing failed",
|
335
|
+
"Directory listing failed for session %s: %s",
|
336
|
+
session_id,
|
337
|
+
str(e),
|
399
338
|
extra={
|
400
339
|
"session_id": session_id,
|
401
340
|
"directory_prefix": directory_prefix,
|
402
|
-
"
|
341
|
+
"operation": "get_directory_contents"
|
403
342
|
}
|
404
343
|
)
|
405
344
|
raise ProviderError(f"Directory listing failed: {e}") from e
|
@@ -410,27 +349,10 @@ class SessionOperations(BaseOperations):
|
|
410
349
|
core_ops = CoreStorageOperations(self._artifact_store)
|
411
350
|
return await core_ops.retrieve(artifact_id)
|
412
351
|
|
413
|
-
#
|
352
|
+
# Session security validation helper
|
414
353
|
async def _validate_session_access(self, artifact_id: str, expected_session_id: str = None) -> Dict[str, Any]:
|
415
354
|
"""
|
416
355
|
Validate that an artifact belongs to the expected session.
|
417
|
-
|
418
|
-
Parameters
|
419
|
-
----------
|
420
|
-
artifact_id : str
|
421
|
-
Artifact to check
|
422
|
-
expected_session_id : str, optional
|
423
|
-
Expected session ID (if None, just returns the session)
|
424
|
-
|
425
|
-
Returns
|
426
|
-
-------
|
427
|
-
dict
|
428
|
-
Artifact metadata
|
429
|
-
|
430
|
-
Raises
|
431
|
-
------
|
432
|
-
ArtifactStoreError
|
433
|
-
If artifact belongs to different session
|
434
356
|
"""
|
435
357
|
record = await self._get_record(artifact_id)
|
436
358
|
actual_session = record.get("session_id")
|
@@ -9,7 +9,7 @@ chuk_artifacts/metadata.py,sha256=cBMMwCuyRtmJHjqHWuKMbK1G-kg_G4QpfqW-7RxhIzw,11
|
|
9
9
|
chuk_artifacts/models.py,sha256=_foXlkr0DprqgztDw5WtlDc-s1OouLgYNp4XM1Ghp-g,837
|
10
10
|
chuk_artifacts/presigned.py,sha256=qonNg7WMd7VmOEXAzF6GssXuPs5be2s8IJhtuFul7JM,9638
|
11
11
|
chuk_artifacts/provider_factory.py,sha256=T0IXx1C8gygJzp417oB44_DxEaZoZR7jcdwQy8FghRE,3398
|
12
|
-
chuk_artifacts/session_operations.py,sha256=
|
12
|
+
chuk_artifacts/session_operations.py,sha256=dolSkSnm4W_9ZElZJy25RmsKuLjUnnkfH8SvZWkbW5A,14232
|
13
13
|
chuk_artifacts/store.py,sha256=0RKSAkSfTM1v-qg3ERv3-8VaRiBVMxdGy2qxjFVz9MY,19749
|
14
14
|
chuk_artifacts/providers/__init__.py,sha256=3lN1lAy1ETT1mQslJo1f22PPR1W4CyxmsqJBclzH4NE,317
|
15
15
|
chuk_artifacts/providers/filesystem.py,sha256=F4EjE-_ItPg0RWe7CqameVpOMjU-b7AigEBkm_ZoNrc,15280
|
@@ -17,8 +17,8 @@ chuk_artifacts/providers/ibm_cos.py,sha256=K1-VAX4UVV9tA161MOeDXOKloQ0hB77jdw1-p
|
|
17
17
|
chuk_artifacts/providers/ibm_cos_iam.py,sha256=VtwvCi9rMMcZx6i9l21ob6wM8jXseqvjzgCnAA82RkY,3186
|
18
18
|
chuk_artifacts/providers/memory.py,sha256=B1C-tR1PcNz-UuDfGm1bhjPz3oITVATIMPekVbE7nm4,10487
|
19
19
|
chuk_artifacts/providers/s3.py,sha256=eWhBhFSaobpRbazn7ySfU_7D8rm_xCfdSVqRtzXzXRY,2858
|
20
|
-
chuk_artifacts-0.1.
|
21
|
-
chuk_artifacts-0.1.
|
22
|
-
chuk_artifacts-0.1.
|
23
|
-
chuk_artifacts-0.1.
|
24
|
-
chuk_artifacts-0.1.
|
20
|
+
chuk_artifacts-0.1.2.dist-info/licenses/LICENSE,sha256=SG9BmgtPBagPV0d-Fep-msdAGl-E1CeoBL7-EDRH2qA,1066
|
21
|
+
chuk_artifacts-0.1.2.dist-info/METADATA,sha256=RYa5j8aK37uuKQeqSp9OKpP1KGU4PoJXLUStrwq_pZY,20975
|
22
|
+
chuk_artifacts-0.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
23
|
+
chuk_artifacts-0.1.2.dist-info/top_level.txt,sha256=1_PVMtWXR0A-ZmeH6apF9mPaMtU0i23JE6wmN4GBRDI,15
|
24
|
+
chuk_artifacts-0.1.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|