elemctl 0.43.2__tar.gz → 0.44.0__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.
- {elemctl-0.43.2 → elemctl-0.44.0}/PKG-INFO +1 -1
- {elemctl-0.43.2 → elemctl-0.44.0}/docs/SPEC.md +9 -1
- {elemctl-0.43.2 → elemctl-0.44.0}/docs/SPEC.ru.md +9 -1
- {elemctl-0.43.2 → elemctl-0.44.0}/docs/changelog.md +9 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/docs/changelog.ru.md +9 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl/__init__.py +1 -1
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl/i18n.py +27 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl/mcp_server.py +3 -1
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl/probe.py +60 -1
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl.egg-info/PKG-INFO +1 -1
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_i18n.py +3 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_probe.py +100 -1
- {elemctl-0.43.2 → elemctl-0.44.0}/.env.example +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/LICENSE +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/MANIFEST.in +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/NOTICE +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/ORIGIN.md +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/README.md +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/docs/cli.md +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/docs/cli.ru.md +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/docs/config.md +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/docs/config.ru.md +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/docs/index.md +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/docs/index.ru.md +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/docs/library.md +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/docs/library.ru.md +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/docs/mcp.md +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/docs/mcp.ru.md +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/docs/platform.md +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/docs/platform.ru.md +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/pyproject.toml +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/setup.cfg +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl/__main__.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl/auth.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl/build.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl/cli.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl/client.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl/config.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl/deploy.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl/errors.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl/plugins.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl/schema.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl/selfupdate.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl/transport.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl/versions.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl.egg-info/SOURCES.txt +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl.egg-info/dependency_links.txt +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl.egg-info/entry_points.txt +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl.egg-info/requires.txt +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/src/elemctl.egg-info/top_level.txt +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_build.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_changelog_link.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_cli.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_cli_docs.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_client.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_config.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_conventions.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_deploy.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_docs_coverage.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_extract_adapter.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_mcp.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_plugins.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_rebuild_docs.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_release_notes.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_schema.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_selfupdate.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_transport.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_user_lists.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_versions.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tests/test_workflows.py +0 -0
- {elemctl-0.43.2 → elemctl-0.44.0}/tools/extract_adapter.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: elemctl
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.44.0
|
|
4
4
|
Summary: CLI, MCP server and library for the Console API v2 of the 1C:Enterprise.Element platform (1cmycloud): applications, builds from source, one-command deploy with verification, a compile probe
|
|
5
5
|
Author: KeyFire
|
|
6
6
|
License-Expression: MIT
|
|
@@ -293,7 +293,15 @@ Commands, with the significant flags in parentheses:
|
|
|
293
293
|
- `probe [--project-dir --output --build-version --name --space-id --keep
|
|
294
294
|
--require-clean]` – an isolated compilation check of the sources: build ->
|
|
295
295
|
upload -> a throwaway application (that is the compilation, section 6.10) ->
|
|
296
|
-
errors with file and position -> cleanup.
|
|
296
|
+
errors with file and position -> cleanup. Before the build the manifest is
|
|
297
|
+
checked for what the server needs to take a probe: `Представление`
|
|
298
|
+
(`Presentation`), without which the console refuses the upload with a bare 500;
|
|
299
|
+
`ЯзыкРазработки` (`DevelopmentLanguage`), a required property without which no
|
|
300
|
+
application is created; and `ЯзыкиЛокализации` (`LocalizationLanguages`)
|
|
301
|
+
whenever `ЯзыкПоУмолчанию` (`DefaultLanguage`) is set, since the server refuses
|
|
302
|
+
that pair without naming the cause. A missing key stops the probe before
|
|
303
|
+
anything is built or uploaded, and the error names every such key with the
|
|
304
|
+
line to add, in the spelling the manifest uses. `ELEMENT_APP_ID` and
|
|
297
305
|
`ELEMENT_PROJECT_ID` are deliberately left unused: the probe must not be able to
|
|
298
306
|
reach the working application, and the target project is chosen by the platform
|
|
299
307
|
out of the vendor and the name of the manifest (section 6.8). The default build
|
|
@@ -668,7 +668,15 @@ stdout перенаправляется в stderr, и в настоящий stdo
|
|
|
668
668
|
- `probe [--project-dir --output --build-version --name --space-id --keep
|
|
669
669
|
--require-clean]` - изолированная проверка компиляции исходников: сборка ->
|
|
670
670
|
загрузка -> одноразовое приложение (это и есть компиляция, п. 6.10) -> ошибки
|
|
671
|
-
с файлом и позицией -> уборка.
|
|
671
|
+
с файлом и позицией -> уборка. До сборки манифест проверяется на то, без чего
|
|
672
|
+
сервер пробник не примет. Это `Представление` (`Presentation`): без него
|
|
673
|
+
консоль отвечает на загрузку 500 без объяснения. Это `ЯзыкРазработки`
|
|
674
|
+
(`DevelopmentLanguage`): обязательное свойство, без него приложение не
|
|
675
|
+
создаётся. И это `ЯзыкиЛокализации` (`LocalizationLanguages`), когда задан
|
|
676
|
+
`ЯзыкПоУмолчанию` (`DefaultLanguage`): такую пару сервер отклоняет, не называя
|
|
677
|
+
причины. Недостающий ключ останавливает пробник до сборки и загрузки, а ошибка
|
|
678
|
+
называет каждый такой ключ вместе со строкой, которую нужно добавить, в
|
|
679
|
+
написании самого манифеста. `ELEMENT_APP_ID` и `ELEMENT_PROJECT_ID`
|
|
672
680
|
намеренно не используются: у пробника не должно быть возможности достать
|
|
673
681
|
рабочее приложение, а проект-цель выбирает сама платформа по поставщику и
|
|
674
682
|
имени манифеста (п. 6.8). Версия сборки по умолчанию - `{база}-probe-{токен}`.
|
|
@@ -21,6 +21,15 @@ entry either – say what the behaviour was, not which id or response field was
|
|
|
21
21
|
The link is written by `python scripts/changelog-link.py <number>`, which rebuilds the generated
|
|
22
22
|
pages of the site in the same run – writing it by hand is how the mirrors get left behind.
|
|
23
23
|
|
|
24
|
+
## 2026-09-24 – 0.44.0
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
- **`probe` checks the manifest before it builds anything.** A probe project without
|
|
28
|
+
`Представление` was refused by the console with a bare 500, one without `ЯзыкРазработки`
|
|
29
|
+
never got an application, and a `ЯзыкПоУмолчанию` without `ЯзыкиЛокализации` was refused
|
|
30
|
+
with no cause named. Now the probe stops before the build and names each missing key with
|
|
31
|
+
the line to add. ([#41](https://github.com/keyfire/elemctl/pull/41))
|
|
32
|
+
|
|
24
33
|
## 2026-09-23 – 0.43.2
|
|
25
34
|
|
|
26
35
|
### Changed
|
|
@@ -21,6 +21,15 @@ sidebar:
|
|
|
21
21
|
Ссылку пишет `python scripts/changelog-link.py <номер>` – он же тут же пересобирает
|
|
22
22
|
сгенерированные страницы сайта: правка руками как раз и оставляет зеркала позади.
|
|
23
23
|
|
|
24
|
+
## 24.09.2026 – 0.44.0
|
|
25
|
+
|
|
26
|
+
### Добавлено
|
|
27
|
+
- **`probe` проверяет манифест до сборки.** Проект пробника без `Представление` консоль
|
|
28
|
+
отклоняла ответом 500 без объяснения, без `ЯзыкРазработки` приложение не создавалось, а
|
|
29
|
+
`ЯзыкПоУмолчанию` без `ЯзыкиЛокализации` сервер отклонял, не называя причины. Теперь
|
|
30
|
+
пробник останавливается до сборки и называет каждый недостающий ключ вместе со строкой,
|
|
31
|
+
которую нужно добавить. ([#41](https://github.com/keyfire/elemctl/pull/41))
|
|
32
|
+
|
|
24
33
|
## 23.09.2026 – 0.43.2
|
|
25
34
|
|
|
26
35
|
### Изменено
|
|
@@ -933,6 +933,33 @@ MESSAGES = {
|
|
|
933
933
|
"ru": "уборка: {problem}",
|
|
934
934
|
"en": "cleanup: {problem}",
|
|
935
935
|
},
|
|
936
|
+
"probe.manifest-incomplete": {
|
|
937
|
+
"ru": "{file}: сервер не примет этот пробник, поэтому он остановлен до сборки. {problems}",
|
|
938
|
+
"en": "{file}: the server will not take this probe, so it stopped before the build. "
|
|
939
|
+
"{problems}",
|
|
940
|
+
},
|
|
941
|
+
"probe.manifest-no-presentation": {
|
|
942
|
+
"ru": "Нет Представление (Presentation): без него консоль отвечает на загрузку сборки "
|
|
943
|
+
"500 \"Internal exception\" и причины не называет. Нужна строка \"{example}\".",
|
|
944
|
+
"en": "There is no Представление (Presentation): without it the console answers the "
|
|
945
|
+
"upload with a 500 \"Internal exception\" and names no cause. The line "
|
|
946
|
+
"\"{example}\" is needed.",
|
|
947
|
+
},
|
|
948
|
+
"probe.manifest-no-development-language": {
|
|
949
|
+
"ru": "Нет ЯзыкРазработки (DevelopmentLanguage): это обязательное свойство проекта, и без "
|
|
950
|
+
"него приложение не создаётся. Нужна строка \"{example}\".",
|
|
951
|
+
"en": "There is no ЯзыкРазработки (DevelopmentLanguage): it is a required property of "
|
|
952
|
+
"the project, and no application is created without it. The line \"{example}\" "
|
|
953
|
+
"is needed.",
|
|
954
|
+
},
|
|
955
|
+
"probe.manifest-no-localization-languages": {
|
|
956
|
+
"ru": "ЯзыкПоУмолчанию (DefaultLanguage) задан без ЯзыкиЛокализации "
|
|
957
|
+
"(LocalizationLanguages): такой проект сервер отклоняет, не называя причины. "
|
|
958
|
+
"Нужна строка \"{example}\".",
|
|
959
|
+
"en": "ЯзыкПоУмолчанию (DefaultLanguage) is set without ЯзыкиЛокализации "
|
|
960
|
+
"(LocalizationLanguages): the server refuses such a project and names no cause. "
|
|
961
|
+
"The line \"{example}\" is needed.",
|
|
962
|
+
},
|
|
936
963
|
# -- help: argparse help texts (cli.py) ---------------------------------------
|
|
937
964
|
# CLI help strings. Key: cli.help.<command> or cli.help.<command>-<flag>.
|
|
938
965
|
# Metavars that already read as English (NAME/APP_ID/FILE) are left untranslated.
|
|
@@ -713,7 +713,9 @@ def create_server(config=None, *, overrides=None, env_file=None):
|
|
|
713
713
|
окружения намеренно не используются. Итог - поле ok; ошибки в errors
|
|
714
714
|
(файл, строка, колонка, окружение, текст), исходные сообщения платформы -
|
|
715
715
|
в messages, итог уборки - в cleanup. keep=true оставляет приложение и
|
|
716
|
-
сборку на стенде для разбора руками.
|
|
716
|
+
сборку на стенде для разбора руками. До сборки проверяется Проект.yaml: без
|
|
717
|
+
Представление, без ЯзыкРазработки или с ЯзыкПоУмолчанию без ЯзыкиЛокализации
|
|
718
|
+
сервер пробник не примет, и инструмент сразу называет недостающий ключ.
|
|
717
719
|
"""
|
|
718
720
|
lines: list[str] = []
|
|
719
721
|
report = probe_project(
|
|
@@ -28,7 +28,13 @@ import uuid
|
|
|
28
28
|
from dataclasses import dataclass, field
|
|
29
29
|
|
|
30
30
|
from . import i18n
|
|
31
|
-
from .build import
|
|
31
|
+
from .build import (
|
|
32
|
+
build_assembly,
|
|
33
|
+
descriptor_value,
|
|
34
|
+
find_project_dir,
|
|
35
|
+
parse_flat_yaml,
|
|
36
|
+
read_project_meta,
|
|
37
|
+
)
|
|
32
38
|
from .client import extract_assembly_id, extract_project_id
|
|
33
39
|
from .errors import ApiError, ElemctlError
|
|
34
40
|
|
|
@@ -183,6 +189,52 @@ def compatibility_refusal(messages):
|
|
|
183
189
|
return ""
|
|
184
190
|
|
|
185
191
|
|
|
192
|
+
def manifest_problems(project_file):
|
|
193
|
+
"""What the manifest lacks for the server to take a probe; [] when nothing.
|
|
194
|
+
|
|
195
|
+
A hand-written probe project tends to carry only the name, the vendor and the version,
|
|
196
|
+
and the server answers each missing key in its own unhelpful way. Without
|
|
197
|
+
`Представление` the console refuses the upload with a bare 500 and names the field only
|
|
198
|
+
in its own event log. `ЯзыкРазработки` is a required property of the project
|
|
199
|
+
descriptor: without it no application is created, so a probe can never come out ok. A
|
|
200
|
+
`ЯзыкПоУмолчанию` without `ЯзыкиЛокализации` is refused with no word about the cause at
|
|
201
|
+
all. Every key is read in both spellings, and the example of a fix is written in the
|
|
202
|
+
spelling the manifest itself uses; the project's own name stands in for a presentation.
|
|
203
|
+
"""
|
|
204
|
+
values = parse_flat_yaml(project_file.read_text(encoding="utf-8-sig"))
|
|
205
|
+
english = "Name" in values and "Имя" not in values
|
|
206
|
+
|
|
207
|
+
def spelled(russian, english_key):
|
|
208
|
+
return english_key if english else russian
|
|
209
|
+
|
|
210
|
+
language = spelled("Русский", "English")
|
|
211
|
+
problems = []
|
|
212
|
+
if not descriptor_value(values, "Представление", "Presentation"):
|
|
213
|
+
name = descriptor_value(values, "Имя", "Name")
|
|
214
|
+
problems.append(i18n.t(
|
|
215
|
+
"probe.manifest-no-presentation",
|
|
216
|
+
example=f"{spelled('Представление', 'Presentation')}: {name}",
|
|
217
|
+
))
|
|
218
|
+
if not descriptor_value(values, "ЯзыкРазработки", "DevelopmentLanguage"):
|
|
219
|
+
problems.append(i18n.t(
|
|
220
|
+
"probe.manifest-no-development-language",
|
|
221
|
+
example=f"{spelled('ЯзыкРазработки', 'DevelopmentLanguage')}: {language}",
|
|
222
|
+
))
|
|
223
|
+
# The list may be written inline or as a nested block; a block leaves the value of the
|
|
224
|
+
# key itself empty, so the key counts by its presence, and only an empty inline list
|
|
225
|
+
# counts as no list.
|
|
226
|
+
languages = [
|
|
227
|
+
values[key] for key in ("ЯзыкиЛокализации", "LocalizationLanguages") if key in values
|
|
228
|
+
]
|
|
229
|
+
no_list = all(value.replace(" ", "") == "[]" for value in languages)
|
|
230
|
+
if descriptor_value(values, "ЯзыкПоУмолчанию", "DefaultLanguage") and no_list:
|
|
231
|
+
problems.append(i18n.t(
|
|
232
|
+
"probe.manifest-no-localization-languages",
|
|
233
|
+
example=f"{spelled('ЯзыкиЛокализации', 'LocalizationLanguages')}: [{language}]",
|
|
234
|
+
))
|
|
235
|
+
return problems
|
|
236
|
+
|
|
237
|
+
|
|
186
238
|
def _all_lines(messages):
|
|
187
239
|
"""Every non-empty line of the messages, in order."""
|
|
188
240
|
return [
|
|
@@ -219,6 +271,13 @@ def probe_project(
|
|
|
219
271
|
token = uuid.uuid4().hex[:8]
|
|
220
272
|
|
|
221
273
|
meta = read_project_meta(find_project_dir(project_dir) if project_dir else find_project_dir())
|
|
274
|
+
# Checked before anything is built or uploaded: each of these ends the run on the
|
|
275
|
+
# server anyway, and the server's own answer does not say which key was missing.
|
|
276
|
+
problems = manifest_problems(meta.project_file)
|
|
277
|
+
if problems:
|
|
278
|
+
raise ElemctlError(i18n.t(
|
|
279
|
+
"probe.manifest-incomplete", file=meta.project_file, problems=" ".join(problems)
|
|
280
|
+
))
|
|
222
281
|
report = ProbeReport(
|
|
223
282
|
project_dir=str(meta.project_dir),
|
|
224
283
|
vendor=meta.vendor,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: elemctl
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.44.0
|
|
4
4
|
Summary: CLI, MCP server and library for the Console API v2 of the 1C:Enterprise.Element platform (1cmycloud): applications, builds from source, one-command deploy with verification, a compile probe
|
|
5
5
|
Author: KeyFire
|
|
6
6
|
License-Expression: MIT
|
|
@@ -198,6 +198,9 @@ def test_no_russian_string_literals_outside_the_catalog():
|
|
|
198
198
|
"Реквизиты", "Измерения", "Ид", "Тип", "Длина", "МаксимальнаяДлина",
|
|
199
199
|
# The primitive type names the guard canonicalizes across the spellings.
|
|
200
200
|
"Строка", "Число", "Булево", "Дата", "ДатаВремя", "Время",
|
|
201
|
+
# The language keys of a descriptor and the value of the language enumeration:
|
|
202
|
+
# the probe checks the keys and quotes them in the line it asks to add.
|
|
203
|
+
"ЯзыкРазработки", "ЯзыкПоУмолчанию", "ЯзыкиЛокализации", "Русский",
|
|
201
204
|
}
|
|
202
205
|
|
|
203
206
|
# Constants that RECOGNIZE the platform's own wording rather than produce ours:
|
|
@@ -5,7 +5,20 @@ from __future__ import annotations
|
|
|
5
5
|
import pytest
|
|
6
6
|
|
|
7
7
|
from elemctl.errors import ApiError, ElemctlError
|
|
8
|
-
from elemctl.probe import PROBE_PREFIX, parse_compilation_errors, probe_project
|
|
8
|
+
from elemctl.probe import PROBE_PREFIX, manifest_problems, parse_compilation_errors, probe_project
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@pytest.fixture
|
|
12
|
+
def project_factory(project_factory):
|
|
13
|
+
"""A probe project carries the manifest keys the server asks for, unless a test drops one."""
|
|
14
|
+
|
|
15
|
+
def make(*args, **kwargs):
|
|
16
|
+
kwargs.setdefault("presentation", "Пробник")
|
|
17
|
+
kwargs.setdefault("language", "Русский")
|
|
18
|
+
return project_factory(*args, **kwargs)
|
|
19
|
+
|
|
20
|
+
return make
|
|
21
|
+
|
|
9
22
|
|
|
10
23
|
# A task message exactly as the platform gives it: the first line carries the
|
|
11
24
|
# platform's own prefix, the rest are bare.
|
|
@@ -403,3 +416,89 @@ def test_the_english_wording_of_the_refusal_is_recognized(project_factory, tmp_p
|
|
|
403
416
|
report = probe_project(client, project_dir=project_factory(), output_dir=tmp_path / "dist")
|
|
404
417
|
|
|
405
418
|
assert report.compatibility_refused == "99.0"
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
def _append(project_dir, text):
|
|
422
|
+
descriptor = project_dir / "Проект.yaml"
|
|
423
|
+
descriptor.write_text(descriptor.read_text(encoding="utf-8") + text, encoding="utf-8")
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
def test_a_manifest_without_a_presentation_stops_the_probe_before_the_build(
|
|
427
|
+
project_factory, tmp_path
|
|
428
|
+
):
|
|
429
|
+
"""Without the presentation the console refused the upload with a bare 500.
|
|
430
|
+
|
|
431
|
+
The field was named only in the event log of the console, so the probe names it before
|
|
432
|
+
it builds or uploads anything.
|
|
433
|
+
"""
|
|
434
|
+
client = FakeProbeClient()
|
|
435
|
+
|
|
436
|
+
with pytest.raises(ElemctlError) as caught:
|
|
437
|
+
probe_project(
|
|
438
|
+
client, project_dir=project_factory(presentation=""), output_dir=tmp_path / "dist"
|
|
439
|
+
)
|
|
440
|
+
|
|
441
|
+
assert "Представление (Presentation)" in str(caught.value)
|
|
442
|
+
assert '"Представление: crm"' in str(caught.value)
|
|
443
|
+
assert client.calls == []
|
|
444
|
+
assert not (tmp_path / "dist").exists()
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
def test_a_manifest_without_a_development_language_stops_the_probe(project_factory, tmp_path):
|
|
448
|
+
"""The application is never created without it, so the probe could never come out ok."""
|
|
449
|
+
client = FakeProbeClient()
|
|
450
|
+
|
|
451
|
+
with pytest.raises(ElemctlError) as caught:
|
|
452
|
+
probe_project(
|
|
453
|
+
client, project_dir=project_factory(language=""), output_dir=tmp_path / "dist"
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
assert "ЯзыкРазработки (DevelopmentLanguage)" in str(caught.value)
|
|
457
|
+
assert '"ЯзыкРазработки: Русский"' in str(caught.value)
|
|
458
|
+
assert client.calls == []
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
def test_every_missing_key_is_named_at_once(project_factory):
|
|
462
|
+
problems = manifest_problems(project_factory(presentation="", language="") / "Проект.yaml")
|
|
463
|
+
|
|
464
|
+
assert len(problems) == 2
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
def test_a_default_language_needs_the_list_of_localization_languages(project_factory):
|
|
468
|
+
"""The server refused such a project and pointed at nothing.
|
|
469
|
+
|
|
470
|
+
The list may be written inline or as a nested block.
|
|
471
|
+
"""
|
|
472
|
+
project_dir = project_factory()
|
|
473
|
+
_append(project_dir, "ЯзыкПоУмолчанию: Русский\n")
|
|
474
|
+
descriptor = project_dir / "Проект.yaml"
|
|
475
|
+
|
|
476
|
+
problems = manifest_problems(descriptor)
|
|
477
|
+
assert len(problems) == 1 and "ЯзыкиЛокализации (LocalizationLanguages)" in problems[0]
|
|
478
|
+
|
|
479
|
+
_append(project_dir, "ЯзыкиЛокализации: []\n")
|
|
480
|
+
assert len(manifest_problems(descriptor)) == 1
|
|
481
|
+
|
|
482
|
+
block = descriptor.read_text(encoding="utf-8").replace(
|
|
483
|
+
"ЯзыкиЛокализации: []\n", "ЯзыкиЛокализации:\n - Русский\n"
|
|
484
|
+
)
|
|
485
|
+
descriptor.write_text(block, encoding="utf-8")
|
|
486
|
+
assert manifest_problems(descriptor) == []
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
def test_an_english_manifest_is_answered_in_its_own_spelling(tmp_path):
|
|
490
|
+
project_dir = tmp_path / "repo" / "acme" / "crm"
|
|
491
|
+
project_dir.mkdir(parents=True)
|
|
492
|
+
descriptor = project_dir / "Project.yaml"
|
|
493
|
+
descriptor.write_text("Name: crm\nVendor: acme\nVersion: 1.0\n", encoding="utf-8")
|
|
494
|
+
|
|
495
|
+
problems = manifest_problems(descriptor)
|
|
496
|
+
|
|
497
|
+
assert '"Presentation: crm"' in problems[0]
|
|
498
|
+
assert '"DevelopmentLanguage: English"' in problems[1]
|
|
499
|
+
|
|
500
|
+
descriptor.write_text(
|
|
501
|
+
"Name: crm\nVendor: acme\nVersion: 1.0\nPresentation: CRM\nDevelopmentLanguage: English\n",
|
|
502
|
+
encoding="utf-8",
|
|
503
|
+
)
|
|
504
|
+
assert manifest_problems(descriptor) == []
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|