mesk 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. mesk-0.1.0/PKG-INFO +205 -0
  2. mesk-0.1.0/README.md +170 -0
  3. mesk-0.1.0/pyproject.toml +125 -0
  4. mesk-0.1.0/setup.cfg +4 -0
  5. mesk-0.1.0/setup.py +3 -0
  6. mesk-0.1.0/src/mesk/__init__.py +10 -0
  7. mesk-0.1.0/src/mesk/__main__.py +80 -0
  8. mesk-0.1.0/src/mesk/__version__.py +1 -0
  9. mesk-0.1.0/src/mesk/py.typed +0 -0
  10. mesk-0.1.0/src/mesk/runner.py +224 -0
  11. mesk-0.1.0/src/mesk/vendor/__init__.py +0 -0
  12. mesk-0.1.0/src/mesk/vendor/boardctrl_phidget/README.md +244 -0
  13. mesk-0.1.0/src/mesk/vendor/boardctrl_phidget/__init__.py +0 -0
  14. mesk-0.1.0/src/mesk/vendor/boardctrl_phidget/monitor.py +232 -0
  15. mesk-0.1.0/src/mesk/vendor/boardctrl_phidget/phidget.py +224 -0
  16. mesk-0.1.0/src/mesk/vendor/boardctrl_phidget/phidget_control.sh +324 -0
  17. mesk-0.1.0/src/mesk/vendor/topo/Android.mk +27 -0
  18. mesk-0.1.0/src/mesk/vendor/topo/TCA9539.py +70 -0
  19. mesk-0.1.0/src/mesk/vendor/topo/__init__.py +0 -0
  20. mesk-0.1.0/src/mesk/vendor/topo/_targets/_PCA953x.py +134 -0
  21. mesk-0.1.0/src/mesk/vendor/topo/_targets/_TCA6408.py +122 -0
  22. mesk-0.1.0/src/mesk/vendor/topo/_targets/__init__.py +0 -0
  23. mesk-0.1.0/src/mesk/vendor/topo/_targets/_common.py +203 -0
  24. mesk-0.1.0/src/mesk/vendor/topo/_targets/_nv_base_orin_target.py +37 -0
  25. mesk-0.1.0/src/mesk/vendor/topo/_targets/_nv_base_thor_target.py +47 -0
  26. mesk-0.1.0/src/mesk/vendor/topo/_targets/_nv_base_topo_target.py +249 -0
  27. mesk-0.1.0/src/mesk/vendor/topo/_targets/_nv_thor_target.py +21 -0
  28. mesk-0.1.0/src/mesk/vendor/topo/_targets/_nv_topo_target.py +21 -0
  29. mesk-0.1.0/src/mesk/vendor/topo/_targets/concord.py +21 -0
  30. mesk-0.1.0/src/mesk/vendor/topo/_targets/horizon-eb1.py +99 -0
  31. mesk-0.1.0/src/mesk/vendor/topo/_targets/jane.py +44 -0
  32. mesk-0.1.0/src/mesk/vendor/topo/_targets/orin-jetson.py +21 -0
  33. mesk-0.1.0/src/mesk/vendor/topo/_targets/orin-slt.py +32 -0
  34. mesk-0.1.0/src/mesk/vendor/topo/_targets/t239-slt.py +28 -0
  35. mesk-0.1.0/src/mesk/vendor/topo/_targets/t268-slt.py +262 -0
  36. mesk-0.1.0/src/mesk/vendor/topo/_targets/tango.py +75 -0
  37. mesk-0.1.0/src/mesk/vendor/topo/_targets/thor-andor-slt.py +253 -0
  38. mesk-0.1.0/src/mesk/vendor/topo/_targets/thor-cassian-slt.py +21 -0
  39. mesk-0.1.0/src/mesk/vendor/topo/_targets/thor-drive-agx.py +21 -0
  40. mesk-0.1.0/src/mesk/vendor/topo/_targets/thor-drive-agx2.py +105 -0
  41. mesk-0.1.0/src/mesk/vendor/topo/_targets/thor-drive-pm.py +21 -0
  42. mesk-0.1.0/src/mesk/vendor/topo/_targets/thor-hope.py +21 -0
  43. mesk-0.1.0/src/mesk/vendor/topo/_targets/thor-jetson-devkit.py +21 -0
  44. mesk-0.1.0/src/mesk/vendor/topo/_targets/thor-jetson-module.py +21 -0
  45. mesk-0.1.0/src/mesk/vendor/topo/_targets/thor-l4t-pm.py +21 -0
  46. mesk-0.1.0/src/mesk/vendor/topo/_targets/thor-slt.py +262 -0
  47. mesk-0.1.0/src/mesk/vendor/topo/_targets/topo.py +21 -0
  48. mesk-0.1.0/src/mesk/vendor/topo/_targets/yukon.py +75 -0
  49. mesk-0.1.0/src/mesk/vendor/topo/bmc_interface.py +441 -0
  50. mesk-0.1.0/src/mesk/vendor/topo/board_control.py +74 -0
  51. mesk-0.1.0/src/mesk/vendor/topo/board_info.py +104 -0
  52. mesk-0.1.0/src/mesk/vendor/topo/boardctl +216 -0
  53. mesk-0.1.0/src/mesk/vendor/topo/debug_board.py +308 -0
  54. mesk-0.1.0/src/mesk/vendor/topo/e2379.py +130 -0
  55. mesk-0.1.0/src/mesk/vendor/topo/ftdi_i2c_lin.py +337 -0
  56. mesk-0.1.0/src/mesk/vendor/topo/ftdi_wrapper.py +103 -0
  57. mesk-0.1.0/src/mesk/vendor/topo/galen_power.py +40 -0
  58. mesk-0.1.0/src/mesk/vendor/topo/ina219.py +167 -0
  59. mesk-0.1.0/src/mesk/vendor/topo/ina226.py +197 -0
  60. mesk-0.1.0/src/mesk/vendor/topo/ina3221.py +135 -0
  61. mesk-0.1.0/src/mesk/vendor/topo/libnvtopo.so +0 -0
  62. mesk-0.1.0/src/mesk/vendor/topo/libnvtopo_wrapper.py +516 -0
  63. mesk-0.1.0/src/mesk/vendor/topo/lspm342.py +49 -0
  64. mesk-0.1.0/src/mesk/vendor/topo/measure +324 -0
  65. mesk-0.1.0/src/mesk/vendor/topo/measure_power +130 -0
  66. mesk-0.1.0/src/mesk/vendor/topo/metadata.py +158 -0
  67. mesk-0.1.0/src/mesk/vendor/topo/nvtopo.py +516 -0
  68. mesk-0.1.0/src/mesk/vendor/topo/pca954x.py +41 -0
  69. mesk-0.1.0/src/mesk/vendor/topo/pm342.py +122 -0
  70. mesk-0.1.0/src/mesk/vendor/topo/power.py +93 -0
  71. mesk-0.1.0/src/mesk/vendor/topo/requirements-bmc.txt +5 -0
  72. mesk-0.1.0/src/mesk/vendor/topo/supported_targets.py +16 -0
  73. mesk-0.1.0/src/mesk/vendor/topo/supported_targets_all.py +16 -0
  74. mesk-0.1.0/src/mesk/vendor/topo/tb500-ctl +792 -0
  75. mesk-0.1.0/src/mesk/vendor/topo/tckctrl +110 -0
  76. mesk-0.1.0/src/mesk/vendor/topo/th500-ctl +282 -0
  77. mesk-0.1.0/src/mesk/vendor/topo/utils.py +91 -0
  78. mesk-0.1.0/src/mesk/vendor/topo_yukon/README.txt +41 -0
  79. mesk-0.1.0/src/mesk/vendor/topo_yukon/__init__.py +6 -0
  80. mesk-0.1.0/src/mesk/vendor/topo_yukon/_targets/__init__.py +0 -0
  81. mesk-0.1.0/src/mesk/vendor/topo_yukon/_targets/_common.py +202 -0
  82. mesk-0.1.0/src/mesk/vendor/topo_yukon/_targets/_nv_base_topo_target.py +246 -0
  83. mesk-0.1.0/src/mesk/vendor/topo_yukon/_targets/yukon.py +75 -0
  84. mesk-0.1.0/src/mesk/vendor/topo_yukon/boardctl +216 -0
  85. mesk-0.1.0/src/mesk/vendor/topo_yukon/libnvtopo.dll +0 -0
  86. mesk-0.1.0/src/mesk/vendor/topo_yukon/libnvtopo.so +0 -0
  87. mesk-0.1.0/src/mesk/vendor/topo_yukon/libnvtopo_wrapper.py +513 -0
  88. mesk-0.1.0/src/mesk/vendor/topo_yukon/nvtopo.py +511 -0
  89. mesk-0.1.0/src/mesk.egg-info/PKG-INFO +205 -0
  90. mesk-0.1.0/src/mesk.egg-info/SOURCES.txt +93 -0
  91. mesk-0.1.0/src/mesk.egg-info/dependency_links.txt +1 -0
  92. mesk-0.1.0/src/mesk.egg-info/entry_points.txt +2 -0
  93. mesk-0.1.0/src/mesk.egg-info/requires.txt +17 -0
  94. mesk-0.1.0/src/mesk.egg-info/top_level.txt +1 -0
  95. mesk-0.1.0/tests/test_reset.py +313 -0
mesk-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,205 @@
1
+ Metadata-Version: 2.4
2
+ Name: mesk
3
+ Version: 0.1.0
4
+ Summary: Unified power and reset control for Concord, N1-auto, Yukon, and Tango platforms
5
+ Author-email: Miley Zhang <mileyz@nvidia.com>
6
+ License-Expression: LicenseRef-NvidiaProprietary
7
+ Project-URL: Repository, https://gitlab-master.nvidia.com/mileyz/mesk
8
+ Keywords: nvidia,board,reset,power,ci
9
+ Classifier: Operating System :: Microsoft :: Windows
10
+ Classifier: Operating System :: POSIX :: Linux
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.8
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: System :: Hardware
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.8
22
+ Description-Content-Type: text/markdown
23
+ Requires-Dist: pyusb
24
+ Provides-Extra: dev
25
+ Requires-Dist: ruff==0.16.6; extra == "dev"
26
+ Requires-Dist: ty==0.0.78; extra == "dev"
27
+ Provides-Extra: test
28
+ Requires-Dist: pytest==8.3.1; extra == "test"
29
+ Requires-Dist: pytest-cov==5.0.0; extra == "test"
30
+ Requires-Dist: pytest-timeout==2.3.1; extra == "test"
31
+ Requires-Dist: pytest-xdist==3.6.1; python_version >= "3.9" and extra == "test"
32
+ Requires-Dist: coverage==7.6.0; extra == "test"
33
+ Provides-Extra: n1-auto
34
+ Requires-Dist: Phidget22; extra == "n1-auto"
35
+
36
+ # mesk
37
+
38
+ Unified power and reset control for Concord, N1-auto, Yukon, and Tango platforms.
39
+ Designed for use in DLA compiler CI/CD pipelines.
40
+
41
+ ## Install and run
42
+
43
+ ```bash
44
+ git clone https://gitlab-master.nvidia.com/mileyz/mesk.git
45
+ cd mesk
46
+ ./mesk concord power_off
47
+ ./mesk concord power_on
48
+ ./mesk concord reset
49
+ ./mesk concord recovery
50
+ ```
51
+
52
+ On Windows (Yukon / Tango), from cmd or PowerShell:
53
+
54
+ ```bat
55
+ git clone https://gitlab-master.nvidia.com/mileyz/mesk.git
56
+ cd mesk
57
+ .\mesk yukon power_off
58
+ .\mesk yukon power_on
59
+ .\mesk yukon reset
60
+ .\mesk yukon recovery
61
+ ```
62
+
63
+ First run creates `.venv` and installs the package. Later runs skip that.
64
+ Do not activate the venv yourself; `./mesk` (Linux) and `.\mesk` (Windows `mesk.cmd`) do that.
65
+ On Linux, the first `./mesk concord <action>` writes `/etc/sudoers.d/mesk` (prompts for sudo once) so all later runs are passwordless. Set `MESK_NO_SUDO=1` to skip sudo entirely.
66
+ `./mesk n1-auto ...` installs `Phidget22` into the venv if it is missing.
67
+
68
+ Developers who want lint/test tools can still use:
69
+
70
+ ```bash
71
+ python3 -m venv .venv
72
+ source .venv/bin/activate
73
+ pip install -e ".[dev,test]"
74
+ ```
75
+
76
+ **Examples:**
77
+
78
+ ```bash
79
+ mesk concord reset
80
+ mesk concord recovery
81
+ mesk concord power_on
82
+ mesk concord power_off
83
+
84
+ mesk n1-auto reset
85
+ mesk n1-auto recovery
86
+ mesk n1-auto power_on
87
+ mesk n1-auto power_off
88
+
89
+ mesk yukon reset
90
+ mesk yukon recovery
91
+ mesk yukon power_on
92
+ mesk yukon power_off
93
+
94
+ mesk tango reset
95
+ mesk tango recovery
96
+ mesk tango power_on
97
+ mesk tango power_off
98
+ ```
99
+
100
+ ## Library Usage
101
+
102
+ ```python
103
+ from mesk import run
104
+
105
+ run("concord", "reset")
106
+ run("n1-auto", "power_on")
107
+ run("yukon", "recovery")
108
+ run("tango", "reset")
109
+ ```
110
+
111
+ `run()` returns 0 on success and a non-zero exit code on failure.
112
+
113
+ ## Project Layout
114
+
115
+ ```
116
+ mesk/
117
+ ├── pyproject.toml # build config + all tool settings
118
+ ├── setup.py # legacy pip editable compatibility
119
+ ├── mesk # Linux/L4T bootstrap launcher
120
+ ├── mesk.cmd # Windows bootstrap launcher
121
+ ├── .pre-commit-config.yaml
122
+ ├── README.md
123
+ ├── src/mesk/
124
+ │ ├── __init__.py # public API: run, ACTIONS, __version__
125
+ │ ├── __version__.py
126
+ │ ├── __main__.py # CLI entry
127
+ │ ├── runner.py # action execution + logging
128
+ │ ├── py.typed
129
+ │ └── vendor/ # bundled board control tools
130
+ │ ├── topo/ # Concord (boardctl)
131
+ │ ├── boardctrl_phidget/ # N1-auto
132
+ │ └── topo_yukon/ # Yukon and Tango (boardctl)
133
+ └── tests/
134
+ ```
135
+
136
+ ## Logging
137
+
138
+ Each run appends to `logs/YYYY-MM-DD.log` under the current working directory
139
+ (timestamp, platform, action, exit code, and full output).
140
+ Override with `MESK_LOG_DIR`.
141
+
142
+ ## Prerequisites
143
+
144
+ Actions call vendor Python APIs in-process (`import`), not shell/`subprocess`.
145
+
146
+ ### Concord (Linux host)
147
+
148
+ - Needs the NVIDIA TOPO USB device (`0955:7045`). The first run of `./mesk concord <action>` installs a NOPASSWD sudoers rule automatically; subsequent runs need no password.
149
+ - `pyusb` is installed with mesk for recovery detection.
150
+ - After `concord recovery`, mesk checks USB for `0955:7023` (APX) and fails if it is missing. boardctl may still print `NOT IN RECOVERY MODE`.
151
+
152
+ ### N1-auto (Linux host)
153
+
154
+ `./mesk n1-auto <action>` installs `Phidget22` into the venv and, if needed, `libphidget22` via apt (sudo). Set `MESK_NO_SUDO=1` to skip the system-library install.
155
+
156
+ ### Yukon / Tango (Windows host)
157
+
158
+ `.\mesk yukon <action>` or `.\mesk tango <action>` creates `.venv` and installs mesk on first run. Needs Python 3.8+ on PATH (or `py -3`) and the TOPO USB device. No sudo.
159
+
160
+ ## Platforms & Supported Operations
161
+
162
+ | Action | Concord (L4T) | N1-auto (Auto-Linux) | Yukon / Tango (WoA) |
163
+ |--------|---------------|----------------------|---------------------|
164
+ | `reset` | `nv_topo(target="topo").target_reset()` | `ResetControl(1).execute_reset()` | `nv_topo(target="yukon").target_reset()` |
165
+ | `recovery` | `nv_topo(target="topo").target_recovery_mode()` | `RecoveryControl(1, 0).execute_recovery()` | `nv_topo(target="yukon").target_recovery_mode()` |
166
+ | `power_on` | `nv_topo(target="topo").target_power_on()` | `PowerMonitor(2, False)` then `relay_off(2)` | `nv_topo(target="yukon").target_power_on()` |
167
+ | `power_off` | `nv_topo(target="topo").target_power_off()` | `PowerMonitor(2, True)` then `relay_on(2)` | `nv_topo(target="yukon").target_power_off()` |
168
+
169
+ Tango uses the same `topo_yukon` `nv_topo` target as Yukon (`target="yukon"`).
170
+ N1-auto power is a one-shot relay set (no background `monitor.py` process).
171
+
172
+ ## Contribute
173
+
174
+ Suggested local Python: 3.12+ (pre-commit assumes > 3.8 for `pytest -n auto`).
175
+
176
+ pre-commit runs Ruff (format + lint), ty, and pytest. All of these skip
177
+ `vendor/` directories (bundled third-party board tools) so upstream trees
178
+ are not rewritten and can be replaced as drop-in upgrades.
179
+
180
+ ```bash
181
+ python -m venv .venv
182
+ source .venv/bin/activate
183
+ pip install -e ".[dev,test]"
184
+ pip install pre-commit
185
+ pre-commit install
186
+ # Optionally run all hooks
187
+ pre-commit run --all-files
188
+ ```
189
+
190
+ ```bash
191
+ pytest
192
+ ruff check .
193
+ ty check
194
+ ```
195
+
196
+ ## Test Status
197
+
198
+ | Platform | reset | power_on | power_off | recovery |
199
+ |----------|-------|----------|-----------|----------|
200
+ | Concord (L4T) | PASS | PASS | PASS | PASS* |
201
+ | N1-auto (Auto-Linux) | PASS | PASS | PASS | PASS |
202
+ | Yukon (WoA) | PASS | PASS | PASS | PASS |
203
+ | Tango (WoA) | same as Yukon | same as Yukon | same as Yukon | same as Yukon |
204
+
205
+ \* Concord recovery is checked in-process for USB `0955:7023` (APX).
mesk-0.1.0/README.md ADDED
@@ -0,0 +1,170 @@
1
+ # mesk
2
+
3
+ Unified power and reset control for Concord, N1-auto, Yukon, and Tango platforms.
4
+ Designed for use in DLA compiler CI/CD pipelines.
5
+
6
+ ## Install and run
7
+
8
+ ```bash
9
+ git clone https://gitlab-master.nvidia.com/mileyz/mesk.git
10
+ cd mesk
11
+ ./mesk concord power_off
12
+ ./mesk concord power_on
13
+ ./mesk concord reset
14
+ ./mesk concord recovery
15
+ ```
16
+
17
+ On Windows (Yukon / Tango), from cmd or PowerShell:
18
+
19
+ ```bat
20
+ git clone https://gitlab-master.nvidia.com/mileyz/mesk.git
21
+ cd mesk
22
+ .\mesk yukon power_off
23
+ .\mesk yukon power_on
24
+ .\mesk yukon reset
25
+ .\mesk yukon recovery
26
+ ```
27
+
28
+ First run creates `.venv` and installs the package. Later runs skip that.
29
+ Do not activate the venv yourself; `./mesk` (Linux) and `.\mesk` (Windows `mesk.cmd`) do that.
30
+ On Linux, the first `./mesk concord <action>` writes `/etc/sudoers.d/mesk` (prompts for sudo once) so all later runs are passwordless. Set `MESK_NO_SUDO=1` to skip sudo entirely.
31
+ `./mesk n1-auto ...` installs `Phidget22` into the venv if it is missing.
32
+
33
+ Developers who want lint/test tools can still use:
34
+
35
+ ```bash
36
+ python3 -m venv .venv
37
+ source .venv/bin/activate
38
+ pip install -e ".[dev,test]"
39
+ ```
40
+
41
+ **Examples:**
42
+
43
+ ```bash
44
+ mesk concord reset
45
+ mesk concord recovery
46
+ mesk concord power_on
47
+ mesk concord power_off
48
+
49
+ mesk n1-auto reset
50
+ mesk n1-auto recovery
51
+ mesk n1-auto power_on
52
+ mesk n1-auto power_off
53
+
54
+ mesk yukon reset
55
+ mesk yukon recovery
56
+ mesk yukon power_on
57
+ mesk yukon power_off
58
+
59
+ mesk tango reset
60
+ mesk tango recovery
61
+ mesk tango power_on
62
+ mesk tango power_off
63
+ ```
64
+
65
+ ## Library Usage
66
+
67
+ ```python
68
+ from mesk import run
69
+
70
+ run("concord", "reset")
71
+ run("n1-auto", "power_on")
72
+ run("yukon", "recovery")
73
+ run("tango", "reset")
74
+ ```
75
+
76
+ `run()` returns 0 on success and a non-zero exit code on failure.
77
+
78
+ ## Project Layout
79
+
80
+ ```
81
+ mesk/
82
+ ├── pyproject.toml # build config + all tool settings
83
+ ├── setup.py # legacy pip editable compatibility
84
+ ├── mesk # Linux/L4T bootstrap launcher
85
+ ├── mesk.cmd # Windows bootstrap launcher
86
+ ├── .pre-commit-config.yaml
87
+ ├── README.md
88
+ ├── src/mesk/
89
+ │ ├── __init__.py # public API: run, ACTIONS, __version__
90
+ │ ├── __version__.py
91
+ │ ├── __main__.py # CLI entry
92
+ │ ├── runner.py # action execution + logging
93
+ │ ├── py.typed
94
+ │ └── vendor/ # bundled board control tools
95
+ │ ├── topo/ # Concord (boardctl)
96
+ │ ├── boardctrl_phidget/ # N1-auto
97
+ │ └── topo_yukon/ # Yukon and Tango (boardctl)
98
+ └── tests/
99
+ ```
100
+
101
+ ## Logging
102
+
103
+ Each run appends to `logs/YYYY-MM-DD.log` under the current working directory
104
+ (timestamp, platform, action, exit code, and full output).
105
+ Override with `MESK_LOG_DIR`.
106
+
107
+ ## Prerequisites
108
+
109
+ Actions call vendor Python APIs in-process (`import`), not shell/`subprocess`.
110
+
111
+ ### Concord (Linux host)
112
+
113
+ - Needs the NVIDIA TOPO USB device (`0955:7045`). The first run of `./mesk concord <action>` installs a NOPASSWD sudoers rule automatically; subsequent runs need no password.
114
+ - `pyusb` is installed with mesk for recovery detection.
115
+ - After `concord recovery`, mesk checks USB for `0955:7023` (APX) and fails if it is missing. boardctl may still print `NOT IN RECOVERY MODE`.
116
+
117
+ ### N1-auto (Linux host)
118
+
119
+ `./mesk n1-auto <action>` installs `Phidget22` into the venv and, if needed, `libphidget22` via apt (sudo). Set `MESK_NO_SUDO=1` to skip the system-library install.
120
+
121
+ ### Yukon / Tango (Windows host)
122
+
123
+ `.\mesk yukon <action>` or `.\mesk tango <action>` creates `.venv` and installs mesk on first run. Needs Python 3.8+ on PATH (or `py -3`) and the TOPO USB device. No sudo.
124
+
125
+ ## Platforms & Supported Operations
126
+
127
+ | Action | Concord (L4T) | N1-auto (Auto-Linux) | Yukon / Tango (WoA) |
128
+ |--------|---------------|----------------------|---------------------|
129
+ | `reset` | `nv_topo(target="topo").target_reset()` | `ResetControl(1).execute_reset()` | `nv_topo(target="yukon").target_reset()` |
130
+ | `recovery` | `nv_topo(target="topo").target_recovery_mode()` | `RecoveryControl(1, 0).execute_recovery()` | `nv_topo(target="yukon").target_recovery_mode()` |
131
+ | `power_on` | `nv_topo(target="topo").target_power_on()` | `PowerMonitor(2, False)` then `relay_off(2)` | `nv_topo(target="yukon").target_power_on()` |
132
+ | `power_off` | `nv_topo(target="topo").target_power_off()` | `PowerMonitor(2, True)` then `relay_on(2)` | `nv_topo(target="yukon").target_power_off()` |
133
+
134
+ Tango uses the same `topo_yukon` `nv_topo` target as Yukon (`target="yukon"`).
135
+ N1-auto power is a one-shot relay set (no background `monitor.py` process).
136
+
137
+ ## Contribute
138
+
139
+ Suggested local Python: 3.12+ (pre-commit assumes > 3.8 for `pytest -n auto`).
140
+
141
+ pre-commit runs Ruff (format + lint), ty, and pytest. All of these skip
142
+ `vendor/` directories (bundled third-party board tools) so upstream trees
143
+ are not rewritten and can be replaced as drop-in upgrades.
144
+
145
+ ```bash
146
+ python -m venv .venv
147
+ source .venv/bin/activate
148
+ pip install -e ".[dev,test]"
149
+ pip install pre-commit
150
+ pre-commit install
151
+ # Optionally run all hooks
152
+ pre-commit run --all-files
153
+ ```
154
+
155
+ ```bash
156
+ pytest
157
+ ruff check .
158
+ ty check
159
+ ```
160
+
161
+ ## Test Status
162
+
163
+ | Platform | reset | power_on | power_off | recovery |
164
+ |----------|-------|----------|-----------|----------|
165
+ | Concord (L4T) | PASS | PASS | PASS | PASS* |
166
+ | N1-auto (Auto-Linux) | PASS | PASS | PASS | PASS |
167
+ | Yukon (WoA) | PASS | PASS | PASS | PASS |
168
+ | Tango (WoA) | same as Yukon | same as Yukon | same as Yukon | same as Yukon |
169
+
170
+ \* Concord recovery is checked in-process for USB `0955:7023` (APX).
@@ -0,0 +1,125 @@
1
+ [build-system]
2
+ requires = ["setuptools >= 60"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "mesk"
7
+ dynamic = ["version"]
8
+ authors = [
9
+ {name = "Miley Zhang", email = "mileyz@nvidia.com"},
10
+ ]
11
+ description = "Unified power and reset control for Concord, N1-auto, Yukon, and Tango platforms"
12
+ readme = "README.md"
13
+ requires-python = ">=3.8"
14
+ license = "LicenseRef-NvidiaProprietary"
15
+ keywords = ["nvidia", "board", "reset", "power", "ci"]
16
+ classifiers = [
17
+ "Operating System :: Microsoft :: Windows",
18
+ "Operating System :: POSIX :: Linux",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.8",
21
+ "Programming Language :: Python :: 3.9",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
26
+ "Topic :: System :: Hardware",
27
+ "Topic :: Software Development :: Libraries :: Python Modules",
28
+ "Typing :: Typed",
29
+ ]
30
+ dependencies = [
31
+ "pyusb",
32
+ ]
33
+
34
+ [project.urls]
35
+ Repository = "https://gitlab-master.nvidia.com/mileyz/mesk"
36
+
37
+ [project.optional-dependencies]
38
+ dev = [
39
+ "ruff == 0.16.6",
40
+ "ty == 0.0.78",
41
+ ]
42
+ test = [
43
+ "pytest == 8.3.1",
44
+ "pytest-cov == 5.0.0",
45
+ "pytest-timeout == 2.3.1",
46
+ "pytest-xdist == 3.6.1; python_version >= '3.9'",
47
+ "coverage == 7.6.0",
48
+ ]
49
+ n1-auto = [
50
+ "Phidget22",
51
+ ]
52
+
53
+ [project.scripts]
54
+ mesk = "mesk.__main__:main"
55
+
56
+ [tool.setuptools]
57
+ package-dir = {"" = "src"}
58
+
59
+ [tool.setuptools.packages.find]
60
+ where = ["src"]
61
+ include = ["mesk*"]
62
+ exclude = [
63
+ "mesk.vendor.boardctrl_phidget.venv*",
64
+ ]
65
+
66
+ [tool.setuptools.package-data]
67
+ "*" = ["*"]
68
+
69
+ [tool.setuptools.dynamic]
70
+ version = {attr = "mesk.__version__"}
71
+
72
+ [tool.ty.environment]
73
+ python-version = "3.8"
74
+
75
+ [tool.ty.src]
76
+ include = ["src"]
77
+ exclude = ["src/mesk/vendor", "src/vendor"]
78
+
79
+ [tool.ty.terminal]
80
+ error-on-warning = false
81
+
82
+ [tool.ruff]
83
+ src = ["src"]
84
+ target-version = "py38"
85
+ # Third-party vendor trees; keep them unmodified for drop-in upgrades.
86
+ extend-exclude = ["src/mesk/vendor", "src/vendor"]
87
+
88
+ [tool.ruff.lint]
89
+ ignore = [
90
+ # Below ignored to avoid conflict with Ruff format
91
+ # Refer https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules
92
+ "W191", # tab-indentation
93
+ "E111", # indentation-with-invalid-multiple
94
+ "E114", # indentation-with-invalid-multiple-comment
95
+ "E117", # over-indented
96
+ "D206", # indent-with-spaces
97
+ "D300", # triple-single-quotes
98
+ "Q000", # bad-quotes-inline-string
99
+ "Q001", # bad-quotes-multiline-string
100
+ "Q002", # bad-quotes-docstring
101
+ "Q003", # avoidable-escaped-quote
102
+ "COM812", # missing-trailing-comma
103
+ "COM819", # prohibited-trailing-comma
104
+ "ISC001", # single-line-implicit-string-concatenation
105
+ "ISC002", # multi-line-implicit-string-concatenation
106
+ ]
107
+
108
+ [tool.pytest.ini_options]
109
+ testpaths = ["tests"]
110
+ pythonpath = ["src"]
111
+ norecursedirs = [".*", "build", "dist", "vendor"]
112
+
113
+ [tool.coverage.paths]
114
+ source = ["src/"]
115
+
116
+ [tool.coverage.run]
117
+ source = ["src/mesk"]
118
+ relative_files = true
119
+ omit = ["tests/*", "src/mesk/vendor/*", "src/vendor/*"]
120
+
121
+ [tool.coverage.report]
122
+ exclude_lines = ["NotImplementedError", "pragma: no cover"]
123
+
124
+ [tool.coverage.json]
125
+ pretty_print = true
mesk-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
mesk-0.1.0/setup.py ADDED
@@ -0,0 +1,3 @@
1
+ from setuptools import setup
2
+
3
+ setup()
@@ -0,0 +1,10 @@
1
+ """Unified power and reset control for Concord, N1-auto, Yukon, and Tango platforms."""
2
+
3
+ from .__version__ import __version__
4
+ from .runner import ACTIONS, run
5
+
6
+ __all__ = [
7
+ "ACTIONS",
8
+ "run",
9
+ "__version__",
10
+ ]
@@ -0,0 +1,80 @@
1
+ """CLI entry point for mesk."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import sys
7
+
8
+ from mesk.runner import _PLATFORMS, ACTIONS, run
9
+
10
+ _SUDO_PLATFORMS = frozenset({"concord"})
11
+
12
+
13
+ def _needs_sudo(platform: str) -> bool:
14
+ if platform not in _SUDO_PLATFORMS:
15
+ return False
16
+ if os.environ.get("MESK_NO_SUDO"):
17
+ return False
18
+ try:
19
+ return os.geteuid() != 0
20
+ except AttributeError:
21
+ return False
22
+
23
+
24
+ def _reexec_with_sudo() -> None:
25
+ os.execvp("sudo", ["sudo", sys.executable, "-m", "mesk", *sys.argv[1:]])
26
+
27
+
28
+ def _phidget_lib_present() -> bool:
29
+ from ctypes.util import find_library
30
+
31
+ return find_library("phidget22") is not None
32
+
33
+
34
+ def _ensure_libphidget22() -> None:
35
+ if _phidget_lib_present():
36
+ return
37
+ if os.environ.get("MESK_NO_SUDO"):
38
+ raise RuntimeError("libphidget22 is missing; install it or unset MESK_NO_SUDO")
39
+ import subprocess
40
+
41
+ print("Installing libphidget22 (may prompt for sudo)...")
42
+ apt = subprocess.run(["sudo", "apt-get", "install", "-y", "libphidget22"])
43
+ if apt.returncode == 0 and _phidget_lib_present():
44
+ return
45
+ print("Adding Phidget apt repository...")
46
+ setup = subprocess.run(
47
+ ["curl", "-fsSL", "https://www.phidgets.com/downloads/setup_linux"],
48
+ check=True,
49
+ stdout=subprocess.PIPE,
50
+ )
51
+ subprocess.run(["sudo", "bash"], input=setup.stdout, check=True)
52
+ subprocess.check_call(["sudo", "apt-get", "install", "-y", "libphidget22"])
53
+ if not _phidget_lib_present():
54
+ raise RuntimeError("libphidget22 is still missing after install")
55
+
56
+
57
+ def _ensure_phidget22() -> None:
58
+ import importlib.util
59
+ import subprocess
60
+
61
+ if importlib.util.find_spec("Phidget22") is None:
62
+ print("Installing Phidget22 into this environment...")
63
+ subprocess.check_call([sys.executable, "-m", "pip", "install", "Phidget22"])
64
+ _ensure_libphidget22()
65
+
66
+
67
+ def main() -> None:
68
+ platforms = list(_PLATFORMS)
69
+ if len(sys.argv) != 3 or sys.argv[1] not in platforms or sys.argv[2] not in ACTIONS:
70
+ print(f"Usage: mesk <{'|'.join(platforms)}> <{'|'.join(ACTIONS)}>")
71
+ sys.exit(1)
72
+ if sys.argv[1] == "n1-auto":
73
+ _ensure_phidget22()
74
+ if _needs_sudo(sys.argv[1]):
75
+ _reexec_with_sudo()
76
+ sys.exit(run(sys.argv[1], sys.argv[2]))
77
+
78
+
79
+ if __name__ == "__main__":
80
+ main()
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"
File without changes