esp-test-utils 0.2.3__tar.gz → 0.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.
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/.gitignore +1 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/.gitlab-ci.yml +71 -4
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/CHANGELOG.md +16 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/PKG-INFO +3 -1
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esp_test_utils.egg-info/PKG-INFO +3 -1
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esp_test_utils.egg-info/SOURCES.txt +3 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esp_test_utils.egg-info/requires.txt +2 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/adapter/dut/dut_base.py +2 -2
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/adapter/dut/wrapper.py +6 -1
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/adapter/port/base_port.py +45 -20
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/adapter/port/serial_port.py +60 -18
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/adapter/port/shell_port.py +100 -11
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/common/compat_typing.py +9 -3
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/common/data_monitor.py +2 -2
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/common/decorators.py +20 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/common/shell.py +18 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/config/env_config.py +4 -2
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/db/runners.py +4 -1
- esp_test_utils-0.3.1/esptest/devices/switch.py +544 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/interface/port.py +6 -5
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/iperf_utility/iperf_results.py +27 -24
- esp_test_utils-0.3.1/esptest/iperf_utility/line_chart.py +244 -0
- esp_test_utils-0.3.1/esptest/network/mac.py +31 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/network/netif.py +35 -11
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/scripts/downbin.py +10 -1
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/scripts/list_ports.py +20 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/tools/copy_bin.py +2 -2
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/tools/download_bin.py +41 -9
- esp_test_utils-0.3.1/esptest/tools/uart_monitor.py +324 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/utility/parse_bin_path.py +26 -6
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/pyproject.toml +6 -1
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/adapter/test_Dut.py +83 -1
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/adapter/test_shell_port.py +41 -11
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/basic/test_decorators.py +25 -1
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/basic/test_network.py +39 -3
- esp_test_utils-0.3.1/tests/devices/test_switch.py +217 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/esp_console/test_WifiCmd.py +56 -1
- esp_test_utils-0.3.1/tests/iperf_utility/test_chart.py +101 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/iperf_utility/test_iperf_results.py +8 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/test_common.py +7 -2
- esp_test_utils-0.2.3/esptest/iperf_utility/line_chart.py +0 -86
- esp_test_utils-0.2.3/esptest/network/mac.py +0 -5
- esp_test_utils-0.2.3/tests/iperf_utility/test_chart.py +0 -46
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/.github/.gitkeep +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/.github/workflows/pypi-publish.yml +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/.pre-commit-config.yaml +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/CONTRIBUTING.md +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/LICENSE +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/README.md +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/docs/Makefile +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/docs/conf.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/docs/index.rst +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/docs/make.bat +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esp_test_utils.egg-info/dependency_links.txt +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esp_test_utils.egg-info/entry_points.txt +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esp_test_utils.egg-info/top_level.txt +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/__init__.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/__main__.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/adapter/__init__.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/adapter/dut/__init__.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/adapter/dut/create_dut.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/adapter/dut/esp_dut.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/adapter/dut/esp_mixin.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/adapter/dut/esp_port.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/adapter/dut/mac_mixin.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/adapter/port/__init__.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/all.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/common/__init__.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/common/encoding.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/common/generator.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/common/timestamp.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/config/__init__.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/config/default_config.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/db/__init__.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/devices/__init__.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/devices/attenuator.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/devices/esp_serial.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/devices/serial_dut.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/devices/serial_tools.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/env/__init__.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/env/base_env.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/env/wifi_env.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/esp_console/__init__.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/esp_console/wifi_cmd.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/interface/__init__.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/interface/dut.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/iperf_utility/__init__.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/iperf_utility/iperf_test.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/iperf_utility/iperf_test.test.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/logger/__init__.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/logger/logger.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/network/__init__.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/network/nic.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/scripts/monitor.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/scripts/set_att.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/tools/http_download.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/tools/pip_check.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/esptest/utility/gen_esp32part.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/example/jap_test.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/example/restart_test.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/setup.cfg +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/__init__.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/conftest.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/db/test_db_runners.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/esp_console/_files/wifi_cmd_connected_1.log +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/esp_console/_files/wifi_cmd_connected_2.log +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/esp_console/conftest.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/iperf_utility/_files/dut_iperf_rx1.log +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/iperf_utility/_files/dut_iperf_rx2.log +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/iperf_utility/_files/pc_iperf_rx.log +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/iperf_utility/_files/pc_iperf_rx2.log +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/iperf_utility/test_iperf_util.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/test_EnvConfig.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/test_import.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/tools/test_download_file.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/tools/test_pip_check.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/utility/_files/test-bin.zip +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/utility/_files/test-get-baud/ESP32AT-V4.1.1.0/sdkconfig +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tests/utility/test_parse_bin_path.py +0 -0
- {esp_test_utils-0.2.3 → esp_test_utils-0.3.1}/tools/ci/check_dev_version.py +0 -0
|
@@ -30,20 +30,87 @@ pre-commit-check:
|
|
|
30
30
|
# ------------------------------------------------------------------------------------------------------
|
|
31
31
|
# Pytest
|
|
32
32
|
# ------------------------------------------------------------------------------------------------------
|
|
33
|
-
pytest-
|
|
33
|
+
pytest-linux:
|
|
34
34
|
stage: test
|
|
35
35
|
needs: []
|
|
36
|
+
image: ${IMG}
|
|
36
37
|
before_script:
|
|
37
38
|
- pip install -e '.[test]'
|
|
38
39
|
script:
|
|
39
|
-
- pytest --junitxml=reports/junit.xml --cov=esptest --cov-report=term --cov-report xml:reports/coverage.xml
|
|
40
|
-
|
|
40
|
+
# - pytest --junitxml=reports/junit.xml --cov=esptest --cov-report=term --cov-report xml:reports/coverage.xml
|
|
41
|
+
- if [ "$IMG" = "python:3.11-bookworm" ]; then pip install pyecharts; fi # test with pyecharts installed
|
|
42
|
+
- export COVERAGE_FILE=.coverage.${CI_JOB_ID}
|
|
43
|
+
- pytest --junitxml=reports/junit.xml --cov=esptest --cov-report=term
|
|
44
|
+
# coverage: '/TOTAL.*\s+(\d+)\%/'
|
|
41
45
|
artifacts:
|
|
42
46
|
paths:
|
|
43
|
-
- reports/
|
|
47
|
+
# - reports/
|
|
44
48
|
- '.coverage*'
|
|
45
49
|
reports:
|
|
46
50
|
junit: reports/junit.xml
|
|
51
|
+
expire_in: 2 days
|
|
52
|
+
parallel:
|
|
53
|
+
matrix:
|
|
54
|
+
- IMG: "python:3.7-bullseye"
|
|
55
|
+
- IMG: "python:3.11-bookworm"
|
|
56
|
+
- IMG: "python:3.14-trixie"
|
|
57
|
+
tags:
|
|
58
|
+
- host_test
|
|
59
|
+
|
|
60
|
+
pytest-win32:
|
|
61
|
+
stage: test
|
|
62
|
+
needs:
|
|
63
|
+
- job: pytest-linux
|
|
64
|
+
artifacts: false
|
|
65
|
+
before_script:
|
|
66
|
+
- pymanager exec -V:$env:PYTHON_VER -m venv venv
|
|
67
|
+
- 'venv\Scripts\Activate.ps1'
|
|
68
|
+
- python -V
|
|
69
|
+
- pip install '.[test]'
|
|
70
|
+
script:
|
|
71
|
+
# - pytest --junitxml=reports/junit.xml --cov=esptest --cov-report=term --cov-report xml:reports/coverage.xml
|
|
72
|
+
- $env:COVERAGE_FILE = ".coverage.$env:CI_JOB_ID"
|
|
73
|
+
- pytest --junitxml=reports/junit.xml --cov=esptest --cov-report=term
|
|
74
|
+
# coverage: '/TOTAL.*\s+(\d+)\%/'
|
|
75
|
+
artifacts:
|
|
76
|
+
paths:
|
|
77
|
+
# - reports/
|
|
78
|
+
- '.coverage*'
|
|
79
|
+
reports:
|
|
80
|
+
junit: reports/junit.xml
|
|
81
|
+
expire_in: 2 days
|
|
82
|
+
parallel:
|
|
83
|
+
matrix:
|
|
84
|
+
- PYTHON_VER: "3.7"
|
|
85
|
+
- PYTHON_VER: "3.11"
|
|
86
|
+
- PYTHON_VER: "3.14"
|
|
87
|
+
tags:
|
|
88
|
+
- windows
|
|
89
|
+
- pymanager
|
|
90
|
+
|
|
91
|
+
pytest-coverage:
|
|
92
|
+
stage: test
|
|
93
|
+
needs:
|
|
94
|
+
- job: pytest-linux
|
|
95
|
+
artifacts: true
|
|
96
|
+
- job: pytest-win32
|
|
97
|
+
artifacts: false # Do not merge coverage from win32
|
|
98
|
+
before_script:
|
|
99
|
+
- pip install coverage
|
|
100
|
+
script:
|
|
101
|
+
- coverage combine .coverage*
|
|
102
|
+
- coverage report
|
|
103
|
+
- coverage xml
|
|
104
|
+
- coverage html
|
|
105
|
+
coverage: '/TOTAL.*\s+(\d+)\%/'
|
|
106
|
+
artifacts:
|
|
107
|
+
paths:
|
|
108
|
+
- htmlcov/
|
|
109
|
+
- '.coverage'
|
|
110
|
+
- coverage.xml
|
|
111
|
+
# reports:
|
|
112
|
+
# coverage: 'coverage.xml'
|
|
113
|
+
expire_in: 1 week
|
|
47
114
|
tags:
|
|
48
115
|
- host_test
|
|
49
116
|
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
## v0.3.1 (2026-01-16)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
- feat: add diff values for pyecharts
|
|
5
|
+
- feat: add secure boot check
|
|
6
|
+
- fix: pass pytest on windows
|
|
7
|
+
|
|
8
|
+
## v0.3.0 (2025-12-10)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
- feat: esp-listports support monitor mode
|
|
12
|
+
- feat: add more logs to H3CSwitch
|
|
13
|
+
- feat: esp-downbin support argument --force-no-stub
|
|
14
|
+
- feat: add h3c switch device control
|
|
15
|
+
- feat: add decorator timeit
|
|
16
|
+
|
|
1
17
|
## v0.2.3 (2025-11-14)
|
|
2
18
|
|
|
3
19
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: esp-test-utils
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: ESP Test Utils
|
|
5
5
|
Author-email: Chen Yudong <chenyudong@espressif.com>
|
|
6
6
|
License: Apache License
|
|
@@ -228,8 +228,10 @@ Requires-Dist: pyserial
|
|
|
228
228
|
Requires-Dist: PyYAML
|
|
229
229
|
Requires-Dist: pexpect
|
|
230
230
|
Requires-Dist: pyusb
|
|
231
|
+
Requires-Dist: pyudev
|
|
231
232
|
Requires-Dist: esptool
|
|
232
233
|
Requires-Dist: packaging
|
|
234
|
+
Requires-Dist: rich
|
|
233
235
|
Requires-Dist: sqlalchemy
|
|
234
236
|
Requires-Dist: typing_extensions; python_version < "3.11"
|
|
235
237
|
Provides-Extra: idfci
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: esp-test-utils
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: ESP Test Utils
|
|
5
5
|
Author-email: Chen Yudong <chenyudong@espressif.com>
|
|
6
6
|
License: Apache License
|
|
@@ -228,8 +228,10 @@ Requires-Dist: pyserial
|
|
|
228
228
|
Requires-Dist: PyYAML
|
|
229
229
|
Requires-Dist: pexpect
|
|
230
230
|
Requires-Dist: pyusb
|
|
231
|
+
Requires-Dist: pyudev
|
|
231
232
|
Requires-Dist: esptool
|
|
232
233
|
Requires-Dist: packaging
|
|
234
|
+
Requires-Dist: rich
|
|
233
235
|
Requires-Dist: sqlalchemy
|
|
234
236
|
Requires-Dist: typing_extensions; python_version < "3.11"
|
|
235
237
|
Provides-Extra: idfci
|
|
@@ -52,6 +52,7 @@ esptest/devices/attenuator.py
|
|
|
52
52
|
esptest/devices/esp_serial.py
|
|
53
53
|
esptest/devices/serial_dut.py
|
|
54
54
|
esptest/devices/serial_tools.py
|
|
55
|
+
esptest/devices/switch.py
|
|
55
56
|
esptest/env/__init__.py
|
|
56
57
|
esptest/env/base_env.py
|
|
57
58
|
esptest/env/wifi_env.py
|
|
@@ -79,6 +80,7 @@ esptest/tools/copy_bin.py
|
|
|
79
80
|
esptest/tools/download_bin.py
|
|
80
81
|
esptest/tools/http_download.py
|
|
81
82
|
esptest/tools/pip_check.py
|
|
83
|
+
esptest/tools/uart_monitor.py
|
|
82
84
|
esptest/utility/gen_esp32part.py
|
|
83
85
|
esptest/utility/parse_bin_path.py
|
|
84
86
|
example/jap_test.py
|
|
@@ -93,6 +95,7 @@ tests/adapter/test_shell_port.py
|
|
|
93
95
|
tests/basic/test_decorators.py
|
|
94
96
|
tests/basic/test_network.py
|
|
95
97
|
tests/db/test_db_runners.py
|
|
98
|
+
tests/devices/test_switch.py
|
|
96
99
|
tests/esp_console/conftest.py
|
|
97
100
|
tests/esp_console/test_WifiCmd.py
|
|
98
101
|
tests/esp_console/_files/wifi_cmd_connected_1.log
|
|
@@ -258,9 +258,9 @@ class DutBase(VariablesMixin, DutInterface): # pylint: disable=too-many-public-
|
|
|
258
258
|
@overload
|
|
259
259
|
def expect(self, pattern: bytes, timeout: float = 30) -> None: ...
|
|
260
260
|
@overload
|
|
261
|
-
def expect(self, pattern: re.Pattern[str], timeout: float = 30) -> re.Match[str]: ...
|
|
261
|
+
def expect(self, pattern: 're.Pattern[str]', timeout: float = 30) -> 're.Match[str]': ...
|
|
262
262
|
@overload
|
|
263
|
-
def expect(self, pattern: re.Pattern[bytes], timeout: float = 30) -> re.Match[bytes]: ...
|
|
263
|
+
def expect(self, pattern: 're.Pattern[bytes]', timeout: float = 30) -> 're.Match[bytes]': ...
|
|
264
264
|
|
|
265
265
|
def expect(self, pattern, timeout=30): # type: ignore
|
|
266
266
|
if self._base_port_proxy:
|
|
@@ -6,7 +6,7 @@ from ...common.generator import get_next_index
|
|
|
6
6
|
from ...interface.dut import DutInterface
|
|
7
7
|
from ...logger import get_logger
|
|
8
8
|
from ..port.base_port import RawPort
|
|
9
|
-
from ..port.serial_port import SerialExt, SerialPort
|
|
9
|
+
from ..port.serial_port import SerialExt, SerialPort, serial_add_mixin
|
|
10
10
|
from .create_dut import create_dut
|
|
11
11
|
from .dut_base import DutBase, DutConfig
|
|
12
12
|
from .esp_dut import EspDut
|
|
@@ -62,6 +62,11 @@ def dut_wrapper(dut, name='', log_file='', wrap_cls=None): # type: ignore
|
|
|
62
62
|
dut.__class__ = SerialExt
|
|
63
63
|
dut_config = DutConfig(opened_port=dut, name=_name, log_file=log_file)
|
|
64
64
|
wrap_dut = wrap_cls(dut_config=dut_config)
|
|
65
|
+
elif isinstance(dut, serial.SerialBase):
|
|
66
|
+
_name = name or dut.port.split('/')[-1]
|
|
67
|
+
dut.__class__ = serial_add_mixin(dut.__class__)
|
|
68
|
+
dut_config = DutConfig(opened_port=dut, name=_name, log_file=log_file)
|
|
69
|
+
wrap_dut = wrap_cls(dut_config=dut_config)
|
|
65
70
|
elif isinstance(dut, RawPort):
|
|
66
71
|
_name = name
|
|
67
72
|
if not _name:
|
|
@@ -5,13 +5,12 @@ import logging
|
|
|
5
5
|
import os
|
|
6
6
|
import queue
|
|
7
7
|
import re
|
|
8
|
+
import sys
|
|
8
9
|
import threading
|
|
9
10
|
import time
|
|
10
11
|
from dataclasses import dataclass
|
|
11
12
|
from typing import overload
|
|
12
13
|
|
|
13
|
-
import pexpect.spawnbase
|
|
14
|
-
|
|
15
14
|
import esptest.common.compat_typing as t
|
|
16
15
|
|
|
17
16
|
from ...common import timestamp_str, to_bytes, to_str
|
|
@@ -19,6 +18,18 @@ from ...common.decorators import deprecated
|
|
|
19
18
|
from ...interface.port import PortInterface
|
|
20
19
|
from ...logger import get_logger
|
|
21
20
|
|
|
21
|
+
if sys.platform == 'win32':
|
|
22
|
+
import pexpect
|
|
23
|
+
from pexpect.exceptions import ExceptionPexpect
|
|
24
|
+
from pexpect.spawnbase import SpawnBase
|
|
25
|
+
# from wexpect import SpawnPipe as SpawnBase
|
|
26
|
+
# from wexpect import ExceptionPexpect
|
|
27
|
+
else:
|
|
28
|
+
import pexpect
|
|
29
|
+
from pexpect.exceptions import ExceptionPexpect
|
|
30
|
+
from pexpect.spawnbase import SpawnBase
|
|
31
|
+
|
|
32
|
+
|
|
22
33
|
logger = get_logger('port')
|
|
23
34
|
NEVER_MATCHED_MAGIC_STRING = 'o6K,Q.(w+~yr~N9R'
|
|
24
35
|
|
|
@@ -26,6 +37,13 @@ NEVER_MATCHED_MAGIC_STRING = 'o6K,Q.(w+~yr~N9R'
|
|
|
26
37
|
class ExpectTimeout(TimeoutError):
|
|
27
38
|
"""raise same ExpectTimeout rather than different Exception from different framework"""
|
|
28
39
|
|
|
40
|
+
def __init__(self, message: str, data_in_buffer: t.Union[str, bytes] = b'') -> None:
|
|
41
|
+
super().__init__(message)
|
|
42
|
+
self.data_in_buffer: t.Union[str, bytes] = data_in_buffer
|
|
43
|
+
|
|
44
|
+
def __str__(self) -> str:
|
|
45
|
+
return f'{super().__str__()}\n data_in_buffer={repr(self.data_in_buffer)}'
|
|
46
|
+
|
|
29
47
|
|
|
30
48
|
class RawPort(metaclass=abc.ABCMeta):
|
|
31
49
|
"""Define a minimum Dut class, the dut objects should at least support these methods
|
|
@@ -74,7 +92,7 @@ class SpawnConfig:
|
|
|
74
92
|
# TODO: monitors
|
|
75
93
|
|
|
76
94
|
|
|
77
|
-
class PortSpawn(
|
|
95
|
+
class PortSpawn(SpawnBase, t.Generic[T]):
|
|
78
96
|
"""Create a new class for pexpect with port read()/write() method.
|
|
79
97
|
|
|
80
98
|
There's some reason that we can not use pyserial with pexpect.fdpexpect directly:
|
|
@@ -261,6 +279,27 @@ class PortSpawn(pexpect.spawnbase.SpawnBase, t.Generic[T]):
|
|
|
261
279
|
self._line_cache = b''
|
|
262
280
|
|
|
263
281
|
|
|
282
|
+
def handle_expect_timeout(func: t.Callable) -> t.Callable:
|
|
283
|
+
"""Raise same type exception ExpectTimeout for ports from different frameworks"""
|
|
284
|
+
|
|
285
|
+
@functools.wraps(func)
|
|
286
|
+
def wrap(obj: 'BasePort', *args, **kwargs): # type: ignore
|
|
287
|
+
try:
|
|
288
|
+
result = func(obj, *args, **kwargs)
|
|
289
|
+
except obj.expect_timeout_exceptions as e:
|
|
290
|
+
data_in_buffer = ''
|
|
291
|
+
try:
|
|
292
|
+
if obj._pexpect_spawn: # pylint: disable=protected-access
|
|
293
|
+
data_in_buffer = obj._pexpect_spawn.before # pylint: disable=protected-access
|
|
294
|
+
except AttributeError:
|
|
295
|
+
pass # ignore
|
|
296
|
+
obj.logger.debug(f'ExpectTimeout: {str(e)}, data_in_buffer={repr(data_in_buffer)}')
|
|
297
|
+
raise ExpectTimeout(str(e), data_in_buffer=data_in_buffer) from e
|
|
298
|
+
return result
|
|
299
|
+
|
|
300
|
+
return wrap
|
|
301
|
+
|
|
302
|
+
|
|
264
303
|
class BasePort(PortInterface, t.Generic[T]):
|
|
265
304
|
"""A class to simply port methods for all devices / shell / sockets to similar usage
|
|
266
305
|
|
|
@@ -271,7 +310,7 @@ class BasePort(PortInterface, t.Generic[T]):
|
|
|
271
310
|
|
|
272
311
|
EXPECT_TIMEOUT_EXCEPTIONS: t.Tuple[t.Type[Exception], ...] = (
|
|
273
312
|
TimeoutError,
|
|
274
|
-
|
|
313
|
+
ExceptionPexpect,
|
|
275
314
|
)
|
|
276
315
|
INIT_START_REDIRECT_THREAD: bool = True
|
|
277
316
|
PEXPECT_DEFAULT_TIMEOUT: float = 30
|
|
@@ -399,20 +438,6 @@ class BasePort(PortInterface, t.Generic[T]):
|
|
|
399
438
|
if stopped:
|
|
400
439
|
self.start_redirect_thread()
|
|
401
440
|
|
|
402
|
-
@staticmethod
|
|
403
|
-
def handle_expect_timeout(func: t.Callable) -> t.Callable:
|
|
404
|
-
"""Raise same type exception ExpectTimeout for ports from different frameworks"""
|
|
405
|
-
|
|
406
|
-
@functools.wraps(func)
|
|
407
|
-
def wrap(self, *args, **kwargs): # type: ignore
|
|
408
|
-
try:
|
|
409
|
-
result = func(self, *args, **kwargs)
|
|
410
|
-
except self.expect_timeout_exceptions as e:
|
|
411
|
-
raise ExpectTimeout(str(e)) from e
|
|
412
|
-
return result
|
|
413
|
-
|
|
414
|
-
return wrap
|
|
415
|
-
|
|
416
441
|
def write(self, data: t.AnyStr) -> None:
|
|
417
442
|
if self._pexpect_spawn:
|
|
418
443
|
return self._pexpect_spawn.write(data)
|
|
@@ -434,9 +459,9 @@ class BasePort(PortInterface, t.Generic[T]):
|
|
|
434
459
|
@overload
|
|
435
460
|
def expect(self, pattern: bytes, timeout: float = 30) -> None: ...
|
|
436
461
|
@overload
|
|
437
|
-
def expect(self, pattern: re.Pattern[str], timeout: float = 30) -> re.Match[str]: ...
|
|
462
|
+
def expect(self, pattern: 're.Pattern[str]', timeout: float = 30) -> 're.Match[str]': ...
|
|
438
463
|
@overload
|
|
439
|
-
def expect(self, pattern: re.Pattern[bytes], timeout: float = 30) -> re.Match[bytes]: ...
|
|
464
|
+
def expect(self, pattern: 're.Pattern[bytes]', timeout: float = 30) -> 're.Match[bytes]': ...
|
|
440
465
|
|
|
441
466
|
@handle_expect_timeout
|
|
442
467
|
def expect(self, pattern, timeout=PEXPECT_DEFAULT_TIMEOUT): # type: ignore
|
|
@@ -1,28 +1,43 @@
|
|
|
1
1
|
import time
|
|
2
|
-
from typing import TYPE_CHECKING
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
3
|
|
|
4
4
|
import serial
|
|
5
|
-
from serial import Serial
|
|
5
|
+
from serial import Serial, SerialBase
|
|
6
|
+
|
|
7
|
+
import esptest.common.compat_typing as t
|
|
6
8
|
|
|
7
9
|
from ...common import to_bytes
|
|
8
10
|
from ...logger import get_logger
|
|
9
11
|
from .base_port import BasePort
|
|
10
12
|
|
|
11
13
|
if TYPE_CHECKING:
|
|
12
|
-
MixinBase: TypeAlias = 'BasePort'
|
|
14
|
+
MixinBase: t.TypeAlias = 'BasePort'
|
|
13
15
|
else:
|
|
14
16
|
MixinBase = object
|
|
15
17
|
|
|
16
18
|
logger = get_logger('ser_port')
|
|
17
19
|
|
|
18
20
|
|
|
19
|
-
class
|
|
20
|
-
|
|
21
|
+
class SerialBaseProtocol(t.Protocol):
|
|
22
|
+
@property
|
|
23
|
+
def port(self) -> t.Optional[str]: ...
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
def baudrate(self) -> t.Optional[int]: ...
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def timeout(self) -> t.Optional[float]: ...
|
|
30
|
+
|
|
31
|
+
def read(self, size: int = 1) -> bytes: ...
|
|
32
|
+
|
|
33
|
+
def write(self, data: t.AnyStr) -> int: ...
|
|
21
34
|
|
|
35
|
+
|
|
36
|
+
class SerMixin(SerialBaseProtocol):
|
|
22
37
|
@property
|
|
23
38
|
def read_timeout(self) -> float:
|
|
24
39
|
# For PortSpawn
|
|
25
|
-
return
|
|
40
|
+
return self.timeout or 0.001 # type: ignore
|
|
26
41
|
|
|
27
42
|
def read_bytes(self, timeout: float = 0.001) -> bytes:
|
|
28
43
|
# For PortSpawn
|
|
@@ -30,25 +45,52 @@ class SerialExt(Serial):
|
|
|
30
45
|
assert self.timeout >= 0.001
|
|
31
46
|
if timeout > self.timeout:
|
|
32
47
|
time.sleep(timeout - self.timeout)
|
|
33
|
-
return
|
|
48
|
+
return self.read(1024) # type: ignore
|
|
34
49
|
|
|
35
|
-
def write_bytes(self, data: AnyStr) ->
|
|
50
|
+
def write_bytes(self, data: t.AnyStr) -> int:
|
|
36
51
|
# For PortSpawn
|
|
37
|
-
|
|
52
|
+
self.write(to_bytes(data))
|
|
53
|
+
return len(to_bytes(data))
|
|
38
54
|
|
|
39
55
|
def __str__(self) -> str:
|
|
40
|
-
"""
|
|
41
|
-
return f'
|
|
56
|
+
"""SerialExt<device=xxx,baudrate=xxx,timeout=xxx>"""
|
|
57
|
+
return f'SerialExt<device={self.port},baudrate={self.baudrate},timeout={self.timeout}>'
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class SerialExt(Serial, SerMixin):
|
|
61
|
+
"""Add RawPort methods to serial.Serial"""
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def serial_add_mixin(cls: t.Type[t.Any]) -> t.Type[t.Any]:
|
|
65
|
+
"""动态为类添加 SerMixin"""
|
|
66
|
+
# 创建一个新的类,继承自原始类和 SerMixin
|
|
67
|
+
# 基类顺序与 SerialExt(Serial, SerMixin) 保持一致
|
|
68
|
+
return type(f'{cls.__name__}Ext', (cls, SerMixin), {})
|
|
42
69
|
|
|
43
70
|
|
|
44
71
|
class SerialPortMixin(MixinBase):
|
|
45
72
|
"""Add RawPort methods to serial.Serial"""
|
|
46
73
|
|
|
47
|
-
|
|
48
|
-
|
|
74
|
+
@staticmethod
|
|
75
|
+
def _add_mixin_by_type(raw_port: t.Any) -> None:
|
|
76
|
+
"""根据原始类型添加对应的 mixin"""
|
|
77
|
+
if raw_port is None:
|
|
78
|
+
return
|
|
79
|
+
original_type = type(raw_port)
|
|
80
|
+
# If the original type already includes SerMixin, do nothing.
|
|
81
|
+
# This prevents repeatedly nesting mixin classes when the serial
|
|
82
|
+
# object is reassigned and _add_mixin_by_type is called multiple times.
|
|
83
|
+
if issubclass(original_type, SerMixin):
|
|
84
|
+
return
|
|
85
|
+
if issubclass(original_type, Serial):
|
|
49
86
|
raw_port.__class__ = SerialExt
|
|
87
|
+
elif issubclass(original_type, SerialBase):
|
|
88
|
+
raw_port.__class__ = serial_add_mixin(original_type)
|
|
89
|
+
|
|
90
|
+
def __init__(self, raw_port: t.Any, name: str, log_file: str = '') -> None:
|
|
91
|
+
self._add_mixin_by_type(raw_port)
|
|
50
92
|
super().__init__(raw_port, name, log_file)
|
|
51
|
-
self._serial_config: Dict[str, Any] = {}
|
|
93
|
+
self._serial_config: t.Dict[str, t.Any] = {}
|
|
52
94
|
|
|
53
95
|
def start_redirect_thread(self) -> None:
|
|
54
96
|
if not self.serial:
|
|
@@ -72,12 +114,12 @@ class SerialPortMixin(MixinBase):
|
|
|
72
114
|
super().start_redirect_thread()
|
|
73
115
|
|
|
74
116
|
@property
|
|
75
|
-
def serial(self) -> Optional[SerialExt]:
|
|
117
|
+
def serial(self) -> t.Optional[SerialExt]:
|
|
76
118
|
"""Get Current serial instance."""
|
|
77
119
|
return self._raw_port # type: ignore
|
|
78
120
|
|
|
79
121
|
@serial.setter
|
|
80
|
-
def serial(self, serial_instance: Optional[Serial]) -> None:
|
|
122
|
+
def serial(self, serial_instance: t.Optional[Serial]) -> None:
|
|
81
123
|
"""Set serial instance, will close and clean up the old serial resources"""
|
|
82
124
|
if self._raw_port:
|
|
83
125
|
# Close pexpect proc
|
|
@@ -87,7 +129,7 @@ class SerialPortMixin(MixinBase):
|
|
|
87
129
|
# self._port.close()
|
|
88
130
|
if serial_instance:
|
|
89
131
|
self._raw_port = serial_instance
|
|
90
|
-
self.
|
|
132
|
+
self._add_mixin_by_type(serial_instance)
|
|
91
133
|
self.start_redirect_thread()
|
|
92
134
|
|
|
93
135
|
def close(self) -> None:
|
|
@@ -107,7 +149,7 @@ class SerialPort(SerialPortMixin, BasePort):
|
|
|
107
149
|
This class using serial with pexpect.
|
|
108
150
|
"""
|
|
109
151
|
|
|
110
|
-
def __init__(self, dut: Serial, name: str, log_file: str = '', **kwargs: Any) -> None:
|
|
152
|
+
def __init__(self, dut: Serial, name: str, log_file: str = '', **kwargs: t.Any) -> None:
|
|
111
153
|
if not dut:
|
|
112
154
|
self.INIT_START_REDIRECT_THREAD = False # pylint: disable=invalid-name
|
|
113
155
|
super().__init__(dut, name, log_file, **kwargs)
|