mposcli 0.1.0__tar.gz → 0.2.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.
- {mposcli-0.1.0 → mposcli-0.2.0}/PKG-INFO +76 -3
- {mposcli-0.1.0 → mposcli-0.2.0}/README.md +75 -2
- {mposcli-0.1.0 → mposcli-0.2.0}/mposcli/__init__.py +1 -1
- mposcli-0.2.0/mposcli/cli_app/copy_mpos.py +92 -0
- mposcli-0.2.0/mposcli/cli_app/flash.py +87 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/mposcli/tests/test_readme.py +1 -1
- mposcli-0.2.0/mposcli/tools.py +27 -0
- mposcli-0.2.0/mposcli/user_input.py +87 -0
- mposcli-0.1.0/mposcli/user_input.py +0 -37
- {mposcli-0.1.0 → mposcli-0.2.0}/.editorconfig +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/.github/workflows/tests.yml +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/.gitignore +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/.idea/.gitignore +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/.pre-commit-config.yaml +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/.pre-commit-hooks.yaml +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/.run/Template Python tests.run.xml +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/.run/Template Python.run.xml +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/.run/Unittests __all__.run.xml +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/.run/cli --help.run.xml +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/.run/dev-cli --help.run.xml +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/.run/dev-cli test.run.xml +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/.venv-app/.gitignore +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/cli.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/dev-cli.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/dist/.gitignore +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/mposcli/__main__.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/mposcli/cli_app/__init__.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/mposcli/cli_app/build.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/mposcli/cli_app/run_deskop.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/mposcli/cli_app/update.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/mposcli/cli_dev/__init__.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/mposcli/cli_dev/__main__.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/mposcli/cli_dev/code_style.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/mposcli/cli_dev/packaging.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/mposcli/cli_dev/shell_completion.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/mposcli/cli_dev/testing.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/mposcli/cli_dev/update_readme_history.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/mposcli/constants.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/mposcli/fs_utils.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/mposcli/mpos_utils.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/mposcli/tests/__init__.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/mposcli/tests/test_doctests.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/mposcli/tests/test_project_setup.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/mposcli/tests/test_readme_history.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/noxfile.py +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/pyproject.toml +0 -0
- {mposcli-0.1.0 → mposcli-0.2.0}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mposcli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: CLI helper for MicroPythonOS: https://github.com/MicroPythonOS/MicroPythonOS
|
|
5
5
|
Project-URL: Documentation, https://github.com/jedie/mposcli
|
|
6
6
|
Project-URL: Source, https://github.com/jedie/mposcli
|
|
@@ -25,11 +25,29 @@ Experimental CLI helper for MicroPythonOS: https://github.com/MicroPythonOS/Micr
|
|
|
25
25
|
|
|
26
26
|
Main Idea: Install it via pipx (see below) and use `mposcli` command in MicroPythonOS repository path.
|
|
27
27
|
|
|
28
|
+
Install, e.g.:
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
sudo apt install pipx
|
|
32
|
+
|
|
33
|
+
pipx install mposcli
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
To upgrade an existing installation: Just call: `pipx upgrade PyHardLinkBackup`
|
|
37
|
+
|
|
38
|
+
Usage e.g.:
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
cd ~/MicroPythonOS
|
|
42
|
+
~/MicroPythonOS$ mposcli run-desktop
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
|
|
28
46
|
## CLI
|
|
29
47
|
|
|
30
48
|
[comment]: <> (✂✂✂ auto generated main help start ✂✂✂)
|
|
31
49
|
```
|
|
32
|
-
usage: mposcli [-h] {build,run-desktop,update-submodules,version}
|
|
50
|
+
usage: mposcli [-h] {build,cp,flash,run-desktop,update-submodules,version}
|
|
33
51
|
|
|
34
52
|
|
|
35
53
|
|
|
@@ -40,6 +58,12 @@ usage: mposcli [-h] {build,run-desktop,update-submodules,version}
|
|
|
40
58
|
│ (required) │
|
|
41
59
|
│ • build Build MicroPythonOS by calling: ./scripts/build_mpos.sh <target> see: │
|
|
42
60
|
│ https://docs.micropythonos.com/os-development/ │
|
|
61
|
+
│ • cp Copy/update internal_filesystem/lib/mpos files to the device via "mpremote fs cp". Display a │
|
|
62
|
+
│ file chooser to select which files to copy/update. But can also be used to copy/update all │
|
|
63
|
+
│ files. see: https://docs.micropythonos.com/os-development/installing-on-esp32/ │
|
|
64
|
+
│ • flash Flash MicroPythonOS to the device. Display a file chooser to select the image to flash. All │
|
|
65
|
+
│ lvgl_micropython/build/*.bin files will be shown in the file chooser. see: │
|
|
66
|
+
│ https://docs.micropythonos.com/os-development/installing-on-esp32/ │
|
|
43
67
|
│ • run-desktop Run MicroPythonOS on desktop. see: │
|
|
44
68
|
│ https://docs.micropythonos.com/getting-started/running/#running-on-desktop │
|
|
45
69
|
│ • update-submodules Update MicroPythonOS repository and all submodules see: │
|
|
@@ -50,6 +74,7 @@ usage: mposcli [-h] {build,run-desktop,update-submodules,version}
|
|
|
50
74
|
[comment]: <> (✂✂✂ auto generated main help end ✂✂✂)
|
|
51
75
|
|
|
52
76
|
|
|
77
|
+
|
|
53
78
|
## CLI - build
|
|
54
79
|
|
|
55
80
|
[comment]: <> (✂✂✂ auto generated build start ✂✂✂)
|
|
@@ -69,6 +94,50 @@ Build MicroPythonOS by calling: ./scripts/build_mpos.sh <target> see: https://do
|
|
|
69
94
|
|
|
70
95
|
|
|
71
96
|
|
|
97
|
+
## CLI - cp
|
|
98
|
+
|
|
99
|
+
[comment]: <> (✂✂✂ auto generated cp start ✂✂✂)
|
|
100
|
+
```
|
|
101
|
+
usage: mposcli cp [-h] [--new-file-limit INT] [--reset | --no-reset] [--repl | --no-repl] [-v]
|
|
102
|
+
|
|
103
|
+
Copy/update internal_filesystem/lib/mpos files to the device via "mpremote fs cp". Display a file chooser to select which files to copy/update. But can also be used to copy/update all files. see: https://docs.micropythonos.com/os-development/installing-on-esp32/
|
|
104
|
+
|
|
105
|
+
╭─ options ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
|
106
|
+
│ -h, --help show this help message and exit │
|
|
107
|
+
│ --new-file-limit INT How many of the newest files to show in the file chooser? (default: 10) │
|
|
108
|
+
│ --reset, --no-reset Reset the device after copy/update? (default: True) │
|
|
109
|
+
│ --repl, --no-repl After flashing/verify start REPL with mpremote to see the output of the device? (default: │
|
|
110
|
+
│ True) │
|
|
111
|
+
│ -v, --verbosity Verbosity level; e.g.: -v, -vv, -vvv, etc. (repeatable) │
|
|
112
|
+
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
|
113
|
+
```
|
|
114
|
+
[comment]: <> (✂✂✂ auto generated cp end ✂✂✂)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
## CLI - flash
|
|
119
|
+
|
|
120
|
+
[comment]: <> (✂✂✂ auto generated flash start ✂✂✂)
|
|
121
|
+
```
|
|
122
|
+
usage: mposcli flash [-h] [FLASH OPTIONS]
|
|
123
|
+
|
|
124
|
+
Flash MicroPythonOS to the device. Display a file chooser to select the image to flash. All lvgl_micropython/build/*.bin files will be shown in the file chooser. see: https://docs.micropythonos.com/os-development/installing-on-esp32/
|
|
125
|
+
|
|
126
|
+
╭─ options ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
|
127
|
+
│ -h, --help show this help message and exit │
|
|
128
|
+
│ --port STR Port used for esptool and mpremote (default: /dev/ttyUSB0) │
|
|
129
|
+
│ --address STR Address (default: 0x0) │
|
|
130
|
+
│ --flash-size STR Flash Size (default: detect) │
|
|
131
|
+
│ --verify, --no-verify Verify after flashing? (default: True) │
|
|
132
|
+
│ --repl, --no-repl After flashing/verify start REPL with mpremote to see the output of the device? (default: │
|
|
133
|
+
│ True) │
|
|
134
|
+
│ -v, --verbosity Verbosity level; e.g.: -v, -vv, -vvv, etc. (repeatable) │
|
|
135
|
+
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
|
136
|
+
```
|
|
137
|
+
[comment]: <> (✂✂✂ auto generated flash end ✂✂✂)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
72
141
|
## CLI - run-desktop
|
|
73
142
|
|
|
74
143
|
|
|
@@ -169,7 +238,11 @@ usage: ./dev-cli.py [-h] {coverage,install,lint,mypy,nox,pip-audit,publish,shell
|
|
|
169
238
|
|
|
170
239
|
[comment]: <> (✂✂✂ auto generated history start ✂✂✂)
|
|
171
240
|
|
|
172
|
-
* [
|
|
241
|
+
* [v0.2.0](https://github.com/jedie/mposcli/compare/v0.1.0...v0.2.0)
|
|
242
|
+
* 2026-02-16 - New CLI command: "cp" with convenience features.
|
|
243
|
+
* 2026-02-16 - New command: "flash" with file selector
|
|
244
|
+
* 2026-02-16 - Update README.md
|
|
245
|
+
* [v0.1.0](https://github.com/jedie/mposcli/compare/1695026...v0.1.0)
|
|
173
246
|
* 2026-02-16 - Add "update-submodules" command
|
|
174
247
|
* 2026-02-16 - Add "build" command
|
|
175
248
|
* 2026-02-16 - CLI command: "run-desktop"
|
|
@@ -10,11 +10,29 @@ Experimental CLI helper for MicroPythonOS: https://github.com/MicroPythonOS/Micr
|
|
|
10
10
|
|
|
11
11
|
Main Idea: Install it via pipx (see below) and use `mposcli` command in MicroPythonOS repository path.
|
|
12
12
|
|
|
13
|
+
Install, e.g.:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
sudo apt install pipx
|
|
17
|
+
|
|
18
|
+
pipx install mposcli
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
To upgrade an existing installation: Just call: `pipx upgrade PyHardLinkBackup`
|
|
22
|
+
|
|
23
|
+
Usage e.g.:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
cd ~/MicroPythonOS
|
|
27
|
+
~/MicroPythonOS$ mposcli run-desktop
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
|
|
13
31
|
## CLI
|
|
14
32
|
|
|
15
33
|
[comment]: <> (✂✂✂ auto generated main help start ✂✂✂)
|
|
16
34
|
```
|
|
17
|
-
usage: mposcli [-h] {build,run-desktop,update-submodules,version}
|
|
35
|
+
usage: mposcli [-h] {build,cp,flash,run-desktop,update-submodules,version}
|
|
18
36
|
|
|
19
37
|
|
|
20
38
|
|
|
@@ -25,6 +43,12 @@ usage: mposcli [-h] {build,run-desktop,update-submodules,version}
|
|
|
25
43
|
│ (required) │
|
|
26
44
|
│ • build Build MicroPythonOS by calling: ./scripts/build_mpos.sh <target> see: │
|
|
27
45
|
│ https://docs.micropythonos.com/os-development/ │
|
|
46
|
+
│ • cp Copy/update internal_filesystem/lib/mpos files to the device via "mpremote fs cp". Display a │
|
|
47
|
+
│ file chooser to select which files to copy/update. But can also be used to copy/update all │
|
|
48
|
+
│ files. see: https://docs.micropythonos.com/os-development/installing-on-esp32/ │
|
|
49
|
+
│ • flash Flash MicroPythonOS to the device. Display a file chooser to select the image to flash. All │
|
|
50
|
+
│ lvgl_micropython/build/*.bin files will be shown in the file chooser. see: │
|
|
51
|
+
│ https://docs.micropythonos.com/os-development/installing-on-esp32/ │
|
|
28
52
|
│ • run-desktop Run MicroPythonOS on desktop. see: │
|
|
29
53
|
│ https://docs.micropythonos.com/getting-started/running/#running-on-desktop │
|
|
30
54
|
│ • update-submodules Update MicroPythonOS repository and all submodules see: │
|
|
@@ -35,6 +59,7 @@ usage: mposcli [-h] {build,run-desktop,update-submodules,version}
|
|
|
35
59
|
[comment]: <> (✂✂✂ auto generated main help end ✂✂✂)
|
|
36
60
|
|
|
37
61
|
|
|
62
|
+
|
|
38
63
|
## CLI - build
|
|
39
64
|
|
|
40
65
|
[comment]: <> (✂✂✂ auto generated build start ✂✂✂)
|
|
@@ -54,6 +79,50 @@ Build MicroPythonOS by calling: ./scripts/build_mpos.sh <target> see: https://do
|
|
|
54
79
|
|
|
55
80
|
|
|
56
81
|
|
|
82
|
+
## CLI - cp
|
|
83
|
+
|
|
84
|
+
[comment]: <> (✂✂✂ auto generated cp start ✂✂✂)
|
|
85
|
+
```
|
|
86
|
+
usage: mposcli cp [-h] [--new-file-limit INT] [--reset | --no-reset] [--repl | --no-repl] [-v]
|
|
87
|
+
|
|
88
|
+
Copy/update internal_filesystem/lib/mpos files to the device via "mpremote fs cp". Display a file chooser to select which files to copy/update. But can also be used to copy/update all files. see: https://docs.micropythonos.com/os-development/installing-on-esp32/
|
|
89
|
+
|
|
90
|
+
╭─ options ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
|
91
|
+
│ -h, --help show this help message and exit │
|
|
92
|
+
│ --new-file-limit INT How many of the newest files to show in the file chooser? (default: 10) │
|
|
93
|
+
│ --reset, --no-reset Reset the device after copy/update? (default: True) │
|
|
94
|
+
│ --repl, --no-repl After flashing/verify start REPL with mpremote to see the output of the device? (default: │
|
|
95
|
+
│ True) │
|
|
96
|
+
│ -v, --verbosity Verbosity level; e.g.: -v, -vv, -vvv, etc. (repeatable) │
|
|
97
|
+
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
|
98
|
+
```
|
|
99
|
+
[comment]: <> (✂✂✂ auto generated cp end ✂✂✂)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
## CLI - flash
|
|
104
|
+
|
|
105
|
+
[comment]: <> (✂✂✂ auto generated flash start ✂✂✂)
|
|
106
|
+
```
|
|
107
|
+
usage: mposcli flash [-h] [FLASH OPTIONS]
|
|
108
|
+
|
|
109
|
+
Flash MicroPythonOS to the device. Display a file chooser to select the image to flash. All lvgl_micropython/build/*.bin files will be shown in the file chooser. see: https://docs.micropythonos.com/os-development/installing-on-esp32/
|
|
110
|
+
|
|
111
|
+
╭─ options ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
|
112
|
+
│ -h, --help show this help message and exit │
|
|
113
|
+
│ --port STR Port used for esptool and mpremote (default: /dev/ttyUSB0) │
|
|
114
|
+
│ --address STR Address (default: 0x0) │
|
|
115
|
+
│ --flash-size STR Flash Size (default: detect) │
|
|
116
|
+
│ --verify, --no-verify Verify after flashing? (default: True) │
|
|
117
|
+
│ --repl, --no-repl After flashing/verify start REPL with mpremote to see the output of the device? (default: │
|
|
118
|
+
│ True) │
|
|
119
|
+
│ -v, --verbosity Verbosity level; e.g.: -v, -vv, -vvv, etc. (repeatable) │
|
|
120
|
+
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
|
121
|
+
```
|
|
122
|
+
[comment]: <> (✂✂✂ auto generated flash end ✂✂✂)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
57
126
|
## CLI - run-desktop
|
|
58
127
|
|
|
59
128
|
|
|
@@ -154,7 +223,11 @@ usage: ./dev-cli.py [-h] {coverage,install,lint,mypy,nox,pip-audit,publish,shell
|
|
|
154
223
|
|
|
155
224
|
[comment]: <> (✂✂✂ auto generated history start ✂✂✂)
|
|
156
225
|
|
|
157
|
-
* [
|
|
226
|
+
* [v0.2.0](https://github.com/jedie/mposcli/compare/v0.1.0...v0.2.0)
|
|
227
|
+
* 2026-02-16 - New CLI command: "cp" with convenience features.
|
|
228
|
+
* 2026-02-16 - New command: "flash" with file selector
|
|
229
|
+
* 2026-02-16 - Update README.md
|
|
230
|
+
* [v0.1.0](https://github.com/jedie/mposcli/compare/1695026...v0.1.0)
|
|
158
231
|
* 2026-02-16 - Add "update-submodules" command
|
|
159
232
|
* 2026-02-16 - Add "build" command
|
|
160
233
|
* 2026-02-16 - CLI command: "run-desktop"
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
|
|
2
|
+
import logging
|
|
3
|
+
from typing import Annotated
|
|
4
|
+
|
|
5
|
+
import tyro
|
|
6
|
+
from bx_py_utils.path import assert_is_dir
|
|
7
|
+
from cli_base.cli_tools.subprocess_utils import verbose_check_call
|
|
8
|
+
from cli_base.cli_tools.verbosity import setup_logging
|
|
9
|
+
from cli_base.tyro_commands import TyroVerbosityArgType
|
|
10
|
+
from rich import print # noqa
|
|
11
|
+
|
|
12
|
+
from mposcli.cli_app import app
|
|
13
|
+
from mposcli.mpos_utils import get_mpos_path
|
|
14
|
+
from mposcli.tools import get_mpremote_bin
|
|
15
|
+
from mposcli.user_input import get_newest_files
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@app.command
|
|
22
|
+
def cp(
|
|
23
|
+
new_file_limit: Annotated[
|
|
24
|
+
int,
|
|
25
|
+
tyro.conf.arg(help='How many of the newest files to show in the file chooser?'),
|
|
26
|
+
] = 10,
|
|
27
|
+
reset: Annotated[
|
|
28
|
+
bool,
|
|
29
|
+
tyro.conf.arg(help='Reset the device after copy/update?'),
|
|
30
|
+
] = True,
|
|
31
|
+
repl: Annotated[
|
|
32
|
+
bool,
|
|
33
|
+
tyro.conf.arg(help='After flashing/verify start REPL with mpremote to see the output of the device?'),
|
|
34
|
+
] = True,
|
|
35
|
+
verbosity: TyroVerbosityArgType = 1,
|
|
36
|
+
):
|
|
37
|
+
"""
|
|
38
|
+
Copy/update internal_filesystem/lib/mpos files to the device via "mpremote fs cp".
|
|
39
|
+
Display a file chooser to select which files to copy/update.
|
|
40
|
+
But can also be used to copy/update all files.
|
|
41
|
+
see: https://docs.micropythonos.com/os-development/installing-on-esp32/
|
|
42
|
+
"""
|
|
43
|
+
setup_logging(verbosity=verbosity)
|
|
44
|
+
|
|
45
|
+
mpos_path = get_mpos_path()
|
|
46
|
+
|
|
47
|
+
internal_fs = mpos_path / 'internal_filesystem'
|
|
48
|
+
lib_mpos = internal_fs / 'lib' / 'mpos'
|
|
49
|
+
assert_is_dir(lib_mpos)
|
|
50
|
+
|
|
51
|
+
mpremote_bin = get_mpremote_bin()
|
|
52
|
+
|
|
53
|
+
print('\n')
|
|
54
|
+
|
|
55
|
+
local_path = get_newest_files(lib_mpos, limit=new_file_limit)
|
|
56
|
+
|
|
57
|
+
popenargs = (mpremote_bin, 'fs', 'cp')
|
|
58
|
+
|
|
59
|
+
if not local_path:
|
|
60
|
+
print('Copy/update all files in lib/mpos to the device')
|
|
61
|
+
local_path = lib_mpos
|
|
62
|
+
popenargs += ('-r',)
|
|
63
|
+
|
|
64
|
+
local_rel_path = local_path.relative_to(mpos_path)
|
|
65
|
+
remote_path = f':/{local_path.relative_to(lib_mpos.parent)}'
|
|
66
|
+
|
|
67
|
+
print(f'Copying "[bold]{local_rel_path}[/bold]" to device at "[bold]{remote_path}[/bold]" ...')
|
|
68
|
+
|
|
69
|
+
popenargs += (local_rel_path, remote_path)
|
|
70
|
+
verbose_check_call(
|
|
71
|
+
*popenargs,
|
|
72
|
+
verbose=True,
|
|
73
|
+
cwd=mpos_path,
|
|
74
|
+
text=None,
|
|
75
|
+
)
|
|
76
|
+
if reset:
|
|
77
|
+
verbose_check_call(
|
|
78
|
+
mpremote_bin,
|
|
79
|
+
'reset',
|
|
80
|
+
verbose=True,
|
|
81
|
+
cwd=mpos_path,
|
|
82
|
+
text=None,
|
|
83
|
+
)
|
|
84
|
+
if repl:
|
|
85
|
+
verbose_check_call(
|
|
86
|
+
mpremote_bin,
|
|
87
|
+
'repl',
|
|
88
|
+
verbose=True,
|
|
89
|
+
cwd=mpos_path,
|
|
90
|
+
timeout=None,
|
|
91
|
+
text=None,
|
|
92
|
+
)
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Annotated
|
|
3
|
+
|
|
4
|
+
import tyro
|
|
5
|
+
from cli_base.cli_tools.subprocess_utils import verbose_check_call
|
|
6
|
+
from cli_base.cli_tools.verbosity import setup_logging
|
|
7
|
+
from cli_base.tyro_commands import TyroVerbosityArgType
|
|
8
|
+
from rich import print # noqa
|
|
9
|
+
|
|
10
|
+
from mposcli.cli_app import app
|
|
11
|
+
from mposcli.mpos_utils import get_mpos_path
|
|
12
|
+
from mposcli.tools import get_esptool_bin, get_mpremote_bin
|
|
13
|
+
from mposcli.user_input import file_chooser
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@app.command
|
|
20
|
+
def flash(
|
|
21
|
+
port: Annotated[str, tyro.conf.arg(help='Port used for esptool and mpremote')] = '/dev/ttyUSB0',
|
|
22
|
+
address: Annotated[str, tyro.conf.arg(help='Address')] = '0x0',
|
|
23
|
+
flash_size: Annotated[str, tyro.conf.arg(help='Flash Size')] = 'detect',
|
|
24
|
+
verify: Annotated[bool, tyro.conf.arg(help='Verify after flashing?')] = True,
|
|
25
|
+
repl: Annotated[
|
|
26
|
+
bool,
|
|
27
|
+
tyro.conf.arg(help='After flashing/verify start REPL with mpremote to see the output of the device?'),
|
|
28
|
+
] = True,
|
|
29
|
+
verbosity: TyroVerbosityArgType = 1,
|
|
30
|
+
):
|
|
31
|
+
"""
|
|
32
|
+
Flash MicroPythonOS to the device. Display a file chooser to select the image to flash.
|
|
33
|
+
All lvgl_micropython/build/*.bin files will be shown in the file chooser.
|
|
34
|
+
see: https://docs.micropythonos.com/os-development/installing-on-esp32/
|
|
35
|
+
"""
|
|
36
|
+
setup_logging(verbosity=verbosity)
|
|
37
|
+
|
|
38
|
+
mpos_path = get_mpos_path()
|
|
39
|
+
|
|
40
|
+
esptool_bin = get_esptool_bin()
|
|
41
|
+
mpremote_bin = get_mpremote_bin()
|
|
42
|
+
|
|
43
|
+
print('\n')
|
|
44
|
+
|
|
45
|
+
lvgl_micropython_build_path = mpos_path / 'lvgl_micropython' / 'build'
|
|
46
|
+
image_files = lvgl_micropython_build_path.glob('*.bin')
|
|
47
|
+
image_file = file_chooser(image_files)
|
|
48
|
+
|
|
49
|
+
verbose_check_call(
|
|
50
|
+
esptool_bin,
|
|
51
|
+
'--port',
|
|
52
|
+
port,
|
|
53
|
+
'write-flash',
|
|
54
|
+
'--flash-size',
|
|
55
|
+
flash_size,
|
|
56
|
+
address,
|
|
57
|
+
image_file,
|
|
58
|
+
verbose=True,
|
|
59
|
+
cwd=mpos_path,
|
|
60
|
+
timeout=None,
|
|
61
|
+
text=None,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
if verify:
|
|
65
|
+
verbose_check_call(
|
|
66
|
+
esptool_bin,
|
|
67
|
+
'--port',
|
|
68
|
+
port,
|
|
69
|
+
'verify-flash',
|
|
70
|
+
address,
|
|
71
|
+
image_file,
|
|
72
|
+
verbose=True,
|
|
73
|
+
cwd=mpos_path,
|
|
74
|
+
timeout=None,
|
|
75
|
+
text=None,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
if repl:
|
|
79
|
+
verbose_check_call(
|
|
80
|
+
mpremote_bin,
|
|
81
|
+
'repl',
|
|
82
|
+
port,
|
|
83
|
+
verbose=True,
|
|
84
|
+
cwd=mpos_path,
|
|
85
|
+
timeout=None,
|
|
86
|
+
text=None,
|
|
87
|
+
)
|
|
@@ -71,7 +71,7 @@ class ReadmeTestCase(BaseTestCase):
|
|
|
71
71
|
|
|
72
72
|
commands.discard('version') # version is pseudo command, because the version always printed on every CLI call
|
|
73
73
|
commands = sorted(commands)
|
|
74
|
-
self.assertEqual(commands, ['build', 'run-desktop', 'update-submodules'])
|
|
74
|
+
self.assertEqual(commands, ['build', 'cp', 'flash', 'run-desktop', 'update-submodules'])
|
|
75
75
|
|
|
76
76
|
for command in commands:
|
|
77
77
|
with self.subTest(command):
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
import sys
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from cli_base.cli_tools.subprocess_utils import verbose_check_call
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_bin(name: str) -> Path:
|
|
9
|
+
bin_path = shutil.which(name)
|
|
10
|
+
if bin_path is None:
|
|
11
|
+
print(f'[red]Error: {name} is not installed or not found in PATH.[/red]')
|
|
12
|
+
print('Hint: Install via pipx, e.g.:')
|
|
13
|
+
print(f'\tpipx install {name}')
|
|
14
|
+
sys.exit(1)
|
|
15
|
+
return Path(bin_path)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_esptool_bin() -> Path:
|
|
19
|
+
esptool_bin = get_bin('esptool')
|
|
20
|
+
verbose_check_call(esptool_bin, 'version')
|
|
21
|
+
return esptool_bin
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_mpremote_bin():
|
|
25
|
+
mpremote_bin = get_bin('mpremote')
|
|
26
|
+
verbose_check_call(mpremote_bin, '--version')
|
|
27
|
+
return mpremote_bin
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from rich import print
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def file_chooser(paths) -> Path | None:
|
|
10
|
+
"""
|
|
11
|
+
Display a numbered list of files sorted by modification time (newest first).
|
|
12
|
+
Show mtime and file name. Input number, ENTER = 1. Return selected Path.
|
|
13
|
+
"""
|
|
14
|
+
print()
|
|
15
|
+
|
|
16
|
+
files = [(p, p.stat().st_mtime) for p in paths if p.is_file()]
|
|
17
|
+
if not files:
|
|
18
|
+
print('[red]No files found.[/red]')
|
|
19
|
+
return None
|
|
20
|
+
files.sort(key=lambda x: x[1], reverse=True)
|
|
21
|
+
|
|
22
|
+
print('[bold]Choose a file:[/bold]\n')
|
|
23
|
+
for idx, (p, mtime) in enumerate(files):
|
|
24
|
+
dt = datetime.datetime.fromtimestamp(mtime).strftime('%Y-%m-%d %H:%M:%S')
|
|
25
|
+
print(f'[{idx}] {dt} - {p.name}')
|
|
26
|
+
|
|
27
|
+
print()
|
|
28
|
+
|
|
29
|
+
number = input('Enter number (ENTER = 0 - the newest file): ').strip() or 0
|
|
30
|
+
print('Selected:', number)
|
|
31
|
+
try:
|
|
32
|
+
number = int(number)
|
|
33
|
+
except Exception as err:
|
|
34
|
+
print(f'[red]Invalid input: {err}[/red]')
|
|
35
|
+
sys.exit(1)
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
selection = files[number][0]
|
|
39
|
+
except IndexError:
|
|
40
|
+
print(f'[red]Invalid selection: {number}[/red]')
|
|
41
|
+
sys.exit(1)
|
|
42
|
+
|
|
43
|
+
print(f'Selected file: {selection}')
|
|
44
|
+
return selection
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def get_newest_files(directory, limit=10) -> Path | None:
|
|
48
|
+
files = []
|
|
49
|
+
|
|
50
|
+
def scan(dir_path):
|
|
51
|
+
with os.scandir(dir_path) as it:
|
|
52
|
+
for entry in it:
|
|
53
|
+
if entry.is_file(follow_symlinks=False):
|
|
54
|
+
files.append((entry, entry.stat().st_mtime))
|
|
55
|
+
elif entry.is_dir(follow_symlinks=False):
|
|
56
|
+
scan(entry.path)
|
|
57
|
+
|
|
58
|
+
scan(directory)
|
|
59
|
+
files.sort(key=lambda x: x[1], reverse=True)
|
|
60
|
+
|
|
61
|
+
print(f'[bold]Choose a file[/bold] (only from the newest {limit}):\n')
|
|
62
|
+
for idx, (entry, mtime) in enumerate(files[:limit]):
|
|
63
|
+
dt = datetime.datetime.fromtimestamp(mtime).strftime('%Y-%m-%d %H:%M:%S')
|
|
64
|
+
rel_path = Path(entry.path).relative_to(directory)
|
|
65
|
+
print(f'[{idx}] {dt} - {rel_path}')
|
|
66
|
+
|
|
67
|
+
print()
|
|
68
|
+
|
|
69
|
+
number = input('Enter number (ENTER = 0 - the newest file, "a" for all files): ').strip() or '0'
|
|
70
|
+
print('Selected:', number)
|
|
71
|
+
if number.lower() == 'a':
|
|
72
|
+
return None
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
number = int(number)
|
|
76
|
+
except Exception as err:
|
|
77
|
+
print(f'[red]Invalid input: {err}[/red]')
|
|
78
|
+
sys.exit(1)
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
selection = files[number][0]
|
|
82
|
+
except IndexError:
|
|
83
|
+
print(f'[red]Invalid selection: {number}[/red]')
|
|
84
|
+
sys.exit(1)
|
|
85
|
+
|
|
86
|
+
print(f'Selected file: {selection}')
|
|
87
|
+
return Path(selection)
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import datetime
|
|
2
|
-
import sys
|
|
3
|
-
|
|
4
|
-
from rich import print
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def file_chooser(paths):
|
|
8
|
-
"""
|
|
9
|
-
Display a numbered list of files sorted by modification time (newest first).
|
|
10
|
-
Show mtime and file name. Input number, ENTER = 1. Return selected Path.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
files = [(p, p.stat().st_mtime) for p in paths if p.is_file()]
|
|
14
|
-
if not files:
|
|
15
|
-
print('[red]No files found.[/red]')
|
|
16
|
-
return None
|
|
17
|
-
files.sort(key=lambda x: x[1], reverse=True)
|
|
18
|
-
|
|
19
|
-
print('[bold]Choose a file:[/bold]')
|
|
20
|
-
for idx, (p, mtime) in enumerate(files):
|
|
21
|
-
dt = datetime.datetime.fromtimestamp(mtime).strftime('%Y-%m-%d %H:%M:%S')
|
|
22
|
-
print(f'[{idx}] {dt} {p.name}')
|
|
23
|
-
|
|
24
|
-
number = input('Enter number (ENTER = 0 - the newest file): ').strip() or 0
|
|
25
|
-
try:
|
|
26
|
-
number = int(number)
|
|
27
|
-
except Exception as err:
|
|
28
|
-
print(f'[red]Invalid input: {err}[/red]')
|
|
29
|
-
sys.exit(1)
|
|
30
|
-
|
|
31
|
-
try:
|
|
32
|
-
selection = files[number][0]
|
|
33
|
-
except IndexError:
|
|
34
|
-
print(f'[red]Invalid selection: {number}[/red]')
|
|
35
|
-
sys.exit(1)
|
|
36
|
-
|
|
37
|
-
return selection
|
|
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
|