chatenv 0.2.2__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.
- {chatenv-0.2.2/src/chatenv.egg-info → chatenv-0.2.4}/PKG-INFO +12 -6
- {chatenv-0.2.2 → chatenv-0.2.4}/README.md +3 -0
- {chatenv-0.2.2 → chatenv-0.2.4}/pyproject.toml +10 -5
- {chatenv-0.2.2 → chatenv-0.2.4}/src/chatenv/__init__.py +1 -1
- {chatenv-0.2.2 → chatenv-0.2.4}/src/chatenv/cli.py +128 -4
- {chatenv-0.2.2 → chatenv-0.2.4/src/chatenv.egg-info}/PKG-INFO +12 -6
- {chatenv-0.2.2 → chatenv-0.2.4}/src/chatenv.egg-info/requires.txt +5 -5
- {chatenv-0.2.2 → chatenv-0.2.4}/tests/test_chatenv_core.py +33 -0
- chatenv-0.2.4/tests/test_version.py +44 -0
- chatenv-0.2.2/tests/test_version.py +0 -14
- {chatenv-0.2.2 → chatenv-0.2.4}/LICENSE +0 -0
- {chatenv-0.2.2 → chatenv-0.2.4}/setup.cfg +0 -0
- {chatenv-0.2.2 → chatenv-0.2.4}/src/chatenv/configs.py +0 -0
- {chatenv-0.2.2 → chatenv-0.2.4}/src/chatenv/discovery.py +0 -0
- {chatenv-0.2.2 → chatenv-0.2.4}/src/chatenv/fields.py +0 -0
- {chatenv-0.2.2 → chatenv-0.2.4}/src/chatenv/paste.py +0 -0
- {chatenv-0.2.2 → chatenv-0.2.4}/src/chatenv/paths.py +0 -0
- {chatenv-0.2.2 → chatenv-0.2.4}/src/chatenv/presets/__init__.py +0 -0
- {chatenv-0.2.2 → chatenv-0.2.4}/src/chatenv/registry.py +0 -0
- {chatenv-0.2.2 → chatenv-0.2.4}/src/chatenv/source_chain.py +0 -0
- {chatenv-0.2.2 → chatenv-0.2.4}/src/chatenv/store.py +0 -0
- {chatenv-0.2.2 → chatenv-0.2.4}/src/chatenv/utils.py +0 -0
- {chatenv-0.2.2 → chatenv-0.2.4}/src/chatenv.egg-info/SOURCES.txt +0 -0
- {chatenv-0.2.2 → chatenv-0.2.4}/src/chatenv.egg-info/dependency_links.txt +0 -0
- {chatenv-0.2.2 → chatenv-0.2.4}/src/chatenv.egg-info/entry_points.txt +0 -0
- {chatenv-0.2.2 → chatenv-0.2.4}/src/chatenv.egg-info/top_level.txt +0 -0
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: chatenv
|
|
3
|
-
Version: 0.2.
|
|
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
|
|
22
|
-
Requires-Dist: mkdocs-material
|
|
23
|
-
Requires-Dist: mkdocs-minify-plugin
|
|
24
|
-
Requires-Dist: mkdocs-redirects
|
|
25
|
-
Requires-Dist: mike
|
|
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
|
]
|
|
@@ -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):
|
|
@@ -277,7 +380,9 @@ def _resolve_config_types_or_prompt(
|
|
|
277
380
|
return [_select_config_interactive(action=action, configs=selectable)]
|
|
278
381
|
|
|
279
382
|
if not config_types and allow_multi:
|
|
280
|
-
|
|
383
|
+
raise click.ClickException(
|
|
384
|
+
f"{action} requires --type/-t outside interactive mode.\n{_available_config_types_message()}"
|
|
385
|
+
)
|
|
281
386
|
if not config_types:
|
|
282
387
|
raise click.ClickException(
|
|
283
388
|
f"{action} requires --type/-t outside interactive mode.\n{_available_config_types_message()}"
|
|
@@ -377,6 +482,23 @@ def init_env(ctx: click.Context, config_types: tuple[str, ...], interactive: boo
|
|
|
377
482
|
click.echo(f"Configuration saved to {_envs_dir(ctx)}")
|
|
378
483
|
|
|
379
484
|
|
|
485
|
+
def _has_configured_values(config_cls: type[BaseEnvConfig], values: dict[str, str]) -> bool:
|
|
486
|
+
"""Return true when a profile has values beyond blanks and schema defaults."""
|
|
487
|
+
fields_by_key = {field.env_key: field for field in config_cls.get_fields().values()}
|
|
488
|
+
for key, value in values.items():
|
|
489
|
+
field = fields_by_key.get(key)
|
|
490
|
+
if field is None:
|
|
491
|
+
if value:
|
|
492
|
+
return True
|
|
493
|
+
continue
|
|
494
|
+
if value == "":
|
|
495
|
+
continue
|
|
496
|
+
if field.default is not None and str(field.default) == str(value):
|
|
497
|
+
continue
|
|
498
|
+
return True
|
|
499
|
+
return False
|
|
500
|
+
|
|
501
|
+
|
|
380
502
|
@cli.command(name="list")
|
|
381
503
|
@click.option("--type", "config_types", "-t", multiple=True, help="Filter config types.")
|
|
382
504
|
@click.pass_context
|
|
@@ -390,12 +512,14 @@ def list_env(ctx: click.Context, config_types: tuple[str, ...]):
|
|
|
390
512
|
found = False
|
|
391
513
|
for config_cls in configs:
|
|
392
514
|
profiles = store.list_profiles(config_cls)
|
|
393
|
-
|
|
394
|
-
|
|
515
|
+
active_path = store.active_path(config_cls)
|
|
516
|
+
has_default = active_path.exists()
|
|
517
|
+
show_default = has_default and _has_configured_values(config_cls, store.load_active(config_cls))
|
|
518
|
+
if not show_default and not profiles:
|
|
395
519
|
continue
|
|
396
520
|
found = True
|
|
397
521
|
click.echo(f"[{config_cls.get_storage_name()}]")
|
|
398
|
-
if
|
|
522
|
+
if show_default:
|
|
399
523
|
click.echo("- .env [default]")
|
|
400
524
|
for profile in profiles:
|
|
401
525
|
click.echo(f"- {profile}.env")
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: chatenv
|
|
3
|
-
Version: 0.2.
|
|
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
|
|
22
|
-
Requires-Dist: mkdocs-material
|
|
23
|
-
Requires-Dist: mkdocs-minify-plugin
|
|
24
|
-
Requires-Dist: mkdocs-redirects
|
|
25
|
-
Requires-Dist: mike
|
|
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
|
|
12
|
-
mkdocs-material
|
|
13
|
-
mkdocs-minify-plugin
|
|
14
|
-
mkdocs-redirects
|
|
15
|
-
mike
|
|
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
|
|
@@ -210,6 +210,21 @@ def test_list_keeps_named_only_profiles_without_default_marker(tmp_path):
|
|
|
210
210
|
assert "- .env [default]" not in result.output
|
|
211
211
|
assert "- work.env" in result.output
|
|
212
212
|
|
|
213
|
+
|
|
214
|
+
def test_list_hides_default_only_active_profile_by_default(tmp_path):
|
|
215
|
+
runner = CliRunner()
|
|
216
|
+
home = tmp_path / "arch"
|
|
217
|
+
store = EnvStore(home / "envs")
|
|
218
|
+
store.save_active(UnitConfig, {"UNIT_KEY": "", "UNIT_VALUE": "default"})
|
|
219
|
+
|
|
220
|
+
result = runner.invoke(cli, ["--home", str(home), "list", "--type", "unit"])
|
|
221
|
+
|
|
222
|
+
assert result.exit_code == 0, result.output
|
|
223
|
+
assert "No profiles found under" in result.output
|
|
224
|
+
assert "[Unit]" not in result.output
|
|
225
|
+
assert "- .env [default]" not in result.output
|
|
226
|
+
|
|
227
|
+
|
|
213
228
|
def test_list_reports_no_profiles_when_active_and_named_profiles_absent(tmp_path):
|
|
214
229
|
runner = CliRunner()
|
|
215
230
|
home = tmp_path / "arch"
|
|
@@ -530,6 +545,24 @@ def test_cli_init_with_type_still_prompts_fields_when_auto_prompt_disabled(
|
|
|
530
545
|
assert "UNIT_VALUE='from-init'" in env_text
|
|
531
546
|
|
|
532
547
|
|
|
548
|
+
def test_cli_init_without_type_fails_outside_interactive_without_writing_all(
|
|
549
|
+
tmp_path, monkeypatch
|
|
550
|
+
):
|
|
551
|
+
runner = CliRunner()
|
|
552
|
+
home = tmp_path / "arch"
|
|
553
|
+
monkeypatch.setenv("CHATARCH_AUTO_PROMPT", "false")
|
|
554
|
+
monkeypatch.setattr(
|
|
555
|
+
"chatenv.cli._chatstyle_resolve_interactive_mode",
|
|
556
|
+
_tty_resolution,
|
|
557
|
+
)
|
|
558
|
+
|
|
559
|
+
result = runner.invoke(cli, ["--home", str(home), "init", "-I"])
|
|
560
|
+
|
|
561
|
+
assert result.exit_code != 0
|
|
562
|
+
assert "init requires --type/-t outside interactive mode" in result.output
|
|
563
|
+
assert not (home / "envs").exists()
|
|
564
|
+
|
|
565
|
+
|
|
533
566
|
def test_cli_new_prompts_for_config_type_when_type_missing(
|
|
534
567
|
tmp_path, monkeypatch
|
|
535
568
|
):
|
|
@@ -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.2"
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|