wexample-cli 2.1.0__tar.gz → 2.1.2__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.
- wexample_cli-2.1.2/PKG-INFO +294 -0
- wexample_cli-2.1.2/README.md +274 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/pyproject.toml +5 -5
- wexample_cli-2.1.0/tests/__init__.py → wexample_cli-2.1.2/tests/.gitkeep +0 -0
- {wexample_cli-2.1.0/tests/helper → wexample_cli-2.1.2/tests}/__init__.py +0 -0
- wexample_cli-2.1.2/tests/unit/helper/__init__.py +0 -0
- wexample_cli-2.1.0/PKG-INFO +0 -169
- wexample_cli-2.1.0/README.md +0 -149
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/__init__.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/command/__init__.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/command/extended_command.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/common/__init__.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/common/command_method_wrapper.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/const/__init__.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/const/middleware.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/const/tags.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/const/types.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/context/__init__.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/context/execution_context.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/decorator/__init__.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/decorator/alias.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/decorator/as_sudo.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/decorator/command.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/decorator/middleware.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/decorator/option.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/decorator/option_stop_on_failure.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/decorator/screenable.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/decorator/webhook.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/exception/__init__.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/exception/abstract_command_option_exception.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/exception/command_option_missing_exception.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/exception/command_option_validation_exception.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/helper/__init__.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/helper/extra_args.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/middleware/__init__.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/middleware/abstract_middleware.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/py.typed +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/testing/__init__.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/testing/kernel.py +0 -0
- {wexample_cli-2.1.0/tests/unit → wexample_cli-2.1.2/tests/helper}/__init__.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/tests/helper/test_extra_args.py +0 -0
- {wexample_cli-2.1.0/tests/unit/helper → wexample_cli-2.1.2/tests/unit}/__init__.py +0 -0
- {wexample_cli-2.1.0 → wexample_cli-2.1.2}/tests/unit/helper/test_extra_args.py +0 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: wexample-cli
|
|
3
|
+
Version: 2.1.2
|
|
4
|
+
Summary: Supplies command decorators, typed options, and a composable middleware pipeline for kernels built on wexample-app
|
|
5
|
+
Author-Email: weeger <contact@wexample.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Project-URL: homepage, https://github.com/wexample/python-cli
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Requires-Dist: attrs>=23.1.0
|
|
13
|
+
Requires-Dist: wexample-app>=19.2.0
|
|
14
|
+
Requires-Dist: wexample-helpers>=20.0.0
|
|
15
|
+
Requires-Dist: wexample-prompt>=15.0.0
|
|
16
|
+
Provides-Extra: dev
|
|
17
|
+
Requires-Dist: pytest; extra == "dev"
|
|
18
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# cli
|
|
22
|
+
|
|
23
|
+
Version: 2.1.2
|
|
24
|
+
|
|
25
|
+
`wexample-cli` supplies the decorator layer — `@command`, `@option`, and `@middleware` — that turns plain Python methods into typed, discoverable commands for kernels built on `wexample-app`. Options are declared with Python types, short names, defaults, required flags, and per-value validators; a composable middleware pipeline can fan a single invocation across multiple execution contexts, run them in parallel, and abort on the first failure. It is aimed at Python developers building or extending a `wexample-app` kernel with new CLI commands.
|
|
26
|
+
|
|
27
|
+
## Table of Contents
|
|
28
|
+
|
|
29
|
+
- [Installation](#installation)
|
|
30
|
+
- [Quickstart](#quickstart)
|
|
31
|
+
- [Tests](#tests)
|
|
32
|
+
- [Architecture](#architecture)
|
|
33
|
+
- [Integration in the Suite](#integration-in-the-suite)
|
|
34
|
+
- [Dependencies](#dependencies)
|
|
35
|
+
- [Versioning & Compatibility Policy](#versioning--compatibility-policy)
|
|
36
|
+
- [License](#license)
|
|
37
|
+
- [About us](#about-us)
|
|
38
|
+
- [Known Limitations & Roadmap](#known-limitations--roadmap)
|
|
39
|
+
- [Status & Compatibility](#status--compatibility)
|
|
40
|
+
- [Useful Links](#useful-links)
|
|
41
|
+
- [Migration Notes](#migration-notes)
|
|
42
|
+
|
|
43
|
+
## Installation
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pip install wexample-cli
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Requires Python >=3.10.
|
|
50
|
+
|
|
51
|
+
## Quickstart
|
|
52
|
+
|
|
53
|
+
Install the package:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install wexample-cli
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Declare a command inside your kernel class. `@command` wraps the method into a `CommandMethodWrapper`; each `@option` stacks on top in outer-to-inner order to append a typed option to it.
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from wexample_cli.decorator.command import command
|
|
63
|
+
from wexample_cli.decorator.option import option
|
|
64
|
+
|
|
65
|
+
@option(name="name", type=str, description="Who to greet", required=True)
|
|
66
|
+
@command(type="demo", description="Print a greeting")
|
|
67
|
+
def demo__greet(context, name: str) -> None:
|
|
68
|
+
context.io.log(f"Hello, {name}!")
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The decorated object is a `CommandMethodWrapper`. You can inspect it immediately:
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
demo__greet.description # "Print a greeting"
|
|
75
|
+
demo__greet.options[0].name # "name"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The kernel maps the function name `demo__greet` to the command path `demo/greet`. To exercise the full decorator and middleware pipeline in a test, use the helpers in src/wexample_cli/testing/kernel.py:
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
from wexample_cli.testing.kernel import boot_kernel, dispatch_command
|
|
82
|
+
|
|
83
|
+
kernel = boot_kernel(MyKernel, entrypoint_path="/path/to/__main__.py")
|
|
84
|
+
response = dispatch_command(kernel, "demo/greet", {"name": "world"})
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
`dispatch_command` accepts pre-parsed kwargs (`{"name": "world"}`) or CLI-style strings (`["--name", "world"]`).
|
|
88
|
+
|
|
89
|
+
## Tests
|
|
90
|
+
|
|
91
|
+
This project uses `pytest` for testing and `pytest-cov` for code coverage analysis.
|
|
92
|
+
|
|
93
|
+
### Installation
|
|
94
|
+
|
|
95
|
+
First, install the required testing dependencies:
|
|
96
|
+
```bash
|
|
97
|
+
.venv/bin/python -m pip install pytest pytest-cov
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Basic Usage
|
|
101
|
+
|
|
102
|
+
Run all tests with coverage:
|
|
103
|
+
```bash
|
|
104
|
+
.venv/bin/python -m pytest --cov --cov-report=html
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Common Commands
|
|
108
|
+
```bash
|
|
109
|
+
# Run tests with coverage for a specific module
|
|
110
|
+
.venv/bin/python -m pytest --cov=your_module
|
|
111
|
+
|
|
112
|
+
# Show which lines are not covered
|
|
113
|
+
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing
|
|
114
|
+
|
|
115
|
+
# Generate an HTML coverage report
|
|
116
|
+
.venv/bin/python -m pytest --cov=your_module --cov-report=html
|
|
117
|
+
|
|
118
|
+
# Combine terminal and HTML reports
|
|
119
|
+
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing --cov-report=html
|
|
120
|
+
|
|
121
|
+
# Run specific test file with coverage
|
|
122
|
+
.venv/bin/python -m pytest tests/test_file.py --cov=your_module --cov-report=term-missing
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Viewing HTML Reports
|
|
126
|
+
|
|
127
|
+
After generating an HTML report, open `htmlcov/index.html` in your browser to view detailed line-by-line coverage information.
|
|
128
|
+
|
|
129
|
+
### Coverage Threshold
|
|
130
|
+
|
|
131
|
+
To enforce a minimum coverage percentage:
|
|
132
|
+
```bash
|
|
133
|
+
.venv/bin/python -m pytest --cov=your_module --cov-fail-under=80
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
This will cause the test suite to fail if coverage drops below 80%.
|
|
137
|
+
|
|
138
|
+
## Architecture
|
|
139
|
+
|
|
140
|
+
`wexample-cli` is a decorator and dispatch layer that sits between a `wexample-app` kernel and the Python functions that implement its commands. It has no entry-point of its own; downstream kernels import its decorators, wrap their methods, and pass the resulting objects to the kernel's registration machinery.
|
|
141
|
+
|
|
142
|
+
### Parts
|
|
143
|
+
|
|
144
|
+
**Decorators** — `src/wexample_cli/decorator/`
|
|
145
|
+
|
|
146
|
+
The decorators are the only thing a command author touches directly. Applied bottom-to-top on a plain function, they produce a `CommandMethodWrapper`:
|
|
147
|
+
|
|
148
|
+
- `@command(type, description, tags)` — creates the wrapper; must be the innermost decorator.
|
|
149
|
+
- `@option(name, type, ...)` — calls `wrapper.set_option(Option(...))` to append a typed option.
|
|
150
|
+
- `@middleware(name, **kwargs)` — calls `wrapper.register_middleware(name, kwargs)` to schedule a middleware class at runtime.
|
|
151
|
+
- `@alias(*names)` — extends `wrapper.aliases`.
|
|
152
|
+
- `@screenable(interval, height)` — adds `--screen` and `--screen-interval` options and pushes a pipeline wrapper that drives a refresh loop.
|
|
153
|
+
- `@as_sudo()` — sets `wrapper.sudo = True`.
|
|
154
|
+
- `@webhook()` — sets `wrapper.webhook = True`.
|
|
155
|
+
- `@option_stop_on_failure()` — adds a `--stop-on-failure` flag option.
|
|
156
|
+
|
|
157
|
+
**`CommandMethodWrapper`** — `src/wexample_cli/common/command_method_wrapper.py`
|
|
158
|
+
|
|
159
|
+
The data structure produced by decoration. It carries everything the runtime needs: `function`, `options`, `middlewares_attributes` (names → init-kwargs, resolved at call time), `pipeline_wrappers` (registered in outer-to-inner order), `aliases`, `tags`, and the boolean flags `sudo` and `webhook`. It owns no execution logic.
|
|
160
|
+
|
|
161
|
+
**`ExtendedCommand`** — `src/wexample_cli/command/extended_command.py`
|
|
162
|
+
|
|
163
|
+
The runtime command object registered with the kernel; extends `wexample_app.common.command.Command`. It owns the full execution path for one `CommandRequest`.
|
|
164
|
+
|
|
165
|
+
**`AbstractMiddleware`** — `src/wexample_cli/middleware/abstract_middleware.py`
|
|
166
|
+
|
|
167
|
+
Base class for middleware. A middleware can add options dynamically (`append_options`), produce multiple `ExecutionContext` objects from a single request (`build_execution_contexts`), and declare whether execution should be parallel, show a progress bar, or abort on the first failure. The values `"allways"` and `"optional"` (defined in `src/wexample_cli/const/middleware.py`) allow a middleware to make a behaviour mandatory or user-selectable.
|
|
168
|
+
|
|
169
|
+
**`ExecutionContext`** — `src/wexample_cli/context/execution_context.py`
|
|
170
|
+
|
|
171
|
+
A single unit of work inside one dispatch. Holds `function_kwargs`, `request`, `kernel`, `middleware`, and an optional `function` override. Its `__attrs_post_init__` injects `context=self` into `function_kwargs` so every command function receives it. Also provides progress-tracking helpers (`create_progress_range`, `finish_progress`, `get_or_create_progress`).
|
|
172
|
+
|
|
173
|
+
**Exceptions** — `src/wexample_cli/exception/`
|
|
174
|
+
|
|
175
|
+
`CommandOptionMissingException` and `CommandOptionValidationException` both extend `AbstractCommandOptionException`. The first is raised when a required option is absent; the second when an `AbstractValidator` rejects a value.
|
|
176
|
+
|
|
177
|
+
**Constants** — `src/wexample_cli/const/`
|
|
178
|
+
|
|
179
|
+
- `types.py` — `ParsedArgs = dict[str, Any]`.
|
|
180
|
+
- `middleware.py` — the `"allways"` / `"optional"` sentinel strings.
|
|
181
|
+
- `tags.py` — `EffectTag`, `AudienceTag`, and `ScopeTag` class-level string constants for `@command(tags=[...])`.
|
|
182
|
+
|
|
183
|
+
**Testing helpers** — `src/wexample_cli/testing/kernel.py`
|
|
184
|
+
|
|
185
|
+
`boot_kernel(KernelClass, entrypoint_path)` and `dispatch_command(kernel, name, arguments)` exercise the full decorator and dispatch pipeline from a test, identical to a real invocation.
|
|
186
|
+
|
|
187
|
+
**Helper** — `src/wexample_cli/helper/extra_args.py`
|
|
188
|
+
|
|
189
|
+
`resolve_shell_command(context, command, extra_args)` — resolves a shell command string from either a `--command "..."` option or positional `-- args`, preferring the positional form.
|
|
190
|
+
|
|
191
|
+
### Call path
|
|
192
|
+
|
|
193
|
+
**At import time** (decorators run):
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
@alias / @as_sudo / @webhook
|
|
197
|
+
@screenable → set_option(screen, screen_interval) + register_pipeline_wrapper(screen_wrapper)
|
|
198
|
+
@middleware(name) → register_middleware(name, kwargs)
|
|
199
|
+
@option(...) → set_option(Option(...))
|
|
200
|
+
@command(type, ...) → CommandMethodWrapper(function=fn, ...)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
The resulting `CommandMethodWrapper` is what the kernel stores; `ExtendedCommand` wraps it.
|
|
204
|
+
|
|
205
|
+
**At invocation** (`ExtendedCommand.execute_request`):
|
|
206
|
+
|
|
207
|
+
1. Instantiate each middleware from the kernel's `"middlewares"` registry using `middlewares_attributes`; attach it with `set_middleware` (which also extends `wrapper.options` with the middleware's own options).
|
|
208
|
+
2. If `--help` or `-h` is in the raw arguments, render help via `_render_help` and return.
|
|
209
|
+
3. `_build_function_kwargs`:
|
|
210
|
+
- Each middleware calls `append_options` to inject any dynamic options (e.g. `--parallel`, `--progress`).
|
|
211
|
+
- Raw arguments (list or dict) are parsed by `_parse_arguments` into `ParsedArgs`.
|
|
212
|
+
- Each declared option is resolved from parsed args, then its default, then `CommandOptionMissingException` if required.
|
|
213
|
+
- Each non-`None` value is run through its validators; failure raises `CommandOptionValidationException`.
|
|
214
|
+
- If `--` passthrough tokens are present, they land in `parsed_args["__extra_args__"]` and are forwarded as `extra_args` if the function declares that parameter, otherwise `CommandUnexpectedArgumentException`.
|
|
215
|
+
4. Build the pipeline: `_make_dispatch` produces the innermost callable; each entry in `pipeline_wrappers` is composed around it with `_wrap_dispatch`.
|
|
216
|
+
5. Call `dispatch(function_kwargs)`.
|
|
217
|
+
|
|
218
|
+
**Inside `_execute_dispatch`:**
|
|
219
|
+
|
|
220
|
+
- With middlewares: each middleware calls `build_execution_contexts` (base returns one context; subclasses may fan out). Contexts are executed sequentially or in parallel (`asyncio` + `ThreadPoolExecutor`). Parallel runs each context with a `PromptBufferOutputHandler` so output is buffered per-context. Results accumulate in a `MultipleResponse`; a single result is unwrapped. `stop_on_failure` halts the loop early on `FailureResponse`.
|
|
221
|
+
- Without middlewares: a single `ExecutionContext` is built by `request.resolver.build_execution_context`, and the function is called directly.
|
|
222
|
+
|
|
223
|
+
In both paths, `ExecutionContext.__attrs_post_init__` injects `context=self` so the function can access `context.io`, `context.kernel`, progress handles, and the resolved `function_kwargs`.
|
|
224
|
+
|
|
225
|
+
## Integration in the Suite
|
|
226
|
+
|
|
227
|
+
This package is part of the Wexample Suite — a collection of high-quality, modular tools designed to work seamlessly together across multiple languages and environments.
|
|
228
|
+
|
|
229
|
+
### Related Packages
|
|
230
|
+
|
|
231
|
+
The suite includes packages for configuration management, file handling, prompts, and more. Each package can be used independently or as part of the integrated suite.
|
|
232
|
+
|
|
233
|
+
Visit the [Wexample Suite documentation](https://docs.wexample.com) for the complete package ecosystem.
|
|
234
|
+
|
|
235
|
+
## Dependencies
|
|
236
|
+
|
|
237
|
+
- attrs: >=23.1.0
|
|
238
|
+
- wexample-app: >=19.2.0
|
|
239
|
+
- wexample-helpers: >=20.0.0
|
|
240
|
+
- wexample-prompt: >=15.0.0
|
|
241
|
+
|
|
242
|
+
## Versioning & Compatibility Policy
|
|
243
|
+
|
|
244
|
+
Wexample packages follow **Semantic Versioning** (SemVer):
|
|
245
|
+
|
|
246
|
+
- **MAJOR**: Breaking changes
|
|
247
|
+
- **MINOR**: New features, backward compatible
|
|
248
|
+
- **PATCH**: Bug fixes, backward compatible
|
|
249
|
+
|
|
250
|
+
We maintain backward compatibility within major versions and provide clear migration guides for breaking changes.
|
|
251
|
+
|
|
252
|
+
## License
|
|
253
|
+
|
|
254
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
255
|
+
|
|
256
|
+
Free to use in both personal and commercial projects.
|
|
257
|
+
|
|
258
|
+
## About us
|
|
259
|
+
|
|
260
|
+
[Wexample](https://wexample.com) stands as a cornerstone of the digital ecosystem — a collective of seasoned engineers, researchers, and creators driven by a relentless pursuit of technological excellence. More than a media platform, it has grown into a vibrant community where innovation meets craftsmanship, and where every line of code reflects a commitment to clarity, durability, and shared intelligence.
|
|
261
|
+
|
|
262
|
+
This packages suite embodies this spirit. Trusted by professionals and enthusiasts alike, it delivers a consistent, high-quality foundation for modern development — open, elegant, and battle-tested. Its reputation is built on years of collaboration, refinement, and rigorous attention to detail, making it a natural choice for those who demand both robustness and beauty in their tools.
|
|
263
|
+
|
|
264
|
+
Wexample cultivates a culture of mastery. Each package, each contribution carries the mark of a community that values precision, ethics, and innovation — a community proud to shape the future of digital craftsmanship.
|
|
265
|
+
|
|
266
|
+
## Known Limitations & Roadmap
|
|
267
|
+
|
|
268
|
+
Current limitations and planned features are tracked in the GitHub issues.
|
|
269
|
+
|
|
270
|
+
See the [project roadmap](https://github.com/wexample/python-cli/issues) for upcoming features and improvements.
|
|
271
|
+
|
|
272
|
+
## Status & Compatibility
|
|
273
|
+
|
|
274
|
+
**Maturity**: Production-ready
|
|
275
|
+
|
|
276
|
+
**Python Support**: >=3.10
|
|
277
|
+
|
|
278
|
+
**OS Support**: Linux, macOS, Windows
|
|
279
|
+
|
|
280
|
+
**Status**: Actively maintained
|
|
281
|
+
|
|
282
|
+
## Useful Links
|
|
283
|
+
|
|
284
|
+
- **Homepage**: https://github.com/wexample/python-cli
|
|
285
|
+
- **Documentation**: [docs.wexample.com](https://docs.wexample.com)
|
|
286
|
+
- **Issue Tracker**: https://github.com/wexample/python-cli/issues
|
|
287
|
+
- **Discussions**: https://github.com/wexample/python-cli/discussions
|
|
288
|
+
- **PyPI**: [pypi.org/project/wexample-cli](https://pypi.org/project/wexample-cli/)
|
|
289
|
+
|
|
290
|
+
## Migration Notes
|
|
291
|
+
|
|
292
|
+
When upgrading between major versions, refer to the migration guides in the documentation.
|
|
293
|
+
|
|
294
|
+
Breaking changes are clearly documented with upgrade paths and examples.
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# cli
|
|
2
|
+
|
|
3
|
+
Version: 2.1.2
|
|
4
|
+
|
|
5
|
+
`wexample-cli` supplies the decorator layer — `@command`, `@option`, and `@middleware` — that turns plain Python methods into typed, discoverable commands for kernels built on `wexample-app`. Options are declared with Python types, short names, defaults, required flags, and per-value validators; a composable middleware pipeline can fan a single invocation across multiple execution contexts, run them in parallel, and abort on the first failure. It is aimed at Python developers building or extending a `wexample-app` kernel with new CLI commands.
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [Installation](#installation)
|
|
10
|
+
- [Quickstart](#quickstart)
|
|
11
|
+
- [Tests](#tests)
|
|
12
|
+
- [Architecture](#architecture)
|
|
13
|
+
- [Integration in the Suite](#integration-in-the-suite)
|
|
14
|
+
- [Dependencies](#dependencies)
|
|
15
|
+
- [Versioning & Compatibility Policy](#versioning--compatibility-policy)
|
|
16
|
+
- [License](#license)
|
|
17
|
+
- [About us](#about-us)
|
|
18
|
+
- [Known Limitations & Roadmap](#known-limitations--roadmap)
|
|
19
|
+
- [Status & Compatibility](#status--compatibility)
|
|
20
|
+
- [Useful Links](#useful-links)
|
|
21
|
+
- [Migration Notes](#migration-notes)
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install wexample-cli
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Requires Python >=3.10.
|
|
30
|
+
|
|
31
|
+
## Quickstart
|
|
32
|
+
|
|
33
|
+
Install the package:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install wexample-cli
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Declare a command inside your kernel class. `@command` wraps the method into a `CommandMethodWrapper`; each `@option` stacks on top in outer-to-inner order to append a typed option to it.
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from wexample_cli.decorator.command import command
|
|
43
|
+
from wexample_cli.decorator.option import option
|
|
44
|
+
|
|
45
|
+
@option(name="name", type=str, description="Who to greet", required=True)
|
|
46
|
+
@command(type="demo", description="Print a greeting")
|
|
47
|
+
def demo__greet(context, name: str) -> None:
|
|
48
|
+
context.io.log(f"Hello, {name}!")
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The decorated object is a `CommandMethodWrapper`. You can inspect it immediately:
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
demo__greet.description # "Print a greeting"
|
|
55
|
+
demo__greet.options[0].name # "name"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The kernel maps the function name `demo__greet` to the command path `demo/greet`. To exercise the full decorator and middleware pipeline in a test, use the helpers in src/wexample_cli/testing/kernel.py:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from wexample_cli.testing.kernel import boot_kernel, dispatch_command
|
|
62
|
+
|
|
63
|
+
kernel = boot_kernel(MyKernel, entrypoint_path="/path/to/__main__.py")
|
|
64
|
+
response = dispatch_command(kernel, "demo/greet", {"name": "world"})
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`dispatch_command` accepts pre-parsed kwargs (`{"name": "world"}`) or CLI-style strings (`["--name", "world"]`).
|
|
68
|
+
|
|
69
|
+
## Tests
|
|
70
|
+
|
|
71
|
+
This project uses `pytest` for testing and `pytest-cov` for code coverage analysis.
|
|
72
|
+
|
|
73
|
+
### Installation
|
|
74
|
+
|
|
75
|
+
First, install the required testing dependencies:
|
|
76
|
+
```bash
|
|
77
|
+
.venv/bin/python -m pip install pytest pytest-cov
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Basic Usage
|
|
81
|
+
|
|
82
|
+
Run all tests with coverage:
|
|
83
|
+
```bash
|
|
84
|
+
.venv/bin/python -m pytest --cov --cov-report=html
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Common Commands
|
|
88
|
+
```bash
|
|
89
|
+
# Run tests with coverage for a specific module
|
|
90
|
+
.venv/bin/python -m pytest --cov=your_module
|
|
91
|
+
|
|
92
|
+
# Show which lines are not covered
|
|
93
|
+
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing
|
|
94
|
+
|
|
95
|
+
# Generate an HTML coverage report
|
|
96
|
+
.venv/bin/python -m pytest --cov=your_module --cov-report=html
|
|
97
|
+
|
|
98
|
+
# Combine terminal and HTML reports
|
|
99
|
+
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing --cov-report=html
|
|
100
|
+
|
|
101
|
+
# Run specific test file with coverage
|
|
102
|
+
.venv/bin/python -m pytest tests/test_file.py --cov=your_module --cov-report=term-missing
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Viewing HTML Reports
|
|
106
|
+
|
|
107
|
+
After generating an HTML report, open `htmlcov/index.html` in your browser to view detailed line-by-line coverage information.
|
|
108
|
+
|
|
109
|
+
### Coverage Threshold
|
|
110
|
+
|
|
111
|
+
To enforce a minimum coverage percentage:
|
|
112
|
+
```bash
|
|
113
|
+
.venv/bin/python -m pytest --cov=your_module --cov-fail-under=80
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
This will cause the test suite to fail if coverage drops below 80%.
|
|
117
|
+
|
|
118
|
+
## Architecture
|
|
119
|
+
|
|
120
|
+
`wexample-cli` is a decorator and dispatch layer that sits between a `wexample-app` kernel and the Python functions that implement its commands. It has no entry-point of its own; downstream kernels import its decorators, wrap their methods, and pass the resulting objects to the kernel's registration machinery.
|
|
121
|
+
|
|
122
|
+
### Parts
|
|
123
|
+
|
|
124
|
+
**Decorators** — `src/wexample_cli/decorator/`
|
|
125
|
+
|
|
126
|
+
The decorators are the only thing a command author touches directly. Applied bottom-to-top on a plain function, they produce a `CommandMethodWrapper`:
|
|
127
|
+
|
|
128
|
+
- `@command(type, description, tags)` — creates the wrapper; must be the innermost decorator.
|
|
129
|
+
- `@option(name, type, ...)` — calls `wrapper.set_option(Option(...))` to append a typed option.
|
|
130
|
+
- `@middleware(name, **kwargs)` — calls `wrapper.register_middleware(name, kwargs)` to schedule a middleware class at runtime.
|
|
131
|
+
- `@alias(*names)` — extends `wrapper.aliases`.
|
|
132
|
+
- `@screenable(interval, height)` — adds `--screen` and `--screen-interval` options and pushes a pipeline wrapper that drives a refresh loop.
|
|
133
|
+
- `@as_sudo()` — sets `wrapper.sudo = True`.
|
|
134
|
+
- `@webhook()` — sets `wrapper.webhook = True`.
|
|
135
|
+
- `@option_stop_on_failure()` — adds a `--stop-on-failure` flag option.
|
|
136
|
+
|
|
137
|
+
**`CommandMethodWrapper`** — `src/wexample_cli/common/command_method_wrapper.py`
|
|
138
|
+
|
|
139
|
+
The data structure produced by decoration. It carries everything the runtime needs: `function`, `options`, `middlewares_attributes` (names → init-kwargs, resolved at call time), `pipeline_wrappers` (registered in outer-to-inner order), `aliases`, `tags`, and the boolean flags `sudo` and `webhook`. It owns no execution logic.
|
|
140
|
+
|
|
141
|
+
**`ExtendedCommand`** — `src/wexample_cli/command/extended_command.py`
|
|
142
|
+
|
|
143
|
+
The runtime command object registered with the kernel; extends `wexample_app.common.command.Command`. It owns the full execution path for one `CommandRequest`.
|
|
144
|
+
|
|
145
|
+
**`AbstractMiddleware`** — `src/wexample_cli/middleware/abstract_middleware.py`
|
|
146
|
+
|
|
147
|
+
Base class for middleware. A middleware can add options dynamically (`append_options`), produce multiple `ExecutionContext` objects from a single request (`build_execution_contexts`), and declare whether execution should be parallel, show a progress bar, or abort on the first failure. The values `"allways"` and `"optional"` (defined in `src/wexample_cli/const/middleware.py`) allow a middleware to make a behaviour mandatory or user-selectable.
|
|
148
|
+
|
|
149
|
+
**`ExecutionContext`** — `src/wexample_cli/context/execution_context.py`
|
|
150
|
+
|
|
151
|
+
A single unit of work inside one dispatch. Holds `function_kwargs`, `request`, `kernel`, `middleware`, and an optional `function` override. Its `__attrs_post_init__` injects `context=self` into `function_kwargs` so every command function receives it. Also provides progress-tracking helpers (`create_progress_range`, `finish_progress`, `get_or_create_progress`).
|
|
152
|
+
|
|
153
|
+
**Exceptions** — `src/wexample_cli/exception/`
|
|
154
|
+
|
|
155
|
+
`CommandOptionMissingException` and `CommandOptionValidationException` both extend `AbstractCommandOptionException`. The first is raised when a required option is absent; the second when an `AbstractValidator` rejects a value.
|
|
156
|
+
|
|
157
|
+
**Constants** — `src/wexample_cli/const/`
|
|
158
|
+
|
|
159
|
+
- `types.py` — `ParsedArgs = dict[str, Any]`.
|
|
160
|
+
- `middleware.py` — the `"allways"` / `"optional"` sentinel strings.
|
|
161
|
+
- `tags.py` — `EffectTag`, `AudienceTag`, and `ScopeTag` class-level string constants for `@command(tags=[...])`.
|
|
162
|
+
|
|
163
|
+
**Testing helpers** — `src/wexample_cli/testing/kernel.py`
|
|
164
|
+
|
|
165
|
+
`boot_kernel(KernelClass, entrypoint_path)` and `dispatch_command(kernel, name, arguments)` exercise the full decorator and dispatch pipeline from a test, identical to a real invocation.
|
|
166
|
+
|
|
167
|
+
**Helper** — `src/wexample_cli/helper/extra_args.py`
|
|
168
|
+
|
|
169
|
+
`resolve_shell_command(context, command, extra_args)` — resolves a shell command string from either a `--command "..."` option or positional `-- args`, preferring the positional form.
|
|
170
|
+
|
|
171
|
+
### Call path
|
|
172
|
+
|
|
173
|
+
**At import time** (decorators run):
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
@alias / @as_sudo / @webhook
|
|
177
|
+
@screenable → set_option(screen, screen_interval) + register_pipeline_wrapper(screen_wrapper)
|
|
178
|
+
@middleware(name) → register_middleware(name, kwargs)
|
|
179
|
+
@option(...) → set_option(Option(...))
|
|
180
|
+
@command(type, ...) → CommandMethodWrapper(function=fn, ...)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
The resulting `CommandMethodWrapper` is what the kernel stores; `ExtendedCommand` wraps it.
|
|
184
|
+
|
|
185
|
+
**At invocation** (`ExtendedCommand.execute_request`):
|
|
186
|
+
|
|
187
|
+
1. Instantiate each middleware from the kernel's `"middlewares"` registry using `middlewares_attributes`; attach it with `set_middleware` (which also extends `wrapper.options` with the middleware's own options).
|
|
188
|
+
2. If `--help` or `-h` is in the raw arguments, render help via `_render_help` and return.
|
|
189
|
+
3. `_build_function_kwargs`:
|
|
190
|
+
- Each middleware calls `append_options` to inject any dynamic options (e.g. `--parallel`, `--progress`).
|
|
191
|
+
- Raw arguments (list or dict) are parsed by `_parse_arguments` into `ParsedArgs`.
|
|
192
|
+
- Each declared option is resolved from parsed args, then its default, then `CommandOptionMissingException` if required.
|
|
193
|
+
- Each non-`None` value is run through its validators; failure raises `CommandOptionValidationException`.
|
|
194
|
+
- If `--` passthrough tokens are present, they land in `parsed_args["__extra_args__"]` and are forwarded as `extra_args` if the function declares that parameter, otherwise `CommandUnexpectedArgumentException`.
|
|
195
|
+
4. Build the pipeline: `_make_dispatch` produces the innermost callable; each entry in `pipeline_wrappers` is composed around it with `_wrap_dispatch`.
|
|
196
|
+
5. Call `dispatch(function_kwargs)`.
|
|
197
|
+
|
|
198
|
+
**Inside `_execute_dispatch`:**
|
|
199
|
+
|
|
200
|
+
- With middlewares: each middleware calls `build_execution_contexts` (base returns one context; subclasses may fan out). Contexts are executed sequentially or in parallel (`asyncio` + `ThreadPoolExecutor`). Parallel runs each context with a `PromptBufferOutputHandler` so output is buffered per-context. Results accumulate in a `MultipleResponse`; a single result is unwrapped. `stop_on_failure` halts the loop early on `FailureResponse`.
|
|
201
|
+
- Without middlewares: a single `ExecutionContext` is built by `request.resolver.build_execution_context`, and the function is called directly.
|
|
202
|
+
|
|
203
|
+
In both paths, `ExecutionContext.__attrs_post_init__` injects `context=self` so the function can access `context.io`, `context.kernel`, progress handles, and the resolved `function_kwargs`.
|
|
204
|
+
|
|
205
|
+
## Integration in the Suite
|
|
206
|
+
|
|
207
|
+
This package is part of the Wexample Suite — a collection of high-quality, modular tools designed to work seamlessly together across multiple languages and environments.
|
|
208
|
+
|
|
209
|
+
### Related Packages
|
|
210
|
+
|
|
211
|
+
The suite includes packages for configuration management, file handling, prompts, and more. Each package can be used independently or as part of the integrated suite.
|
|
212
|
+
|
|
213
|
+
Visit the [Wexample Suite documentation](https://docs.wexample.com) for the complete package ecosystem.
|
|
214
|
+
|
|
215
|
+
## Dependencies
|
|
216
|
+
|
|
217
|
+
- attrs: >=23.1.0
|
|
218
|
+
- wexample-app: >=19.2.0
|
|
219
|
+
- wexample-helpers: >=20.0.0
|
|
220
|
+
- wexample-prompt: >=15.0.0
|
|
221
|
+
|
|
222
|
+
## Versioning & Compatibility Policy
|
|
223
|
+
|
|
224
|
+
Wexample packages follow **Semantic Versioning** (SemVer):
|
|
225
|
+
|
|
226
|
+
- **MAJOR**: Breaking changes
|
|
227
|
+
- **MINOR**: New features, backward compatible
|
|
228
|
+
- **PATCH**: Bug fixes, backward compatible
|
|
229
|
+
|
|
230
|
+
We maintain backward compatibility within major versions and provide clear migration guides for breaking changes.
|
|
231
|
+
|
|
232
|
+
## License
|
|
233
|
+
|
|
234
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
235
|
+
|
|
236
|
+
Free to use in both personal and commercial projects.
|
|
237
|
+
|
|
238
|
+
## About us
|
|
239
|
+
|
|
240
|
+
[Wexample](https://wexample.com) stands as a cornerstone of the digital ecosystem — a collective of seasoned engineers, researchers, and creators driven by a relentless pursuit of technological excellence. More than a media platform, it has grown into a vibrant community where innovation meets craftsmanship, and where every line of code reflects a commitment to clarity, durability, and shared intelligence.
|
|
241
|
+
|
|
242
|
+
This packages suite embodies this spirit. Trusted by professionals and enthusiasts alike, it delivers a consistent, high-quality foundation for modern development — open, elegant, and battle-tested. Its reputation is built on years of collaboration, refinement, and rigorous attention to detail, making it a natural choice for those who demand both robustness and beauty in their tools.
|
|
243
|
+
|
|
244
|
+
Wexample cultivates a culture of mastery. Each package, each contribution carries the mark of a community that values precision, ethics, and innovation — a community proud to shape the future of digital craftsmanship.
|
|
245
|
+
|
|
246
|
+
## Known Limitations & Roadmap
|
|
247
|
+
|
|
248
|
+
Current limitations and planned features are tracked in the GitHub issues.
|
|
249
|
+
|
|
250
|
+
See the [project roadmap](https://github.com/wexample/python-cli/issues) for upcoming features and improvements.
|
|
251
|
+
|
|
252
|
+
## Status & Compatibility
|
|
253
|
+
|
|
254
|
+
**Maturity**: Production-ready
|
|
255
|
+
|
|
256
|
+
**Python Support**: >=3.10
|
|
257
|
+
|
|
258
|
+
**OS Support**: Linux, macOS, Windows
|
|
259
|
+
|
|
260
|
+
**Status**: Actively maintained
|
|
261
|
+
|
|
262
|
+
## Useful Links
|
|
263
|
+
|
|
264
|
+
- **Homepage**: https://github.com/wexample/python-cli
|
|
265
|
+
- **Documentation**: [docs.wexample.com](https://docs.wexample.com)
|
|
266
|
+
- **Issue Tracker**: https://github.com/wexample/python-cli/issues
|
|
267
|
+
- **Discussions**: https://github.com/wexample/python-cli/discussions
|
|
268
|
+
- **PyPI**: [pypi.org/project/wexample-cli](https://pypi.org/project/wexample-cli/)
|
|
269
|
+
|
|
270
|
+
## Migration Notes
|
|
271
|
+
|
|
272
|
+
When upgrading between major versions, refer to the migration guides in the documentation.
|
|
273
|
+
|
|
274
|
+
Breaking changes are clearly documented with upgrade paths and examples.
|
|
@@ -6,8 +6,8 @@ build-backend = "pdm.backend"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "wexample-cli"
|
|
9
|
-
version = "2.1.
|
|
10
|
-
description = "
|
|
9
|
+
version = "2.1.2"
|
|
10
|
+
description = "Supplies command decorators, typed options, and a composable middleware pipeline for kernels built on wexample-app"
|
|
11
11
|
authors = [
|
|
12
12
|
{ name = "weeger", email = "contact@wexample.com" },
|
|
13
13
|
]
|
|
@@ -19,9 +19,9 @@ classifiers = [
|
|
|
19
19
|
]
|
|
20
20
|
dependencies = [
|
|
21
21
|
"attrs>=23.1.0",
|
|
22
|
-
"wexample-app>=19.
|
|
23
|
-
"wexample-helpers>=
|
|
24
|
-
"wexample-prompt>=
|
|
22
|
+
"wexample-app>=19.2.0",
|
|
23
|
+
"wexample-helpers>=20.0.0",
|
|
24
|
+
"wexample-prompt>=15.0.0",
|
|
25
25
|
]
|
|
26
26
|
|
|
27
27
|
[project.readme]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
wexample_cli-2.1.0/PKG-INFO
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: wexample-cli
|
|
3
|
-
Version: 2.1.0
|
|
4
|
-
Summary: Reusable CLI primitives — command decorators, options, middlewares, and the enriched command runner — extracted from wex-core so any kernel built on wexample-app can opt in without depending on the full wex framework.
|
|
5
|
-
Author-Email: weeger <contact@wexample.com>
|
|
6
|
-
License: MIT
|
|
7
|
-
Classifier: Programming Language :: Python :: 3
|
|
8
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
-
Classifier: Operating System :: OS Independent
|
|
10
|
-
Project-URL: homepage, https://github.com/wexample/python-cli
|
|
11
|
-
Requires-Python: >=3.10
|
|
12
|
-
Requires-Dist: attrs>=23.1.0
|
|
13
|
-
Requires-Dist: wexample-app>=19.0.0
|
|
14
|
-
Requires-Dist: wexample-helpers>=19.0.0
|
|
15
|
-
Requires-Dist: wexample-prompt>=14.1.0
|
|
16
|
-
Provides-Extra: dev
|
|
17
|
-
Requires-Dist: pytest; extra == "dev"
|
|
18
|
-
Requires-Dist: pytest-cov; extra == "dev"
|
|
19
|
-
Description-Content-Type: text/markdown
|
|
20
|
-
|
|
21
|
-
# cli
|
|
22
|
-
|
|
23
|
-
Version: 2.1.0
|
|
24
|
-
|
|
25
|
-
Reusable CLI primitives — command decorators, options, middlewares, and the enriched command runner — extracted from wex-core so any kernel built on wexample-app can opt in without depending on the full wex framework.
|
|
26
|
-
|
|
27
|
-
## Table of Contents
|
|
28
|
-
|
|
29
|
-
- [Tests](#tests)
|
|
30
|
-
- [Suite Integration](#suite-integration)
|
|
31
|
-
- [Dependencies](#dependencies)
|
|
32
|
-
- [Versioning](#versioning)
|
|
33
|
-
- [License](#license)
|
|
34
|
-
- [Suite Integration](#suite-integration)
|
|
35
|
-
- [Suite Signature](#suite-signature)
|
|
36
|
-
- [Roadmap](#roadmap)
|
|
37
|
-
- [Status Compatibility](#status-compatibility)
|
|
38
|
-
- [Useful Links](#useful-links)
|
|
39
|
-
- [Migration Notes](#migration-notes)
|
|
40
|
-
|
|
41
|
-
## Tests
|
|
42
|
-
|
|
43
|
-
This project uses `pytest` for testing and `pytest-cov` for code coverage analysis.
|
|
44
|
-
|
|
45
|
-
### Installation
|
|
46
|
-
|
|
47
|
-
First, install the required testing dependencies:
|
|
48
|
-
```bash
|
|
49
|
-
.venv/bin/python -m pip install pytest pytest-cov
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
### Basic Usage
|
|
53
|
-
|
|
54
|
-
Run all tests with coverage:
|
|
55
|
-
```bash
|
|
56
|
-
.venv/bin/python -m pytest --cov --cov-report=html
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
### Common Commands
|
|
60
|
-
```bash
|
|
61
|
-
# Run tests with coverage for a specific module
|
|
62
|
-
.venv/bin/python -m pytest --cov=your_module
|
|
63
|
-
|
|
64
|
-
# Show which lines are not covered
|
|
65
|
-
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing
|
|
66
|
-
|
|
67
|
-
# Generate an HTML coverage report
|
|
68
|
-
.venv/bin/python -m pytest --cov=your_module --cov-report=html
|
|
69
|
-
|
|
70
|
-
# Combine terminal and HTML reports
|
|
71
|
-
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing --cov-report=html
|
|
72
|
-
|
|
73
|
-
# Run specific test file with coverage
|
|
74
|
-
.venv/bin/python -m pytest tests/test_file.py --cov=your_module --cov-report=term-missing
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### Viewing HTML Reports
|
|
78
|
-
|
|
79
|
-
After generating an HTML report, open `htmlcov/index.html` in your browser to view detailed line-by-line coverage information.
|
|
80
|
-
|
|
81
|
-
### Coverage Threshold
|
|
82
|
-
|
|
83
|
-
To enforce a minimum coverage percentage:
|
|
84
|
-
```bash
|
|
85
|
-
.venv/bin/python -m pytest --cov=your_module --cov-fail-under=80
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
This will cause the test suite to fail if coverage drops below 80%.
|
|
89
|
-
|
|
90
|
-
## Integration in the Suite
|
|
91
|
-
|
|
92
|
-
This package is part of the Wexample Suite — a collection of high-quality, modular tools designed to work seamlessly together across multiple languages and environments.
|
|
93
|
-
|
|
94
|
-
### Related Packages
|
|
95
|
-
|
|
96
|
-
The suite includes packages for configuration management, file handling, prompts, and more. Each package can be used independently or as part of the integrated suite.
|
|
97
|
-
|
|
98
|
-
Visit the [Wexample Suite documentation](https://docs.wexample.com) for the complete package ecosystem.
|
|
99
|
-
|
|
100
|
-
## Dependencies
|
|
101
|
-
|
|
102
|
-
- attrs: >=23.1.0
|
|
103
|
-
- wexample-app: >=19.0.0
|
|
104
|
-
- wexample-helpers: >=19.0.0
|
|
105
|
-
- wexample-prompt: >=14.1.0
|
|
106
|
-
|
|
107
|
-
## Versioning & Compatibility Policy
|
|
108
|
-
|
|
109
|
-
Wexample packages follow **Semantic Versioning** (SemVer):
|
|
110
|
-
|
|
111
|
-
- **MAJOR**: Breaking changes
|
|
112
|
-
- **MINOR**: New features, backward compatible
|
|
113
|
-
- **PATCH**: Bug fixes, backward compatible
|
|
114
|
-
|
|
115
|
-
We maintain backward compatibility within major versions and provide clear migration guides for breaking changes.
|
|
116
|
-
|
|
117
|
-
## License
|
|
118
|
-
|
|
119
|
-
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
120
|
-
|
|
121
|
-
Free to use in both personal and commercial projects.
|
|
122
|
-
|
|
123
|
-
## Integration in the Suite
|
|
124
|
-
|
|
125
|
-
This package is part of the Wexample Suite — a collection of high-quality, modular tools designed to work seamlessly together across multiple languages and environments.
|
|
126
|
-
|
|
127
|
-
### Related Packages
|
|
128
|
-
|
|
129
|
-
The suite includes packages for configuration management, file handling, prompts, and more. Each package can be used independently or as part of the integrated suite.
|
|
130
|
-
|
|
131
|
-
Visit the [Wexample Suite documentation](https://docs.wexample.com) for the complete package ecosystem.
|
|
132
|
-
|
|
133
|
-
# About us
|
|
134
|
-
|
|
135
|
-
[Wexample](https://wexample.com) stands as a cornerstone of the digital ecosystem — a collective of seasoned engineers, researchers, and creators driven by a relentless pursuit of technological excellence. More than a media platform, it has grown into a vibrant community where innovation meets craftsmanship, and where every line of code reflects a commitment to clarity, durability, and shared intelligence.
|
|
136
|
-
|
|
137
|
-
This packages suite embodies this spirit. Trusted by professionals and enthusiasts alike, it delivers a consistent, high-quality foundation for modern development — open, elegant, and battle-tested. Its reputation is built on years of collaboration, refinement, and rigorous attention to detail, making it a natural choice for those who demand both robustness and beauty in their tools.
|
|
138
|
-
|
|
139
|
-
Wexample cultivates a culture of mastery. Each package, each contribution carries the mark of a community that values precision, ethics, and innovation — a community proud to shape the future of digital craftsmanship.
|
|
140
|
-
|
|
141
|
-
## Known Limitations & Roadmap
|
|
142
|
-
|
|
143
|
-
Current limitations and planned features are tracked in the GitHub issues.
|
|
144
|
-
|
|
145
|
-
See the [project roadmap](https://github.com/wexample/python-cli/issues) for upcoming features and improvements.
|
|
146
|
-
|
|
147
|
-
## Status & Compatibility
|
|
148
|
-
|
|
149
|
-
**Maturity**: Production-ready
|
|
150
|
-
|
|
151
|
-
**Python Support**: >=3.10
|
|
152
|
-
|
|
153
|
-
**OS Support**: Linux, macOS, Windows
|
|
154
|
-
|
|
155
|
-
**Status**: Actively maintained
|
|
156
|
-
|
|
157
|
-
## Useful Links
|
|
158
|
-
|
|
159
|
-
- **Homepage**: https://github.com/wexample/python-cli
|
|
160
|
-
- **Documentation**: [docs.wexample.com](https://docs.wexample.com)
|
|
161
|
-
- **Issue Tracker**: https://github.com/wexample/python-cli/issues
|
|
162
|
-
- **Discussions**: https://github.com/wexample/python-cli/discussions
|
|
163
|
-
- **PyPI**: [pypi.org/project/cli](https://pypi.org/project/cli/)
|
|
164
|
-
|
|
165
|
-
## Migration Notes
|
|
166
|
-
|
|
167
|
-
When upgrading between major versions, refer to the migration guides in the documentation.
|
|
168
|
-
|
|
169
|
-
Breaking changes are clearly documented with upgrade paths and examples.
|
wexample_cli-2.1.0/README.md
DELETED
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
# cli
|
|
2
|
-
|
|
3
|
-
Version: 2.1.0
|
|
4
|
-
|
|
5
|
-
Reusable CLI primitives — command decorators, options, middlewares, and the enriched command runner — extracted from wex-core so any kernel built on wexample-app can opt in without depending on the full wex framework.
|
|
6
|
-
|
|
7
|
-
## Table of Contents
|
|
8
|
-
|
|
9
|
-
- [Tests](#tests)
|
|
10
|
-
- [Suite Integration](#suite-integration)
|
|
11
|
-
- [Dependencies](#dependencies)
|
|
12
|
-
- [Versioning](#versioning)
|
|
13
|
-
- [License](#license)
|
|
14
|
-
- [Suite Integration](#suite-integration)
|
|
15
|
-
- [Suite Signature](#suite-signature)
|
|
16
|
-
- [Roadmap](#roadmap)
|
|
17
|
-
- [Status Compatibility](#status-compatibility)
|
|
18
|
-
- [Useful Links](#useful-links)
|
|
19
|
-
- [Migration Notes](#migration-notes)
|
|
20
|
-
|
|
21
|
-
## Tests
|
|
22
|
-
|
|
23
|
-
This project uses `pytest` for testing and `pytest-cov` for code coverage analysis.
|
|
24
|
-
|
|
25
|
-
### Installation
|
|
26
|
-
|
|
27
|
-
First, install the required testing dependencies:
|
|
28
|
-
```bash
|
|
29
|
-
.venv/bin/python -m pip install pytest pytest-cov
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
### Basic Usage
|
|
33
|
-
|
|
34
|
-
Run all tests with coverage:
|
|
35
|
-
```bash
|
|
36
|
-
.venv/bin/python -m pytest --cov --cov-report=html
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
### Common Commands
|
|
40
|
-
```bash
|
|
41
|
-
# Run tests with coverage for a specific module
|
|
42
|
-
.venv/bin/python -m pytest --cov=your_module
|
|
43
|
-
|
|
44
|
-
# Show which lines are not covered
|
|
45
|
-
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing
|
|
46
|
-
|
|
47
|
-
# Generate an HTML coverage report
|
|
48
|
-
.venv/bin/python -m pytest --cov=your_module --cov-report=html
|
|
49
|
-
|
|
50
|
-
# Combine terminal and HTML reports
|
|
51
|
-
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing --cov-report=html
|
|
52
|
-
|
|
53
|
-
# Run specific test file with coverage
|
|
54
|
-
.venv/bin/python -m pytest tests/test_file.py --cov=your_module --cov-report=term-missing
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### Viewing HTML Reports
|
|
58
|
-
|
|
59
|
-
After generating an HTML report, open `htmlcov/index.html` in your browser to view detailed line-by-line coverage information.
|
|
60
|
-
|
|
61
|
-
### Coverage Threshold
|
|
62
|
-
|
|
63
|
-
To enforce a minimum coverage percentage:
|
|
64
|
-
```bash
|
|
65
|
-
.venv/bin/python -m pytest --cov=your_module --cov-fail-under=80
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
This will cause the test suite to fail if coverage drops below 80%.
|
|
69
|
-
|
|
70
|
-
## Integration in the Suite
|
|
71
|
-
|
|
72
|
-
This package is part of the Wexample Suite — a collection of high-quality, modular tools designed to work seamlessly together across multiple languages and environments.
|
|
73
|
-
|
|
74
|
-
### Related Packages
|
|
75
|
-
|
|
76
|
-
The suite includes packages for configuration management, file handling, prompts, and more. Each package can be used independently or as part of the integrated suite.
|
|
77
|
-
|
|
78
|
-
Visit the [Wexample Suite documentation](https://docs.wexample.com) for the complete package ecosystem.
|
|
79
|
-
|
|
80
|
-
## Dependencies
|
|
81
|
-
|
|
82
|
-
- attrs: >=23.1.0
|
|
83
|
-
- wexample-app: >=19.0.0
|
|
84
|
-
- wexample-helpers: >=19.0.0
|
|
85
|
-
- wexample-prompt: >=14.1.0
|
|
86
|
-
|
|
87
|
-
## Versioning & Compatibility Policy
|
|
88
|
-
|
|
89
|
-
Wexample packages follow **Semantic Versioning** (SemVer):
|
|
90
|
-
|
|
91
|
-
- **MAJOR**: Breaking changes
|
|
92
|
-
- **MINOR**: New features, backward compatible
|
|
93
|
-
- **PATCH**: Bug fixes, backward compatible
|
|
94
|
-
|
|
95
|
-
We maintain backward compatibility within major versions and provide clear migration guides for breaking changes.
|
|
96
|
-
|
|
97
|
-
## License
|
|
98
|
-
|
|
99
|
-
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
100
|
-
|
|
101
|
-
Free to use in both personal and commercial projects.
|
|
102
|
-
|
|
103
|
-
## Integration in the Suite
|
|
104
|
-
|
|
105
|
-
This package is part of the Wexample Suite — a collection of high-quality, modular tools designed to work seamlessly together across multiple languages and environments.
|
|
106
|
-
|
|
107
|
-
### Related Packages
|
|
108
|
-
|
|
109
|
-
The suite includes packages for configuration management, file handling, prompts, and more. Each package can be used independently or as part of the integrated suite.
|
|
110
|
-
|
|
111
|
-
Visit the [Wexample Suite documentation](https://docs.wexample.com) for the complete package ecosystem.
|
|
112
|
-
|
|
113
|
-
# About us
|
|
114
|
-
|
|
115
|
-
[Wexample](https://wexample.com) stands as a cornerstone of the digital ecosystem — a collective of seasoned engineers, researchers, and creators driven by a relentless pursuit of technological excellence. More than a media platform, it has grown into a vibrant community where innovation meets craftsmanship, and where every line of code reflects a commitment to clarity, durability, and shared intelligence.
|
|
116
|
-
|
|
117
|
-
This packages suite embodies this spirit. Trusted by professionals and enthusiasts alike, it delivers a consistent, high-quality foundation for modern development — open, elegant, and battle-tested. Its reputation is built on years of collaboration, refinement, and rigorous attention to detail, making it a natural choice for those who demand both robustness and beauty in their tools.
|
|
118
|
-
|
|
119
|
-
Wexample cultivates a culture of mastery. Each package, each contribution carries the mark of a community that values precision, ethics, and innovation — a community proud to shape the future of digital craftsmanship.
|
|
120
|
-
|
|
121
|
-
## Known Limitations & Roadmap
|
|
122
|
-
|
|
123
|
-
Current limitations and planned features are tracked in the GitHub issues.
|
|
124
|
-
|
|
125
|
-
See the [project roadmap](https://github.com/wexample/python-cli/issues) for upcoming features and improvements.
|
|
126
|
-
|
|
127
|
-
## Status & Compatibility
|
|
128
|
-
|
|
129
|
-
**Maturity**: Production-ready
|
|
130
|
-
|
|
131
|
-
**Python Support**: >=3.10
|
|
132
|
-
|
|
133
|
-
**OS Support**: Linux, macOS, Windows
|
|
134
|
-
|
|
135
|
-
**Status**: Actively maintained
|
|
136
|
-
|
|
137
|
-
## Useful Links
|
|
138
|
-
|
|
139
|
-
- **Homepage**: https://github.com/wexample/python-cli
|
|
140
|
-
- **Documentation**: [docs.wexample.com](https://docs.wexample.com)
|
|
141
|
-
- **Issue Tracker**: https://github.com/wexample/python-cli/issues
|
|
142
|
-
- **Discussions**: https://github.com/wexample/python-cli/discussions
|
|
143
|
-
- **PyPI**: [pypi.org/project/cli](https://pypi.org/project/cli/)
|
|
144
|
-
|
|
145
|
-
## Migration Notes
|
|
146
|
-
|
|
147
|
-
When upgrading between major versions, refer to the migration guides in the documentation.
|
|
148
|
-
|
|
149
|
-
Breaking changes are clearly documented with upgrade paths and examples.
|
|
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
|
|
File without changes
|
{wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/decorator/option_stop_on_failure.py
RENAMED
|
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
|
{wexample_cli-2.1.0 → wexample_cli-2.1.2}/src/wexample_cli/middleware/abstract_middleware.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|