rosetta-cli 3.0.6__tar.gz → 3.0.7__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.
- {rosetta_cli-3.0.6/rosetta_cli.egg-info → rosetta_cli-3.0.7}/PKG-INFO +1 -1
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/pyproject.toml +1 -1
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli/rosetta_publisher.py +53 -21
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli/services/document_data.py +10 -3
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7/rosetta_cli.egg-info}/PKG-INFO +1 -1
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/MANIFEST.in +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/README.md +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/env.template +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli/__init__.py +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli/__main__.py +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli/cli.py +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli/commands/__init__.py +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli/commands/base_command.py +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli/commands/cleanup_command.py +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli/commands/list_command.py +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli/commands/parse_command.py +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli/commands/publish_command.py +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli/commands/verify_command.py +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli/ragflow_client.py +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli/rosetta_auth.py +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli/rosetta_config.py +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli/rosetta_utils.py +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli/services/__init__.py +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli/services/auth_service.py +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli/services/dataset_service.py +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli/services/document_service.py +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli/typing_utils.py +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli.egg-info/SOURCES.txt +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli.egg-info/dependency_links.txt +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli.egg-info/entry_points.txt +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli.egg-info/requires.txt +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/rosetta_cli.egg-info/top_level.txt +0 -0
- {rosetta_cli-3.0.6 → rosetta_cli-3.0.7}/setup.cfg +0 -0
|
@@ -23,7 +23,7 @@ from pathlib import Path
|
|
|
23
23
|
from typing import cast
|
|
24
24
|
|
|
25
25
|
from .services.document_service import DocumentService
|
|
26
|
-
from .services.document_data import DocumentData
|
|
26
|
+
from .services.document_data import DocumentData, InvalidTextEncodingError
|
|
27
27
|
from .ragflow_client import DocumentMetadata, RAGFlowClient, RAGFlowClientError
|
|
28
28
|
from .rosetta_config import DEFAULT_PARSE_TIMEOUT
|
|
29
29
|
from .typing_utils import DocumentLike, JsonDict
|
|
@@ -171,6 +171,7 @@ class ContentPublisher:
|
|
|
171
171
|
print("Reading files...")
|
|
172
172
|
all_caches = [] # ALL successfully read caches (for cleanup/orphan detection)
|
|
173
173
|
results = []
|
|
174
|
+
read_failures: list[Path] = []
|
|
174
175
|
|
|
175
176
|
for file in files:
|
|
176
177
|
try:
|
|
@@ -178,17 +179,32 @@ class ContentPublisher:
|
|
|
178
179
|
cache = DocumentData.from_file(
|
|
179
180
|
file,
|
|
180
181
|
self.workspace_root,
|
|
181
|
-
self.file_extensions,
|
|
182
182
|
publish_root=folder,
|
|
183
183
|
)
|
|
184
184
|
all_caches.append(cache)
|
|
185
185
|
|
|
186
186
|
except Exception as e:
|
|
187
|
+
read_failures.append(file)
|
|
187
188
|
print(f"✗ Error reading {file.name}: {e}")
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
189
|
+
results.append(PublishResult(
|
|
190
|
+
success=False,
|
|
191
|
+
document_id="",
|
|
192
|
+
file_path=str(file),
|
|
193
|
+
tags=[],
|
|
194
|
+
error=str(e),
|
|
195
|
+
))
|
|
196
|
+
|
|
197
|
+
# Destructive cleanup requires a complete local inventory. If even one
|
|
198
|
+
# file could not be read, preserve remote documents until a full run can
|
|
199
|
+
# determine which paths are truly stale.
|
|
200
|
+
if read_failures:
|
|
201
|
+
print(
|
|
202
|
+
"\nDuplicate cleanup skipped "
|
|
203
|
+
f"({len(read_failures)} local file(s) could not be read)"
|
|
204
|
+
)
|
|
205
|
+
else:
|
|
206
|
+
# Remove stale server copies of the same file before publishing.
|
|
207
|
+
self._cleanup_duplicates(all_caches, dry_run)
|
|
192
208
|
|
|
193
209
|
# Check for changes after cleanup so skip decisions reflect current server state.
|
|
194
210
|
doc_caches = [] # Only changed caches (for publishing)
|
|
@@ -271,15 +287,23 @@ class ContentPublisher:
|
|
|
271
287
|
# docs — running orphan detection would delete everything else.
|
|
272
288
|
is_full_publish = folder.name == "instructions" or folder.parent == self.workspace_root
|
|
273
289
|
if is_full_publish:
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
290
|
+
if read_failures:
|
|
291
|
+
# The local inventory is incomplete, so a failed read must not
|
|
292
|
+
# make an existing server document look like an orphan.
|
|
293
|
+
print(
|
|
294
|
+
"\nOrphan detection skipped "
|
|
295
|
+
f"({len(read_failures)} local file(s) could not be read)"
|
|
296
|
+
)
|
|
297
|
+
else:
|
|
298
|
+
managed_domains_by_dataset: dict[str, set[str]] = {}
|
|
299
|
+
for cache in all_caches:
|
|
300
|
+
dataset_name = self._resolve_dataset_name({"release": cache.release})
|
|
301
|
+
managed_domains_by_dataset.setdefault(dataset_name, set()).add(cache.domain)
|
|
302
|
+
self._cleanup_orphans(
|
|
303
|
+
all_caches,
|
|
304
|
+
dry_run,
|
|
305
|
+
managed_domains_by_dataset=managed_domains_by_dataset,
|
|
306
|
+
)
|
|
283
307
|
else:
|
|
284
308
|
print("\nOrphan detection skipped (subfolder publish)")
|
|
285
309
|
|
|
@@ -347,12 +371,20 @@ class ContentPublisher:
|
|
|
347
371
|
)
|
|
348
372
|
|
|
349
373
|
# Create cache on-the-fly (still better than reading multiple times)
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
374
|
+
try:
|
|
375
|
+
cache = DocumentData.from_file(
|
|
376
|
+
file,
|
|
377
|
+
self.workspace_root,
|
|
378
|
+
publish_root=file.parent,
|
|
379
|
+
)
|
|
380
|
+
except InvalidTextEncodingError as e:
|
|
381
|
+
return PublishResult(
|
|
382
|
+
success=False,
|
|
383
|
+
document_id="",
|
|
384
|
+
file_path=str(file),
|
|
385
|
+
tags=[],
|
|
386
|
+
error=str(e),
|
|
387
|
+
)
|
|
356
388
|
|
|
357
389
|
ims_doc_id = cache.ims_doc_id
|
|
358
390
|
content = cache.content
|
|
@@ -18,6 +18,13 @@ except Exception: # pragma: no cover - guarded at runtime
|
|
|
18
18
|
frontmatter = None
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
class InvalidTextEncodingError(ValueError):
|
|
22
|
+
"""Raised when a text-suffix file cannot be decoded as UTF-8."""
|
|
23
|
+
|
|
24
|
+
def __init__(self, file_path: Path):
|
|
25
|
+
super().__init__(f"{file_path} is not valid UTF-8")
|
|
26
|
+
|
|
27
|
+
|
|
21
28
|
def _is_r2_or_later(release: str) -> bool:
|
|
22
29
|
"""Check if release is r2 or later (r2, r3, r2.5, etc.)."""
|
|
23
30
|
if not release or not release.startswith("r"):
|
|
@@ -85,8 +92,8 @@ class DocumentData:
|
|
|
85
92
|
if is_text:
|
|
86
93
|
try:
|
|
87
94
|
content_str = content.decode("utf-8")
|
|
88
|
-
except UnicodeDecodeError:
|
|
89
|
-
|
|
95
|
+
except UnicodeDecodeError as error:
|
|
96
|
+
raise InvalidTextEncodingError(file_path) from error
|
|
90
97
|
|
|
91
98
|
# Count lines platform-independently: \r\n, \n\r, \r, \n all count as separators
|
|
92
99
|
line_count = None
|
|
@@ -111,7 +118,7 @@ class DocumentData:
|
|
|
111
118
|
doc_title = cls._compute_doc_title(parsed_path, file_path.name)
|
|
112
119
|
|
|
113
120
|
content_hash = cls._calculate_hash(
|
|
114
|
-
content_str if content_str is not None else
|
|
121
|
+
content_str if content_str is not None else hashlib.sha256(content).hexdigest(),
|
|
115
122
|
tags,
|
|
116
123
|
domain,
|
|
117
124
|
release,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|