mpytool 2.2.2__tar.gz → 2.2.3__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.
- {mpytool-2.2.2 → mpytool-2.2.3}/PKG-INFO +42 -23
- {mpytool-2.2.2 → mpytool-2.2.3}/README.md +41 -22
- {mpytool-2.2.2 → mpytool-2.2.3}/mpytool/mpy.py +25 -6
- {mpytool-2.2.2 → mpytool-2.2.3}/mpytool/mpy_comm.py +18 -7
- {mpytool-2.2.2 → mpytool-2.2.3}/mpytool/mpytool.py +48 -39
- mpytool-2.2.3/mpytool/speedtest.py +121 -0
- {mpytool-2.2.2 → mpytool-2.2.3}/mpytool/utils.py +15 -0
- {mpytool-2.2.2 → mpytool-2.2.3}/mpytool.egg-info/PKG-INFO +42 -23
- {mpytool-2.2.2 → mpytool-2.2.3}/mpytool.egg-info/SOURCES.txt +1 -0
- {mpytool-2.2.2 → mpytool-2.2.3}/pyproject.toml +1 -1
- {mpytool-2.2.2 → mpytool-2.2.3}/tests/test_integration.py +92 -0
- {mpytool-2.2.2 → mpytool-2.2.3}/tests/test_mpy.py +78 -0
- {mpytool-2.2.2 → mpytool-2.2.3}/tests/test_mpytool.py +50 -0
- {mpytool-2.2.2 → mpytool-2.2.3}/LICENSE +0 -0
- {mpytool-2.2.2 → mpytool-2.2.3}/mpytool/__init__.py +0 -0
- {mpytool-2.2.2 → mpytool-2.2.3}/mpytool/conn.py +0 -0
- {mpytool-2.2.2 → mpytool-2.2.3}/mpytool/conn_serial.py +0 -0
- {mpytool-2.2.2 → mpytool-2.2.3}/mpytool/conn_socket.py +0 -0
- {mpytool-2.2.2 → mpytool-2.2.3}/mpytool/logger.py +0 -0
- {mpytool-2.2.2 → mpytool-2.2.3}/mpytool/terminal.py +0 -0
- {mpytool-2.2.2 → mpytool-2.2.3}/mpytool/terminal_unix.py +0 -0
- {mpytool-2.2.2 → mpytool-2.2.3}/mpytool/terminal_win.py +0 -0
- {mpytool-2.2.2 → mpytool-2.2.3}/mpytool.egg-info/dependency_links.txt +0 -0
- {mpytool-2.2.2 → mpytool-2.2.3}/mpytool.egg-info/entry_points.txt +0 -0
- {mpytool-2.2.2 → mpytool-2.2.3}/mpytool.egg-info/requires.txt +0 -0
- {mpytool-2.2.2 → mpytool-2.2.3}/mpytool.egg-info/top_level.txt +0 -0
- {mpytool-2.2.2 → mpytool-2.2.3}/setup.cfg +0 -0
- {mpytool-2.2.2 → mpytool-2.2.3}/tests/test_errors.py +0 -0
- {mpytool-2.2.2 → mpytool-2.2.3}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mpytool
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.3
|
|
4
4
|
Summary: MPY tool - manage files on devices running MicroPython
|
|
5
5
|
Author-email: Pavel Revak <pavel.revak@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -74,25 +74,25 @@ Then restart your shell (`exec zsh` or `exec bash`) and use `mpytool` directly.
|
|
|
74
74
|
|
|
75
75
|
Adding venv bin at the end of PATH keeps your system `python` and `pip` as default, while making `mpytool` available when not found elsewhere.
|
|
76
76
|
|
|
77
|
-
## Examples
|
|
77
|
+
## Examples
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
### Help
|
|
80
80
|
```
|
|
81
81
|
$ mpytool --help
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
### List files
|
|
85
85
|
```
|
|
86
86
|
$ mpytool -p /dev/ttyACM0 ls # list CWD (default)
|
|
87
87
|
$ mpytool -p /dev/ttyACM0 ls :/lib # list /lib
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
### Tree
|
|
91
91
|
```
|
|
92
92
|
$ mpytool -p /dev/ttyACM0 tree # tree of CWD (default)
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
### Copy files (: prefix = device path)
|
|
96
96
|
```
|
|
97
97
|
$ mpytool cp main.py :/ # upload file to device root
|
|
98
98
|
$ mpytool cp main.py lib.py :/lib/ # upload multiple files to directory
|
|
@@ -109,7 +109,7 @@ Path semantics: `:` = device CWD, `:/` = device root. Trailing `/` on source = c
|
|
|
109
109
|
Unchanged files are automatically skipped (compares size and SHA256 hash).
|
|
110
110
|
Use `-f` or `--force` to upload all files regardless.
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
### Transfer options
|
|
113
113
|
```
|
|
114
114
|
$ mpytool cp -z main.py :/ # force compression (auto-detected by default)
|
|
115
115
|
$ mpytool cp --no-compress data.bin :/ # disable compression
|
|
@@ -119,20 +119,20 @@ $ mpytool -c 8K cp main.py :/ # set chunk size (512, 1K, 2K, 4K, 8K, 16K,
|
|
|
119
119
|
Compression is auto-detected based on device RAM and deflate module availability.
|
|
120
120
|
Chunk size is auto-detected based on free RAM (larger chunks = faster transfer).
|
|
121
121
|
|
|
122
|
-
|
|
122
|
+
### Move/rename on device
|
|
123
123
|
```
|
|
124
124
|
$ mpytool mv :/old.py :/new.py # rename file
|
|
125
125
|
$ mpytool mv :/file.py :/lib/ # move file to directory
|
|
126
126
|
$ mpytool mv :/a.py :/b.py :/lib/ # move multiple files to directory
|
|
127
127
|
```
|
|
128
128
|
|
|
129
|
-
|
|
129
|
+
### View file contents
|
|
130
130
|
```
|
|
131
131
|
$ mpytool cat :boot.py # print file from CWD
|
|
132
132
|
$ mpytool cat :/lib/module.py # print file with absolute path
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
-
|
|
135
|
+
### Make directory, delete files (: prefix = device path)
|
|
136
136
|
```
|
|
137
137
|
$ mpytool mkdir :lib :data # create directories in CWD
|
|
138
138
|
$ mpytool mkdir :/lib/subdir # create with absolute path
|
|
@@ -143,7 +143,7 @@ $ mpytool rm : # delete everything in CWD
|
|
|
143
143
|
$ mpytool rm :/ # delete everything on device (root)
|
|
144
144
|
```
|
|
145
145
|
|
|
146
|
-
|
|
146
|
+
### Current working directory
|
|
147
147
|
```
|
|
148
148
|
$ mpytool pwd # print current directory
|
|
149
149
|
/
|
|
@@ -153,7 +153,7 @@ $ mpytool cd :.. # change to parent directory
|
|
|
153
153
|
$ mpytool cd :/lib -- ls # change directory and list files
|
|
154
154
|
```
|
|
155
155
|
|
|
156
|
-
|
|
156
|
+
### Reset and REPL
|
|
157
157
|
```
|
|
158
158
|
$ mpytool reset # soft reset (Ctrl-D, runs boot.py/main.py)
|
|
159
159
|
$ mpytool reset --raw # soft reset in raw REPL (clears RAM only)
|
|
@@ -167,7 +167,7 @@ $ mpytool repl # enter REPL mode
|
|
|
167
167
|
$ mpytool sleep 2 # sleep for 2 seconds (useful between commands)
|
|
168
168
|
```
|
|
169
169
|
|
|
170
|
-
|
|
170
|
+
### Serial terminal and monitor (general purpose)
|
|
171
171
|
```
|
|
172
172
|
$ mpytool repl # auto-detect port, 115200 baud
|
|
173
173
|
$ mpytool -p /dev/ttyUSB0 repl # specify port
|
|
@@ -177,13 +177,32 @@ $ mpytool -p /dev/ttyUSB0 -b 9600 monitor # monitor at 9600 baud
|
|
|
177
177
|
|
|
178
178
|
Both `repl` and `monitor` can be used as general-purpose serial tools - not just for MicroPython devices. Use them to interact with any serial device (Arduino, ESP with custom firmware, GPS modules, etc.). When only one serial port is detected, it is used automatically. Default baudrate is 115200.
|
|
179
179
|
|
|
180
|
-
|
|
180
|
+
### Execute Python code on device
|
|
181
181
|
```
|
|
182
182
|
$ mpytool exec "print('Hello!')"
|
|
183
183
|
$ mpytool exec "import sys; print(sys.version)"
|
|
184
184
|
```
|
|
185
185
|
|
|
186
|
-
|
|
186
|
+
### Run local Python file on device
|
|
187
|
+
```
|
|
188
|
+
$ mpytool run script.py # run script (fire-and-forget)
|
|
189
|
+
$ mpytool run script.py -- monitor # run script and capture output
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Serial link speed test
|
|
193
|
+
```
|
|
194
|
+
$ mpytool speedtest
|
|
195
|
+
SPEEDTEST
|
|
196
|
+
upload download verify
|
|
197
|
+
0B - - ok
|
|
198
|
+
16B 11.8K/s 24.4K/s ok
|
|
199
|
+
32B 13.1K/s 42.6K/s ok
|
|
200
|
+
...
|
|
201
|
+
4.00K 120K/s 11.1K/s ok
|
|
202
|
+
8.00K 157K/s 11.0K/s ok
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Show device information
|
|
187
206
|
```
|
|
188
207
|
$ mpytool info
|
|
189
208
|
Platform: rp2
|
|
@@ -201,7 +220,7 @@ MAC WiFi: aa:bb:cc:dd:ee:01
|
|
|
201
220
|
MAC WiFi AP: aa:bb:cc:dd:ee:02
|
|
202
221
|
```
|
|
203
222
|
|
|
204
|
-
|
|
223
|
+
### Flash operations (RP2 and ESP32)
|
|
205
224
|
```
|
|
206
225
|
# RP2 - user flash (entire filesystem area)
|
|
207
226
|
$ mpytool flash # show flash info and filesystem type
|
|
@@ -227,20 +246,20 @@ $ mpytool flash erase vfs # quick erase partition
|
|
|
227
246
|
$ mpytool flash erase vfs --full # full erase partition
|
|
228
247
|
```
|
|
229
248
|
|
|
230
|
-
OTA firmware update (ESP32)
|
|
249
|
+
### OTA firmware update (ESP32)
|
|
231
250
|
```
|
|
232
251
|
$ mpytool ota firmware.app-bin # flash to next OTA partition
|
|
233
252
|
$ mpytool ota firmware.app-bin -- reset --machine # flash and reboot
|
|
234
253
|
$ mpytool ota firmware.app-bin -- reset --machine -t 30 # flash and reboot with 30s timeout
|
|
235
254
|
```
|
|
236
255
|
|
|
237
|
-
|
|
256
|
+
### Multiple commands separated by `--`
|
|
238
257
|
```
|
|
239
258
|
$ mpytool cp main.py boot.py : -- reset -- monitor
|
|
240
259
|
$ mpytool rm :old.py -- cp new.py : -- reset
|
|
241
260
|
```
|
|
242
261
|
|
|
243
|
-
|
|
262
|
+
### Auto-detect serial port (if only one device is connected)
|
|
244
263
|
```
|
|
245
264
|
$ mpytool ls lib/
|
|
246
265
|
uhttp/
|
|
@@ -248,7 +267,7 @@ $ mpytool ls lib/
|
|
|
248
267
|
4.95 KB wlan_http.py
|
|
249
268
|
```
|
|
250
269
|
|
|
251
|
-
|
|
270
|
+
### Tree view
|
|
252
271
|
```
|
|
253
272
|
$ mpytool tree
|
|
254
273
|
142 KB ./
|
|
@@ -266,18 +285,18 @@ $ mpytool tree
|
|
|
266
285
|
3.03 KB └─ main.py
|
|
267
286
|
```
|
|
268
287
|
|
|
269
|
-
|
|
288
|
+
### Connect over network (TCP, default port 23)
|
|
270
289
|
```
|
|
271
290
|
$ mpytool -a 192.168.1.100 ls
|
|
272
291
|
$ mpytool -a 192.168.1.100:8266 tree
|
|
273
292
|
```
|
|
274
293
|
|
|
275
|
-
|
|
294
|
+
### Set baudrate (default 115200)
|
|
276
295
|
```
|
|
277
296
|
$ mpytool -p /dev/ttyACM0 -b 9600 ls
|
|
278
297
|
```
|
|
279
298
|
|
|
280
|
-
|
|
299
|
+
### Show version
|
|
281
300
|
```
|
|
282
301
|
$ mpytool -V
|
|
283
302
|
```
|
|
@@ -60,25 +60,25 @@ Then restart your shell (`exec zsh` or `exec bash`) and use `mpytool` directly.
|
|
|
60
60
|
|
|
61
61
|
Adding venv bin at the end of PATH keeps your system `python` and `pip` as default, while making `mpytool` available when not found elsewhere.
|
|
62
62
|
|
|
63
|
-
## Examples
|
|
63
|
+
## Examples
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
### Help
|
|
66
66
|
```
|
|
67
67
|
$ mpytool --help
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
### List files
|
|
71
71
|
```
|
|
72
72
|
$ mpytool -p /dev/ttyACM0 ls # list CWD (default)
|
|
73
73
|
$ mpytool -p /dev/ttyACM0 ls :/lib # list /lib
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
### Tree
|
|
77
77
|
```
|
|
78
78
|
$ mpytool -p /dev/ttyACM0 tree # tree of CWD (default)
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
### Copy files (: prefix = device path)
|
|
82
82
|
```
|
|
83
83
|
$ mpytool cp main.py :/ # upload file to device root
|
|
84
84
|
$ mpytool cp main.py lib.py :/lib/ # upload multiple files to directory
|
|
@@ -95,7 +95,7 @@ Path semantics: `:` = device CWD, `:/` = device root. Trailing `/` on source = c
|
|
|
95
95
|
Unchanged files are automatically skipped (compares size and SHA256 hash).
|
|
96
96
|
Use `-f` or `--force` to upload all files regardless.
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
### Transfer options
|
|
99
99
|
```
|
|
100
100
|
$ mpytool cp -z main.py :/ # force compression (auto-detected by default)
|
|
101
101
|
$ mpytool cp --no-compress data.bin :/ # disable compression
|
|
@@ -105,20 +105,20 @@ $ mpytool -c 8K cp main.py :/ # set chunk size (512, 1K, 2K, 4K, 8K, 16K,
|
|
|
105
105
|
Compression is auto-detected based on device RAM and deflate module availability.
|
|
106
106
|
Chunk size is auto-detected based on free RAM (larger chunks = faster transfer).
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
### Move/rename on device
|
|
109
109
|
```
|
|
110
110
|
$ mpytool mv :/old.py :/new.py # rename file
|
|
111
111
|
$ mpytool mv :/file.py :/lib/ # move file to directory
|
|
112
112
|
$ mpytool mv :/a.py :/b.py :/lib/ # move multiple files to directory
|
|
113
113
|
```
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
### View file contents
|
|
116
116
|
```
|
|
117
117
|
$ mpytool cat :boot.py # print file from CWD
|
|
118
118
|
$ mpytool cat :/lib/module.py # print file with absolute path
|
|
119
119
|
```
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
### Make directory, delete files (: prefix = device path)
|
|
122
122
|
```
|
|
123
123
|
$ mpytool mkdir :lib :data # create directories in CWD
|
|
124
124
|
$ mpytool mkdir :/lib/subdir # create with absolute path
|
|
@@ -129,7 +129,7 @@ $ mpytool rm : # delete everything in CWD
|
|
|
129
129
|
$ mpytool rm :/ # delete everything on device (root)
|
|
130
130
|
```
|
|
131
131
|
|
|
132
|
-
|
|
132
|
+
### Current working directory
|
|
133
133
|
```
|
|
134
134
|
$ mpytool pwd # print current directory
|
|
135
135
|
/
|
|
@@ -139,7 +139,7 @@ $ mpytool cd :.. # change to parent directory
|
|
|
139
139
|
$ mpytool cd :/lib -- ls # change directory and list files
|
|
140
140
|
```
|
|
141
141
|
|
|
142
|
-
|
|
142
|
+
### Reset and REPL
|
|
143
143
|
```
|
|
144
144
|
$ mpytool reset # soft reset (Ctrl-D, runs boot.py/main.py)
|
|
145
145
|
$ mpytool reset --raw # soft reset in raw REPL (clears RAM only)
|
|
@@ -153,7 +153,7 @@ $ mpytool repl # enter REPL mode
|
|
|
153
153
|
$ mpytool sleep 2 # sleep for 2 seconds (useful between commands)
|
|
154
154
|
```
|
|
155
155
|
|
|
156
|
-
|
|
156
|
+
### Serial terminal and monitor (general purpose)
|
|
157
157
|
```
|
|
158
158
|
$ mpytool repl # auto-detect port, 115200 baud
|
|
159
159
|
$ mpytool -p /dev/ttyUSB0 repl # specify port
|
|
@@ -163,13 +163,32 @@ $ mpytool -p /dev/ttyUSB0 -b 9600 monitor # monitor at 9600 baud
|
|
|
163
163
|
|
|
164
164
|
Both `repl` and `monitor` can be used as general-purpose serial tools - not just for MicroPython devices. Use them to interact with any serial device (Arduino, ESP with custom firmware, GPS modules, etc.). When only one serial port is detected, it is used automatically. Default baudrate is 115200.
|
|
165
165
|
|
|
166
|
-
|
|
166
|
+
### Execute Python code on device
|
|
167
167
|
```
|
|
168
168
|
$ mpytool exec "print('Hello!')"
|
|
169
169
|
$ mpytool exec "import sys; print(sys.version)"
|
|
170
170
|
```
|
|
171
171
|
|
|
172
|
-
|
|
172
|
+
### Run local Python file on device
|
|
173
|
+
```
|
|
174
|
+
$ mpytool run script.py # run script (fire-and-forget)
|
|
175
|
+
$ mpytool run script.py -- monitor # run script and capture output
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Serial link speed test
|
|
179
|
+
```
|
|
180
|
+
$ mpytool speedtest
|
|
181
|
+
SPEEDTEST
|
|
182
|
+
upload download verify
|
|
183
|
+
0B - - ok
|
|
184
|
+
16B 11.8K/s 24.4K/s ok
|
|
185
|
+
32B 13.1K/s 42.6K/s ok
|
|
186
|
+
...
|
|
187
|
+
4.00K 120K/s 11.1K/s ok
|
|
188
|
+
8.00K 157K/s 11.0K/s ok
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Show device information
|
|
173
192
|
```
|
|
174
193
|
$ mpytool info
|
|
175
194
|
Platform: rp2
|
|
@@ -187,7 +206,7 @@ MAC WiFi: aa:bb:cc:dd:ee:01
|
|
|
187
206
|
MAC WiFi AP: aa:bb:cc:dd:ee:02
|
|
188
207
|
```
|
|
189
208
|
|
|
190
|
-
|
|
209
|
+
### Flash operations (RP2 and ESP32)
|
|
191
210
|
```
|
|
192
211
|
# RP2 - user flash (entire filesystem area)
|
|
193
212
|
$ mpytool flash # show flash info and filesystem type
|
|
@@ -213,20 +232,20 @@ $ mpytool flash erase vfs # quick erase partition
|
|
|
213
232
|
$ mpytool flash erase vfs --full # full erase partition
|
|
214
233
|
```
|
|
215
234
|
|
|
216
|
-
OTA firmware update (ESP32)
|
|
235
|
+
### OTA firmware update (ESP32)
|
|
217
236
|
```
|
|
218
237
|
$ mpytool ota firmware.app-bin # flash to next OTA partition
|
|
219
238
|
$ mpytool ota firmware.app-bin -- reset --machine # flash and reboot
|
|
220
239
|
$ mpytool ota firmware.app-bin -- reset --machine -t 30 # flash and reboot with 30s timeout
|
|
221
240
|
```
|
|
222
241
|
|
|
223
|
-
|
|
242
|
+
### Multiple commands separated by `--`
|
|
224
243
|
```
|
|
225
244
|
$ mpytool cp main.py boot.py : -- reset -- monitor
|
|
226
245
|
$ mpytool rm :old.py -- cp new.py : -- reset
|
|
227
246
|
```
|
|
228
247
|
|
|
229
|
-
|
|
248
|
+
### Auto-detect serial port (if only one device is connected)
|
|
230
249
|
```
|
|
231
250
|
$ mpytool ls lib/
|
|
232
251
|
uhttp/
|
|
@@ -234,7 +253,7 @@ $ mpytool ls lib/
|
|
|
234
253
|
4.95 KB wlan_http.py
|
|
235
254
|
```
|
|
236
255
|
|
|
237
|
-
|
|
256
|
+
### Tree view
|
|
238
257
|
```
|
|
239
258
|
$ mpytool tree
|
|
240
259
|
142 KB ./
|
|
@@ -252,18 +271,18 @@ $ mpytool tree
|
|
|
252
271
|
3.03 KB └─ main.py
|
|
253
272
|
```
|
|
254
273
|
|
|
255
|
-
|
|
274
|
+
### Connect over network (TCP, default port 23)
|
|
256
275
|
```
|
|
257
276
|
$ mpytool -a 192.168.1.100 ls
|
|
258
277
|
$ mpytool -a 192.168.1.100:8266 tree
|
|
259
278
|
```
|
|
260
279
|
|
|
261
|
-
|
|
280
|
+
### Set baudrate (default 115200)
|
|
262
281
|
```
|
|
263
282
|
$ mpytool -p /dev/ttyACM0 -b 9600 ls
|
|
264
283
|
```
|
|
265
284
|
|
|
266
|
-
|
|
285
|
+
### Show version
|
|
267
286
|
```
|
|
268
287
|
$ mpytool -V
|
|
269
288
|
```
|
|
@@ -5,6 +5,9 @@ import zlib
|
|
|
5
5
|
|
|
6
6
|
import mpytool.mpy_comm as _mpy_comm
|
|
7
7
|
|
|
8
|
+
# Timeout for flash I/O operations (open/close/gc) - some FLASH GC can block >5s
|
|
9
|
+
FLASH_IO_TIMEOUT = 20
|
|
10
|
+
|
|
8
11
|
|
|
9
12
|
def _escape_path(path: str) -> str:
|
|
10
13
|
"""Escape path for use in Python string literal"""
|
|
@@ -515,7 +518,7 @@ def _mt_pfind(label):
|
|
|
515
518
|
self.import_module('deflate as df')
|
|
516
519
|
self.import_module('io as _io')
|
|
517
520
|
|
|
518
|
-
self._mpy_comm.exec(f"f = open('{_escape_path(path)}', 'wb')")
|
|
521
|
+
self._mpy_comm.exec(f"f = open('{_escape_path(path)}', 'wb')", timeout=FLASH_IO_TIMEOUT)
|
|
519
522
|
while data:
|
|
520
523
|
chunk = data[:chunk_size]
|
|
521
524
|
cmd, orig_size, enc_type = self._encode_chunk(chunk, compress)
|
|
@@ -527,10 +530,10 @@ def _mt_pfind(label):
|
|
|
527
530
|
transferred += orig_size
|
|
528
531
|
if progress_callback:
|
|
529
532
|
progress_callback(transferred, total_size)
|
|
530
|
-
self._mpy_comm.exec("f.close()")
|
|
533
|
+
self._mpy_comm.exec("f.close()", timeout=FLASH_IO_TIMEOUT)
|
|
531
534
|
# Run garbage collection to free memory and allow flash to settle
|
|
532
535
|
self.import_module('gc')
|
|
533
|
-
self._mpy_comm.exec("gc.collect()")
|
|
536
|
+
self._mpy_comm.exec("gc.collect()", timeout=FLASH_IO_TIMEOUT)
|
|
534
537
|
return encodings_used, wire_bytes
|
|
535
538
|
|
|
536
539
|
def platform(self):
|
|
@@ -540,15 +543,20 @@ def _mt_pfind(label):
|
|
|
540
543
|
dict with keys:
|
|
541
544
|
'platform': platform name (e.g. 'esp32')
|
|
542
545
|
'version': MicroPython version string
|
|
543
|
-
'
|
|
546
|
+
'impl_name': implementation name (e.g. 'micropython')
|
|
547
|
+
'impl_version': implementation version tuple (e.g. (1, 24, 0))
|
|
544
548
|
'machine': machine description (or None)
|
|
549
|
+
'mpy_ver': mpy bytecode major version (e.g. 6) or None
|
|
550
|
+
'mpy_sub': mpy bytecode sub-version (e.g. 3) or None
|
|
545
551
|
"""
|
|
546
552
|
self.import_module('sys')
|
|
547
553
|
self.import_module('os')
|
|
548
554
|
|
|
549
555
|
platform = self._mpy_comm.exec_eval("repr(sys.platform)")
|
|
550
556
|
version = self._mpy_comm.exec_eval("repr(sys.version)")
|
|
551
|
-
|
|
557
|
+
impl_name = self._mpy_comm.exec_eval("repr(sys.implementation.name)")
|
|
558
|
+
impl_version = self._mpy_comm.exec_eval(
|
|
559
|
+
"tuple(sys.implementation.version)")
|
|
552
560
|
|
|
553
561
|
try:
|
|
554
562
|
uname = self._mpy_comm.exec_eval("tuple(os.uname())")
|
|
@@ -556,11 +564,22 @@ def _mt_pfind(label):
|
|
|
556
564
|
except _mpy_comm.CmdError:
|
|
557
565
|
machine = None
|
|
558
566
|
|
|
567
|
+
try:
|
|
568
|
+
mpy_int = self._mpy_comm.exec_eval("sys.implementation._mpy")
|
|
569
|
+
mpy_ver = mpy_int & 0xFF
|
|
570
|
+
mpy_sub = (mpy_int >> 8) & 3
|
|
571
|
+
except (_mpy_comm.CmdError, AttributeError):
|
|
572
|
+
mpy_ver = None
|
|
573
|
+
mpy_sub = None
|
|
574
|
+
|
|
559
575
|
return {
|
|
560
576
|
'platform': platform,
|
|
561
577
|
'version': version,
|
|
562
|
-
'
|
|
578
|
+
'impl_name': impl_name,
|
|
579
|
+
'impl_version': impl_version,
|
|
563
580
|
'machine': machine,
|
|
581
|
+
'mpy_ver': mpy_ver,
|
|
582
|
+
'mpy_sub': mpy_sub,
|
|
564
583
|
}
|
|
565
584
|
|
|
566
585
|
def memory(self):
|
|
@@ -174,7 +174,8 @@ class MpyComm():
|
|
|
174
174
|
|
|
175
175
|
Arguments:
|
|
176
176
|
command: command to execute
|
|
177
|
-
timeout: maximum waiting time for result
|
|
177
|
+
timeout: maximum waiting time for result,
|
|
178
|
+
0 = submit only (send code, don't wait for output)
|
|
178
179
|
|
|
179
180
|
Returns:
|
|
180
181
|
command STDOUT result
|
|
@@ -182,12 +183,16 @@ class MpyComm():
|
|
|
182
183
|
Raises:
|
|
183
184
|
CmdError when command return error
|
|
184
185
|
"""
|
|
186
|
+
send_timeout = 5 if timeout == 0 else timeout
|
|
185
187
|
self.enter_raw_repl()
|
|
186
188
|
if self._log:
|
|
187
189
|
self._log.info("CMD: %s", command)
|
|
188
190
|
self._conn.write(bytes(command, 'utf-8'))
|
|
189
191
|
self._conn.write(CTRL_D)
|
|
190
|
-
self._conn.read_until(b'OK',
|
|
192
|
+
self._conn.read_until(b'OK', send_timeout)
|
|
193
|
+
if timeout == 0:
|
|
194
|
+
self._repl_mode = False
|
|
195
|
+
return b''
|
|
191
196
|
result = self._conn.read_until(CTRL_D, timeout)
|
|
192
197
|
if result:
|
|
193
198
|
if self._log:
|
|
@@ -209,7 +214,8 @@ class MpyComm():
|
|
|
209
214
|
|
|
210
215
|
Arguments:
|
|
211
216
|
command: command to execute (str or bytes)
|
|
212
|
-
timeout: maximum waiting time for result
|
|
217
|
+
timeout: maximum waiting time for result,
|
|
218
|
+
0 = submit only (send code, don't wait for output)
|
|
213
219
|
|
|
214
220
|
Returns:
|
|
215
221
|
command STDOUT result
|
|
@@ -218,6 +224,7 @@ class MpyComm():
|
|
|
218
224
|
CmdError when command returns error
|
|
219
225
|
MpyError when raw-paste mode is not supported
|
|
220
226
|
"""
|
|
227
|
+
send_timeout = 5 if timeout == 0 else timeout
|
|
221
228
|
self.enter_raw_repl()
|
|
222
229
|
|
|
223
230
|
if isinstance(command, str):
|
|
@@ -229,7 +236,7 @@ class MpyComm():
|
|
|
229
236
|
self._conn.write(RAW_PASTE_ENTER)
|
|
230
237
|
|
|
231
238
|
# Read response: 'R' + status (0=not supported, 1=supported)
|
|
232
|
-
header, status = self._conn.read_bytes(2,
|
|
239
|
+
header, status = self._conn.read_bytes(2, send_timeout)
|
|
233
240
|
if header != ord('R'):
|
|
234
241
|
raise MpyError(f"Unexpected raw-paste header: {header!r}")
|
|
235
242
|
|
|
@@ -243,7 +250,7 @@ class MpyComm():
|
|
|
243
250
|
self._raw_paste_supported = True
|
|
244
251
|
|
|
245
252
|
# Read window size (16-bit little-endian)
|
|
246
|
-
window_bytes = self._conn.read_bytes(2,
|
|
253
|
+
window_bytes = self._conn.read_bytes(2, send_timeout)
|
|
247
254
|
window_size = int.from_bytes(window_bytes, 'little')
|
|
248
255
|
if self._log:
|
|
249
256
|
self._log.info("Raw-paste window size: %d", window_size)
|
|
@@ -255,7 +262,7 @@ class MpyComm():
|
|
|
255
262
|
while offset < len(command):
|
|
256
263
|
# Check for incoming flow control byte (non-blocking)
|
|
257
264
|
if remaining_window == 0 or self._conn._has_data(0):
|
|
258
|
-
flow_byte = self._conn.read_bytes(1,
|
|
265
|
+
flow_byte = self._conn.read_bytes(1, send_timeout)
|
|
259
266
|
if flow_byte == RAW_PASTE_ACK:
|
|
260
267
|
remaining_window += window_size
|
|
261
268
|
elif flow_byte == CTRL_D:
|
|
@@ -274,10 +281,14 @@ class MpyComm():
|
|
|
274
281
|
|
|
275
282
|
# Consume remaining ACKs and wait for CTRL_D echo
|
|
276
283
|
while True:
|
|
277
|
-
byte = self._conn.read_bytes(1,
|
|
284
|
+
byte = self._conn.read_bytes(1, send_timeout)
|
|
278
285
|
if byte == CTRL_D:
|
|
279
286
|
break
|
|
280
287
|
|
|
288
|
+
if timeout == 0:
|
|
289
|
+
self._repl_mode = False
|
|
290
|
+
return b''
|
|
291
|
+
|
|
281
292
|
result = self._conn.read_until(CTRL_D, timeout)
|
|
282
293
|
if result and self._log:
|
|
283
294
|
self._log.info('RES: %s', bytes(result))
|