mpytool 2.2.4__tar.gz → 2.3.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. {mpytool-2.2.4 → mpytool-2.3.1}/PKG-INFO +269 -41
  2. {mpytool-2.2.4 → mpytool-2.3.1}/README.md +268 -40
  3. {mpytool-2.2.4 → mpytool-2.3.1}/mpytool/__init__.py +1 -1
  4. mpytool-2.3.1/mpytool/cmd_cp.py +844 -0
  5. {mpytool-2.2.4 → mpytool-2.3.1}/mpytool/conn.py +99 -13
  6. {mpytool-2.2.4 → mpytool-2.3.1}/mpytool/conn_serial.py +6 -1
  7. {mpytool-2.2.4 → mpytool-2.3.1}/mpytool/conn_socket.py +14 -1
  8. {mpytool-2.2.4 → mpytool-2.3.1}/mpytool/logger.py +27 -6
  9. mpytool-2.3.1/mpytool/mount.py +1147 -0
  10. {mpytool-2.2.4 → mpytool-2.3.1}/mpytool/mpy.py +318 -37
  11. {mpytool-2.2.4 → mpytool-2.3.1}/mpytool/mpy_comm.py +111 -56
  12. {mpytool-2.2.4 → mpytool-2.3.1}/mpytool/mpy_cross.py +21 -3
  13. mpytool-2.3.1/mpytool/mpytool.py +1552 -0
  14. {mpytool-2.2.4 → mpytool-2.3.1}/mpytool/terminal.py +6 -6
  15. {mpytool-2.2.4 → mpytool-2.3.1}/mpytool/terminal_unix.py +0 -2
  16. {mpytool-2.2.4 → mpytool-2.3.1}/mpytool/utils.py +6 -7
  17. {mpytool-2.2.4 → mpytool-2.3.1}/mpytool.egg-info/PKG-INFO +269 -41
  18. {mpytool-2.2.4 → mpytool-2.3.1}/mpytool.egg-info/SOURCES.txt +4 -0
  19. {mpytool-2.2.4 → mpytool-2.3.1}/pyproject.toml +1 -1
  20. mpytool-2.2.4/tests/test_mpytool.py → mpytool-2.3.1/tests/test_cmd_cp.py +144 -523
  21. {mpytool-2.2.4 → mpytool-2.3.1}/tests/test_integration.py +1187 -7
  22. mpytool-2.3.1/tests/test_mount.py +2062 -0
  23. {mpytool-2.2.4 → mpytool-2.3.1}/tests/test_mpy.py +86 -30
  24. mpytool-2.3.1/tests/test_mpytool.py +966 -0
  25. mpytool-2.2.4/mpytool/mpytool.py +0 -1639
  26. {mpytool-2.2.4 → mpytool-2.3.1}/LICENSE +0 -0
  27. {mpytool-2.2.4 → mpytool-2.3.1}/mpytool/speedtest.py +0 -0
  28. {mpytool-2.2.4 → mpytool-2.3.1}/mpytool/terminal_win.py +0 -0
  29. {mpytool-2.2.4 → mpytool-2.3.1}/mpytool.egg-info/dependency_links.txt +0 -0
  30. {mpytool-2.2.4 → mpytool-2.3.1}/mpytool.egg-info/entry_points.txt +0 -0
  31. {mpytool-2.2.4 → mpytool-2.3.1}/mpytool.egg-info/requires.txt +0 -0
  32. {mpytool-2.2.4 → mpytool-2.3.1}/mpytool.egg-info/top_level.txt +0 -0
  33. {mpytool-2.2.4 → mpytool-2.3.1}/setup.cfg +0 -0
  34. {mpytool-2.2.4 → mpytool-2.3.1}/tests/test_errors.py +0 -0
  35. {mpytool-2.2.4 → mpytool-2.3.1}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mpytool
3
- Version: 2.2.4
3
+ Version: 2.3.1
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
@@ -20,16 +20,31 @@ It is an alternative to the official [mpremote](https://docs.micropython.org/en/
20
20
 
21
21
  ## Features
22
22
 
23
- - **Fast file transfers** - optimized chunked transfer with automatic compression
24
- - **Skip unchanged files** - compares size + SHA256 hash, re-upload in <1s
25
- - **Auto-detect serial port** - no need to specify `-p` when only one device connected
26
- - **Robust REPL handling** - works reliably with USB-UART bridges (CP2102, CH340)
27
- - **Multiple reset options** - soft, MCU, hardware (RTS), bootloader entry
28
- - **General-purpose serial terminal** - `repl` and `monitor` work with any serial device
23
+ - **Fast file transfers** - optimized chunked transfer with
24
+ automatic compression
25
+ - **Skip unchanged files** - compares size + SHA256 hash,
26
+ re-upload in <1s
27
+ - **Auto-detect serial port** - no need to specify `-p` when only
28
+ one device connected
29
+ - **Robust REPL handling** - works reliably with USB-UART bridges
30
+ (CP2102, CH340)
31
+ - **Multiple reset options** - soft, MCU, hardware (RTS),
32
+ bootloader entry
33
+ - **General-purpose serial terminal** - `repl` and `monitor` work
34
+ with any serial device
35
+ - **Mount local directory** - VFS mount (read-only or read-write)
36
+ for development without uploading to flash, with transparent
37
+ `.mpy` compilation and auto-remount after soft reset
38
+ - **Virtual submounts** - `ln` links files/directories into
39
+ mounted VFS (PC-side only, no device changes)
29
40
  - **Python API** - suitable for IDE integration and automation
30
- - **Raw-paste mode** - flow-controlled code execution with reduced RAM usage (API)
41
+ - **Raw-paste mode** - flow-controlled code execution with reduced
42
+ RAM usage (API)
31
43
  - **Shell completion** - ZSH and Bash with remote path completion
32
44
  - **Network support** - connect over TCP
45
+ - **Full Unicode support** - handles Unicode in file names and content
46
+
47
+ See [README_mpremote.md](README_mpremote.md) for detailed comparison with mpremote.
33
48
 
34
49
  ## Installation
35
50
 
@@ -83,13 +98,34 @@ $ mpytool --help
83
98
 
84
99
  ### List files
85
100
  ```
86
- $ mpytool -p /dev/ttyACM0 ls # list CWD (default)
87
- $ mpytool -p /dev/ttyACM0 ls :/lib # list /lib
101
+ $ mpytool -p /dev/ttyACM0 ls # Linux: list CWD (default)
102
+ LS: /
103
+ 215B boot.py
104
+ 3.03K main.py
105
+ lib/
106
+
107
+ $ mpytool ls :/lib # list /lib (auto-detect port)
108
+ LS: /lib
109
+ uhttp/
110
+ 23.1K wlan.py
111
+
112
+ $ mpytool ls :/data # Unicode file names supported
113
+ LS: /data
114
+ 64B データ.csv
115
+ 32B 🍅.py
116
+ 128B súbor.txt
117
+ 256B 配置.json
88
118
  ```
89
119
 
90
120
  ### Tree
91
121
  ```
92
- $ mpytool -p /dev/ttyACM0 tree # tree of CWD (default)
122
+ $ mpytool -p /dev/cu.usbmodem1101 tree # macOS: tree of CWD
123
+ TREE: /
124
+ 142K ./
125
+ 97.7K ├─ lib/
126
+ 69.6K │ └─ uhttp/
127
+ 23 ├─ boot.py
128
+ 3.03K └─ main.py
93
129
  ```
94
130
 
95
131
  ### Copy files (: prefix = device path)
@@ -139,66 +175,255 @@ $ mpytool mv :/a.py :/b.py :/lib/ # move multiple files to directory
139
175
  ### View file contents
140
176
  ```
141
177
  $ mpytool cat :boot.py # print file from CWD
178
+ CAT: /boot.py
179
+ import machine
180
+ ...
181
+
142
182
  $ mpytool cat :/lib/module.py # print file with absolute path
183
+ CAT: /lib/module.py
184
+ def hello():
185
+ print("Hello!")
143
186
  ```
144
187
 
145
188
  ### Make directory, delete files (: prefix = device path)
146
189
  ```
147
190
  $ mpytool mkdir :lib :data # create directories in CWD
191
+ MKDIR: /lib
192
+ MKDIR: /data
193
+
148
194
  $ mpytool mkdir :/lib/subdir # create with absolute path
195
+ MKDIR: /lib/subdir
196
+
149
197
  $ mpytool rm :old.py # delete file in CWD
198
+ RM: /old.py
199
+
150
200
  $ mpytool rm :mydir # delete directory and contents
201
+ RM: /mydir
202
+
151
203
  $ mpytool rm :mydir/ # delete contents only, keep directory
152
- $ mpytool rm : # delete everything in CWD
153
- $ mpytool rm :/ # delete everything on device (root)
204
+ RM contents: /mydir
154
205
  ```
155
206
 
156
207
  ### Current working directory
157
208
  ```
158
209
  $ mpytool pwd # print current directory
210
+ PWD
159
211
  /
212
+
160
213
  $ mpytool cd :/lib # change to /lib
214
+ CD: /lib
215
+
161
216
  $ mpytool cd :subdir # change to relative path (from CWD)
162
- $ mpytool cd :.. # change to parent directory
217
+ CD: /lib/subdir
218
+
163
219
  $ mpytool cd :/lib -- ls # change directory and list files
220
+ CD: /lib
221
+ LS: /lib
222
+ uhttp/
223
+ 23.1K wlan.py
224
+ ```
225
+
226
+ ### Module search path (sys.path)
227
+ ```
228
+ $ mpytool path # show current sys.path
229
+ : :/lib
230
+
231
+ $ mpytool path : :/lib # replace entire sys.path
232
+ PATH set to 2 entries
233
+
234
+ $ mpytool path -f :/custom # prepend to sys.path (remove duplicates)
235
+ PATH prepended 1 entries
236
+
237
+ $ mpytool path -a :/sdcard/lib # append to sys.path (remove duplicates)
238
+ PATH appended 1 entries
239
+
240
+ $ mpytool path -d :/custom # delete from sys.path
241
+ PATH removed 1 entries
164
242
  ```
165
243
 
166
- ### Reset and REPL
244
+ Path semantics: `:` = empty string (CWD) in sys.path, `:/` = root directory. The `-f` and `-a` flags automatically remove duplicates (move existing paths to new position).
245
+
246
+ ### Stop, reset and REPL
167
247
  ```
248
+ $ mpytool stop # stop running program (Ctrl-C)
249
+ STOP
250
+
168
251
  $ mpytool reset # soft reset (Ctrl-D, runs boot.py/main.py)
169
- $ mpytool reset --raw # soft reset in raw REPL (clears RAM only)
252
+ RESET soft
253
+
170
254
  $ mpytool reset --machine # MCU reset (machine.reset, auto-reconnect)
171
- $ mpytool reset --machine -t 30 # MCU reset with 30s reconnect timeout
172
- $ mpytool reset --rts # hardware reset via RTS signal (serial only)
173
- $ mpytool reset --boot # enter bootloader (machine.bootloader)
174
- $ mpytool reset --dtr-boot # enter bootloader via DTR/RTS (ESP32 only)
255
+ RESET machine
256
+
175
257
  $ mpytool reset -- monitor # reset and monitor output
258
+ RESET soft
259
+ MONITOR (Ctrl+C to stop)
260
+
176
261
  $ mpytool repl # enter REPL mode
262
+ REPL (Ctrl+] to exit)
263
+
177
264
  $ mpytool sleep 2 # sleep for 2 seconds (useful between commands)
265
+ SLEEP 2.0s
178
266
  ```
179
267
 
180
268
  ### Serial terminal and monitor (general purpose)
181
269
  ```
182
270
  $ mpytool repl # auto-detect port, 115200 baud
271
+ REPL (Ctrl+] to exit)
272
+
273
+ $ mpytool -v repl # verbose: shows CWD and sys.path before REPL
274
+ REPL (Ctrl+] to exit) CWD: / PATH: : :.frozen :/lib
275
+
183
276
  $ mpytool -p /dev/ttyUSB0 repl # specify port
184
277
  $ mpytool -b 9600 repl # specify baudrate
185
278
  $ mpytool -p /dev/ttyUSB0 -b 9600 monitor # monitor at 9600 baud
186
279
  ```
187
280
 
281
+ The `repl` command with `-v` flag displays current working directory (CWD) and `sys.path` before entering REPL, making it easy to see the device state after `mount`, `cd`, or `path` commands.
282
+
188
283
  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.
189
284
 
190
285
  ### Execute Python code on device
191
286
  ```
192
287
  $ mpytool exec "print('Hello!')"
288
+ EXEC: print('Hello!')
289
+ Hello!
290
+
193
291
  $ mpytool exec "import sys; print(sys.version)"
292
+ EXEC: import sys; print(sys.version)
293
+ 3.4.0; MicroPython v1.24.0
194
294
  ```
195
295
 
196
296
  ### Run local Python file on device
197
297
  ```
198
298
  $ mpytool run script.py # run script (fire-and-forget)
299
+ RUN: script.py (128 bytes)
300
+
199
301
  $ mpytool run script.py -- monitor # run script and capture output
302
+ RUN: script.py (128 bytes)
303
+ MONITOR (Ctrl+C to stop)
304
+ Hello from script!
200
305
  ```
201
306
 
307
+ ### Edit file on device
308
+ ```
309
+ $ mpytool edit :boot.py # edit file (uses $VISUAL or $EDITOR)
310
+ EDIT: /boot.py
311
+
312
+ $ mpytool edit :/lib/config.py # absolute path
313
+ EDIT: /lib/config.py
314
+
315
+ $ mpytool edit :newfile.py # create new file if doesn't exist
316
+ EDIT: /newfile.py (new file)
317
+ ```
318
+
319
+ Downloads file to a temp file, opens in editor, uploads back if changed.
320
+ Editor priority: `--editor` > `$VISUAL` > `$EDITOR` > error.
321
+
322
+ ### Device RTC (real-time clock)
323
+ ```
324
+ $ mpytool rtc # display current RTC
325
+ RTC
326
+ 2026-02-21 15:30:45
327
+
328
+ $ mpytool rtc --set # set RTC to local PC time
329
+ RTC set to 2026-02-21 15:30:45 (local)
330
+
331
+ $ mpytool rtc --utc # set RTC to UTC time
332
+ RTC set to 2026-02-21 14:30:45 (UTC)
333
+
334
+ $ mpytool rtc "2026-02-21 14:30:00" # set RTC to specific datetime
335
+ RTC set to 2026-02-21 14:30:00
336
+ ```
337
+
338
+ Flags: `-s`/`--set` and `-l`/`--local` both set local time, `-u`/`--utc` sets UTC.
339
+ Manual datetime format: `YYYY-MM-DD HH:MM:SS`.
340
+
341
+ ### Mount local directory on device
342
+ ```
343
+ $ mpytool mount ./src # mount ./src as /remote, auto-start REPL
344
+ Mounted ./src on /remote (readonly)
345
+ Changed CWD to /remote
346
+ REPL (Ctrl+] to exit)
347
+
348
+ $ mpytool -v mount ./src :/app # mount as /app instead of /remote (verbose)
349
+ Mounted ./src on /app (readonly)
350
+ Changed CWD to /app
351
+ REPL (Ctrl+] to exit) CWD: /app PATH: : :.frozen :/lib
352
+
353
+ $ mpytool mount -m ./src :/app # mount with automatic .mpy compilation
354
+ Mounted ./src on /app (readonly, .mpy compilation)
355
+ Changed CWD to /app
356
+ >>> import foo # imports /app/foo.mpy (compiled from ./src/foo.py)
357
+
358
+ $ mpytool mount -w ./workspace :/work # mount as read-write (can create/modify/delete files)
359
+ Mounted ./workspace on /work (read-write)
360
+ Changed CWD to /work
361
+ >>> f = open('/work/test.txt', 'w'); f.write('hello'); f.close() # creates local file
362
+ >>> import os; os.mkdir('/work/newdir') # creates local directory
363
+
364
+ $ mpytool mount ./src -- exec "import main" # mount and run code
365
+ $ mpytool mount ./src -- monitor # mount and monitor output
366
+ $ mpytool mount ./app :/app -- mount ./lib :/lib -- repl # multiple mounts (CWD = /app)
367
+ Mounted ./app on /app (readonly)
368
+ Changed CWD to /app
369
+ Mounted ./lib on /lib (readonly)
370
+ ```
371
+
372
+ Mounts a local directory on the device as a VFS. The device can read,
373
+ import and execute files from the local directory without uploading
374
+ them to flash. Changes to local files are immediately visible on
375
+ the device.
376
+
377
+ **Memory overhead:** The VFS agent uses ~4.2KB of RAM on the device
378
+ (154 lines of MicroPython code injected during mount).
379
+
380
+ **By default, mounts are read-only.** Use `-w` / `--writable` flag
381
+ to enable write support — the device can create, modify and delete
382
+ files in the mounted directory. All changes are written directly to
383
+ the local filesystem.
384
+
385
+ **`-m` / `--mpy` flag:** Enables transparent `.mpy` compilation.
386
+ When the device imports a module, the `.py` file is automatically
387
+ compiled to `.mpy` bytecode on-demand and served from cache
388
+ (`__pycache__/`). Benefits: faster imports, less RAM usage, support
389
+ for `@native`/`@viper` code with `-march`. Boot files (`boot.py`,
390
+ `main.py`) and empty files remain as `.py`. If compilation fails,
391
+ automatically falls back to `.py`. Prebuilt `.mpy` files have
392
+ priority over cache.
393
+
394
+ The first mount automatically changes CWD to the mount point (mpremote
395
+ compatibility). Subsequent mounts do not change CWD. Use `cd` command
396
+ to change working directory manually if needed. Multiple independent
397
+ (non-nested) mounts are supported.
398
+
399
+ After mount, mpytool automatically enters REPL (unless `monitor` or
400
+ `repl` follows). In REPL you can import modules from the mounted
401
+ directory, Ctrl+D triggers soft reset with automatic re-mount and CWD
402
+ restoration to the mount point.
403
+
404
+ **Best for:** Development, testing, prototyping, debugging. For bulk
405
+ file transfers (uploading/downloading many files), use `cp` command
406
+ instead — it's optimized for throughput.
407
+
408
+ **Security:** Paths are validated to prevent traversal outside mount
409
+ root. Symlinks are followed and checked. Write operations require
410
+ explicit `-w` flag.
411
+
412
+ See [Mount VFS Comparison](README_mpremote.md#mount-vfs-comparison) for detailed comparison with mpremote.
413
+
414
+ ### Link files into mounted VFS
415
+ ```
416
+ $ mpytool mount ./app :/ -- ln ./drivers :/lib/ -- repl # mount app, link drivers into /lib/
417
+ $ mpytool mount ./app :/ -- ln ./extra.py :/lib/ -- repl # link single file into /lib/
418
+ $ mpytool mount ./app :/ -- ln ./pkg :/lib/pkg -- repl # link as specific name
419
+ $ mpytool mount ./app :/ -- ln ./pkg/ :/lib/ -- repl # link package contents into /lib/
420
+ $ mpytool mount ./app :/ -- ln ./a.py ./b.py :/lib/ -- repl # link multiple sources
421
+ ```
422
+
423
+ Links local files or directories into an already mounted VFS as virtual submounts. Works entirely on the PC side — no changes needed on the device. Useful for composing a virtual filesystem from multiple local directories without copying.
424
+
425
+ Path semantics follow the same trailing `/` rules as `cp`: `ln dir :/lib/` creates `:/lib/dir/...`, `ln dir/ :/lib/` copies contents into `:/lib/...`. Destination must be an absolute device path with `:` prefix.
426
+
202
427
  ### Serial link speed test
203
428
  ```
204
429
  $ mpytool speedtest
@@ -214,7 +439,8 @@ SPEEDTEST
214
439
 
215
440
  ### Show device information
216
441
  ```
217
- $ mpytool info
442
+ $ mpytool -p COM3 info # Windows
443
+ INFO
218
444
  Platform: rp2
219
445
  Version: 3.4.0; MicroPython v1.27.0 on 2025-12-09
220
446
  Impl: micropython
@@ -258,9 +484,9 @@ $ mpytool flash erase vfs --full # full erase partition
258
484
 
259
485
  ### OTA firmware update (ESP32)
260
486
  ```
261
- $ mpytool ota firmware.app-bin # flash to next OTA partition
262
- $ mpytool ota firmware.app-bin -- reset --machine # flash and reboot
263
- $ mpytool ota firmware.app-bin -- reset --machine -t 30 # flash and reboot with 30s timeout
487
+ $ mpytool flash ota firmware.app-bin # flash to next OTA partition
488
+ $ mpytool flash ota firmware.app-bin -- reset --machine # flash and reboot
489
+ $ mpytool flash ota firmware.app-bin -- reset --machine -t 30 # flash and reboot with 30s timeout
264
490
  ```
265
491
 
266
492
  ### Multiple commands separated by `--`
@@ -271,28 +497,30 @@ $ mpytool rm :old.py -- cp new.py : -- reset
271
497
 
272
498
  ### Auto-detect serial port (if only one device is connected)
273
499
  ```
274
- $ mpytool ls lib/
500
+ $ mpytool ls :/lib
501
+ LS: /lib
275
502
  uhttp/
276
- 23.2 KB wlan.py
277
- 4.95 KB wlan_http.py
503
+ 23.1K wlan.py
504
+ 4.95K wlan_http.py
278
505
  ```
279
506
 
280
507
  ### Tree view
281
508
  ```
282
509
  $ mpytool tree
283
- 142 KB ./
284
- 41.3 KB ├─ html/
285
- 587 B │ ├─ index.html
286
- 40.8 KB └─ wlan.html
287
- 97.7 KB ├─ lib/
288
- 69.6 KB │ ├─ uhttp/
289
- 93 B ├─ __init__.py
290
- 26.3 KB │ │ ├─ client.py
291
- 43.2 KB │ │ └─ server.py
292
- 23.2 KB ├─ wlan.py
293
- 4.95 KB └─ wlan_http.py
294
- 23 B ├─ boot.py
295
- 3.03 KB └─ main.py
510
+ TREE: /
511
+ 142K ./
512
+ 41.3K ├─ html/
513
+ 587├─ index.html
514
+ 40.8K │ └─ wlan.html
515
+ 97.7K ├─ lib/
516
+ 69.6K │ ├─ uhttp/
517
+ 93 │ │ ├─ __init__.py
518
+ 26.3K │ │ ├─ client.py
519
+ 43.2K│ └─ server.py
520
+ 23.1K├─ wlan.py
521
+ 4.95K │ └─ wlan_http.py
522
+ 23 ├─ boot.py
523
+ 3.03K └─ main.py
296
524
  ```
297
525
 
298
526
  ### Connect over network (TCP, default port 23)
@@ -388,7 +616,7 @@ For reporting bugs, please include `-ddd` output in the issue.
388
616
 
389
617
  ## Performance
390
618
 
391
- `mpytool` uses optimized chunked transfer with automatic compression, which allows copying files very quickly. See [README_BENCH.md](README_BENCH.md) for detailed benchmarks.
619
+ `mpytool` uses optimized chunked transfer with automatic compression, which allows copying files very quickly. See [README_bench.md](README_bench.md) for detailed benchmarks.
392
620
 
393
621
  ### Summary
394
622