sysic-root 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.
- sysic_root-0.1.0/LICENSE +21 -0
- sysic_root-0.1.0/PKG-INFO +78 -0
- sysic_root-0.1.0/README.md +55 -0
- sysic_root-0.1.0/pyproject.toml +32 -0
- sysic_root-0.1.0/setup.cfg +4 -0
- sysic_root-0.1.0/sysic_root/__init__.py +10 -0
- sysic_root-0.1.0/sysic_root/core.py +118 -0
- sysic_root-0.1.0/sysic_root.egg-info/PKG-INFO +78 -0
- sysic_root-0.1.0/sysic_root.egg-info/SOURCES.txt +10 -0
- sysic_root-0.1.0/sysic_root.egg-info/dependency_links.txt +1 -0
- sysic_root-0.1.0/sysic_root.egg-info/top_level.txt +1 -0
- sysic_root-0.1.0/tests/test_sysic.py +99 -0
sysic_root-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Your Name
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: sysic-root
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: sysic_root: Windows system-level toolkit. Admin detection, subprocess wrapper, thread-io helper.
|
|
5
|
+
Author-email: SYSIC <a.0146@icloud.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: windows,system,admin,cmd,powershell,subprocess,thread,toolkit
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
+
Classifier: Topic :: System :: Systems Administration
|
|
20
|
+
Requires-Python: >=3.8
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
|
|
24
|
+
# sysic_root
|
|
25
|
+
|
|
26
|
+
纯 Python 实现的 Windows 系统级工具库,无第三方依赖。
|
|
27
|
+
|
|
28
|
+
- 管理员权限检测
|
|
29
|
+
- cmd / PowerShell 命令调用
|
|
30
|
+
- 后台线程文件读取解析
|
|
31
|
+
|
|
32
|
+
## 安装
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install -e . # 可编辑模式(开发调试,改源码即时生效)
|
|
36
|
+
# 或打包后安装
|
|
37
|
+
pip install ./dist/sysic_root-0.1.0-py3-none-any.whl
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 快速上手
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
import sysic_root as si
|
|
44
|
+
|
|
45
|
+
si.cmd("echo hello") # 执行 cmd,返回输出文本
|
|
46
|
+
si.powershell("Get-Process") # 执行 PowerShell,返回输出文本
|
|
47
|
+
si.admin() # 当前是否管理员权限 True/False
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
命令失败时抛 `RuntimeError`。
|
|
51
|
+
|
|
52
|
+
## API 一览
|
|
53
|
+
|
|
54
|
+
| 函数 | 说明 |
|
|
55
|
+
|---|---|
|
|
56
|
+
| `cmd(command)` | 执行 cmd 命令,返回标准输出文本 |
|
|
57
|
+
| `powershell(command)` | 执行 PowerShell 命令,返回标准输出文本 |
|
|
58
|
+
| `admin()` | 当前进程是否为管理员权限 |
|
|
59
|
+
| `is_admin()` | 同 `admin()`,旧版命名 |
|
|
60
|
+
| `run_cmd(cmd, ...)` | 进阶:执行 cmd,返回 `(stdout, stderr, returncode)` |
|
|
61
|
+
| `run_powershell(ps_cmd, ...)` | 进阶:执行 PowerShell,返回三元组 |
|
|
62
|
+
| `ThreadedFileLoader` | 进阶:后台线程读取文件,子类覆写 `parse_chunk` 自定义解析 |
|
|
63
|
+
|
|
64
|
+
## 测试
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
python -m unittest discover -s tests -v
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## 构建
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
python -m pip wheel . -w dist --no-deps
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## 许可
|
|
77
|
+
|
|
78
|
+
MIT
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# sysic_root
|
|
2
|
+
|
|
3
|
+
纯 Python 实现的 Windows 系统级工具库,无第三方依赖。
|
|
4
|
+
|
|
5
|
+
- 管理员权限检测
|
|
6
|
+
- cmd / PowerShell 命令调用
|
|
7
|
+
- 后台线程文件读取解析
|
|
8
|
+
|
|
9
|
+
## 安装
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install -e . # 可编辑模式(开发调试,改源码即时生效)
|
|
13
|
+
# 或打包后安装
|
|
14
|
+
pip install ./dist/sysic_root-0.1.0-py3-none-any.whl
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 快速上手
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
import sysic_root as si
|
|
21
|
+
|
|
22
|
+
si.cmd("echo hello") # 执行 cmd,返回输出文本
|
|
23
|
+
si.powershell("Get-Process") # 执行 PowerShell,返回输出文本
|
|
24
|
+
si.admin() # 当前是否管理员权限 True/False
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
命令失败时抛 `RuntimeError`。
|
|
28
|
+
|
|
29
|
+
## API 一览
|
|
30
|
+
|
|
31
|
+
| 函数 | 说明 |
|
|
32
|
+
|---|---|
|
|
33
|
+
| `cmd(command)` | 执行 cmd 命令,返回标准输出文本 |
|
|
34
|
+
| `powershell(command)` | 执行 PowerShell 命令,返回标准输出文本 |
|
|
35
|
+
| `admin()` | 当前进程是否为管理员权限 |
|
|
36
|
+
| `is_admin()` | 同 `admin()`,旧版命名 |
|
|
37
|
+
| `run_cmd(cmd, ...)` | 进阶:执行 cmd,返回 `(stdout, stderr, returncode)` |
|
|
38
|
+
| `run_powershell(ps_cmd, ...)` | 进阶:执行 PowerShell,返回三元组 |
|
|
39
|
+
| `ThreadedFileLoader` | 进阶:后台线程读取文件,子类覆写 `parse_chunk` 自定义解析 |
|
|
40
|
+
|
|
41
|
+
## 测试
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
python -m unittest discover -s tests -v
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## 构建
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
python -m pip wheel . -w dist --no-deps
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## 许可
|
|
54
|
+
|
|
55
|
+
MIT
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "sysic-root"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "sysic_root: Windows system-level toolkit. Admin detection, subprocess wrapper, thread-io helper."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "SYSIC", email = "a.0146@icloud.com" }
|
|
14
|
+
]
|
|
15
|
+
keywords = ["windows", "system", "admin", "cmd", "powershell", "subprocess", "thread", "toolkit"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Operating System :: Microsoft :: Windows",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.8",
|
|
23
|
+
"Programming Language :: Python :: 3.9",
|
|
24
|
+
"Programming Language :: Python :: 3.10",
|
|
25
|
+
"Programming Language :: Python :: 3.11",
|
|
26
|
+
"Programming Language :: Python :: 3.12",
|
|
27
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
28
|
+
"Topic :: System :: Systems Administration",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[tool.setuptools]
|
|
32
|
+
packages = ["sysic_root"]
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import ctypes
|
|
2
|
+
import sys
|
|
3
|
+
import subprocess
|
|
4
|
+
import threading
|
|
5
|
+
import queue
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def is_admin() -> bool:
|
|
9
|
+
"""检测当前进程是否拥有管理员权限(仅Windows)"""
|
|
10
|
+
if sys.platform != "win32":
|
|
11
|
+
return False
|
|
12
|
+
try:
|
|
13
|
+
return bool(ctypes.windll.shell32.IsUserAnAdmin())
|
|
14
|
+
except Exception:
|
|
15
|
+
return False
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def run_cmd(cmd: str, capture_output: bool = True, text: bool = True):
|
|
19
|
+
"""执行cmd.exe命令
|
|
20
|
+
:param cmd: cmd命令字符串
|
|
21
|
+
:param capture_output: 是否捕获输出
|
|
22
|
+
:param text: 返回字符串,否则返回bytes
|
|
23
|
+
:return: (stdout, stderr, returncode)
|
|
24
|
+
"""
|
|
25
|
+
proc = subprocess.run(
|
|
26
|
+
["cmd.exe", "/c", cmd],
|
|
27
|
+
capture_output=capture_output,
|
|
28
|
+
text=text
|
|
29
|
+
)
|
|
30
|
+
return proc.stdout, proc.stderr, proc.returncode
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def cmd(command: str) -> str:
|
|
34
|
+
"""简化版:执行cmd命令,直接返回输出文本。失败抛RuntimeError。"""
|
|
35
|
+
proc = subprocess.run(
|
|
36
|
+
["cmd.exe", "/c", command],
|
|
37
|
+
capture_output=True, text=True, errors="replace"
|
|
38
|
+
)
|
|
39
|
+
if proc.returncode != 0:
|
|
40
|
+
raise RuntimeError(proc.stderr.strip() or f"命令失败, 退出码 {proc.returncode}")
|
|
41
|
+
return proc.stdout
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def powershell(command: str) -> str:
|
|
45
|
+
"""简化版:执行PowerShell命令,直接返回输出文本。失败抛RuntimeError。"""
|
|
46
|
+
proc = subprocess.run(
|
|
47
|
+
["powershell.exe", "-Command", command],
|
|
48
|
+
capture_output=True, text=True, errors="replace"
|
|
49
|
+
)
|
|
50
|
+
if proc.returncode != 0:
|
|
51
|
+
raise RuntimeError(proc.stderr.strip() or f"命令失败, 退出码 {proc.returncode}")
|
|
52
|
+
return proc.stdout
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def admin() -> bool:
|
|
56
|
+
"""简化版:当前进程是否为管理员权限。"""
|
|
57
|
+
return is_admin()
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def run_powershell(ps_cmd: str, capture_output: bool = True, text: bool = True):
|
|
61
|
+
"""执行PowerShell命令"""
|
|
62
|
+
proc = subprocess.run(
|
|
63
|
+
["powershell.exe", "-Command", ps_cmd],
|
|
64
|
+
capture_output=capture_output,
|
|
65
|
+
text=text
|
|
66
|
+
)
|
|
67
|
+
return proc.stdout, proc.stderr, proc.returncode
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class ThreadedFileLoader:
|
|
71
|
+
"""后台线程读取文件,解析结果放入线程安全队列"""
|
|
72
|
+
|
|
73
|
+
def __init__(self):
|
|
74
|
+
self._q = queue.Queue()
|
|
75
|
+
self._thread = None
|
|
76
|
+
self._running = False
|
|
77
|
+
self._error = None
|
|
78
|
+
|
|
79
|
+
def _worker(self, filepath: str, chunk_size: int):
|
|
80
|
+
try:
|
|
81
|
+
with open(filepath, "rb") as f:
|
|
82
|
+
while self._running:
|
|
83
|
+
chunk = f.read(chunk_size)
|
|
84
|
+
if not chunk:
|
|
85
|
+
break
|
|
86
|
+
parsed = self.parse_chunk(chunk)
|
|
87
|
+
self._q.put(parsed)
|
|
88
|
+
except Exception as e:
|
|
89
|
+
self._error = e
|
|
90
|
+
|
|
91
|
+
def start_load(self, filepath: str, chunk_size: int = 1024):
|
|
92
|
+
"""启动后台读取线程(daemon)"""
|
|
93
|
+
if self._thread and self._thread.is_alive():
|
|
94
|
+
return
|
|
95
|
+
self._running = True
|
|
96
|
+
self._thread = threading.Thread(
|
|
97
|
+
target=self._worker, args=(filepath, chunk_size), daemon=True
|
|
98
|
+
)
|
|
99
|
+
self._thread.start()
|
|
100
|
+
|
|
101
|
+
def get_available(self) -> list:
|
|
102
|
+
"""取出所有已解析数据(非阻塞)。若读取线程出错,抛出错异常"""
|
|
103
|
+
if self._error is not None:
|
|
104
|
+
raise self._error
|
|
105
|
+
out = []
|
|
106
|
+
while not self._q.empty():
|
|
107
|
+
out.append(self._q.get_nowait())
|
|
108
|
+
return out
|
|
109
|
+
|
|
110
|
+
def stop(self):
|
|
111
|
+
"""停止读取线程并等待其退出"""
|
|
112
|
+
self._running = False
|
|
113
|
+
if self._thread:
|
|
114
|
+
self._thread.join(timeout=5)
|
|
115
|
+
|
|
116
|
+
def parse_chunk(self, chunk: bytes):
|
|
117
|
+
"""子类可覆写:自定义二进制/文本解析逻辑"""
|
|
118
|
+
return chunk
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: sysic-root
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: sysic_root: Windows system-level toolkit. Admin detection, subprocess wrapper, thread-io helper.
|
|
5
|
+
Author-email: SYSIC <a.0146@icloud.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: windows,system,admin,cmd,powershell,subprocess,thread,toolkit
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
+
Classifier: Topic :: System :: Systems Administration
|
|
20
|
+
Requires-Python: >=3.8
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
|
|
24
|
+
# sysic_root
|
|
25
|
+
|
|
26
|
+
纯 Python 实现的 Windows 系统级工具库,无第三方依赖。
|
|
27
|
+
|
|
28
|
+
- 管理员权限检测
|
|
29
|
+
- cmd / PowerShell 命令调用
|
|
30
|
+
- 后台线程文件读取解析
|
|
31
|
+
|
|
32
|
+
## 安装
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install -e . # 可编辑模式(开发调试,改源码即时生效)
|
|
36
|
+
# 或打包后安装
|
|
37
|
+
pip install ./dist/sysic_root-0.1.0-py3-none-any.whl
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 快速上手
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
import sysic_root as si
|
|
44
|
+
|
|
45
|
+
si.cmd("echo hello") # 执行 cmd,返回输出文本
|
|
46
|
+
si.powershell("Get-Process") # 执行 PowerShell,返回输出文本
|
|
47
|
+
si.admin() # 当前是否管理员权限 True/False
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
命令失败时抛 `RuntimeError`。
|
|
51
|
+
|
|
52
|
+
## API 一览
|
|
53
|
+
|
|
54
|
+
| 函数 | 说明 |
|
|
55
|
+
|---|---|
|
|
56
|
+
| `cmd(command)` | 执行 cmd 命令,返回标准输出文本 |
|
|
57
|
+
| `powershell(command)` | 执行 PowerShell 命令,返回标准输出文本 |
|
|
58
|
+
| `admin()` | 当前进程是否为管理员权限 |
|
|
59
|
+
| `is_admin()` | 同 `admin()`,旧版命名 |
|
|
60
|
+
| `run_cmd(cmd, ...)` | 进阶:执行 cmd,返回 `(stdout, stderr, returncode)` |
|
|
61
|
+
| `run_powershell(ps_cmd, ...)` | 进阶:执行 PowerShell,返回三元组 |
|
|
62
|
+
| `ThreadedFileLoader` | 进阶:后台线程读取文件,子类覆写 `parse_chunk` 自定义解析 |
|
|
63
|
+
|
|
64
|
+
## 测试
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
python -m unittest discover -s tests -v
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## 构建
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
python -m pip wheel . -w dist --no-deps
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## 许可
|
|
77
|
+
|
|
78
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
sysic_root
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import tempfile
|
|
4
|
+
import time
|
|
5
|
+
import unittest
|
|
6
|
+
|
|
7
|
+
import sysic_root
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TestAdmin(unittest.TestCase):
|
|
11
|
+
def test_admin_returns_bool(self):
|
|
12
|
+
self.assertIsInstance(sysic_root.admin(), bool)
|
|
13
|
+
|
|
14
|
+
def test_is_admin_alias(self):
|
|
15
|
+
self.assertEqual(sysic_root.is_admin(), sysic_root.admin())
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class TestCmd(unittest.TestCase):
|
|
19
|
+
def test_cmd_output(self):
|
|
20
|
+
out = sysic_root.cmd("echo hello")
|
|
21
|
+
self.assertEqual(out.strip(), "hello")
|
|
22
|
+
|
|
23
|
+
def test_cmd_failure_raises(self):
|
|
24
|
+
with self.assertRaises(RuntimeError):
|
|
25
|
+
sysic_root.cmd("this_command_does_not_exist_xyz")
|
|
26
|
+
|
|
27
|
+
def test_run_cmd_returns_tuple(self):
|
|
28
|
+
out, err, code = sysic_root.run_cmd("echo ok")
|
|
29
|
+
self.assertEqual(out.strip(), "ok")
|
|
30
|
+
self.assertEqual(code, 0)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class TestPowershell(unittest.TestCase):
|
|
34
|
+
def test_powershell_output(self):
|
|
35
|
+
out = sysic_root.powershell("Write-Output hi")
|
|
36
|
+
self.assertEqual(out.strip(), "hi")
|
|
37
|
+
|
|
38
|
+
def test_powershell_failure_raises(self):
|
|
39
|
+
with self.assertRaises(RuntimeError):
|
|
40
|
+
sysic_root.powershell("this-command-does-not-exist-xyz")
|
|
41
|
+
|
|
42
|
+
def test_run_powershell_returns_tuple(self):
|
|
43
|
+
out, err, code = sysic_root.run_powershell("Write-Output ok")
|
|
44
|
+
self.assertEqual(out.strip(), "ok")
|
|
45
|
+
self.assertEqual(code, 0)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class TestThreadedFileLoader(unittest.TestCase):
|
|
49
|
+
def _make_file(self, data: bytes):
|
|
50
|
+
fd, path = tempfile.mkstemp(suffix=".bin")
|
|
51
|
+
with os.fdopen(fd, "wb") as f:
|
|
52
|
+
f.write(data)
|
|
53
|
+
self.addCleanup(os.remove, path)
|
|
54
|
+
return path
|
|
55
|
+
|
|
56
|
+
def test_full_read_integrity(self):
|
|
57
|
+
data = b"HELLO" * 20
|
|
58
|
+
path = self._make_file(data)
|
|
59
|
+
loader = sysic_root.ThreadedFileLoader()
|
|
60
|
+
loader.start_load(path, chunk_size=6)
|
|
61
|
+
time.sleep(0.3)
|
|
62
|
+
loader.stop()
|
|
63
|
+
chunks = loader.get_available()
|
|
64
|
+
self.assertEqual(b"".join(chunks), data)
|
|
65
|
+
|
|
66
|
+
def test_missing_file_raises(self):
|
|
67
|
+
loader = sysic_root.ThreadedFileLoader()
|
|
68
|
+
loader.start_load(os.path.join(tempfile.gettempdir(), "no_such_file_xyz.bin"))
|
|
69
|
+
time.sleep(0.3)
|
|
70
|
+
loader.stop()
|
|
71
|
+
with self.assertRaises(FileNotFoundError):
|
|
72
|
+
loader.get_available()
|
|
73
|
+
|
|
74
|
+
def test_error_like_tuple_not_misjudged(self):
|
|
75
|
+
class TupleLoader(sysic_root.ThreadedFileLoader):
|
|
76
|
+
def parse_chunk(self, chunk):
|
|
77
|
+
return ("__error__", chunk) if len(chunk) > 3 else chunk
|
|
78
|
+
|
|
79
|
+
path = self._make_file(b"12345678")
|
|
80
|
+
loader = TupleLoader()
|
|
81
|
+
loader.start_load(path, chunk_size=4)
|
|
82
|
+
time.sleep(0.3)
|
|
83
|
+
loader.stop()
|
|
84
|
+
got = loader.get_available()
|
|
85
|
+
self.assertEqual(got[0], ("__error__", b"1234"))
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class TestModule(unittest.TestCase):
|
|
89
|
+
def test_version(self):
|
|
90
|
+
self.assertTrue(sysic_root.__version__)
|
|
91
|
+
|
|
92
|
+
def test_public_names(self):
|
|
93
|
+
for name in ("cmd", "powershell", "admin", "is_admin",
|
|
94
|
+
"run_cmd", "run_powershell", "ThreadedFileLoader"):
|
|
95
|
+
self.assertTrue(hasattr(sysic_root, name), name)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
if __name__ == "__main__":
|
|
99
|
+
unittest.main()
|