dcheckdev 0.1.0__py3-none-any.whl

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.
checkdev.py ADDED
@@ -0,0 +1,198 @@
1
+ import os
2
+ import shutil
3
+ import subprocess
4
+ import sys
5
+
6
+ import psutil
7
+ from rich import box
8
+ from rich.console import Console
9
+ from rich.table import Table
10
+
11
+ # 真正的终端能自动测出宽度;PyCharm 运行窗口测不出,就固定按 200 宽排版
12
+ console = Console(width=None if sys.stdout.isatty() else 200)
13
+
14
+ # 要检查的工具:(显示名, 命令)
15
+ TOOLS = [
16
+ ("Python", ["python", "--version"]),
17
+ ("Go", ["go", "version"]),
18
+ ("Node", ["node", "--version"]),
19
+ ("Git", ["git", "--version"]),
20
+ ("Java", ["java", "-version"]),
21
+ ("Wails", ["wails", "version"]),
22
+ ]
23
+
24
+ # 每个工具要查看的配置:工具名 -> [(配置名, 命令), ...]
25
+ CONFIGS = {
26
+ "Go": [
27
+ ("GOROOT", ["go", "env", "GOROOT"]),
28
+ ("GOPATH", ["go", "env", "GOPATH"]),
29
+ ("GOPROXY", ["go", "env", "GOPROXY"]),
30
+ ],
31
+ "Python": [
32
+ ("pip 镜像", ["python", "-m", "pip", "config", "get", "global.index-url"]),
33
+ ],
34
+ "Node": [
35
+ ("npm 镜像", ["npm", "config", "get", "registry"]),
36
+ ("全局目录", ["npm", "config", "get", "prefix"]),
37
+ ],
38
+ "Git": [
39
+ ("user.name", ["git", "config", "--global", "user.name"]),
40
+ ("user.email", ["git", "config", "--global", "user.email"]),
41
+ ],
42
+ }
43
+
44
+ # 直接读取的环境变量
45
+ ENV_VARS = ["JAVA_HOME"]
46
+
47
+ # 要检查的端口:端口号 -> 通常是谁在用
48
+ PORTS = {
49
+ 8000: "FastAPI / Django",
50
+ 8080: "Spring Boot / Tomcat",
51
+ 5173: "Vite 前端",
52
+ 3306: "MySQL",
53
+ 5672: "RabbitMQ",
54
+ 6379: "Redis",
55
+ }
56
+
57
+
58
+ def make_table(title, *columns):
59
+ """创建统一样式的表格:没有竖线,每列都不折行,宽度按最长的文字"""
60
+ table = Table(title=title, box=box.SIMPLE_HEAD, title_justify="left")
61
+ for col in columns:
62
+ table.add_column(col, no_wrap=True)
63
+ return table
64
+
65
+
66
+ def run(cmd):
67
+ """运行命令,返回 (返回码, 第一行输出);没安装返回 None"""
68
+ exe = shutil.which(cmd[0])
69
+ if exe is None:
70
+ return None
71
+ try:
72
+ result = subprocess.run(
73
+ [exe] + cmd[1:],
74
+ capture_output=True,
75
+ text=True,
76
+ encoding="utf-8",
77
+ errors="replace",
78
+ timeout=10,
79
+ )
80
+ except subprocess.TimeoutExpired:
81
+ return -1, "超时"
82
+
83
+ output = (result.stdout or result.stderr).strip()
84
+ first_line = output.splitlines()[0] if output else ""
85
+ return result.returncode, first_line
86
+
87
+
88
+ def check_tools():
89
+ table = make_table("1. 工具版本", "工具", "状态", "版本", "位置")
90
+
91
+ for name, cmd in TOOLS:
92
+ location = shutil.which(cmd[0]) or ""
93
+ res = run(cmd)
94
+ if res is None:
95
+ status, version = "[red]未安装[/red]", ""
96
+ elif res[0] == 0:
97
+ status, version = "[green]已安装[/green]", res[1]
98
+ else:
99
+ status, version = "[yellow]出错[/yellow]", res[1]
100
+ table.add_row(f"[bold]{name}[/bold]", status, version, f"[dim]{location}[/dim]")
101
+
102
+ console.print(table)
103
+
104
+
105
+ def check_path():
106
+ table = make_table("2. PATH 检查", "问题", "路径")
107
+
108
+ paths = os.environ.get("PATH", "").split(os.pathsep)
109
+ seen = set()
110
+ for raw in paths:
111
+ raw = raw.strip()
112
+ if not raw:
113
+ continue
114
+ p = os.path.expandvars(raw)
115
+ key = os.path.normcase(os.path.normpath(p))
116
+ if key in seen:
117
+ table.add_row("[yellow]重复[/yellow]", raw)
118
+ elif "%" in p:
119
+ table.add_row("[red]变量无法展开[/red]", raw)
120
+ elif os.path.isfile(p):
121
+ table.add_row("[yellow]是文件不是目录[/yellow]", raw)
122
+ elif not os.path.isdir(p):
123
+ table.add_row("[red]失效[/red]", raw)
124
+ seen.add(key)
125
+
126
+ if table.row_count == 0:
127
+ console.print(f"[green]2. PATH 检查:共 {len(paths)} 项,没有问题[/green]")
128
+ else:
129
+ table.caption = f"PATH 共 {len(paths)} 项,发现 {table.row_count} 个问题"
130
+ console.print(table)
131
+
132
+
133
+ def check_configs():
134
+ table = make_table("3. 关键配置", "工具", "配置", "值")
135
+
136
+ for tool, items in CONFIGS.items():
137
+ for label, cmd in items:
138
+ res = run(cmd)
139
+ if res is None:
140
+ table.add_row(tool, label, f"[dim]没找到 {cmd[0]},跳过[/dim]")
141
+ break
142
+ if res[0] == 0 and res[1]:
143
+ value = res[1]
144
+ else:
145
+ value = "[yellow](未设置)[/yellow]"
146
+ table.add_row(f"[bold]{tool}[/bold]", label, value)
147
+
148
+ for name in ENV_VARS:
149
+ value = os.environ.get(name) or "[yellow](未设置)[/yellow]"
150
+ table.add_row("[bold]环境变量[/bold]", name, value)
151
+
152
+ console.print(table)
153
+
154
+
155
+ def find_listeners():
156
+ """返回 {端口: 进程 PID},只看正在监听的 TCP 端口"""
157
+ listeners = {}
158
+ for conn in psutil.net_connections(kind="tcp"):
159
+ if conn.status == psutil.CONN_LISTEN and conn.laddr:
160
+ listeners.setdefault(conn.laddr.port, conn.pid)
161
+ return listeners
162
+
163
+
164
+ def process_name(pid):
165
+ """根据 PID 查进程名,查不到返回问号"""
166
+ if not pid:
167
+ return "?"
168
+ try:
169
+ return psutil.Process(pid).name()
170
+ except (psutil.NoSuchProcess, psutil.AccessDenied):
171
+ return "?"
172
+
173
+
174
+ def check_ports():
175
+ table = make_table("4. 端口占用", "端口", "用途", "状态", "占用程序")
176
+ table.columns[0].justify = "right"
177
+
178
+ listeners = find_listeners()
179
+ for port, usage in PORTS.items():
180
+ if port in listeners:
181
+ pid = listeners[port]
182
+ table.add_row(str(port), usage, "[yellow]占用[/yellow]",
183
+ f"{process_name(pid)} (PID {pid})")
184
+ else:
185
+ table.add_row(str(port), usage, "[green]空闲[/green]", "")
186
+
187
+ console.print(table)
188
+
189
+
190
+ def main():
191
+ check_tools()
192
+ check_path()
193
+ check_configs()
194
+ check_ports()
195
+
196
+
197
+ if __name__ == "__main__":
198
+ main()
@@ -0,0 +1,72 @@
1
+ Metadata-Version: 2.4
2
+ Name: dcheckdev
3
+ Version: 0.1.0
4
+ Summary: One-command local dev environment checker: tool versions, PATH, key configs and port usage
5
+ Author: dongzhongcen
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/dongzhongcen
8
+ Keywords: cli,devtools,environment,path,windows
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Environment :: Console
12
+ Classifier: Topic :: Software Development
13
+ Requires-Python: >=3.9
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+ Requires-Dist: rich
17
+ Requires-Dist: psutil
18
+ Dynamic: license-file
19
+
20
+ # dcheckdev
21
+
22
+ 一键检查本地开发环境的命令行工具。 / A one-command local dev environment checker.
23
+
24
+ ## 简介
25
+
26
+ `dcheckdev` 会用彩色表格列出:
27
+
28
+ 1. **工具版本**:Python、Go、Node、Git、Java、Wails 是否安装、版本号和实际使用的位置
29
+ 2. **PATH 检查**:重复、失效、变量无法展开、误把文件写进 PATH 的条目
30
+ 3. **关键配置**:GOROOT / GOPATH / GOPROXY、pip 镜像、npm 镜像和全局目录、Git 用户名和邮箱、JAVA_HOME
31
+ 4. **端口占用**:8000、8080、5173、3306、5672、6379 是否被占用,以及占用的程序
32
+
33
+ ### 安装
34
+
35
+ ```bash
36
+ python -m pip install dcheckdev
37
+ ```
38
+
39
+ ### 使用
40
+
41
+ ```bash
42
+ devcheck
43
+ ```
44
+
45
+ 建议在 PowerShell、Windows Terminal 等真正的终端里运行,颜色显示最完整。
46
+
47
+ ---
48
+
49
+ ## Overview
50
+
51
+ `dcheckdev` prints colored tables showing:
52
+
53
+ 1. **Tool versions**: whether Python, Go, Node, Git, Java and Wails are installed, their versions and which executable is actually used
54
+ 2. **PATH check**: duplicate, missing, unexpanded-variable and file-instead-of-directory entries
55
+ 3. **Key configs**: GOROOT / GOPATH / GOPROXY, pip index, npm registry and global prefix, Git user name and email, JAVA_HOME
56
+ 4. **Port usage**: whether ports 8000, 8080, 5173, 3306, 5672 and 6379 are in use, and by which process
57
+
58
+ ### Install
59
+
60
+ ```bash
61
+ python -m pip install dcheckdev
62
+ ```
63
+
64
+ ### Usage
65
+
66
+ ```bash
67
+ devcheck
68
+ ```
69
+
70
+ ## License
71
+
72
+ MIT
@@ -0,0 +1,7 @@
1
+ checkdev.py,sha256=8YRpLHpYJ0dRNmebLGaYNtdPfhDIg2Mx68GMicZ1-Mw,5901
2
+ dcheckdev-0.1.0.dist-info/licenses/LICENSE,sha256=MgRS43voHFNBfApVAUys1wwJL8aVk79str6vtQ1jacA,1069
3
+ dcheckdev-0.1.0.dist-info/METADATA,sha256=WAvibpQRJ5OnTLlYB0T85xL3cPPxepWOVIVGeoTOunk,2041
4
+ dcheckdev-0.1.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
5
+ dcheckdev-0.1.0.dist-info/entry_points.txt,sha256=V06FywvcuFON36OJpBP9u7k5j80tZ0-i4nrCnzksow8,43
6
+ dcheckdev-0.1.0.dist-info/top_level.txt,sha256=FgCTAotE_eUOZ_gdLhg2YUfRrMXS46Vxodx3dv0Dkaw,9
7
+ dcheckdev-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ devcheck = checkdev:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 dongzhongcen
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 @@
1
+ checkdev