savetest-cli 0.3.0rc1__tar.gz → 0.3.0rc2__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.
- {savetest_cli-0.3.0rc1/savetest_cli.egg-info → savetest_cli-0.3.0rc2}/PKG-INFO +2 -2
- {savetest_cli-0.3.0rc1 → savetest_cli-0.3.0rc2}/README.md +1 -1
- {savetest_cli-0.3.0rc1 → savetest_cli-0.3.0rc2}/pyproject.toml +1 -1
- savetest_cli-0.3.0rc2/savetest_cli/__init__.py +1 -0
- {savetest_cli-0.3.0rc1 → savetest_cli-0.3.0rc2}/savetest_cli/cli.py +37 -10
- {savetest_cli-0.3.0rc1 → savetest_cli-0.3.0rc2/savetest_cli.egg-info}/PKG-INFO +2 -2
- savetest_cli-0.3.0rc1/savetest_cli/__init__.py +0 -1
- {savetest_cli-0.3.0rc1 → savetest_cli-0.3.0rc2}/MANIFEST.in +0 -0
- {savetest_cli-0.3.0rc1 → savetest_cli-0.3.0rc2}/savetest_cli/pwa-512x512.png +0 -0
- {savetest_cli-0.3.0rc1 → savetest_cli-0.3.0rc2}/savetest_cli.egg-info/SOURCES.txt +0 -0
- {savetest_cli-0.3.0rc1 → savetest_cli-0.3.0rc2}/savetest_cli.egg-info/dependency_links.txt +0 -0
- {savetest_cli-0.3.0rc1 → savetest_cli-0.3.0rc2}/savetest_cli.egg-info/entry_points.txt +0 -0
- {savetest_cli-0.3.0rc1 → savetest_cli-0.3.0rc2}/savetest_cli.egg-info/requires.txt +0 -0
- {savetest_cli-0.3.0rc1 → savetest_cli-0.3.0rc2}/savetest_cli.egg-info/top_level.txt +0 -0
- {savetest_cli-0.3.0rc1 → savetest_cli-0.3.0rc2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: savetest-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.0rc2
|
|
4
4
|
Summary: CLI for SaveTest: upload Allure results as a ZIP, as raw files, or by watching a directory
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Requires-Python: >=3.8
|
|
@@ -220,7 +220,7 @@ savetest watch ./allure-results \
|
|
|
220
220
|
- Если тесты и загрузка — разные джобы, отдайте каталог `allure-results` артефактом тоже с `when: always`.
|
|
221
221
|
- `--wait` оставляйте включённым: джоба должна завершиться только когда импорт дошёл до конца.
|
|
222
222
|
- Вложения включайте только если они реально нужны. По умолчанию CLI их не шлёт.
|
|
223
|
-
- `0.3.
|
|
223
|
+
- `0.3.0rc2` — предварительная версия для SaveTest 1.5.0: `pip install savetest-cli==0.3.0rc2`. Обычный `pip install savetest-cli` остаётся на последней стабильной версии.
|
|
224
224
|
|
|
225
225
|
### Результаты по мере прогона
|
|
226
226
|
|
|
@@ -210,7 +210,7 @@ savetest watch ./allure-results \
|
|
|
210
210
|
- Если тесты и загрузка — разные джобы, отдайте каталог `allure-results` артефактом тоже с `when: always`.
|
|
211
211
|
- `--wait` оставляйте включённым: джоба должна завершиться только когда импорт дошёл до конца.
|
|
212
212
|
- Вложения включайте только если они реально нужны. По умолчанию CLI их не шлёт.
|
|
213
|
-
- `0.3.
|
|
213
|
+
- `0.3.0rc2` — предварительная версия для SaveTest 1.5.0: `pip install savetest-cli==0.3.0rc2`. Обычный `pip install savetest-cli` остаётся на последней стабильной версии.
|
|
214
214
|
|
|
215
215
|
### Результаты по мере прогона
|
|
216
216
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "savetest-cli"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.0rc2"
|
|
8
8
|
description = "CLI for SaveTest: upload Allure results as a ZIP, as raw files, or by watching a directory"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.3.0rc2"
|
|
@@ -22,6 +22,7 @@ DEFAULT_POLL_INTERVAL_SEC = 1.5
|
|
|
22
22
|
DEFAULT_WAIT_TIMEOUT_SEC = 3600
|
|
23
23
|
DEFAULT_FILE_BATCH_COUNT = 20
|
|
24
24
|
DEFAULT_FILE_BATCH_BYTES = 32 * 1024 * 1024
|
|
25
|
+
DEFAULT_WATCH_BATCH_COUNT = 200
|
|
25
26
|
DEFAULT_WATCH_INTERVAL_SEC = 0.5
|
|
26
27
|
DEFAULT_SETTLE_SEC = 1.0
|
|
27
28
|
DEFAULT_ATTACHMENT_WAIT_SEC = 5.0
|
|
@@ -868,14 +869,28 @@ def _snapshot_raw_files(root: Path, include_attachments: bool) -> Dict[str, Tupl
|
|
|
868
869
|
return found
|
|
869
870
|
|
|
870
871
|
|
|
872
|
+
def _index_snapshot_names(
|
|
873
|
+
snapshot: Dict[str, Tuple[Path, int, int]],
|
|
874
|
+
) -> Dict[str, List[str]]:
|
|
875
|
+
"""Имя файла → пути. Сопоставление вложений не должно перебирать весь каталог."""
|
|
876
|
+
index: Dict[str, List[str]] = {}
|
|
877
|
+
for rel in snapshot:
|
|
878
|
+
index.setdefault(Path(rel).name, []).append(rel)
|
|
879
|
+
return index
|
|
880
|
+
|
|
881
|
+
|
|
871
882
|
def _resolve_named_file(
|
|
872
883
|
snapshot: Dict[str, Tuple[Path, int, int]],
|
|
873
884
|
result_rel: str,
|
|
874
885
|
source_name: str,
|
|
886
|
+
name_index: Optional[Dict[str, List[str]]] = None,
|
|
875
887
|
) -> Optional[str]:
|
|
876
888
|
name = Path(source_name).name
|
|
877
889
|
result_dir = str(Path(result_rel).parent)
|
|
878
|
-
|
|
890
|
+
if name_index is None:
|
|
891
|
+
matches = [rel for rel in snapshot if Path(rel).name == name]
|
|
892
|
+
else:
|
|
893
|
+
matches = name_index.get(name) or []
|
|
879
894
|
if not matches:
|
|
880
895
|
return None
|
|
881
896
|
for rel in matches:
|
|
@@ -921,6 +936,7 @@ def _pick_watch_batch(
|
|
|
921
936
|
continue
|
|
922
937
|
ready[rel] = path
|
|
923
938
|
|
|
939
|
+
name_index = _index_snapshot_names(snapshot)
|
|
924
940
|
held = set()
|
|
925
941
|
if include_attachments:
|
|
926
942
|
for rel, path in list(ready.items()):
|
|
@@ -929,7 +945,7 @@ def _pick_watch_batch(
|
|
|
929
945
|
document = _load_json_if_complete(path) or {}
|
|
930
946
|
missing = False
|
|
931
947
|
for source in _attachment_sources(document):
|
|
932
|
-
attachment_rel = _resolve_named_file(snapshot, rel, source)
|
|
948
|
+
attachment_rel = _resolve_named_file(snapshot, rel, source, name_index)
|
|
933
949
|
if attachment_rel is None or attachment_rel not in ready:
|
|
934
950
|
missing = True
|
|
935
951
|
break
|
|
@@ -952,7 +968,7 @@ def _pick_watch_batch(
|
|
|
952
968
|
for rel, path in send_results:
|
|
953
969
|
document = _load_json_if_complete(path) or {}
|
|
954
970
|
for source in _attachment_sources(document):
|
|
955
|
-
attachment_rel = _resolve_named_file(snapshot, rel, source)
|
|
971
|
+
attachment_rel = _resolve_named_file(snapshot, rel, source, name_index)
|
|
956
972
|
if attachment_rel and attachment_rel in ready:
|
|
957
973
|
needed.add(attachment_rel)
|
|
958
974
|
|
|
@@ -1005,6 +1021,9 @@ def _chunk_watch_selection(
|
|
|
1005
1021
|
"""Режет готовые файлы на пачки. Результат не отрывается от своих вложений."""
|
|
1006
1022
|
results = [(rel, path) for rel, path in selected if _is_result_file(path)]
|
|
1007
1023
|
extras = {rel: (rel, path) for rel, path in selected if not _is_result_file(path)}
|
|
1024
|
+
extras_by_name: Dict[str, List[str]] = {}
|
|
1025
|
+
for extra_rel in extras:
|
|
1026
|
+
extras_by_name.setdefault(Path(extra_rel).name, []).append(extra_rel)
|
|
1008
1027
|
used = set()
|
|
1009
1028
|
groups: List[List[Tuple[str, Path]]] = []
|
|
1010
1029
|
for rel, path in results:
|
|
@@ -1012,10 +1031,10 @@ def _chunk_watch_selection(
|
|
|
1012
1031
|
document = _load_json_if_complete(path) or {}
|
|
1013
1032
|
for source in _attachment_sources(document):
|
|
1014
1033
|
name = Path(source).name
|
|
1015
|
-
for extra_rel
|
|
1016
|
-
if extra_rel in used
|
|
1034
|
+
for extra_rel in extras_by_name.get(name) or []:
|
|
1035
|
+
if extra_rel in used:
|
|
1017
1036
|
continue
|
|
1018
|
-
group.append(
|
|
1037
|
+
group.append(extras[extra_rel])
|
|
1019
1038
|
used.add(extra_rel)
|
|
1020
1039
|
break
|
|
1021
1040
|
groups.append(group)
|
|
@@ -1193,8 +1212,8 @@ def watch(
|
|
|
1193
1212
|
|
|
1194
1213
|
Готовые файлы не уходят по одному. Если они появляются подряд, watch держит их
|
|
1195
1214
|
--batch-window секунд после последнего нового и отправляет вместе. Дольше
|
|
1196
|
-
--batch-max-wait секунд пачка не копится. Предел одной отправки —
|
|
1197
|
-
или 32
|
|
1215
|
+
--batch-max-wait секунд пачка не копится. Предел одной отправки — 200 файлов
|
|
1216
|
+
или 32 МБ.
|
|
1198
1217
|
"""
|
|
1199
1218
|
command = [arg for arg in ctx.args if arg != "--"]
|
|
1200
1219
|
host = host.rstrip("/")
|
|
@@ -1209,6 +1228,7 @@ def watch(
|
|
|
1209
1228
|
run_create_failed = False
|
|
1210
1229
|
sent_batches = 0
|
|
1211
1230
|
drain_until = 0.0
|
|
1231
|
+
announced_flush = False
|
|
1212
1232
|
hold_opened = 0.0
|
|
1213
1233
|
hold_quiet = 0.0
|
|
1214
1234
|
hold_key: Optional[Tuple[str, ...]] = None
|
|
@@ -1267,6 +1287,10 @@ def watch(
|
|
|
1267
1287
|
flushing = stop["requested"] or timed_out
|
|
1268
1288
|
|
|
1269
1289
|
snapshot = _snapshot_raw_files(root, include_attachments) if root.is_dir() else {}
|
|
1290
|
+
if flushing and not announced_flush:
|
|
1291
|
+
pending = sum(1 for rel in snapshot if rel not in uploaded)
|
|
1292
|
+
click.echo(f"После остановки осталось файлов: {pending}.")
|
|
1293
|
+
announced_flush = True
|
|
1270
1294
|
if any(rel not in uploaded for rel in snapshot):
|
|
1271
1295
|
last_activity = now
|
|
1272
1296
|
|
|
@@ -1300,7 +1324,7 @@ def watch(
|
|
|
1300
1324
|
hold_key = ready_key
|
|
1301
1325
|
|
|
1302
1326
|
batch_full = bool(batch) and (
|
|
1303
|
-
len(batch) >=
|
|
1327
|
+
len(batch) >= DEFAULT_WATCH_BATCH_COUNT
|
|
1304
1328
|
or _selection_bytes(batch) >= DEFAULT_FILE_BATCH_BYTES
|
|
1305
1329
|
)
|
|
1306
1330
|
send_now = bool(batch) and _watch_batch_due(
|
|
@@ -1313,7 +1337,10 @@ def watch(
|
|
|
1313
1337
|
flushing=flushing,
|
|
1314
1338
|
)
|
|
1315
1339
|
if send_now and not run_create_failed and (known_run_id or not inflight):
|
|
1316
|
-
chunks = _chunk_watch_selection(
|
|
1340
|
+
chunks = _chunk_watch_selection(
|
|
1341
|
+
batch,
|
|
1342
|
+
max_count=DEFAULT_WATCH_BATCH_COUNT,
|
|
1343
|
+
)
|
|
1317
1344
|
if not known_run_id:
|
|
1318
1345
|
chunks = chunks[:1]
|
|
1319
1346
|
for chunk in chunks:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: savetest-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.0rc2
|
|
4
4
|
Summary: CLI for SaveTest: upload Allure results as a ZIP, as raw files, or by watching a directory
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Requires-Python: >=3.8
|
|
@@ -220,7 +220,7 @@ savetest watch ./allure-results \
|
|
|
220
220
|
- Если тесты и загрузка — разные джобы, отдайте каталог `allure-results` артефактом тоже с `when: always`.
|
|
221
221
|
- `--wait` оставляйте включённым: джоба должна завершиться только когда импорт дошёл до конца.
|
|
222
222
|
- Вложения включайте только если они реально нужны. По умолчанию CLI их не шлёт.
|
|
223
|
-
- `0.3.
|
|
223
|
+
- `0.3.0rc2` — предварительная версия для SaveTest 1.5.0: `pip install savetest-cli==0.3.0rc2`. Обычный `pip install savetest-cli` остаётся на последней стабильной версии.
|
|
224
224
|
|
|
225
225
|
### Результаты по мере прогона
|
|
226
226
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.3.0rc1"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|