mpytool 2.3.2__tar.gz → 2.3.4__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.3.2/mpytool.egg-info → mpytool-2.3.4}/PKG-INFO +32 -20
- mpytool-2.3.2/PKG-INFO → mpytool-2.3.4/README.md +29 -31
- {mpytool-2.3.2 → mpytool-2.3.4}/mpytool/__init__.py +1 -1
- {mpytool-2.3.2 → mpytool-2.3.4}/mpytool/cmd_cp.py +6 -6
- {mpytool-2.3.2 → mpytool-2.3.4}/mpytool/conn.py +3 -1
- {mpytool-2.3.2 → mpytool-2.3.4}/mpytool/conn_serial.py +19 -18
- {mpytool-2.3.2 → mpytool-2.3.4}/mpytool/conn_socket.py +2 -4
- {mpytool-2.3.2 → mpytool-2.3.4}/mpytool/logger.py +27 -6
- {mpytool-2.3.2 → mpytool-2.3.4}/mpytool/mount.py +76 -114
- {mpytool-2.3.2 → mpytool-2.3.4}/mpytool/mpy.py +21 -39
- {mpytool-2.3.2 → mpytool-2.3.4}/mpytool/mpy_comm.py +155 -44
- {mpytool-2.3.2 → mpytool-2.3.4}/mpytool/mpy_cross.py +18 -11
- {mpytool-2.3.2 → mpytool-2.3.4}/mpytool/mpytool.py +106 -42
- {mpytool-2.3.2 → mpytool-2.3.4}/mpytool/terminal.py +2 -2
- {mpytool-2.3.2 → mpytool-2.3.4}/mpytool/utils.py +98 -10
- mpytool-2.3.2/README.md → mpytool-2.3.4/mpytool.egg-info/PKG-INFO +43 -17
- {mpytool-2.3.2 → mpytool-2.3.4}/pyproject.toml +3 -3
- {mpytool-2.3.2 → mpytool-2.3.4}/tests/test_cli.py +31 -26
- {mpytool-2.3.2 → mpytool-2.3.4}/tests/test_cmd_cp.py +1 -1
- {mpytool-2.3.2 → mpytool-2.3.4}/tests/test_integration.py +62 -53
- {mpytool-2.3.2 → mpytool-2.3.4}/tests/test_mount.py +11 -3
- {mpytool-2.3.2 → mpytool-2.3.4}/tests/test_mpy.py +383 -70
- {mpytool-2.3.2 → mpytool-2.3.4}/tests/test_mpytool.py +69 -27
- {mpytool-2.3.2 → mpytool-2.3.4}/tests/test_utils.py +96 -0
- {mpytool-2.3.2 → mpytool-2.3.4}/LICENSE +0 -0
- {mpytool-2.3.2 → mpytool-2.3.4}/mpytool/speedtest.py +0 -0
- {mpytool-2.3.2 → mpytool-2.3.4}/mpytool/terminal_unix.py +0 -0
- {mpytool-2.3.2 → mpytool-2.3.4}/mpytool/terminal_win.py +0 -0
- {mpytool-2.3.2 → mpytool-2.3.4}/mpytool.egg-info/SOURCES.txt +0 -0
- {mpytool-2.3.2 → mpytool-2.3.4}/mpytool.egg-info/dependency_links.txt +0 -0
- {mpytool-2.3.2 → mpytool-2.3.4}/mpytool.egg-info/entry_points.txt +0 -0
- {mpytool-2.3.2 → mpytool-2.3.4}/mpytool.egg-info/requires.txt +0 -0
- {mpytool-2.3.2 → mpytool-2.3.4}/mpytool.egg-info/top_level.txt +0 -0
- {mpytool-2.3.2 → mpytool-2.3.4}/setup.cfg +0 -0
- {mpytool-2.3.2 → mpytool-2.3.4}/tests/test_errors.py +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mpytool
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.4
|
|
4
4
|
Summary: MPY tool - manage files on devices running MicroPython
|
|
5
|
-
Author-email: Pavel Revak <
|
|
5
|
+
Author-email: Pavel Revak <pavelrevak@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
7
|
-
Project-URL: Homepage, https://github.com/
|
|
7
|
+
Project-URL: Homepage, https://github.com/cortexm/mpytool
|
|
8
8
|
Keywords: MPY,micropython
|
|
9
9
|
Requires-Python: >=3.10
|
|
10
10
|
Description-Content-Type: text/markdown
|
|
@@ -55,7 +55,7 @@ pip3 install mpytool
|
|
|
55
55
|
### Installation from git (latest development version)
|
|
56
56
|
|
|
57
57
|
```bash
|
|
58
|
-
pip3 install git+https://github.com/
|
|
58
|
+
pip3 install git+https://github.com/cortexm/mpytool.git
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
### Installation in virtualenv
|
|
@@ -254,7 +254,11 @@ RESET soft
|
|
|
254
254
|
$ mpytool reset --machine # MCU reset (machine.reset, auto-reconnect)
|
|
255
255
|
RESET machine
|
|
256
256
|
|
|
257
|
-
$ mpytool reset -- monitor # reset and monitor
|
|
257
|
+
$ mpytool reset -- monitor # reset and monitor until program ends
|
|
258
|
+
RESET soft
|
|
259
|
+
MONITOR (until program ends, -f to follow)
|
|
260
|
+
|
|
261
|
+
$ mpytool reset -- monitor -f # reset and monitor continuously
|
|
258
262
|
RESET soft
|
|
259
263
|
MONITOR (Ctrl+C to stop)
|
|
260
264
|
|
|
@@ -275,7 +279,8 @@ REPL (Ctrl+] to exit) CWD: / PATH: : :.frozen :/lib
|
|
|
275
279
|
|
|
276
280
|
$ mpytool -p /dev/ttyUSB0 repl # specify port
|
|
277
281
|
$ mpytool -b 9600 repl # specify baudrate
|
|
278
|
-
$ mpytool -p /dev/ttyUSB0 -b 9600 monitor # monitor
|
|
282
|
+
$ mpytool -p /dev/ttyUSB0 -b 9600 monitor # monitor until program ends
|
|
283
|
+
$ mpytool monitor -f # follow output continuously (Ctrl-C to stop)
|
|
279
284
|
```
|
|
280
285
|
|
|
281
286
|
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.
|
|
@@ -284,24 +289,30 @@ Both `repl` and `monitor` can be used as general-purpose serial tools - not just
|
|
|
284
289
|
|
|
285
290
|
### Execute Python code on device
|
|
286
291
|
```
|
|
287
|
-
$ mpytool exec "print('Hello!')"
|
|
292
|
+
$ mpytool exec "print('Hello!')" # execute and stream output
|
|
288
293
|
EXEC: print('Hello!')
|
|
289
294
|
Hello!
|
|
290
295
|
|
|
291
296
|
$ mpytool exec "import sys; print(sys.version)"
|
|
292
297
|
EXEC: import sys; print(sys.version)
|
|
293
298
|
3.4.0; MicroPython v1.24.0
|
|
299
|
+
|
|
300
|
+
$ mpytool exec "long_task()" -t 30 # timeout after 30 seconds
|
|
301
|
+
$ mpytool exec "start_server()" -t 0 # fire-and-forget (don't wait)
|
|
294
302
|
```
|
|
295
303
|
|
|
296
304
|
### Run local Python file on device
|
|
297
305
|
```
|
|
298
|
-
$ mpytool run script.py # run
|
|
306
|
+
$ mpytool run script.py # run and stream output
|
|
299
307
|
RUN: script.py (128 bytes)
|
|
308
|
+
Hello from script!
|
|
300
309
|
|
|
301
|
-
$ mpytool run script.py
|
|
310
|
+
$ mpytool run script.py -t 0 # fire-and-forget (don't wait)
|
|
302
311
|
RUN: script.py (128 bytes)
|
|
303
|
-
|
|
304
|
-
|
|
312
|
+
|
|
313
|
+
$ mpytool run script.py -t 10 # timeout after 10 seconds
|
|
314
|
+
RUN: script.py (128 bytes)
|
|
315
|
+
Done!
|
|
305
316
|
```
|
|
306
317
|
|
|
307
318
|
### Edit file on device
|
|
@@ -608,11 +619,12 @@ Scanning...
|
|
|
608
619
|
|
|
609
620
|
## Debug output
|
|
610
621
|
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
- `-
|
|
622
|
+
By default, errors and warnings are shown.
|
|
623
|
+
|
|
624
|
+
- `-d` also print info messages (purple)
|
|
625
|
+
- `-dd` also print debug messages (blue)
|
|
614
626
|
|
|
615
|
-
For reporting bugs, please include `-
|
|
627
|
+
For reporting bugs, please include `-dd` output in the issue.
|
|
616
628
|
|
|
617
629
|
## Performance
|
|
618
630
|
|
|
@@ -649,7 +661,7 @@ autoload -Uz compinit && compinit
|
|
|
649
661
|
**Quick install (or update):**
|
|
650
662
|
```bash
|
|
651
663
|
mkdir -p ~/.zsh/completions
|
|
652
|
-
curl -fsSL https://raw.githubusercontent.com/
|
|
664
|
+
curl -fsSL https://raw.githubusercontent.com/cortexm/mpytool/main/completions/_mpytool -o ~/.zsh/completions/_mpytool
|
|
653
665
|
grep -q '\.zsh/completions' ~/.zshrc || echo 'fpath=(~/.zsh/completions $fpath); autoload -Uz compinit && compinit' >> ~/.zshrc
|
|
654
666
|
exec zsh
|
|
655
667
|
```
|
|
@@ -670,17 +682,17 @@ source ~/.mpytool-completion.bash
|
|
|
670
682
|
|
|
671
683
|
**Quick install (Linux system-wide):**
|
|
672
684
|
```bash
|
|
673
|
-
sudo curl -fsSL https://raw.githubusercontent.com/
|
|
685
|
+
sudo curl -fsSL https://raw.githubusercontent.com/cortexm/mpytool/main/completions/mpytool.bash -o /etc/bash_completion.d/mpytool && exec bash
|
|
674
686
|
```
|
|
675
687
|
|
|
676
688
|
**Quick install (macOS Homebrew):**
|
|
677
689
|
```bash
|
|
678
|
-
curl -fsSL https://raw.githubusercontent.com/
|
|
690
|
+
curl -fsSL https://raw.githubusercontent.com/cortexm/mpytool/main/completions/mpytool.bash -o /usr/local/etc/bash_completion.d/mpytool && exec bash
|
|
679
691
|
```
|
|
680
692
|
|
|
681
693
|
**Quick install (user directory):**
|
|
682
694
|
```bash
|
|
683
|
-
curl -fsSL https://raw.githubusercontent.com/
|
|
695
|
+
curl -fsSL https://raw.githubusercontent.com/cortexm/mpytool/main/completions/mpytool.bash -o ~/.mpytool-completion.bash
|
|
684
696
|
grep -q 'mpytool-completion' ~/.bashrc || echo 'source ~/.mpytool-completion.bash' >> ~/.bashrc
|
|
685
697
|
exec bash
|
|
686
698
|
```
|
|
@@ -756,4 +768,4 @@ MIT
|
|
|
756
768
|
### Support
|
|
757
769
|
|
|
758
770
|
- Basic support is free over GitHub issues.
|
|
759
|
-
- Professional support is available over email: [Pavel Revak](mailto:
|
|
771
|
+
- Professional support is available over email: [Pavel Revak](mailto:pavelrevak@gmail.com?subject=[GitHub]%20mpytool).
|
|
@@ -1,17 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: mpytool
|
|
3
|
-
Version: 2.3.2
|
|
4
|
-
Summary: MPY tool - manage files on devices running MicroPython
|
|
5
|
-
Author-email: Pavel Revak <pavel.revak@gmail.com>
|
|
6
|
-
License-Expression: MIT
|
|
7
|
-
Project-URL: Homepage, https://github.com/pavelrevak/mpytool
|
|
8
|
-
Keywords: MPY,micropython
|
|
9
|
-
Requires-Python: >=3.10
|
|
10
|
-
Description-Content-Type: text/markdown
|
|
11
|
-
License-File: LICENSE
|
|
12
|
-
Requires-Dist: pyserial>=3.0
|
|
13
|
-
Dynamic: license-file
|
|
14
|
-
|
|
15
1
|
# mpytool
|
|
16
2
|
|
|
17
3
|
MPY tool - manage files on devices running MicroPython
|
|
@@ -55,7 +41,7 @@ pip3 install mpytool
|
|
|
55
41
|
### Installation from git (latest development version)
|
|
56
42
|
|
|
57
43
|
```bash
|
|
58
|
-
pip3 install git+https://github.com/
|
|
44
|
+
pip3 install git+https://github.com/cortexm/mpytool.git
|
|
59
45
|
```
|
|
60
46
|
|
|
61
47
|
### Installation in virtualenv
|
|
@@ -254,7 +240,11 @@ RESET soft
|
|
|
254
240
|
$ mpytool reset --machine # MCU reset (machine.reset, auto-reconnect)
|
|
255
241
|
RESET machine
|
|
256
242
|
|
|
257
|
-
$ mpytool reset -- monitor # reset and monitor
|
|
243
|
+
$ mpytool reset -- monitor # reset and monitor until program ends
|
|
244
|
+
RESET soft
|
|
245
|
+
MONITOR (until program ends, -f to follow)
|
|
246
|
+
|
|
247
|
+
$ mpytool reset -- monitor -f # reset and monitor continuously
|
|
258
248
|
RESET soft
|
|
259
249
|
MONITOR (Ctrl+C to stop)
|
|
260
250
|
|
|
@@ -275,7 +265,8 @@ REPL (Ctrl+] to exit) CWD: / PATH: : :.frozen :/lib
|
|
|
275
265
|
|
|
276
266
|
$ mpytool -p /dev/ttyUSB0 repl # specify port
|
|
277
267
|
$ mpytool -b 9600 repl # specify baudrate
|
|
278
|
-
$ mpytool -p /dev/ttyUSB0 -b 9600 monitor # monitor
|
|
268
|
+
$ mpytool -p /dev/ttyUSB0 -b 9600 monitor # monitor until program ends
|
|
269
|
+
$ mpytool monitor -f # follow output continuously (Ctrl-C to stop)
|
|
279
270
|
```
|
|
280
271
|
|
|
281
272
|
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.
|
|
@@ -284,24 +275,30 @@ Both `repl` and `monitor` can be used as general-purpose serial tools - not just
|
|
|
284
275
|
|
|
285
276
|
### Execute Python code on device
|
|
286
277
|
```
|
|
287
|
-
$ mpytool exec "print('Hello!')"
|
|
278
|
+
$ mpytool exec "print('Hello!')" # execute and stream output
|
|
288
279
|
EXEC: print('Hello!')
|
|
289
280
|
Hello!
|
|
290
281
|
|
|
291
282
|
$ mpytool exec "import sys; print(sys.version)"
|
|
292
283
|
EXEC: import sys; print(sys.version)
|
|
293
284
|
3.4.0; MicroPython v1.24.0
|
|
285
|
+
|
|
286
|
+
$ mpytool exec "long_task()" -t 30 # timeout after 30 seconds
|
|
287
|
+
$ mpytool exec "start_server()" -t 0 # fire-and-forget (don't wait)
|
|
294
288
|
```
|
|
295
289
|
|
|
296
290
|
### Run local Python file on device
|
|
297
291
|
```
|
|
298
|
-
$ mpytool run script.py # run
|
|
292
|
+
$ mpytool run script.py # run and stream output
|
|
293
|
+
RUN: script.py (128 bytes)
|
|
294
|
+
Hello from script!
|
|
295
|
+
|
|
296
|
+
$ mpytool run script.py -t 0 # fire-and-forget (don't wait)
|
|
299
297
|
RUN: script.py (128 bytes)
|
|
300
298
|
|
|
301
|
-
$ mpytool run script.py
|
|
299
|
+
$ mpytool run script.py -t 10 # timeout after 10 seconds
|
|
302
300
|
RUN: script.py (128 bytes)
|
|
303
|
-
|
|
304
|
-
Hello from script!
|
|
301
|
+
Done!
|
|
305
302
|
```
|
|
306
303
|
|
|
307
304
|
### Edit file on device
|
|
@@ -608,11 +605,12 @@ Scanning...
|
|
|
608
605
|
|
|
609
606
|
## Debug output
|
|
610
607
|
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
- `-
|
|
608
|
+
By default, errors and warnings are shown.
|
|
609
|
+
|
|
610
|
+
- `-d` also print info messages (purple)
|
|
611
|
+
- `-dd` also print debug messages (blue)
|
|
614
612
|
|
|
615
|
-
For reporting bugs, please include `-
|
|
613
|
+
For reporting bugs, please include `-dd` output in the issue.
|
|
616
614
|
|
|
617
615
|
## Performance
|
|
618
616
|
|
|
@@ -649,7 +647,7 @@ autoload -Uz compinit && compinit
|
|
|
649
647
|
**Quick install (or update):**
|
|
650
648
|
```bash
|
|
651
649
|
mkdir -p ~/.zsh/completions
|
|
652
|
-
curl -fsSL https://raw.githubusercontent.com/
|
|
650
|
+
curl -fsSL https://raw.githubusercontent.com/cortexm/mpytool/main/completions/_mpytool -o ~/.zsh/completions/_mpytool
|
|
653
651
|
grep -q '\.zsh/completions' ~/.zshrc || echo 'fpath=(~/.zsh/completions $fpath); autoload -Uz compinit && compinit' >> ~/.zshrc
|
|
654
652
|
exec zsh
|
|
655
653
|
```
|
|
@@ -670,17 +668,17 @@ source ~/.mpytool-completion.bash
|
|
|
670
668
|
|
|
671
669
|
**Quick install (Linux system-wide):**
|
|
672
670
|
```bash
|
|
673
|
-
sudo curl -fsSL https://raw.githubusercontent.com/
|
|
671
|
+
sudo curl -fsSL https://raw.githubusercontent.com/cortexm/mpytool/main/completions/mpytool.bash -o /etc/bash_completion.d/mpytool && exec bash
|
|
674
672
|
```
|
|
675
673
|
|
|
676
674
|
**Quick install (macOS Homebrew):**
|
|
677
675
|
```bash
|
|
678
|
-
curl -fsSL https://raw.githubusercontent.com/
|
|
676
|
+
curl -fsSL https://raw.githubusercontent.com/cortexm/mpytool/main/completions/mpytool.bash -o /usr/local/etc/bash_completion.d/mpytool && exec bash
|
|
679
677
|
```
|
|
680
678
|
|
|
681
679
|
**Quick install (user directory):**
|
|
682
680
|
```bash
|
|
683
|
-
curl -fsSL https://raw.githubusercontent.com/
|
|
681
|
+
curl -fsSL https://raw.githubusercontent.com/cortexm/mpytool/main/completions/mpytool.bash -o ~/.mpytool-completion.bash
|
|
684
682
|
grep -q 'mpytool-completion' ~/.bashrc || echo 'source ~/.mpytool-completion.bash' >> ~/.bashrc
|
|
685
683
|
exec bash
|
|
686
684
|
```
|
|
@@ -756,4 +754,4 @@ MIT
|
|
|
756
754
|
### Support
|
|
757
755
|
|
|
758
756
|
- Basic support is free over GitHub issues.
|
|
759
|
-
- Professional support is available over email: [Pavel Revak](mailto:
|
|
757
|
+
- Professional support is available over email: [Pavel Revak](mailto:pavelrevak@gmail.com?subject=[GitHub]%20mpytool).
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
from mpytool.conn import ConnError, Timeout
|
|
4
4
|
from mpytool.conn_serial import ConnSerial
|
|
5
5
|
from mpytool.conn_socket import ConnSocket
|
|
6
|
-
from mpytool.mpy_comm import MpyError, CmdError
|
|
6
|
+
from mpytool.mpy_comm import MpyComm, MpyError, CmdError
|
|
7
7
|
from mpytool.mpy import Mpy, PathNotFound, FileNotFound, DirNotFound
|
|
8
8
|
from mpytool.logger import SimpleColorLogger
|
|
@@ -79,8 +79,8 @@ class CopyCommand:
|
|
|
79
79
|
# Cache
|
|
80
80
|
self._remote_file_cache = {}
|
|
81
81
|
|
|
82
|
-
#
|
|
83
|
-
self.
|
|
82
|
+
# Info mode disables progress overwrite (each update on new line)
|
|
83
|
+
self._is_info = self._log.is_info
|
|
84
84
|
|
|
85
85
|
@property
|
|
86
86
|
def _verbose(self):
|
|
@@ -196,7 +196,7 @@ class CopyCommand:
|
|
|
196
196
|
line = self._format_progress_line(percent, total)
|
|
197
197
|
else:
|
|
198
198
|
line = self._format_compact_progress(f"{percent:3d}%", total)
|
|
199
|
-
if self.
|
|
199
|
+
if self._is_info:
|
|
200
200
|
self.verbose(line, color='cyan')
|
|
201
201
|
else:
|
|
202
202
|
self.verbose(line, color='cyan', end='', overwrite=True)
|
|
@@ -207,7 +207,7 @@ class CopyCommand:
|
|
|
207
207
|
line = self._format_progress_line(100, total, encodings)
|
|
208
208
|
else:
|
|
209
209
|
line = self._format_compact_complete(total)
|
|
210
|
-
self.verbose(line, color='cyan', overwrite=not self.
|
|
210
|
+
self.verbose(line, color='cyan', overwrite=not self._is_info)
|
|
211
211
|
|
|
212
212
|
def _set_progress_info(self, src, dst, is_src_remote, is_dst_remote):
|
|
213
213
|
"""Set progress source and destination paths"""
|
|
@@ -673,7 +673,7 @@ class CopyCommand:
|
|
|
673
673
|
self._force = force
|
|
674
674
|
self._compress = compress
|
|
675
675
|
if mpy:
|
|
676
|
-
self._mpy_cross = MpyCross(self._log
|
|
676
|
+
self._mpy_cross = MpyCross(self._log)
|
|
677
677
|
|
|
678
678
|
try:
|
|
679
679
|
self._run_impl(paths)
|
|
@@ -831,7 +831,7 @@ class CopyCommand:
|
|
|
831
831
|
|
|
832
832
|
def print_transfer_info(self):
|
|
833
833
|
"""Print transfer settings (chunk size and compression)"""
|
|
834
|
-
chunk = self.mpy.
|
|
834
|
+
chunk = self.mpy.chunk_size
|
|
835
835
|
chunk_str = f"{chunk // 1024}K" if chunk >= 1024 else str(chunk)
|
|
836
836
|
if self._compress is None:
|
|
837
837
|
compress = self.mpy.detect_deflate()
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
import time as _time
|
|
4
4
|
import select as _select
|
|
5
5
|
|
|
6
|
+
from mpytool.logger import SimpleColorLogger as _SimpleColorLogger
|
|
7
|
+
|
|
6
8
|
# VFS escape byte - signals start of VFS command from device
|
|
7
9
|
ESCAPE = 0x18
|
|
8
10
|
|
|
@@ -17,7 +19,7 @@ class Timeout(ConnError):
|
|
|
17
19
|
|
|
18
20
|
class Conn():
|
|
19
21
|
def __init__(self, log=None):
|
|
20
|
-
self._log = log
|
|
22
|
+
self._log = log if log is not None else _SimpleColorLogger()
|
|
21
23
|
self._buffer = bytearray()
|
|
22
24
|
self._escape_handlers = {} # {escape_byte: handler}
|
|
23
25
|
self._active_handler = None # Currently processing handler
|
|
@@ -22,20 +22,24 @@ class ConnSerial(_conn.Conn):
|
|
|
22
22
|
# Windows: pyserial has no fd, select() works only with sockets
|
|
23
23
|
if not hasattr(self._serial, 'fd'):
|
|
24
24
|
self._has_data = self._has_data_polling
|
|
25
|
-
# Debug info about port
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"Connected to %s [%04X:%04X %s]",
|
|
33
|
-
port, vid, pid, self.port_type)
|
|
34
|
-
else:
|
|
35
|
-
self._log.info("Connected to %s [unknown serial port]", port)
|
|
25
|
+
# Debug info about port
|
|
26
|
+
port = serial_config.get('port', '')
|
|
27
|
+
if self._port_info and self._port_info.vid:
|
|
28
|
+
desc = _utils._port_description(self._port_info)
|
|
29
|
+
self._log.info("Connected to %s [%s]", port, desc)
|
|
30
|
+
else:
|
|
31
|
+
self._log.info("Connected to %s [unknown serial port]", port)
|
|
36
32
|
|
|
37
33
|
def close(self):
|
|
38
34
|
if self._serial:
|
|
35
|
+
# Prevent ESP32 reset when driver clears DTR/RTS on close
|
|
36
|
+
# Only for USB-UART bridges (CP2102, CH340, etc.), not USB-CDC
|
|
37
|
+
if self._is_usb_uart():
|
|
38
|
+
try:
|
|
39
|
+
self._serial.rts = False
|
|
40
|
+
self._serial.dtr = False
|
|
41
|
+
except OSError:
|
|
42
|
+
pass
|
|
39
43
|
self._serial.close()
|
|
40
44
|
self._serial = None
|
|
41
45
|
|
|
@@ -69,7 +73,7 @@ class ConnSerial(_conn.Conn):
|
|
|
69
73
|
in_waiting = self._serial.in_waiting
|
|
70
74
|
if in_waiting > 0:
|
|
71
75
|
data = self._serial.read(in_waiting)
|
|
72
|
-
if data
|
|
76
|
+
if data:
|
|
73
77
|
self._log.debug("RX: %r", data)
|
|
74
78
|
return data
|
|
75
79
|
return None
|
|
@@ -80,8 +84,7 @@ class ConnSerial(_conn.Conn):
|
|
|
80
84
|
"""Write data to serial port"""
|
|
81
85
|
if self._serial is None:
|
|
82
86
|
raise _conn.ConnError("Not connected")
|
|
83
|
-
|
|
84
|
-
self._log.debug("TX: %r", data)
|
|
87
|
+
self._log.debug("TX: %r", data)
|
|
85
88
|
try:
|
|
86
89
|
return self._serial.write(data)
|
|
87
90
|
except OSError as err:
|
|
@@ -117,8 +120,7 @@ class ConnSerial(_conn.Conn):
|
|
|
117
120
|
if not self._is_usb_uart():
|
|
118
121
|
raise _conn.ConnError(
|
|
119
122
|
f"Hardware reset not supported on {self.port_type}")
|
|
120
|
-
|
|
121
|
-
self._log.info("hard_reset: using DTR/RTS")
|
|
123
|
+
self._log.info("hard_reset: using DTR/RTS")
|
|
122
124
|
self._serial.setDTR(False) # GPIO0 high (normal boot)
|
|
123
125
|
self._serial.setRTS(True) # Assert reset
|
|
124
126
|
_time.sleep(0.1)
|
|
@@ -159,8 +161,7 @@ class ConnSerial(_conn.Conn):
|
|
|
159
161
|
if not self._is_usb_uart():
|
|
160
162
|
raise _conn.ConnError(
|
|
161
163
|
f"Bootloader reset not supported on {self.port_type}")
|
|
162
|
-
|
|
163
|
-
self._log.info("reset_to_bootloader: using DTR/RTS")
|
|
164
|
+
self._log.info("reset_to_bootloader: using DTR/RTS")
|
|
164
165
|
self._serial.setDTR(False) # GPIO0 high
|
|
165
166
|
self._serial.setRTS(True) # Assert reset
|
|
166
167
|
_time.sleep(0.1)
|
|
@@ -49,8 +49,7 @@ class ConnSocket(_conn.Conn):
|
|
|
49
49
|
try:
|
|
50
50
|
data = self._socket.recv(4096)
|
|
51
51
|
if data:
|
|
52
|
-
|
|
53
|
-
self._log.debug("RX: %r", data)
|
|
52
|
+
self._log.debug("RX: %r", data)
|
|
54
53
|
return data
|
|
55
54
|
except BlockingIOError:
|
|
56
55
|
pass
|
|
@@ -62,8 +61,7 @@ class ConnSocket(_conn.Conn):
|
|
|
62
61
|
"""Write data to socket"""
|
|
63
62
|
if self._socket is None:
|
|
64
63
|
raise _conn.ConnError("Not connected")
|
|
65
|
-
|
|
66
|
-
self._log.debug("TX: %r", data)
|
|
64
|
+
self._log.debug("TX: %r", data)
|
|
67
65
|
try:
|
|
68
66
|
return self._socket.send(data)
|
|
69
67
|
except OSError as err:
|
|
@@ -4,6 +4,12 @@ import os as _os
|
|
|
4
4
|
import sys as _sys
|
|
5
5
|
|
|
6
6
|
|
|
7
|
+
# Log levels (compatible with Python logging)
|
|
8
|
+
DEBUG = 10
|
|
9
|
+
INFO = 20
|
|
10
|
+
WARNING = 30
|
|
11
|
+
ERROR = 40
|
|
12
|
+
|
|
7
13
|
class SimpleColorLogger():
|
|
8
14
|
# ANSI color codes
|
|
9
15
|
_RESET = '\033[0m'
|
|
@@ -25,7 +31,7 @@ class SimpleColorLogger():
|
|
|
25
31
|
'cyan': _BOLD_CYAN,
|
|
26
32
|
}
|
|
27
33
|
|
|
28
|
-
def __init__(self, loglevel=
|
|
34
|
+
def __init__(self, loglevel=WARNING, verbose_level=0):
|
|
29
35
|
self._loglevel = loglevel
|
|
30
36
|
self._verbose_level = verbose_level
|
|
31
37
|
self._is_tty = _sys.stderr.isatty()
|
|
@@ -40,9 +46,24 @@ class SimpleColorLogger():
|
|
|
40
46
|
|
|
41
47
|
@property
|
|
42
48
|
def loglevel(self):
|
|
43
|
-
"""Return current log level (
|
|
49
|
+
"""Return current log level (DEBUG=10, INFO=20, WARNING=30, ERROR=40)"""
|
|
44
50
|
return self._loglevel
|
|
45
51
|
|
|
52
|
+
@property
|
|
53
|
+
def is_debug(self):
|
|
54
|
+
"""True if debug messages are enabled"""
|
|
55
|
+
return self._loglevel <= DEBUG
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def is_info(self):
|
|
59
|
+
"""True if info messages are enabled"""
|
|
60
|
+
return self._loglevel <= INFO
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def is_warning(self):
|
|
64
|
+
"""True if warning messages are enabled"""
|
|
65
|
+
return self._loglevel <= WARNING
|
|
66
|
+
|
|
46
67
|
def colorize(self, text, color):
|
|
47
68
|
"""Return text wrapped in color codes if colors are enabled"""
|
|
48
69
|
if not self._color:
|
|
@@ -67,7 +88,7 @@ class SimpleColorLogger():
|
|
|
67
88
|
def error(self, msg, *args):
|
|
68
89
|
if args:
|
|
69
90
|
msg = msg % args
|
|
70
|
-
if self._loglevel
|
|
91
|
+
if self._loglevel <= ERROR:
|
|
71
92
|
if self._color:
|
|
72
93
|
self.log(f"{self._BOLD_RED}{msg}{self._RESET}")
|
|
73
94
|
else:
|
|
@@ -76,7 +97,7 @@ class SimpleColorLogger():
|
|
|
76
97
|
def warning(self, msg, *args):
|
|
77
98
|
if args:
|
|
78
99
|
msg = msg % args
|
|
79
|
-
if self._loglevel
|
|
100
|
+
if self._loglevel <= WARNING:
|
|
80
101
|
if self._color:
|
|
81
102
|
self.log(f"{self._BOLD_YELLOW}{msg}{self._RESET}")
|
|
82
103
|
else:
|
|
@@ -85,7 +106,7 @@ class SimpleColorLogger():
|
|
|
85
106
|
def info(self, msg, *args):
|
|
86
107
|
if args:
|
|
87
108
|
msg = msg % args
|
|
88
|
-
if self._loglevel
|
|
109
|
+
if self._loglevel <= INFO:
|
|
89
110
|
if self._color:
|
|
90
111
|
self.log(f"{self._BOLD_MAGENTA}{msg}{self._RESET}")
|
|
91
112
|
else:
|
|
@@ -94,7 +115,7 @@ class SimpleColorLogger():
|
|
|
94
115
|
def debug(self, msg, *args):
|
|
95
116
|
if args:
|
|
96
117
|
msg = msg % args
|
|
97
|
-
if self._loglevel
|
|
118
|
+
if self._loglevel <= DEBUG:
|
|
98
119
|
if self._color:
|
|
99
120
|
self.log(f"{self._BOLD_BLUE}{msg}{self._RESET}")
|
|
100
121
|
else:
|