elemctl 0.2.0__tar.gz → 0.2.1__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.
Files changed (35) hide show
  1. {elemctl-0.2.0 → elemctl-0.2.1}/PKG-INFO +1 -1
  2. {elemctl-0.2.0 → elemctl-0.2.1}/docs/SPEC.md +4 -1
  3. {elemctl-0.2.0 → elemctl-0.2.1}/pyproject.toml +1 -1
  4. {elemctl-0.2.0 → elemctl-0.2.1}/src/elemctl/__init__.py +1 -1
  5. elemctl-0.2.1/src/elemctl/__main__.py +14 -0
  6. {elemctl-0.2.0 → elemctl-0.2.1}/src/elemctl/cli.py +7 -1
  7. {elemctl-0.2.0 → elemctl-0.2.1}/src/elemctl.egg-info/PKG-INFO +1 -1
  8. {elemctl-0.2.0 → elemctl-0.2.1}/src/elemctl.egg-info/SOURCES.txt +1 -0
  9. {elemctl-0.2.0 → elemctl-0.2.1}/tests/test_cli.py +34 -2
  10. {elemctl-0.2.0 → elemctl-0.2.1}/.env.example +0 -0
  11. {elemctl-0.2.0 → elemctl-0.2.1}/LICENSE +0 -0
  12. {elemctl-0.2.0 → elemctl-0.2.1}/MANIFEST.in +0 -0
  13. {elemctl-0.2.0 → elemctl-0.2.1}/NOTICE +0 -0
  14. {elemctl-0.2.0 → elemctl-0.2.1}/ORIGIN.md +0 -0
  15. {elemctl-0.2.0 → elemctl-0.2.1}/README.md +0 -0
  16. {elemctl-0.2.0 → elemctl-0.2.1}/setup.cfg +0 -0
  17. {elemctl-0.2.0 → elemctl-0.2.1}/src/elemctl/auth.py +0 -0
  18. {elemctl-0.2.0 → elemctl-0.2.1}/src/elemctl/build.py +0 -0
  19. {elemctl-0.2.0 → elemctl-0.2.1}/src/elemctl/client.py +0 -0
  20. {elemctl-0.2.0 → elemctl-0.2.1}/src/elemctl/config.py +0 -0
  21. {elemctl-0.2.0 → elemctl-0.2.1}/src/elemctl/deploy.py +0 -0
  22. {elemctl-0.2.0 → elemctl-0.2.1}/src/elemctl/errors.py +0 -0
  23. {elemctl-0.2.0 → elemctl-0.2.1}/src/elemctl/mcp_server.py +0 -0
  24. {elemctl-0.2.0 → elemctl-0.2.1}/src/elemctl/transport.py +0 -0
  25. {elemctl-0.2.0 → elemctl-0.2.1}/src/elemctl/versions.py +0 -0
  26. {elemctl-0.2.0 → elemctl-0.2.1}/src/elemctl.egg-info/dependency_links.txt +0 -0
  27. {elemctl-0.2.0 → elemctl-0.2.1}/src/elemctl.egg-info/entry_points.txt +0 -0
  28. {elemctl-0.2.0 → elemctl-0.2.1}/src/elemctl.egg-info/requires.txt +0 -0
  29. {elemctl-0.2.0 → elemctl-0.2.1}/src/elemctl.egg-info/top_level.txt +0 -0
  30. {elemctl-0.2.0 → elemctl-0.2.1}/tests/test_build.py +0 -0
  31. {elemctl-0.2.0 → elemctl-0.2.1}/tests/test_client.py +0 -0
  32. {elemctl-0.2.0 → elemctl-0.2.1}/tests/test_config.py +0 -0
  33. {elemctl-0.2.0 → elemctl-0.2.1}/tests/test_deploy.py +0 -0
  34. {elemctl-0.2.0 → elemctl-0.2.1}/tests/test_mcp.py +0 -0
  35. {elemctl-0.2.0 → elemctl-0.2.1}/tests/test_versions.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: elemctl
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: CLI, MCP-сервер и библиотека для Console API v2 платформы 1С:Предприятие.Элемент (1cmycloud)
5
5
  Author: KeyFire
6
6
  License-Expression: MIT
@@ -261,7 +261,10 @@ stderr и код возврата 1.
261
261
  `apps start [APP_ID]`, `apps stop [APP_ID]`.
262
262
  - `apps find` ищет по точному совпадению (без учёта регистра) имени среди
263
263
  полей `name`, `display-name`, `publication-context`; вывод
264
- `{"id": ..., "found": true|false}`, код возврата 1 если не найдено.
264
+ `{"id": ..., "found": true|false}`, код возврата 0 в обоих случаях –
265
+ отсутствие приложения это ответ, а не ошибка. Ненулевой код возврата
266
+ означает сбой запроса и сопровождается JSON'ом с полем `error` в stderr.
267
+ В скриптах проверять поле `found`, а не код возврата.
265
268
  - `--latest-build` - взять источником последнюю сборку проекта (защита от
266
269
  пустого каркаса, п. 6.2); `--wait` - дождаться готовности (п. 6.4) и
267
270
  вывести финальную карточку.
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
 
7
7
  [project]
8
8
  name = "elemctl"
9
- version = "0.2.0"
9
+ version = "0.2.1"
10
10
  description = "CLI, MCP-сервер и библиотека для Console API v2 платформы 1С:Предприятие.Элемент (1cmycloud)"
11
11
  readme = "README.md"
12
12
  requires-python = ">=3.10"
@@ -11,7 +11,7 @@ from .client import ElementClient
11
11
  from .config import Config
12
12
  from .errors import ApiError, BuildError, ConfigError, ElemctlError, TransportError
13
13
 
14
- __version__ = "0.2.0"
14
+ __version__ = "0.2.1"
15
15
 
16
16
  __all__ = [
17
17
  "ApiError",
@@ -0,0 +1,14 @@
1
+ """Запуск пакета как модуля: python -m elemctl <аргументы>.
2
+
3
+ Нужен тем, кто вызывает elemctl текущим интерпретатором, не полагаясь на
4
+ консольную точку входа в PATH (например, обёртки в чужих репозиториях).
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import sys
10
+
11
+ from .cli import main
12
+
13
+ if __name__ == "__main__":
14
+ sys.exit(main())
@@ -97,11 +97,17 @@ def cmd_apps_get(args):
97
97
 
98
98
 
99
99
  def cmd_apps_find(args):
100
+ """Поиск приложения по имени. Отсутствие приложения – это ответ, а не ошибка.
101
+
102
+ Код возврата 0 в обоих случаях: признак несёт поле found. Ненулевой код возврата
103
+ означает сбой запроса (нет доступа, сеть, конфигурация) и сопровождается JSON'ом
104
+ с полем error в stderr – иначе вызывающий не отличит "стенда нет" от "не смогли спросить".
105
+ """
100
106
  client = make_client(_config(args))
101
107
  app = client.find_app(args.name)
102
108
  if app is None:
103
109
  _emit({"id": None, "found": False})
104
- return 1
110
+ return 0
105
111
  _emit({"id": app.get("id"), "found": True})
106
112
  return 0
107
113
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: elemctl
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: CLI, MCP-сервер и библиотека для Console API v2 платформы 1С:Предприятие.Элемент (1cmycloud)
5
5
  Author: KeyFire
6
6
  License-Expression: MIT
@@ -7,6 +7,7 @@ README.md
7
7
  pyproject.toml
8
8
  docs/SPEC.md
9
9
  src/elemctl/__init__.py
10
+ src/elemctl/__main__.py
10
11
  src/elemctl/auth.py
11
12
  src/elemctl/build.py
12
13
  src/elemctl/cli.py
@@ -3,11 +3,16 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import json
6
+ import os
7
+ import subprocess
8
+ import sys
6
9
  from pathlib import Path
7
10
 
8
11
  import pytest
9
12
 
13
+ import elemctl
10
14
  from elemctl import cli
15
+ from elemctl.errors import ApiError
11
16
 
12
17
 
13
18
  @pytest.fixture(autouse=True)
@@ -29,7 +34,17 @@ def test_version_flag(capsys):
29
34
  with pytest.raises(SystemExit) as excinfo:
30
35
  cli.main(["--version"])
31
36
  assert excinfo.value.code == 0
32
- assert "elemctl 0.2.0" in capsys.readouterr().out
37
+ assert f"elemctl {elemctl.__version__}" in capsys.readouterr().out
38
+
39
+
40
+ def test_module_entry_point():
41
+ """python -m elemctl – запасной путь для вызывающих без консольной точки входа в PATH."""
42
+ import_root = Path(elemctl.__file__).resolve().parent.parent
43
+ env = {**os.environ, "PYTHONPATH": str(import_root)}
44
+ result = subprocess.run([sys.executable, "-m", "elemctl", "--version"],
45
+ capture_output=True, text=True, env=env)
46
+ assert result.returncode == 0, result.stderr
47
+ assert f"elemctl {elemctl.__version__}" in result.stdout
33
48
 
34
49
 
35
50
  def test_build_command(project_factory, tmp_path, capsys):
@@ -77,11 +92,28 @@ def test_apps_find_found_and_not_found(monkeypatch, capsys):
77
92
  assert rc == 0
78
93
  assert json.loads(capsys.readouterr().out) == {"id": "app-42", "found": True}
79
94
 
95
+ # Отсутствие приложения – штатный ответ: код возврата 0, признак несёт поле found.
80
96
  rc = cli.main(["apps", "find", "нет-такого"])
81
- assert rc == 1
97
+ assert rc == 0
82
98
  assert json.loads(capsys.readouterr().out) == {"id": None, "found": False}
83
99
 
84
100
 
101
+ def test_apps_find_request_failure_is_an_error(monkeypatch, capsys):
102
+ """Сбой запроса отличим от "не найдено": ненулевой код и error в stderr."""
103
+
104
+ class FailingClient:
105
+ def find_app(self, name):
106
+ raise ApiError("нет доступа", status=403)
107
+
108
+ monkeypatch.setattr(cli, "make_client", lambda config: FailingClient())
109
+
110
+ rc = cli.main(["apps", "find", "site-dev"])
111
+ assert rc == 1
112
+ captured = capsys.readouterr()
113
+ assert captured.out == ""
114
+ assert "error" in json.loads(captured.err)
115
+
116
+
85
117
  def test_error_is_json_on_stderr(capsys):
86
118
  # app-id не задан ни аргументом, ни конфигурацией.
87
119
  rc = cli.main(["apps", "get"])
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