chatenv 0.2.3__tar.gz → 0.2.4__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 (26) hide show
  1. {chatenv-0.2.3/src/chatenv.egg-info → chatenv-0.2.4}/PKG-INFO +12 -6
  2. {chatenv-0.2.3 → chatenv-0.2.4}/README.md +3 -0
  3. {chatenv-0.2.3 → chatenv-0.2.4}/pyproject.toml +10 -5
  4. {chatenv-0.2.3 → chatenv-0.2.4}/src/chatenv/__init__.py +1 -1
  5. {chatenv-0.2.3 → chatenv-0.2.4}/src/chatenv/cli.py +103 -0
  6. {chatenv-0.2.3 → chatenv-0.2.4/src/chatenv.egg-info}/PKG-INFO +12 -6
  7. {chatenv-0.2.3 → chatenv-0.2.4}/src/chatenv.egg-info/requires.txt +5 -5
  8. chatenv-0.2.4/tests/test_version.py +44 -0
  9. chatenv-0.2.3/tests/test_version.py +0 -14
  10. {chatenv-0.2.3 → chatenv-0.2.4}/LICENSE +0 -0
  11. {chatenv-0.2.3 → chatenv-0.2.4}/setup.cfg +0 -0
  12. {chatenv-0.2.3 → chatenv-0.2.4}/src/chatenv/configs.py +0 -0
  13. {chatenv-0.2.3 → chatenv-0.2.4}/src/chatenv/discovery.py +0 -0
  14. {chatenv-0.2.3 → chatenv-0.2.4}/src/chatenv/fields.py +0 -0
  15. {chatenv-0.2.3 → chatenv-0.2.4}/src/chatenv/paste.py +0 -0
  16. {chatenv-0.2.3 → chatenv-0.2.4}/src/chatenv/paths.py +0 -0
  17. {chatenv-0.2.3 → chatenv-0.2.4}/src/chatenv/presets/__init__.py +0 -0
  18. {chatenv-0.2.3 → chatenv-0.2.4}/src/chatenv/registry.py +0 -0
  19. {chatenv-0.2.3 → chatenv-0.2.4}/src/chatenv/source_chain.py +0 -0
  20. {chatenv-0.2.3 → chatenv-0.2.4}/src/chatenv/store.py +0 -0
  21. {chatenv-0.2.3 → chatenv-0.2.4}/src/chatenv/utils.py +0 -0
  22. {chatenv-0.2.3 → chatenv-0.2.4}/src/chatenv.egg-info/SOURCES.txt +0 -0
  23. {chatenv-0.2.3 → chatenv-0.2.4}/src/chatenv.egg-info/dependency_links.txt +0 -0
  24. {chatenv-0.2.3 → chatenv-0.2.4}/src/chatenv.egg-info/entry_points.txt +0 -0
  25. {chatenv-0.2.3 → chatenv-0.2.4}/src/chatenv.egg-info/top_level.txt +0 -0
  26. {chatenv-0.2.3 → chatenv-0.2.4}/tests/test_chatenv_core.py +0 -0
@@ -1,9 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chatenv
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: ChatArch typed environment profile manager
5
5
  Author-email: rexwzh <1073853456@qq.com>
6
6
  License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/ChatArch/ChatEnv
8
+ Project-URL: Repository, https://github.com/ChatArch/ChatEnv
9
+ Project-URL: Documentation, https://chatarch.github.io/ChatEnv/
7
10
  Keywords: chatenv,chatarch,env
8
11
  Classifier: Programming Language :: Python :: 3
9
12
  Classifier: Operating System :: OS Independent
@@ -18,11 +21,11 @@ Requires-Dist: build>=1.0; extra == "dev"
18
21
  Requires-Dist: pytest>=8.0; extra == "dev"
19
22
  Requires-Dist: twine>=5.0; extra == "dev"
20
23
  Provides-Extra: docs
21
- Requires-Dist: mkdocs>=1.6; extra == "docs"
22
- Requires-Dist: mkdocs-material>=9.5; extra == "docs"
23
- Requires-Dist: mkdocs-minify-plugin>=0.8; extra == "docs"
24
- Requires-Dist: mkdocs-redirects>=1.2; extra == "docs"
25
- Requires-Dist: mike>=2.1; extra == "docs"
24
+ Requires-Dist: mkdocs<2.0,>=1.6; extra == "docs"
25
+ Requires-Dist: mkdocs-material<9.7,>=9.5; extra == "docs"
26
+ Requires-Dist: mkdocs-minify-plugin<1.0,>=0.8; extra == "docs"
27
+ Requires-Dist: mkdocs-redirects<2.0,>=1.2; extra == "docs"
28
+ Requires-Dist: mike<3.0,>=2.1; extra == "docs"
26
29
  Dynamic: license-file
27
30
 
28
31
  <div align="center">
@@ -87,6 +90,7 @@ $CHATARCH_HOME/envs/
87
90
 
88
91
  ```bash
89
92
  chatenv --version
93
+ chatenv --tree
90
94
  chatenv init -t example
91
95
  chatenv status
92
96
  chatenv status --detail
@@ -114,6 +118,8 @@ export CHATARCH_AUTO_PROMPT=false
114
118
 
115
119
  此时只有缺少必要参数的命令会直接报错;参数已经足够的命令行为不变。
116
120
 
121
+ `chatenv --tree` 可从当前安装包的 Click 注册表实时输出完整命令树,用于验收和脚本 readback。
122
+
117
123
  更多用法见 `docs/cli.md`。
118
124
 
119
125
  ## Paste
@@ -60,6 +60,7 @@ $CHATARCH_HOME/envs/
60
60
 
61
61
  ```bash
62
62
  chatenv --version
63
+ chatenv --tree
63
64
  chatenv init -t example
64
65
  chatenv status
65
66
  chatenv status --detail
@@ -87,6 +88,8 @@ export CHATARCH_AUTO_PROMPT=false
87
88
 
88
89
  此时只有缺少必要参数的命令会直接报错;参数已经足够的命令行为不变。
89
90
 
91
+ `chatenv --tree` 可从当前安装包的 Click 注册表实时输出完整命令树,用于验收和脚本 readback。
92
+
90
93
  更多用法见 `docs/cli.md`。
91
94
 
92
95
  ## Paste
@@ -21,6 +21,11 @@ classifiers = [
21
21
  "Operating System :: OS Independent",
22
22
  ]
23
23
 
24
+ [project.urls]
25
+ Homepage = "https://github.com/ChatArch/ChatEnv"
26
+ Repository = "https://github.com/ChatArch/ChatEnv"
27
+ Documentation = "https://chatarch.github.io/ChatEnv/"
28
+
24
29
  [tool.setuptools.dynamic]
25
30
  version = {attr = "chatenv.__version__"}
26
31
 
@@ -40,9 +45,9 @@ dev = [
40
45
  "twine>=5.0",
41
46
  ]
42
47
  docs = [
43
- "mkdocs>=1.6",
44
- "mkdocs-material>=9.5",
45
- "mkdocs-minify-plugin>=0.8",
46
- "mkdocs-redirects>=1.2",
47
- "mike>=2.1",
48
+ "mkdocs>=1.6,<2.0",
49
+ "mkdocs-material>=9.5,<9.7",
50
+ "mkdocs-minify-plugin>=0.8,<1.0",
51
+ "mkdocs-redirects>=1.2,<2.0",
52
+ "mike>=2.1,<3.0",
48
53
  ]
@@ -20,4 +20,4 @@ __all__ = [
20
20
  "__version__",
21
21
  ]
22
22
 
23
- __version__ = "0.2.3"
23
+ __version__ = "0.2.4"
@@ -123,8 +123,111 @@ class OrderedGroup(click.Group):
123
123
  return ordered
124
124
 
125
125
 
126
+ def _format_metavar(name: str) -> str:
127
+ return name.replace("_", "-").upper()
128
+
129
+
130
+ def _format_argument(param: click.Argument) -> str:
131
+ metavar = _format_metavar(param.name or "ARG")
132
+ if not param.required:
133
+ return f"[{metavar}]"
134
+ if param.nargs == -1:
135
+ return f"<{metavar}...>"
136
+ if param.nargs and param.nargs > 1:
137
+ return " ".join(f"<{metavar}>" for _ in range(param.nargs))
138
+ return f"<{metavar}>"
139
+
140
+
141
+ def _option_name(param: click.Option) -> str:
142
+ long_opts = [opt for opt in param.opts if opt.startswith("--")]
143
+ if long_opts:
144
+ return long_opts[0]
145
+ return param.opts[0] if param.opts else _format_metavar(param.name or "OPTION")
146
+
147
+
148
+ def _format_option(param: click.Option) -> str:
149
+ name = _option_name(param)
150
+ secondary_long = next(
151
+ (opt for opt in param.secondary_opts if opt.startswith("--")),
152
+ None,
153
+ )
154
+ if param.is_bool_flag and secondary_long:
155
+ return f"[{name}/{secondary_long}]"
156
+ if param.is_flag:
157
+ return f"[{name}]"
158
+ metavar = param.metavar or _format_metavar(param.name or "VALUE")
159
+ return f"[{name} <{metavar}>]"
160
+
161
+
162
+ def _command_signature(command: click.Command) -> str:
163
+ parts: list[str] = []
164
+ for param in command.params:
165
+ if isinstance(param, click.Argument):
166
+ parts.append(_format_argument(param))
167
+ for param in command.params:
168
+ if isinstance(param, click.Option):
169
+ if param.name in {"help", "version", "tree"}:
170
+ continue
171
+ parts.append(_format_option(param))
172
+ return " " + " ".join(parts) if parts else ""
173
+
174
+
175
+ def _short_help(command: click.Command) -> str:
176
+ return command.short_help or (command.help or "No description.").strip().splitlines()[0]
177
+
178
+
179
+ def _group_items(group: click.Group) -> list[tuple[str, str | click.Command]]:
180
+ ctx = click.Context(group, resilient_parsing=True)
181
+ return [(name, group.commands[name]) for name in group.list_commands(ctx)]
182
+
183
+
184
+ def render_cli_tree(root: click.Group | None = None) -> str:
185
+ """Render the registered Click command tree for `chatenv --tree`."""
186
+ if root is None:
187
+ root = cli
188
+ lines = [f"chatenv{_command_signature(root)} # {_short_help(root)}"]
189
+ root_items: list[tuple[str, str | click.Command]] = [
190
+ ("--help", "Show this help message."),
191
+ ("--version", "Show the installed package version."),
192
+ ("--tree", "Print the registered command tree."),
193
+ *_group_items(root),
194
+ ]
195
+
196
+ def walk(items: list[tuple[str, str | click.Command]], prefix: str = "") -> None:
197
+ for index, (name, item) in enumerate(items):
198
+ is_last = index == len(items) - 1
199
+ connector = "└── " if is_last else "├── "
200
+ child_prefix = prefix + (" " if is_last else "│ ")
201
+ if isinstance(item, str):
202
+ lines.append(f"{prefix}{connector}{name} # {item}")
203
+ continue
204
+ lines.append(f"{prefix}{connector}{name}{_command_signature(item)} # {_short_help(item)}")
205
+ if isinstance(item, click.Group) and item.commands:
206
+ walk(_group_items(item), child_prefix)
207
+
208
+ walk(root_items)
209
+ return "\n".join(lines)
210
+
211
+
212
+ def _tree_callback(ctx: click.Context, _param: click.Option, value: bool) -> None:
213
+ if not value or ctx.resilient_parsing:
214
+ return
215
+ if not isinstance(ctx.command, click.Group):
216
+ raise click.ClickException("--tree is only available on command groups")
217
+ click.echo(render_cli_tree(ctx.command))
218
+ ctx.exit()
219
+
220
+
126
221
  @click.group(name="chatenv", cls=OrderedGroup)
127
222
  @click.version_option(__version__, prog_name="chatenv")
223
+ @click.option(
224
+ "--tree",
225
+ is_flag=True,
226
+ is_eager=True,
227
+ expose_value=False,
228
+ callback=_tree_callback,
229
+ help="Print the registered command tree.",
230
+ )
128
231
  @click.option("--home", type=click.Path(file_okay=False, path_type=Path), help="Override CHATARCH_HOME for this command.")
129
232
  @click.pass_context
130
233
  def cli(ctx: click.Context, home: Path | None):
@@ -1,9 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chatenv
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: ChatArch typed environment profile manager
5
5
  Author-email: rexwzh <1073853456@qq.com>
6
6
  License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/ChatArch/ChatEnv
8
+ Project-URL: Repository, https://github.com/ChatArch/ChatEnv
9
+ Project-URL: Documentation, https://chatarch.github.io/ChatEnv/
7
10
  Keywords: chatenv,chatarch,env
8
11
  Classifier: Programming Language :: Python :: 3
9
12
  Classifier: Operating System :: OS Independent
@@ -18,11 +21,11 @@ Requires-Dist: build>=1.0; extra == "dev"
18
21
  Requires-Dist: pytest>=8.0; extra == "dev"
19
22
  Requires-Dist: twine>=5.0; extra == "dev"
20
23
  Provides-Extra: docs
21
- Requires-Dist: mkdocs>=1.6; extra == "docs"
22
- Requires-Dist: mkdocs-material>=9.5; extra == "docs"
23
- Requires-Dist: mkdocs-minify-plugin>=0.8; extra == "docs"
24
- Requires-Dist: mkdocs-redirects>=1.2; extra == "docs"
25
- Requires-Dist: mike>=2.1; extra == "docs"
24
+ Requires-Dist: mkdocs<2.0,>=1.6; extra == "docs"
25
+ Requires-Dist: mkdocs-material<9.7,>=9.5; extra == "docs"
26
+ Requires-Dist: mkdocs-minify-plugin<1.0,>=0.8; extra == "docs"
27
+ Requires-Dist: mkdocs-redirects<2.0,>=1.2; extra == "docs"
28
+ Requires-Dist: mike<3.0,>=2.1; extra == "docs"
26
29
  Dynamic: license-file
27
30
 
28
31
  <div align="center">
@@ -87,6 +90,7 @@ $CHATARCH_HOME/envs/
87
90
 
88
91
  ```bash
89
92
  chatenv --version
93
+ chatenv --tree
90
94
  chatenv init -t example
91
95
  chatenv status
92
96
  chatenv status --detail
@@ -114,6 +118,8 @@ export CHATARCH_AUTO_PROMPT=false
114
118
 
115
119
  此时只有缺少必要参数的命令会直接报错;参数已经足够的命令行为不变。
116
120
 
121
+ `chatenv --tree` 可从当前安装包的 Click 注册表实时输出完整命令树,用于验收和脚本 readback。
122
+
117
123
  更多用法见 `docs/cli.md`。
118
124
 
119
125
  ## Paste
@@ -8,8 +8,8 @@ pytest>=8.0
8
8
  twine>=5.0
9
9
 
10
10
  [docs]
11
- mkdocs>=1.6
12
- mkdocs-material>=9.5
13
- mkdocs-minify-plugin>=0.8
14
- mkdocs-redirects>=1.2
15
- mike>=2.1
11
+ mkdocs<2.0,>=1.6
12
+ mkdocs-material<9.7,>=9.5
13
+ mkdocs-minify-plugin<1.0,>=0.8
14
+ mkdocs-redirects<2.0,>=1.2
15
+ mike<3.0,>=2.1
@@ -0,0 +1,44 @@
1
+ from chatenv import __version__
2
+ from chatenv.cli import cli
3
+ from click.testing import CliRunner
4
+
5
+
6
+ def test_version_present():
7
+ assert __version__ == "0.2.4"
8
+
9
+
10
+ def test_cli_version_option():
11
+ result = CliRunner().invoke(cli, ["--version"])
12
+
13
+ assert result.exit_code == 0
14
+ assert __version__ in result.output
15
+
16
+
17
+ def test_help_lists_tree_option():
18
+ result = CliRunner().invoke(cli, ["--help"])
19
+
20
+ assert result.exit_code == 0
21
+ assert "--tree" in result.output
22
+
23
+
24
+ def test_tree_option_renders_registered_command_surface():
25
+ result = CliRunner().invoke(cli, ["--tree"])
26
+
27
+ assert result.exit_code == 0
28
+ assert "chatenv [--home <HOME>] # Manage typed env profiles" in result.output
29
+ assert "├── --help" in result.output
30
+ assert "├── --version" in result.output
31
+ assert "├── --tree" in result.output
32
+ assert "├── init" in result.output
33
+ assert "├── new [NAME]" in result.output
34
+ assert "├── paste" in result.output
35
+ assert "├── use [NAME]" in result.output
36
+ assert "├── list" in result.output
37
+ assert "├── status" in result.output
38
+ assert "├── cat [NAME]" in result.output
39
+ assert "├── get [KEY]" in result.output
40
+ assert "├── set [KEY-VALUE]" in result.output
41
+ assert "├── save [NAME]" in result.output
42
+ assert "├── delete [NAME]" in result.output
43
+ assert "└── test" in result.output
44
+ assert "hello" not in result.output.lower()
@@ -1,14 +0,0 @@
1
- from chatenv import __version__
2
- from chatenv.cli import cli
3
- from click.testing import CliRunner
4
-
5
-
6
- def test_version_present():
7
- assert __version__ == "0.2.3"
8
-
9
-
10
- def test_cli_version_option():
11
- result = CliRunner().invoke(cli, ["--version"])
12
-
13
- assert result.exit_code == 0
14
- assert __version__ in result.output
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes