awcs-scripts 1.0.1__tar.gz → 1.0.2__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.
- awcs_scripts-1.0.2/.vscode/tasks.json +42 -0
- {awcs_scripts-1.0.1 → awcs_scripts-1.0.2}/PKG-INFO +74 -38
- {awcs_scripts-1.0.1 → awcs_scripts-1.0.2}/README.md +73 -37
- {awcs_scripts-1.0.1 → awcs_scripts-1.0.2}/pyproject.toml +1 -1
- awcs_scripts-1.0.2/scripts/release.py +141 -0
- {awcs_scripts-1.0.1 → awcs_scripts-1.0.2}/src/awcs_scripts/__init__.py +1 -1
- {awcs_scripts-1.0.1 → awcs_scripts-1.0.2}/src/awcs_scripts/cli.py +8 -0
- {awcs_scripts-1.0.1 → awcs_scripts-1.0.2}/tests/test_cli.py +10 -0
- {awcs_scripts-1.0.1 → awcs_scripts-1.0.2}/uv.lock +1 -1
- {awcs_scripts-1.0.1 → awcs_scripts-1.0.2}/.gitignore +0 -0
- {awcs_scripts-1.0.1 → awcs_scripts-1.0.2}/.gitlab-ci.yml +0 -0
- {awcs_scripts-1.0.1 → awcs_scripts-1.0.2}/LICENSE +0 -0
- {awcs_scripts-1.0.1 → awcs_scripts-1.0.2}/bash/README.md +0 -0
- {awcs_scripts-1.0.1 → awcs_scripts-1.0.2}/src/awcs_scripts/api.py +0 -0
- {awcs_scripts-1.0.1 → awcs_scripts-1.0.2}/src/awcs_scripts/config.py +0 -0
- {awcs_scripts-1.0.1 → awcs_scripts-1.0.2}/src/awcs_scripts/mrmap/__init__.py +0 -0
- {awcs_scripts-1.0.1 → awcs_scripts-1.0.2}/src/awcs_scripts/mrmap/mrmap-to-bg.py +0 -0
- {awcs_scripts-1.0.1 → awcs_scripts-1.0.2}/src/awcs_scripts/mrmap/mrmap-to-raster.py +0 -0
- {awcs_scripts-1.0.1 → awcs_scripts-1.0.2}/tests/test_api.py +0 -0
- {awcs_scripts-1.0.1 → awcs_scripts-1.0.2}/tests/test_raster.py +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "2.0.0",
|
|
3
|
+
"tasks": [
|
|
4
|
+
{
|
|
5
|
+
"label": "release",
|
|
6
|
+
"type": "shell",
|
|
7
|
+
"command": "python",
|
|
8
|
+
"args": ["scripts/release.py", "${input:releasePart}"],
|
|
9
|
+
"options": {
|
|
10
|
+
"cwd": "${workspaceFolder}"
|
|
11
|
+
},
|
|
12
|
+
"presentation": {
|
|
13
|
+
"reveal": "always",
|
|
14
|
+
"panel": "shared"
|
|
15
|
+
},
|
|
16
|
+
"problemMatcher": []
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"label": "release (dry-run)",
|
|
20
|
+
"type": "shell",
|
|
21
|
+
"command": "python",
|
|
22
|
+
"args": ["scripts/release.py", "--dry-run"],
|
|
23
|
+
"options": {
|
|
24
|
+
"cwd": "${workspaceFolder}"
|
|
25
|
+
},
|
|
26
|
+
"presentation": {
|
|
27
|
+
"reveal": "always",
|
|
28
|
+
"panel": "shared"
|
|
29
|
+
},
|
|
30
|
+
"problemMatcher": []
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
"inputs": [
|
|
34
|
+
{
|
|
35
|
+
"id": "releasePart",
|
|
36
|
+
"type": "pickString",
|
|
37
|
+
"description": "Which part to bump",
|
|
38
|
+
"options": ["patch", "minor", "major"],
|
|
39
|
+
"default": "patch"
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: awcs-scripts
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
4
4
|
Summary: Command line scripts for WCS maps and the ARMS API
|
|
5
5
|
Project-URL: Repository, https://gitlab.sprydev.ru/automacon/agv/wcs/awcs_scripts
|
|
6
6
|
Author: AWCS
|
|
@@ -17,25 +17,9 @@ Description-Content-Type: text/markdown
|
|
|
17
17
|
|
|
18
18
|
Скрипты для карт WCS и части ARMS API. Пакет называется `awcs-scripts`, команда после установки — `awcs`.
|
|
19
19
|
|
|
20
|
-
##
|
|
20
|
+
## Использование
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
Токен в репозиторий не входит. Его нужно завести один раз:
|
|
25
|
-
|
|
26
|
-
1. На [pypi.org](https://pypi.org) создать API-токен с правом загрузки. Для первой выкладки имя `awcs-scripts` должно быть свободно: проект создаётся при первой успешной загрузке. До этого нужен токен уровня аккаунта, после первой публикации его можно ограничить этим проектом.
|
|
27
|
-
2. В GitLab, в CI/CD-переменных этого репозитория, добавить `UV_PUBLISH_TOKEN` со значением токена и включить **Masked**. **Protected** включать только если теги `v*` тоже protected: иначе на теге переменная в джобу не попадёт и `uv publish` упадёт без токена.
|
|
28
|
-
|
|
29
|
-
Тег и отправка:
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
git tag v0.1.0
|
|
33
|
-
git push origin v0.1.0
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
Репозиторий закрытый, а `uv publish` пишет на публичный PyPI. После зелёного пайплайна wheel доступен по имени пакета.
|
|
37
|
-
|
|
38
|
-
## Установка
|
|
22
|
+
### Установка
|
|
39
23
|
|
|
40
24
|
```
|
|
41
25
|
uv tool install awcs-scripts
|
|
@@ -53,30 +37,37 @@ uvx --from git+https://gitlab.sprydev.ru/automacon/agv/wcs/awcs_scripts.git awcs
|
|
|
53
37
|
uv tool install .
|
|
54
38
|
```
|
|
55
39
|
|
|
56
|
-
После этого команда `awcs` доступна в системе.
|
|
40
|
+
После этого команда `awcs` доступна в системе.
|
|
41
|
+
|
|
42
|
+
Разовый запуск после публикации:
|
|
57
43
|
|
|
58
44
|
```
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
45
|
+
uvx --from awcs-scripts awcs help
|
|
46
|
+
uvx --from awcs-scripts awcs mrmap-to-raster path/to/map.mrmap --resolution 0.05 --out-dir path/to/out
|
|
47
|
+
uvx --from awcs-scripts awcs users me
|
|
62
48
|
```
|
|
63
49
|
|
|
64
|
-
|
|
50
|
+
### Команды
|
|
65
51
|
|
|
66
|
-
|
|
52
|
+
#### Основное
|
|
67
53
|
|
|
68
54
|
```
|
|
69
|
-
|
|
55
|
+
awcs help
|
|
56
|
+
awcs version
|
|
70
57
|
```
|
|
71
58
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
## Команды
|
|
59
|
+
#### Карты
|
|
75
60
|
|
|
76
61
|
```
|
|
77
|
-
awcs help
|
|
78
62
|
awcs mrmap-to-raster path/to/map.mrmap --out-dir path/to/out
|
|
79
63
|
awcs mrmap-to-bg path/to/map.mrmap path/to/layout.lif --layout_id layoutId --resolution 0.05 --output path/to/layout.out.lif
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`awcs mrmap-to-raster` пишет PNG, GeoTIFF и JSON. `--resolution` задаёт метры на пиксель, по умолчанию берётся `resolution_2d` из карты. `awcs mrmap-to-bg` подставляет этот растр в `backgroundImage` одного layout. Без `--output` исходный `.lif` перезаписывается.
|
|
67
|
+
|
|
68
|
+
#### API
|
|
69
|
+
|
|
70
|
+
```
|
|
80
71
|
awcs login --url https://dev.wcs.automacon.ru --apikey <apikey>
|
|
81
72
|
awcs users list
|
|
82
73
|
awcs users me
|
|
@@ -90,20 +81,65 @@ awcs projects create --lif_json path/to/layout.lif -m MAIRUI -v 1.0.0 --desc "li
|
|
|
90
81
|
awcs projects activate 12
|
|
91
82
|
```
|
|
92
83
|
|
|
93
|
-
|
|
84
|
+
`awcs login` проверяет ключ через `GET /users/me` и только после ответа 200 сохраняет origin и ключ. Профиль лежит вне репозитория: путь из `AWCS_CONFIG`, иначе `%APPDATA%\awcs\config.ini` на Windows и `~/.config/awcs/config.ini` в остальных системах. Ключ в вывод не печатается. Клиент сам дописывает `/api/v1` и шлёт заголовок `X-Api-Key`.
|
|
85
|
+
|
|
86
|
+
У списков есть `--page`, `--per_page`, `--filter`, `--sort_by`. `awcs missions create` принимает `--template_id` или `--template_code` и необязательный `--params`. `awcs mission_templates execute` отправляет `--params` плоским JSON-объектом. `awcs projects create` загружает LIF как `multipart/form-data`: `-m` это `--manufacturer`, `-v` и `--version` это `--project_version`, `--desc` это `--description`, `--sync` это `--synchronous`.
|
|
87
|
+
|
|
88
|
+
### Удаление
|
|
89
|
+
|
|
90
|
+
Снимает команду `awcs`, поставленную через `uv tool install` из клона или с PyPI:
|
|
94
91
|
|
|
95
92
|
```
|
|
96
|
-
|
|
97
|
-
uvx --from awcs-scripts awcs mrmap-to-raster path/to/map.mrmap --resolution 0.05 --out-dir path/to/out
|
|
98
|
-
uvx --from awcs-scripts awcs users me
|
|
93
|
+
uv tool uninstall awcs-scripts
|
|
99
94
|
```
|
|
100
95
|
|
|
101
|
-
|
|
96
|
+
Профиль с адресом и ключом эта команда не трогает. Его файл лежит по `AWCS_CONFIG`, иначе `%APPDATA%\awcs\config.ini` на Windows и `~/.config/awcs/config.ini` в остальных системах. Чтобы убрать и ключ, удалите этот файл.
|
|
102
97
|
|
|
103
|
-
|
|
98
|
+
## Разработка
|
|
104
99
|
|
|
105
|
-
|
|
100
|
+
### Публикация в PyPI
|
|
106
101
|
|
|
107
|
-
|
|
102
|
+
Выкладка происходит только по тегу `vX.Y.Z`. Обычный push и merge request пакет не публикуют: CI прогоняет тесты и собирает wheel. Как сменить номер версии — в разделе ниже.
|
|
103
|
+
|
|
104
|
+
Токен в репозиторий не входит. Его нужно завести один раз:
|
|
105
|
+
|
|
106
|
+
1. На [pypi.org](https://pypi.org) создать API-токен с правом загрузки. Для первой выкладки имя `awcs-scripts` должно быть свободно: проект создаётся при первой успешной загрузке. До этого нужен токен уровня аккаунта, после первой публикации его можно ограничить этим проектом.
|
|
107
|
+
2. В GitLab, в CI/CD-переменных этого репозитория, добавить `UV_PUBLISH_TOKEN` со значением токена и включить **Masked**. **Protected** включать только если теги `v*` тоже protected: иначе на теге переменная в джобу не попадёт и `uv publish` упадёт без токена.
|
|
108
|
+
|
|
109
|
+
Репозиторий закрытый, а `uv publish` пишет на публичный PyPI. После зелёного пайплайна wheel доступен по имени пакета.
|
|
110
|
+
|
|
111
|
+
### Обновление версии
|
|
112
|
+
|
|
113
|
+
Выпуск — одна команда из корня репозитория. По умолчанию она поднимает patch:
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
python scripts/release.py
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`minor` и `major` передаются аргументом: `python scripts/release.py minor`. Команда берёт последний тег `vX.Y.Z`, при другом номере в `pyproject.toml` сначала записывает туда версию тега, затем выполняет `uv version --bump`. Тот же номер попадает в `__version__` в `src/awcs_scripts/__init__.py` и, если uv его перепишет, в `uv.lock`. Дальше идут коммит `Release X.Y.Z.`, тег `vX.Y.Z`, `git push origin HEAD` и `git push origin vX.Y.Z`.
|
|
120
|
+
|
|
121
|
+
Посмотреть следующий номер:
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
python scripts/release.py --dry-run
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
В Cursor это задачи `release` и `release (dry-run)`: Command Palette → Tasks: Run Task. Команда выпускает из чистого дерева на ветке. Тег должен совпадать с `^v\d+\.\d+\.\d+$`: по нему джоба `publish` подставляет номер командой `uv version` и собирает wheel. PyPI не принимает повторную загрузку той же версии.
|
|
128
|
+
|
|
129
|
+
Уже установленную команду обновляют после зелёного пайплайна тега:
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
uv tool upgrade awcs-scripts
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### В клоне
|
|
136
|
+
|
|
137
|
+
Для разработки в том же клоне:
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
uv sync
|
|
141
|
+
uv run awcs help
|
|
142
|
+
uv build
|
|
143
|
+
```
|
|
108
144
|
|
|
109
145
|
Карта живёт в `src/awcs_scripts/mrmap/`. Имена файлов совпадают с подкомандами: `mrmap-to-raster.py` и `mrmap-to-bg.py`. Будущие shell-скрипты кладутся в `bash/` и тоже вызываются только через `awcs`.
|
|
@@ -2,25 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Скрипты для карт WCS и части ARMS API. Пакет называется `awcs-scripts`, команда после установки — `awcs`.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Использование
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Токен в репозиторий не входит. Его нужно завести один раз:
|
|
10
|
-
|
|
11
|
-
1. На [pypi.org](https://pypi.org) создать API-токен с правом загрузки. Для первой выкладки имя `awcs-scripts` должно быть свободно: проект создаётся при первой успешной загрузке. До этого нужен токен уровня аккаунта, после первой публикации его можно ограничить этим проектом.
|
|
12
|
-
2. В GitLab, в CI/CD-переменных этого репозитория, добавить `UV_PUBLISH_TOKEN` со значением токена и включить **Masked**. **Protected** включать только если теги `v*` тоже protected: иначе на теге переменная в джобу не попадёт и `uv publish` упадёт без токена.
|
|
13
|
-
|
|
14
|
-
Тег и отправка:
|
|
15
|
-
|
|
16
|
-
```
|
|
17
|
-
git tag v0.1.0
|
|
18
|
-
git push origin v0.1.0
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
Репозиторий закрытый, а `uv publish` пишет на публичный PyPI. После зелёного пайплайна wheel доступен по имени пакета.
|
|
22
|
-
|
|
23
|
-
## Установка
|
|
7
|
+
### Установка
|
|
24
8
|
|
|
25
9
|
```
|
|
26
10
|
uv tool install awcs-scripts
|
|
@@ -38,30 +22,37 @@ uvx --from git+https://gitlab.sprydev.ru/automacon/agv/wcs/awcs_scripts.git awcs
|
|
|
38
22
|
uv tool install .
|
|
39
23
|
```
|
|
40
24
|
|
|
41
|
-
После этого команда `awcs` доступна в системе.
|
|
25
|
+
После этого команда `awcs` доступна в системе.
|
|
26
|
+
|
|
27
|
+
Разовый запуск после публикации:
|
|
42
28
|
|
|
43
29
|
```
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
30
|
+
uvx --from awcs-scripts awcs help
|
|
31
|
+
uvx --from awcs-scripts awcs mrmap-to-raster path/to/map.mrmap --resolution 0.05 --out-dir path/to/out
|
|
32
|
+
uvx --from awcs-scripts awcs users me
|
|
47
33
|
```
|
|
48
34
|
|
|
49
|
-
|
|
35
|
+
### Команды
|
|
50
36
|
|
|
51
|
-
|
|
37
|
+
#### Основное
|
|
52
38
|
|
|
53
39
|
```
|
|
54
|
-
|
|
40
|
+
awcs help
|
|
41
|
+
awcs version
|
|
55
42
|
```
|
|
56
43
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
## Команды
|
|
44
|
+
#### Карты
|
|
60
45
|
|
|
61
46
|
```
|
|
62
|
-
awcs help
|
|
63
47
|
awcs mrmap-to-raster path/to/map.mrmap --out-dir path/to/out
|
|
64
48
|
awcs mrmap-to-bg path/to/map.mrmap path/to/layout.lif --layout_id layoutId --resolution 0.05 --output path/to/layout.out.lif
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`awcs mrmap-to-raster` пишет PNG, GeoTIFF и JSON. `--resolution` задаёт метры на пиксель, по умолчанию берётся `resolution_2d` из карты. `awcs mrmap-to-bg` подставляет этот растр в `backgroundImage` одного layout. Без `--output` исходный `.lif` перезаписывается.
|
|
52
|
+
|
|
53
|
+
#### API
|
|
54
|
+
|
|
55
|
+
```
|
|
65
56
|
awcs login --url https://dev.wcs.automacon.ru --apikey <apikey>
|
|
66
57
|
awcs users list
|
|
67
58
|
awcs users me
|
|
@@ -75,20 +66,65 @@ awcs projects create --lif_json path/to/layout.lif -m MAIRUI -v 1.0.0 --desc "li
|
|
|
75
66
|
awcs projects activate 12
|
|
76
67
|
```
|
|
77
68
|
|
|
78
|
-
|
|
69
|
+
`awcs login` проверяет ключ через `GET /users/me` и только после ответа 200 сохраняет origin и ключ. Профиль лежит вне репозитория: путь из `AWCS_CONFIG`, иначе `%APPDATA%\awcs\config.ini` на Windows и `~/.config/awcs/config.ini` в остальных системах. Ключ в вывод не печатается. Клиент сам дописывает `/api/v1` и шлёт заголовок `X-Api-Key`.
|
|
70
|
+
|
|
71
|
+
У списков есть `--page`, `--per_page`, `--filter`, `--sort_by`. `awcs missions create` принимает `--template_id` или `--template_code` и необязательный `--params`. `awcs mission_templates execute` отправляет `--params` плоским JSON-объектом. `awcs projects create` загружает LIF как `multipart/form-data`: `-m` это `--manufacturer`, `-v` и `--version` это `--project_version`, `--desc` это `--description`, `--sync` это `--synchronous`.
|
|
72
|
+
|
|
73
|
+
### Удаление
|
|
74
|
+
|
|
75
|
+
Снимает команду `awcs`, поставленную через `uv tool install` из клона или с PyPI:
|
|
79
76
|
|
|
80
77
|
```
|
|
81
|
-
|
|
82
|
-
uvx --from awcs-scripts awcs mrmap-to-raster path/to/map.mrmap --resolution 0.05 --out-dir path/to/out
|
|
83
|
-
uvx --from awcs-scripts awcs users me
|
|
78
|
+
uv tool uninstall awcs-scripts
|
|
84
79
|
```
|
|
85
80
|
|
|
86
|
-
|
|
81
|
+
Профиль с адресом и ключом эта команда не трогает. Его файл лежит по `AWCS_CONFIG`, иначе `%APPDATA%\awcs\config.ini` на Windows и `~/.config/awcs/config.ini` в остальных системах. Чтобы убрать и ключ, удалите этот файл.
|
|
87
82
|
|
|
88
|
-
|
|
83
|
+
## Разработка
|
|
89
84
|
|
|
90
|
-
|
|
85
|
+
### Публикация в PyPI
|
|
91
86
|
|
|
92
|
-
|
|
87
|
+
Выкладка происходит только по тегу `vX.Y.Z`. Обычный push и merge request пакет не публикуют: CI прогоняет тесты и собирает wheel. Как сменить номер версии — в разделе ниже.
|
|
88
|
+
|
|
89
|
+
Токен в репозиторий не входит. Его нужно завести один раз:
|
|
90
|
+
|
|
91
|
+
1. На [pypi.org](https://pypi.org) создать API-токен с правом загрузки. Для первой выкладки имя `awcs-scripts` должно быть свободно: проект создаётся при первой успешной загрузке. До этого нужен токен уровня аккаунта, после первой публикации его можно ограничить этим проектом.
|
|
92
|
+
2. В GitLab, в CI/CD-переменных этого репозитория, добавить `UV_PUBLISH_TOKEN` со значением токена и включить **Masked**. **Protected** включать только если теги `v*` тоже protected: иначе на теге переменная в джобу не попадёт и `uv publish` упадёт без токена.
|
|
93
|
+
|
|
94
|
+
Репозиторий закрытый, а `uv publish` пишет на публичный PyPI. После зелёного пайплайна wheel доступен по имени пакета.
|
|
95
|
+
|
|
96
|
+
### Обновление версии
|
|
97
|
+
|
|
98
|
+
Выпуск — одна команда из корня репозитория. По умолчанию она поднимает patch:
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
python scripts/release.py
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`minor` и `major` передаются аргументом: `python scripts/release.py minor`. Команда берёт последний тег `vX.Y.Z`, при другом номере в `pyproject.toml` сначала записывает туда версию тега, затем выполняет `uv version --bump`. Тот же номер попадает в `__version__` в `src/awcs_scripts/__init__.py` и, если uv его перепишет, в `uv.lock`. Дальше идут коммит `Release X.Y.Z.`, тег `vX.Y.Z`, `git push origin HEAD` и `git push origin vX.Y.Z`.
|
|
105
|
+
|
|
106
|
+
Посмотреть следующий номер:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
python scripts/release.py --dry-run
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
В Cursor это задачи `release` и `release (dry-run)`: Command Palette → Tasks: Run Task. Команда выпускает из чистого дерева на ветке. Тег должен совпадать с `^v\d+\.\d+\.\d+$`: по нему джоба `publish` подставляет номер командой `uv version` и собирает wheel. PyPI не принимает повторную загрузку той же версии.
|
|
113
|
+
|
|
114
|
+
Уже установленную команду обновляют после зелёного пайплайна тега:
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
uv tool upgrade awcs-scripts
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### В клоне
|
|
121
|
+
|
|
122
|
+
Для разработки в том же клоне:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
uv sync
|
|
126
|
+
uv run awcs help
|
|
127
|
+
uv build
|
|
128
|
+
```
|
|
93
129
|
|
|
94
130
|
Карта живёт в `src/awcs_scripts/mrmap/`. Имена файлов совпадают с подкомандами: `mrmap-to-raster.py` и `mrmap-to-bg.py`. Будущие shell-скрипты кладутся в `bash/` и тоже вызываются только через `awcs`.
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"""Bump the package version, commit it, tag vX.Y.Z, and push the branch and tag."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import re
|
|
7
|
+
import subprocess
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
ROOT = Path(__file__).resolve().parent.parent
|
|
12
|
+
PYPROJECT = ROOT / "pyproject.toml"
|
|
13
|
+
INIT = ROOT / "src" / "awcs_scripts" / "__init__.py"
|
|
14
|
+
VERSION_FILES = (
|
|
15
|
+
"pyproject.toml",
|
|
16
|
+
"src/awcs_scripts/__init__.py",
|
|
17
|
+
"uv.lock",
|
|
18
|
+
)
|
|
19
|
+
TAG = re.compile(r"^v(\d+)\.(\d+)\.(\d+)$")
|
|
20
|
+
PARTS = ("major", "minor", "patch")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _fail(message: str) -> None:
|
|
24
|
+
print(message, file=sys.stderr)
|
|
25
|
+
raise SystemExit(1)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _run(cmd: list[str]) -> subprocess.CompletedProcess[str]:
|
|
29
|
+
result = subprocess.run(cmd, cwd=ROOT, text=True, capture_output=True, check=False)
|
|
30
|
+
if result.returncode != 0:
|
|
31
|
+
detail = (result.stderr or result.stdout).strip()
|
|
32
|
+
_fail(detail or f"command failed: {' '.join(cmd)}")
|
|
33
|
+
return result
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _git(*args: str) -> str:
|
|
37
|
+
return _run(["git", *args]).stdout.strip()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _pyproject_version() -> str:
|
|
41
|
+
text = PYPROJECT.read_text(encoding="utf-8")
|
|
42
|
+
match = re.search(r'(?m)^version = "(\d+\.\d+\.\d+)"\s*$', text)
|
|
43
|
+
if match is None:
|
|
44
|
+
_fail("version in pyproject.toml is not X.Y.Z")
|
|
45
|
+
return match.group(1)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _latest_tag_version() -> str | None:
|
|
49
|
+
for line in _git("tag", "-l", "--sort=-v:refname").splitlines():
|
|
50
|
+
if TAG.fullmatch(line.strip()):
|
|
51
|
+
return line.strip()[1:]
|
|
52
|
+
return None
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _bump(version: str, part: str) -> str:
|
|
56
|
+
major, minor, patch = (int(piece) for piece in version.split("."))
|
|
57
|
+
if part == "major":
|
|
58
|
+
return f"{major + 1}.0.0"
|
|
59
|
+
if part == "minor":
|
|
60
|
+
return f"{major}.{minor + 1}.0"
|
|
61
|
+
return f"{major}.{minor}.{patch + 1}"
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _status_paths() -> list[str]:
|
|
65
|
+
# Keep the leading space in porcelain lines. strip() would turn
|
|
66
|
+
# " M pyproject.toml" into "M pyproject.toml" and drop the first letter.
|
|
67
|
+
paths: list[str] = []
|
|
68
|
+
for line in _run(["git", "status", "--porcelain"]).stdout.splitlines():
|
|
69
|
+
path = line[3:]
|
|
70
|
+
if " -> " in path:
|
|
71
|
+
path = path.split(" -> ", 1)[1]
|
|
72
|
+
paths.append(path.strip().strip('"'))
|
|
73
|
+
return paths
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _require_branch() -> None:
|
|
77
|
+
if _git("rev-parse", "--abbrev-ref", "HEAD") == "HEAD":
|
|
78
|
+
_fail("HEAD is detached; checkout a branch before releasing")
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _require_clean() -> None:
|
|
82
|
+
if _status_paths():
|
|
83
|
+
_fail("working tree is not clean; commit other changes before releasing")
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _write_version(version: str) -> None:
|
|
87
|
+
with INIT.open(encoding="utf-8", newline="") as handle:
|
|
88
|
+
text = handle.read()
|
|
89
|
+
updated, count = re.subn(
|
|
90
|
+
r'^__version__ = "[^"]*"',
|
|
91
|
+
f'__version__ = "{version}"',
|
|
92
|
+
text,
|
|
93
|
+
count=1,
|
|
94
|
+
flags=re.M,
|
|
95
|
+
)
|
|
96
|
+
if count != 1:
|
|
97
|
+
_fail("__version__ not found in src/awcs_scripts/__init__.py")
|
|
98
|
+
with INIT.open("w", encoding="utf-8", newline="") as handle:
|
|
99
|
+
handle.write(updated)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def main(argv: list[str] | None = None) -> None:
|
|
103
|
+
parser = argparse.ArgumentParser(description="Bump, tag, and push a release.")
|
|
104
|
+
parser.add_argument("part", nargs="?", default="patch", choices=PARTS)
|
|
105
|
+
parser.add_argument("--dry-run", action="store_true", help="Print the next version and write nothing")
|
|
106
|
+
args = parser.parse_args(argv)
|
|
107
|
+
|
|
108
|
+
base = _latest_tag_version() or _pyproject_version()
|
|
109
|
+
version = _bump(base, args.part)
|
|
110
|
+
if args.dry_run:
|
|
111
|
+
print(version)
|
|
112
|
+
return
|
|
113
|
+
|
|
114
|
+
_require_branch()
|
|
115
|
+
_require_clean()
|
|
116
|
+
if _git("tag", "-l", f"v{version}"):
|
|
117
|
+
_fail(f"tag v{version} already exists")
|
|
118
|
+
|
|
119
|
+
if _pyproject_version() != base:
|
|
120
|
+
_run(["uv", "version", base, "--no-sync"])
|
|
121
|
+
bumped = _run(["uv", "version", "--bump", args.part, "--short", "--no-sync"]).stdout.strip()
|
|
122
|
+
if bumped != version:
|
|
123
|
+
_fail(f"uv version returned {bumped}, expected {version}")
|
|
124
|
+
_write_version(version)
|
|
125
|
+
|
|
126
|
+
unexpected = [path for path in _status_paths() if path not in VERSION_FILES]
|
|
127
|
+
if unexpected:
|
|
128
|
+
_fail("unexpected changes: " + ", ".join(unexpected))
|
|
129
|
+
if not _status_paths():
|
|
130
|
+
_fail("version did not change")
|
|
131
|
+
|
|
132
|
+
_run(["git", "add", "--", *VERSION_FILES])
|
|
133
|
+
_run(["git", "commit", "-m", f"Release {version}."])
|
|
134
|
+
_run(["git", "tag", f"v{version}"])
|
|
135
|
+
_run(["git", "push", "origin", "HEAD"])
|
|
136
|
+
_run(["git", "push", "origin", f"v{version}"])
|
|
137
|
+
print(f"v{version}")
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
if __name__ == "__main__":
|
|
141
|
+
main()
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import argparse
|
|
6
|
+
import importlib.metadata
|
|
6
7
|
import importlib.util
|
|
7
8
|
import json
|
|
8
9
|
import sys
|
|
@@ -28,6 +29,10 @@ def _load_tool(filename: str):
|
|
|
28
29
|
return module
|
|
29
30
|
|
|
30
31
|
|
|
32
|
+
def _cmd_version(_args: argparse.Namespace) -> None:
|
|
33
|
+
print(importlib.metadata.version("awcs-scripts"))
|
|
34
|
+
|
|
35
|
+
|
|
31
36
|
def _fail(message: str) -> None:
|
|
32
37
|
print(message, file=sys.stderr)
|
|
33
38
|
raise SystemExit(1)
|
|
@@ -172,6 +177,9 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
172
177
|
help_parser = sub.add_parser("help", help="Show this help")
|
|
173
178
|
help_parser.set_defaults(func=lambda _args: parser.print_help())
|
|
174
179
|
|
|
180
|
+
version_parser = sub.add_parser("version", help="Print the package version")
|
|
181
|
+
version_parser.set_defaults(func=_cmd_version)
|
|
182
|
+
|
|
175
183
|
_add_tool(sub, "mrmap-to-raster", "Rasterize a .mrmap to PNG, GeoTIFF, and JSON")
|
|
176
184
|
_add_tool(sub, "mrmap-to-bg", "Set a .mrmap raster as a LIF layout background")
|
|
177
185
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import importlib.metadata
|
|
2
|
+
|
|
1
3
|
import pytest
|
|
2
4
|
|
|
3
5
|
from awcs_scripts.cli import main
|
|
@@ -10,6 +12,13 @@ def test_help_lists_commands(capsys):
|
|
|
10
12
|
assert "mrmap-to-bg" in text
|
|
11
13
|
assert "projects" in text
|
|
12
14
|
assert "login" in text
|
|
15
|
+
assert "version" in text
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_version(capsys):
|
|
19
|
+
main(["version"])
|
|
20
|
+
text = capsys.readouterr().out.strip()
|
|
21
|
+
assert text == importlib.metadata.version("awcs-scripts")
|
|
13
22
|
|
|
14
23
|
|
|
15
24
|
def test_help_command(capsys):
|
|
@@ -17,6 +26,7 @@ def test_help_command(capsys):
|
|
|
17
26
|
text = capsys.readouterr().out
|
|
18
27
|
assert "mission_templates" in text
|
|
19
28
|
assert "users" in text
|
|
29
|
+
assert "version" in text
|
|
20
30
|
|
|
21
31
|
|
|
22
32
|
def test_raster_help():
|
|
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
|