sycommon-python-lib 0.2.2a3__py3-none-any.whl → 0.2.2a4__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.
command/cli.py CHANGED
@@ -49,6 +49,12 @@ def create_init_parser(subparsers) -> None:
49
49
  web - 标准 FastAPI Web 服务,适合 RESTful API 开发
50
50
  agent - AI Agent 服务,基于 langgraph 实现状态图
51
51
 
52
+ CLI 项目结构:
53
+ commands/ - 子命令目录
54
+ model/ - 数据模型
55
+ client/ - 外部服务客户端
56
+ app.py - CLI 入口 (argparse)
57
+
52
58
  Agent 项目结构:
53
59
  agent/ - Agent 核心 (main_agent, nodes, states, enums)
54
60
  api/sse/ - SSE 流式接口
@@ -79,7 +85,7 @@ Web 项目结构:
79
85
  # 位置参数
80
86
  init_parser.add_argument(
81
87
  "project_type",
82
- choices=["web", "agent"],
88
+ choices=["web", "agent", "cli"],
83
89
  help="项目类型:web / agent"
84
90
  )
85
91
  init_parser.add_argument(
@@ -221,6 +227,8 @@ def _detect_project_type(project_path) -> str | None:
221
227
  if (project_path / "agent" / "main_agent.py").exists() or \
222
228
  (project_path / "agent" / "enums").is_dir():
223
229
  return "agent"
230
+ if (project_path / "commands").is_dir() and (project_path / "app.py").exists():
231
+ return "cli"
224
232
  if (project_path / "api").is_dir():
225
233
  return "web"
226
234
  return None
@@ -247,13 +255,19 @@ def handle_doctor_command(args) -> bool:
247
255
  warnings.append("无法识别项目类型 (非 web / agent 标准结构)")
248
256
 
249
257
  # 1. 检查必要文件
250
- required_files = ["app.py", "requirements.txt"]
258
+ if project_type == "cli":
259
+ required_files = ["app.py", "pyproject.toml"]
260
+ else:
261
+ required_files = ["app.py", "requirements.txt"]
251
262
  for file in required_files:
252
263
  if not (project_path / file).exists():
253
264
  issues.append(f"缺少必要文件: {file}")
254
265
 
255
266
  # 2. 检查配置文件
256
- config_files = ["app.yaml", ".env"]
267
+ if project_type == "cli":
268
+ config_files = [".env"]
269
+ else:
270
+ config_files = ["app.yaml", ".env"]
257
271
  for file in config_files:
258
272
  if not (project_path / file).exists():
259
273
  warnings.append(f"缺少配置文件: {file}")
@@ -276,6 +290,8 @@ def handle_doctor_command(args) -> bool:
276
290
  issues.append(f"缺少 Agent 核心文件: {file}")
277
291
  elif project_type == "web":
278
292
  required_dirs = ["api", "model", "tools", "client"]
293
+ elif project_type == "cli":
294
+ required_dirs = ["commands", "model", "tools"]
279
295
  else:
280
296
  required_dirs = ["api", "model", "tools"]
281
297
 
@@ -351,6 +367,11 @@ def handle_list_command(args) -> bool:
351
367
  "api/sse/", "api/query.py", "tools/", "model/", "db/"],
352
368
  "features": "nacos, kafka_log, llm, sentry (默认启用)",
353
369
  },
370
+ "cli": {
371
+ "desc": "Python CLI 命令行工具 (argparse)",
372
+ "dirs": ["commands/", "model/", "client/"],
373
+ "features": "无默认依赖 (精简模板)",
374
+ },
354
375
  }
355
376
 
356
377
  for name, info in templates.items():
command/core/models.py CHANGED
@@ -13,6 +13,19 @@ AGENT_DEFAULTS = {
13
13
  "llm": True,
14
14
  }
15
15
 
16
+ # CLI 项目默认关闭所有服务依赖
17
+ CLI_DEFAULTS = {
18
+ "database": False,
19
+ "rabbitmq": False,
20
+ "nacos": False,
21
+ "kafka_log": False,
22
+ "sse": False,
23
+ "llm": False,
24
+ "redis": False,
25
+ "elasticsearch": False,
26
+ "sentry": False,
27
+ }
28
+
16
29
 
17
30
  @dataclass
18
31
  class FeatureOptions:
@@ -32,6 +45,8 @@ class FeatureOptions:
32
45
  """根据项目类型返回推荐默认配置"""
33
46
  if project_type == "agent":
34
47
  return cls(**AGENT_DEFAULTS)
48
+ if project_type == "cli":
49
+ return cls(**CLI_DEFAULTS)
35
50
  return cls()
36
51
 
37
52
  def to_template_vars(self) -> dict:
command/core/project.py CHANGED
@@ -153,13 +153,19 @@ def init_project(
153
153
  'db/', 'db/service.py', 'db/model/', 'db/model/entity.py',
154
154
  ],
155
155
  }
156
+ # CLI 项目不需要的服务端文件
157
+ cli_skip_files = {'app.yaml', 'app.yaml.tpl', 'requirements.txt', 'requirements.txt.tpl', 'Dockerfile', 'Dockerfile.tpl'}
156
158
  disabled_features = {
157
159
  key for key, flag_val in features.to_template_vars().items()
158
160
  if flag_val == 'false' and key in feature_map
159
161
  }
160
162
 
161
163
  def _should_skip(rel_path: str) -> bool:
162
- """检查文件是否因功能关闭而应跳过"""
164
+ """检查文件是否因功能关闭或项目类型而应跳过"""
165
+ # CLI 项目跳过不需要的服务端文件
166
+ if project_type == "cli":
167
+ if rel_path in cli_skip_files or rel_path.replace('.tpl', '') in cli_skip_files:
168
+ return True
163
169
  for feat_key in disabled_features:
164
170
  for pattern in feature_map[feat_key]:
165
171
  if pattern in rel_path:
@@ -191,7 +197,7 @@ def init_project(
191
197
  copied_files = _render_files(file_mappings, context, project_path, verbose)
192
198
 
193
199
  if copied_files > 0:
194
- _print_success_message(project_path, project_name, copied_files)
200
+ _print_success_message(project_path, project_name, copied_files, project_type)
195
201
  return True
196
202
  else:
197
203
  print_warning("未创建任何文件,可能是缺少模板文件或模板路径配置错误")
@@ -284,7 +290,8 @@ def _render_files(
284
290
  def _print_success_message(
285
291
  project_path: Path,
286
292
  project_name: str,
287
- copied_files: int
293
+ copied_files: int,
294
+ project_type: str = "web",
288
295
  ) -> None:
289
296
  """打印成功信息"""
290
297
  print_success(f"模板工程 {project_name} 创建完成!")
@@ -293,7 +300,11 @@ def _print_success_message(
293
300
  print()
294
301
  print_info("下一步操作:")
295
302
  print(f" cd {project_name}")
296
- print(f" # 建议先创建虚拟环境")
297
- print(f" python -m venv .venv && source .venv/bin/activate")
298
- print(f" pip install -r requirements.txt")
299
- print(f" python app.py")
303
+ if project_type == "cli":
304
+ print(f" uv sync")
305
+ print(f" uv run python app.py")
306
+ else:
307
+ print(f" # 建议先创建虚拟环境")
308
+ print(f" python -m venv .venv && source .venv/bin/activate")
309
+ print(f" pip install -r requirements.txt")
310
+ print(f" python app.py")
@@ -0,0 +1,54 @@
1
+ # {{ project_name }}
2
+
3
+ {{ project_name }} - Python CLI 命令行工具
4
+
5
+ ## 项目结构
6
+
7
+ ```
8
+ {{ project_name }}/
9
+ ├── commands/ # 子命令目录
10
+ │ ├── __init__.py
11
+ │ └── hello.py # 示例子命令
12
+ ├── tools/ # 工具函数
13
+ ├── model/ # 数据模型
14
+ ├── client/ # 外部服务客户端
15
+ ├── app.py # CLI 入口
16
+ ├── pyproject.toml # uv 项目配置
17
+ └── README.md
18
+ ```
19
+
20
+ ## 快速开始
21
+
22
+ ### 安装依赖
23
+ ```bash
24
+ uv sync
25
+ ```
26
+
27
+ ### 使用
28
+ ```bash
29
+ # 查看帮助
30
+ uv run python app.py -h
31
+
32
+ # hello 命令
33
+ uv run python app.py hello --name "World"
34
+
35
+ # 查看版本
36
+ uv run python app.py version
37
+ ```
38
+
39
+ ### 添加新子命令
40
+
41
+ 1. 在 `commands/` 目录下创建新模块,例如 `commands/xxx.py`
42
+ 2. 实现 `handle_xxx(args)` 函数
43
+ 3. 在 `app.py` 中注册子命令:
44
+
45
+ ```python
46
+ from commands.xxx import handle_xxx
47
+
48
+ # 在 create_parser() 中添加:
49
+ xxx_parser = subparsers.add_parser("xxx", help="xxx 说明")
50
+
51
+ # 在 main() 中添加:
52
+ elif args.command == "xxx":
53
+ handle_xxx(args)
54
+ ```
@@ -0,0 +1 @@
1
+ """CLI 项目模板"""
@@ -0,0 +1,45 @@
1
+ """
2
+ {{ project_name }} - CLI 工具入口
3
+ 创建时间: {{ create_time }}
4
+ 作者: {{ author }}
5
+ """
6
+ import argparse
7
+ import sys
8
+
9
+ from commands.hello import handle_hello
10
+
11
+
12
+ def create_parser() -> argparse.ArgumentParser:
13
+ """创建命令行解析器"""
14
+ parser = argparse.ArgumentParser(
15
+ prog="{{ project_name }}",
16
+ description="{{ project_name }} - CLI 命令行工具",
17
+ )
18
+
19
+ subparsers = parser.add_subparsers(dest="command", help="子命令")
20
+
21
+ # hello 子命令
22
+ hello_parser = subparsers.add_parser("hello", help="打招呼")
23
+ hello_parser.add_argument("--name", default="World", help="名字")
24
+
25
+ # version 子命令
26
+ subparsers.add_parser("version", help="显示版本")
27
+
28
+ return parser
29
+
30
+
31
+ def main() -> None:
32
+ """CLI 主入口"""
33
+ parser = create_parser()
34
+ args = parser.parse_args()
35
+
36
+ if args.command == "hello":
37
+ handle_hello(args)
38
+ elif args.command == "version":
39
+ print("{{ project_name }} 1.0.0")
40
+ else:
41
+ parser.print_help()
42
+
43
+
44
+ if __name__ == "__main__":
45
+ main()
@@ -0,0 +1 @@
1
+ """子命令模块"""
@@ -0,0 +1,6 @@
1
+ """hello 子命令"""
2
+
3
+
4
+ def handle_hello(args) -> None:
5
+ """处理 hello 命令"""
6
+ print(f"Hello, {args.name}!")
@@ -0,0 +1,14 @@
1
+ [project]
2
+ name = "{{ project_name }}"
3
+ version = "0.1.0"
4
+ description = "{{ project_name }} - CLI 命令行工具"
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ dependencies = []
8
+
9
+ [project.scripts]
10
+ {{ short_project_name }} = "app:main"
11
+
12
+ [build-system]
13
+ requires = ["hatchling"]
14
+ build-backend = "hatchling.build"
@@ -0,0 +1,3 @@
1
+ """
2
+ 工具函数模块
3
+ """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sycommon-python-lib
3
- Version: 0.2.2a3
3
+ Version: 0.2.2a4
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -11,18 +11,18 @@ Requires-Dist: anyio>=4.12.1
11
11
  Requires-Dist: decorator>=5.2.1
12
12
  Requires-Dist: deepagents>=0.5.3
13
13
  Requires-Dist: elasticsearch>=9.3.0
14
- Requires-Dist: fastapi>=0.136.0
14
+ Requires-Dist: fastapi>=0.136.1
15
15
  Requires-Dist: jinja2>=3.1.6
16
16
  Requires-Dist: kafka-python>=2.3.1
17
17
  Requires-Dist: langchain>=1.2.15
18
- Requires-Dist: langchain-core>=1.3.0
18
+ Requires-Dist: langchain-core>=1.3.1
19
19
  Requires-Dist: langchain-openai>=1.2.0
20
20
  Requires-Dist: langfuse>=4.5.0
21
21
  Requires-Dist: langgraph>=1.1.9
22
22
  Requires-Dist: langgraph-checkpoint-redis>=0.4.1
23
23
  Requires-Dist: ldap3>=2.9.1
24
24
  Requires-Dist: loguru>=0.7.3
25
- Requires-Dist: mysql-connector-python>=9.6.0
25
+ Requires-Dist: mysql-connector-python>=9.7.0
26
26
  Requires-Dist: nacos-sdk-python<3.0,>=2.0.11
27
27
  Requires-Dist: psutil>=7.2.2
28
28
  Requires-Dist: pyxxl>=0.4.6
@@ -35,7 +35,7 @@ Requires-Dist: sentry-sdk[fastapi]>=2.58.0
35
35
  Requires-Dist: sqlalchemy[asyncio]>=2.0.48
36
36
  Requires-Dist: starlette[full]>=1.0.0
37
37
  Requires-Dist: tiktoken>=0.12.0
38
- Requires-Dist: uvicorn>=0.45.0
38
+ Requires-Dist: uvicorn>=0.46.0
39
39
  Requires-Dist: wecom-aibot-python-sdk>=1.0.2
40
40
 
41
41
  # sycommon-python-lib
@@ -1,11 +1,12 @@
1
1
  command/__init__.py,sha256=FQYIr-EnMOm1pBdQbQbDXM0GXf0DSO0nEyEnAOCSyP8,496
2
- command/cli.py,sha256=-0pFHr-ykvb-amQrcuH8gZmwgxz9T6oky3hjnXJEirI,15228
2
+ command/cli.py,sha256=6JOVT8BgLjqAYkPt2Xjl6RzsCNJlO3YpctkbSwbOLiM,15984
3
3
  command/core/__init__.py,sha256=pm4iGEGmKMPgRCF-sC9kd3kGVVX68xYvGt1Z64wnRyQ,480
4
4
  command/core/console.py,sha256=U2vKA2L7Yp9EzdyzyZzgt4EACjc_y0tXx4hl1emJG-M,752
5
- command/core/models.py,sha256=LG8Be4nYgE5mqWaCBo6izqrJ1lUxKEdZYKyUx13VQzA,1960
6
- command/core/project.py,sha256=8X2EFby8h9kEoFsxwJ0Egatsz0IpU0mRp1bUMHV-l98,10516
5
+ command/core/models.py,sha256=AS8vCPSctJoG7yqAvjADOpmdZ285kUGUQCp_nu4VswU,2291
6
+ command/core/project.py,sha256=-2mT0jyf2qoj7SxLb-V-vCACs2ubbva43RC0bfkpN3A,11081
7
7
  command/core/utils.py,sha256=SHwxTBgZ5qoABkKGvyldGai1MlA2EQB9ioZFwMjIWiw,768
8
8
  command/templates/__init__.py,sha256=tA-BvD00oALAAn9Iam-3YPAoJXIAgnEIBsLiyjarATM,19
9
+ command/templates/__pycache__/__init__.cpython-311.pyc,sha256=lh9KKCjSkZqpuuIj8xjDZXcD2PyqZbQbyEOoApR0CMg,236
9
10
  command/templates/agent/README.md.tpl,sha256=fJ1GVxHBncnAafckloDzIqpeXUsgj42n6ok3KDr9ePM,2200
10
11
  command/templates/agent/__init__.py,sha256=7zsuCBh_av1qD1oCTeTPDG7FAtSneIYV5DDEsuwS78M,25
11
12
  command/templates/agent/app.py.tpl,sha256=mYkXraQtJ2o8dHEryK7b_OlUL7QsL4EUHysPKRbTG0I,2788
@@ -40,6 +41,13 @@ command/templates/base/client/FileServiceClient.py.tpl,sha256=t5_bx484rvpwFAe1d0
40
41
  command/templates/base/client/__init__.py.tpl,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
42
  command/templates/base/model/__init__.py.tpl,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
43
  command/templates/base/model/file_info.py.tpl,sha256=N_sFB9kR2Bxlzexu53KuG9voraNtRdOsVd30f3qBCfU,653
44
+ command/templates/cli/README.md.tpl,sha256=r8fVuuXr3BK4ZktSPqxK4XR35xIvLmmdJC15JSvtGVw,1126
45
+ command/templates/cli/__init__.py,sha256=BTnJYTp-jUJi5N7cfwmd62SX4tIKuT9Edvk79lZYIhM,23
46
+ command/templates/cli/app.py.tpl,sha256=8sjXr0tnbzJ1wAI3_k6k2kBcK9O0PE8UZo_33kAbmTI,1056
47
+ command/templates/cli/pyproject.toml.tpl,sha256=LrcSYleLbKKg412_2Kxc4Z-CFzwC_hmp_dRJ7I7BCQM,311
48
+ command/templates/cli/commands/__init__.py.tpl,sha256=4FrbV9-EL4hF-upzGoMCHJg2bNoUK_qY4ATChSfyh5Q,22
49
+ command/templates/cli/commands/hello.py.tpl,sha256=rFdawL-6gHiz_qw58PS3KfHGn-nkp84b5NbAQSuFnY0,120
50
+ command/templates/cli/tools/__init__.py.tpl,sha256=A_YW5Gb8wmc9FwtRi7lkiCz8otVgwQgSqdtzkNrmkHs,27
43
51
  command/templates/web/README.md.tpl,sha256=Slv0EXn4qQmNvUbDJEZYCwLem85qX68aG7DXpnxhiPY,1728
44
52
  command/templates/web/__init__.py,sha256=iBr-dkP_jukCaGfKkAxxCe7bcQEjhQdg0sX8DyX84b8,23
45
53
  command/templates/web/app.py.tpl,sha256=As9zsXmkeNAMR3VWf3uiryOcjqQTbpNcfMSQJuZRGQk,2864
@@ -246,8 +254,8 @@ sycommon/tools/syemail.py,sha256=BDFhgf7WDOQeTcjxJEQdu0dQhnHFPO_p3eI0-Ni3LhQ,561
246
254
  sycommon/tools/timing.py,sha256=OiiE7P07lRoMzX9kzb8sZU9cDb0zNnqIlY5pWqHcnkY,2064
247
255
  sycommon/xxljob/__init__.py,sha256=7eoBlQxv-B39IfRSCY2bkqdGYs1QRe1umAWd88VMEEM,86
248
256
  sycommon/xxljob/xxljob_service.py,sha256=JIEJaGXhqrTLcyxlyynSrsHg9bBnDNzX-D4qIWLRPUE,6815
249
- sycommon_python_lib-0.2.2a3.dist-info/METADATA,sha256=JzdlgU0tqIPnpanKWQWPVrHCKAtpd_gq-8noMxPKdRo,7683
250
- sycommon_python_lib-0.2.2a3.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
251
- sycommon_python_lib-0.2.2a3.dist-info/entry_points.txt,sha256=gsR4SssKxDWjRU8ggidzNcdMXDPRSKRS7UaGyNP84Qg,92
252
- sycommon_python_lib-0.2.2a3.dist-info/top_level.txt,sha256=RgphKrg7nJyZ7irJqbxFr-5H2LUYTvI7ivoWZH2hcD0,29
253
- sycommon_python_lib-0.2.2a3.dist-info/RECORD,,
257
+ sycommon_python_lib-0.2.2a4.dist-info/METADATA,sha256=6N7cf-QKXkNkrczrflLXX4aK3-wtxCzPWeeU0fhBH6w,7683
258
+ sycommon_python_lib-0.2.2a4.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
259
+ sycommon_python_lib-0.2.2a4.dist-info/entry_points.txt,sha256=gsR4SssKxDWjRU8ggidzNcdMXDPRSKRS7UaGyNP84Qg,92
260
+ sycommon_python_lib-0.2.2a4.dist-info/top_level.txt,sha256=RgphKrg7nJyZ7irJqbxFr-5H2LUYTvI7ivoWZH2hcD0,29
261
+ sycommon_python_lib-0.2.2a4.dist-info/RECORD,,