wup 0.2.35__tar.gz → 0.2.38__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.
- {wup-0.2.35/wup.egg-info → wup-0.2.38}/PKG-INFO +51 -8
- {wup-0.2.35 → wup-0.2.38}/README.md +50 -7
- {wup-0.2.35 → wup-0.2.38}/pyproject.toml +1 -1
- {wup-0.2.35 → wup-0.2.38}/wup/__init__.py +9 -2
- {wup-0.2.35 → wup-0.2.38}/wup/cli.py +81 -0
- wup-0.2.38/wup/cli_config_generator.py +223 -0
- wup-0.2.38/wup/cli_scanner.py +302 -0
- wup-0.2.38/wup/testql_cli_generator.py +215 -0
- {wup-0.2.35 → wup-0.2.38}/wup/testql_monitor.py +54 -18
- {wup-0.2.35 → wup-0.2.38}/wup/testql_watcher.py +1 -1
- {wup-0.2.35 → wup-0.2.38/wup.egg-info}/PKG-INFO +51 -8
- {wup-0.2.35 → wup-0.2.38}/wup.egg-info/SOURCES.txt +3 -0
- {wup-0.2.35 → wup-0.2.38}/LICENSE +0 -0
- {wup-0.2.35 → wup-0.2.38}/setup.cfg +0 -0
- {wup-0.2.35 → wup-0.2.38}/tests/test_e2e.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/tests/test_monitoring_manifest.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/tests/test_testql_monitor.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/tests/test_testql_watcher.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/tests/test_web_client.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/tests/test_wup.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/wup/_ast_detector.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/wup/_hash_detector.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/wup/_yaml_detector.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/wup/anomaly_detector.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/wup/anomaly_models.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/wup/assistant.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/wup/config.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/wup/core.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/wup/dependency_mapper.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/wup/models/__init__.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/wup/models/config.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/wup/monitoring_manifest.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/wup/planfile_reporter.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/wup/testql_discovery.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/wup/visual_diff.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/wup/web_client.py +0 -0
- {wup-0.2.35 → wup-0.2.38}/wup.egg-info/dependency_links.txt +0 -0
- {wup-0.2.35 → wup-0.2.38}/wup.egg-info/entry_points.txt +0 -0
- {wup-0.2.35 → wup-0.2.38}/wup.egg-info/requires.txt +0 -0
- {wup-0.2.35 → wup-0.2.38}/wup.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wup
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.38
|
|
4
4
|
Summary: WUP (What's Up) - Intelligent file watcher for regression testing in large projects
|
|
5
5
|
Author-email: Tom Sapletta <tom@sapletta.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -31,17 +31,17 @@ Dynamic: license-file
|
|
|
31
31
|
|
|
32
32
|
## AI Cost Tracking
|
|
33
33
|
|
|
34
|
-
    
|
|
35
|
+
  
|
|
36
36
|
|
|
37
|
-
- 🤖 **LLM usage:** $2.
|
|
38
|
-
- 👤 **Human dev:** ~$
|
|
37
|
+
- 🤖 **LLM usage:** $2.9855 (48 commits)
|
|
38
|
+
- 👤 **Human dev:** ~$2047 (20.5h @ $100/h, 30min dedup)
|
|
39
39
|
|
|
40
|
-
Generated on 2026-05-
|
|
40
|
+
Generated on 2026-05-22 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
41
41
|
|
|
42
42
|
---
|
|
43
43
|
|
|
44
|
-
    
|
|
45
45
|
|
|
46
46
|
**WUP (What's Up)** - Intelligent file watcher for regression testing in large projects.
|
|
47
47
|
|
|
@@ -62,6 +62,7 @@ WUP monitors file changes and runs intelligent regression tests using a 3-layer
|
|
|
62
62
|
- ⚙️ **Configuration System**: Declarative configuration via `wup.yaml` file
|
|
63
63
|
- 🎛️ **Per-Service Settings**: Custom test strategies per service
|
|
64
64
|
- 🧪 **TestQL Integration**: Native support for TestQL scenarios
|
|
65
|
+
- 🔧 **CLI/Shell Automation**: Auto-detection and configuration of CLI tools and shell scripts
|
|
65
66
|
|
|
66
67
|
## Installation
|
|
67
68
|
|
|
@@ -143,6 +144,12 @@ wup init
|
|
|
143
144
|
|
|
144
145
|
# Generate with custom output path
|
|
145
146
|
wup init --output .wup.yaml
|
|
147
|
+
|
|
148
|
+
# Auto-detect and configure CLI/shell services
|
|
149
|
+
wup init-cli ./my-project
|
|
150
|
+
|
|
151
|
+
# Merge CLI configuration with existing wup.yaml
|
|
152
|
+
wup init-cli ./my-project --merge
|
|
146
153
|
```
|
|
147
154
|
|
|
148
155
|
### Check Status
|
|
@@ -155,6 +162,35 @@ wup status
|
|
|
155
162
|
wup status --deps my-deps.json
|
|
156
163
|
```
|
|
157
164
|
|
|
165
|
+
### CLI/Shell Automation
|
|
166
|
+
|
|
167
|
+
WUP can automatically detect and configure CLI tools and shell scripts for testing:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
# Auto-detect CLI commands and generate configuration
|
|
171
|
+
wup init-cli ./my-project
|
|
172
|
+
|
|
173
|
+
# Merge with existing wup.yaml
|
|
174
|
+
wup init-cli ./my-project --merge
|
|
175
|
+
|
|
176
|
+
# Custom output paths
|
|
177
|
+
wup init-cli ./my-project --output-config custom.yaml --output-scenarios custom-scenarios
|
|
178
|
+
|
|
179
|
+
# Skip argument inference (faster)
|
|
180
|
+
wup init-cli ./my-project --no-infer-args
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
The `init-cli` command:
|
|
184
|
+
- Scans `pyproject.toml`, `setup.py`, `setup.cfg` for entry points
|
|
185
|
+
- Detects packages with `__main__.py` modules
|
|
186
|
+
- Generates shell service configuration in `wup.yaml`
|
|
187
|
+
- Creates TestQL scenarios for CLI commands in `testql-scenarios/`
|
|
188
|
+
- Supports merging with existing configurations
|
|
189
|
+
|
|
190
|
+
**Generated files:**
|
|
191
|
+
- `cli-smoke.testql.toon.yaml` - Smoke tests for all CLI commands
|
|
192
|
+
- `cli-{command}.testql.toon.yaml` - Detailed tests for each command
|
|
193
|
+
|
|
158
194
|
## Architecture
|
|
159
195
|
|
|
160
196
|
### 3-Layer Testing Approach
|
|
@@ -417,7 +453,10 @@ wup/
|
|
|
417
453
|
│ ├── __init__.py # Package exports
|
|
418
454
|
│ ├── anomaly_detector.py # AnomalyDetector: hash, YAML structure, AST diff
|
|
419
455
|
│ ├── assistant.py # WupAssistant: interactive configuration wizard
|
|
420
|
-
│ ├── cli.py # CLI: watch, map-deps, status, init, testql-endpoints, assistant, version
|
|
456
|
+
│ ├── cli.py # CLI: watch, map-deps, status, init, testql-endpoints, assistant, version, init-cli
|
|
457
|
+
│ ├── cli_scanner.py # CLIScanner: detects CLI commands from pyproject.toml, setup.py, etc.
|
|
458
|
+
│ ├── cli_config_generator.py # CLIConfigGenerator: generates wup.yaml for shell services
|
|
459
|
+
│ ├── testql_cli_generator.py # TestQLCliGenerator: generates TestQL scenarios for CLI commands
|
|
421
460
|
│ ├── config.py # Config loading/saving + .wup.env support
|
|
422
461
|
│ ├── core.py # WupWatcher: detection, inference, scheduling
|
|
423
462
|
│ ├── dependency_mapper.py # DependencyMapper: codebase → deps.json
|
|
@@ -519,6 +558,7 @@ Comprehensive documentation is available in the `docs/` directory:
|
|
|
519
558
|
- `wup assistant` - Interactive configuration wizard
|
|
520
559
|
- Auto-detects framework and services
|
|
521
560
|
- Intelligent suggestions and validation
|
|
561
|
+
- `wup init-cli` - Automated CLI/shell project setup
|
|
522
562
|
|
|
523
563
|
- **[Anomaly Detection](docs/ANOMALY_DETECTION.md)** - Fast alternatives to Playwright
|
|
524
564
|
- Hash-based change detection (~1ms per file)
|
|
@@ -533,6 +573,9 @@ Comprehensive documentation is available in the `docs/` directory:
|
|
|
533
573
|
- Browser Notifications API integration
|
|
534
574
|
|
|
535
575
|
- **[TestQL Integration](docs/TESTQL_INTEGRATION.md)** - TestQL scenario support
|
|
576
|
+
- `wup init-cli` - Automated CLI command detection and TestQL scenario generation
|
|
577
|
+
- Shell service configuration for CLI tools
|
|
578
|
+
- TestQL scenarios for CLI commands
|
|
536
579
|
|
|
537
580
|
## License
|
|
538
581
|
|
|
@@ -3,17 +3,17 @@
|
|
|
3
3
|
|
|
4
4
|
## AI Cost Tracking
|
|
5
5
|
|
|
6
|
-
    
|
|
7
|
+
  
|
|
8
8
|
|
|
9
|
-
- 🤖 **LLM usage:** $2.
|
|
10
|
-
- 👤 **Human dev:** ~$
|
|
9
|
+
- 🤖 **LLM usage:** $2.9855 (48 commits)
|
|
10
|
+
- 👤 **Human dev:** ~$2047 (20.5h @ $100/h, 30min dedup)
|
|
11
11
|
|
|
12
|
-
Generated on 2026-05-
|
|
12
|
+
Generated on 2026-05-22 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
16
|
-
    
|
|
17
17
|
|
|
18
18
|
**WUP (What's Up)** - Intelligent file watcher for regression testing in large projects.
|
|
19
19
|
|
|
@@ -34,6 +34,7 @@ WUP monitors file changes and runs intelligent regression tests using a 3-layer
|
|
|
34
34
|
- ⚙️ **Configuration System**: Declarative configuration via `wup.yaml` file
|
|
35
35
|
- 🎛️ **Per-Service Settings**: Custom test strategies per service
|
|
36
36
|
- 🧪 **TestQL Integration**: Native support for TestQL scenarios
|
|
37
|
+
- 🔧 **CLI/Shell Automation**: Auto-detection and configuration of CLI tools and shell scripts
|
|
37
38
|
|
|
38
39
|
## Installation
|
|
39
40
|
|
|
@@ -115,6 +116,12 @@ wup init
|
|
|
115
116
|
|
|
116
117
|
# Generate with custom output path
|
|
117
118
|
wup init --output .wup.yaml
|
|
119
|
+
|
|
120
|
+
# Auto-detect and configure CLI/shell services
|
|
121
|
+
wup init-cli ./my-project
|
|
122
|
+
|
|
123
|
+
# Merge CLI configuration with existing wup.yaml
|
|
124
|
+
wup init-cli ./my-project --merge
|
|
118
125
|
```
|
|
119
126
|
|
|
120
127
|
### Check Status
|
|
@@ -127,6 +134,35 @@ wup status
|
|
|
127
134
|
wup status --deps my-deps.json
|
|
128
135
|
```
|
|
129
136
|
|
|
137
|
+
### CLI/Shell Automation
|
|
138
|
+
|
|
139
|
+
WUP can automatically detect and configure CLI tools and shell scripts for testing:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# Auto-detect CLI commands and generate configuration
|
|
143
|
+
wup init-cli ./my-project
|
|
144
|
+
|
|
145
|
+
# Merge with existing wup.yaml
|
|
146
|
+
wup init-cli ./my-project --merge
|
|
147
|
+
|
|
148
|
+
# Custom output paths
|
|
149
|
+
wup init-cli ./my-project --output-config custom.yaml --output-scenarios custom-scenarios
|
|
150
|
+
|
|
151
|
+
# Skip argument inference (faster)
|
|
152
|
+
wup init-cli ./my-project --no-infer-args
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
The `init-cli` command:
|
|
156
|
+
- Scans `pyproject.toml`, `setup.py`, `setup.cfg` for entry points
|
|
157
|
+
- Detects packages with `__main__.py` modules
|
|
158
|
+
- Generates shell service configuration in `wup.yaml`
|
|
159
|
+
- Creates TestQL scenarios for CLI commands in `testql-scenarios/`
|
|
160
|
+
- Supports merging with existing configurations
|
|
161
|
+
|
|
162
|
+
**Generated files:**
|
|
163
|
+
- `cli-smoke.testql.toon.yaml` - Smoke tests for all CLI commands
|
|
164
|
+
- `cli-{command}.testql.toon.yaml` - Detailed tests for each command
|
|
165
|
+
|
|
130
166
|
## Architecture
|
|
131
167
|
|
|
132
168
|
### 3-Layer Testing Approach
|
|
@@ -389,7 +425,10 @@ wup/
|
|
|
389
425
|
│ ├── __init__.py # Package exports
|
|
390
426
|
│ ├── anomaly_detector.py # AnomalyDetector: hash, YAML structure, AST diff
|
|
391
427
|
│ ├── assistant.py # WupAssistant: interactive configuration wizard
|
|
392
|
-
│ ├── cli.py # CLI: watch, map-deps, status, init, testql-endpoints, assistant, version
|
|
428
|
+
│ ├── cli.py # CLI: watch, map-deps, status, init, testql-endpoints, assistant, version, init-cli
|
|
429
|
+
│ ├── cli_scanner.py # CLIScanner: detects CLI commands from pyproject.toml, setup.py, etc.
|
|
430
|
+
│ ├── cli_config_generator.py # CLIConfigGenerator: generates wup.yaml for shell services
|
|
431
|
+
│ ├── testql_cli_generator.py # TestQLCliGenerator: generates TestQL scenarios for CLI commands
|
|
393
432
|
│ ├── config.py # Config loading/saving + .wup.env support
|
|
394
433
|
│ ├── core.py # WupWatcher: detection, inference, scheduling
|
|
395
434
|
│ ├── dependency_mapper.py # DependencyMapper: codebase → deps.json
|
|
@@ -491,6 +530,7 @@ Comprehensive documentation is available in the `docs/` directory:
|
|
|
491
530
|
- `wup assistant` - Interactive configuration wizard
|
|
492
531
|
- Auto-detects framework and services
|
|
493
532
|
- Intelligent suggestions and validation
|
|
533
|
+
- `wup init-cli` - Automated CLI/shell project setup
|
|
494
534
|
|
|
495
535
|
- **[Anomaly Detection](docs/ANOMALY_DETECTION.md)** - Fast alternatives to Playwright
|
|
496
536
|
- Hash-based change detection (~1ms per file)
|
|
@@ -505,6 +545,9 @@ Comprehensive documentation is available in the `docs/` directory:
|
|
|
505
545
|
- Browser Notifications API integration
|
|
506
546
|
|
|
507
547
|
- **[TestQL Integration](docs/TESTQL_INTEGRATION.md)** - TestQL scenario support
|
|
548
|
+
- `wup init-cli` - Automated CLI command detection and TestQL scenario generation
|
|
549
|
+
- Shell service configuration for CLI tools
|
|
550
|
+
- TestQL scenarios for CLI commands
|
|
508
551
|
|
|
509
552
|
## License
|
|
510
553
|
|
|
@@ -7,7 +7,7 @@ WUP monitors file changes and runs intelligent regression tests using a 3-layer
|
|
|
7
7
|
3. Detail Layer: Full tests with blame reports (only on failure)
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
|
-
__version__ = "0.2.
|
|
10
|
+
__version__ = "0.2.38"
|
|
11
11
|
__author__ = "Tom Sapletta"
|
|
12
12
|
|
|
13
13
|
from .config import load_config, save_config, get_default_config
|
|
@@ -21,7 +21,6 @@ from .models.config import (
|
|
|
21
21
|
TestQLConfig,
|
|
22
22
|
NotifyConfig,
|
|
23
23
|
)
|
|
24
|
-
from .testql_watcher import TestQLWatcher
|
|
25
24
|
|
|
26
25
|
__all__ = [
|
|
27
26
|
"WupWatcher",
|
|
@@ -37,3 +36,11 @@ __all__ = [
|
|
|
37
36
|
"TestQLConfig",
|
|
38
37
|
"NotifyConfig",
|
|
39
38
|
]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def __getattr__(name: str):
|
|
42
|
+
"""Lazy import for TestQLWatcher to avoid circular dependency."""
|
|
43
|
+
if name == "TestQLWatcher":
|
|
44
|
+
from .testql_watcher import TestQLWatcher
|
|
45
|
+
return TestQLWatcher
|
|
46
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
@@ -678,5 +678,86 @@ def version():
|
|
|
678
678
|
console.print(f"[bold cyan]WUP[/bold cyan] version [green]{__version__}[/green]")
|
|
679
679
|
|
|
680
680
|
|
|
681
|
+
@app.command("init-cli")
|
|
682
|
+
def init_cli(
|
|
683
|
+
project: str = typer.Argument(".", help="Path to the project root directory"),
|
|
684
|
+
output_config: Optional[str] = typer.Option(None, "--output-config", "-c", help="Path for wup.yaml output"),
|
|
685
|
+
output_scenarios: Optional[str] = typer.Option(None, "--output-scenarios", "-s", help="Path for testql-scenarios directory"),
|
|
686
|
+
merge: bool = typer.Option(False, "--merge", "-m", help="Merge with existing wup.yaml"),
|
|
687
|
+
infer_args: bool = typer.Option(True, "--infer-args/--no-infer-args", help="Infer command arguments by inspection"),
|
|
688
|
+
):
|
|
689
|
+
"""
|
|
690
|
+
Automatically generate wup.yaml configuration and TestQL scenarios for CLI/shell services.
|
|
691
|
+
|
|
692
|
+
Scans the project for CLI commands (entry points, setup.py, pyproject.toml) and generates:
|
|
693
|
+
- wup.yaml with shell service configuration
|
|
694
|
+
- TestQL scenarios in testql-scenarios/ directory
|
|
695
|
+
|
|
696
|
+
Example:
|
|
697
|
+
wup init-cli ./my-project
|
|
698
|
+
wup init-cli ./my-project --merge
|
|
699
|
+
"""
|
|
700
|
+
from pathlib import Path
|
|
701
|
+
from .cli_scanner import CLIScanner
|
|
702
|
+
from .cli_config_generator import CLIConfigGenerator
|
|
703
|
+
from .testql_cli_generator import TestQLCLIGenerator
|
|
704
|
+
|
|
705
|
+
project_path = Path(project).resolve()
|
|
706
|
+
|
|
707
|
+
if not project_path.exists():
|
|
708
|
+
console.print(f"[red]Error: Project path '{project}' does not exist[/red]")
|
|
709
|
+
raise typer.Exit(1)
|
|
710
|
+
|
|
711
|
+
console.print(f"[cyan]🔍 Scanning project for CLI commands...[/cyan]")
|
|
712
|
+
console.print(f"[dim]Project: {project_path}[/dim]\n")
|
|
713
|
+
|
|
714
|
+
try:
|
|
715
|
+
# Scan for CLI commands
|
|
716
|
+
scanner = CLIScanner(str(project_path))
|
|
717
|
+
packages = scanner.scan()
|
|
718
|
+
|
|
719
|
+
if not packages:
|
|
720
|
+
console.print("[yellow]⚠ No CLI packages found in project[/yellow]")
|
|
721
|
+
console.print("[dim]Looking for: setup.py, pyproject.toml, or packages with __main__.py[/dim]")
|
|
722
|
+
raise typer.Exit(1)
|
|
723
|
+
|
|
724
|
+
console.print(f"[green]✓ Found {len(packages)} package(s)[/green]")
|
|
725
|
+
for pkg in packages:
|
|
726
|
+
console.print(f" [cyan]{pkg.name}[/cyan]: {len(pkg.commands)} command(s)")
|
|
727
|
+
for cmd in pkg.commands:
|
|
728
|
+
console.print(f" - {cmd.name} -> {cmd.entry_point}")
|
|
729
|
+
console.print()
|
|
730
|
+
|
|
731
|
+
# Generate wup.yaml
|
|
732
|
+
config_generator = CLIConfigGenerator(str(project_path))
|
|
733
|
+
config_output = Path(output_config) if output_config else None
|
|
734
|
+
config = config_generator.generate(output_path=config_output, merge_existing=merge)
|
|
735
|
+
config_generator.print_summary(config)
|
|
736
|
+
|
|
737
|
+
# Generate TestQL scenarios
|
|
738
|
+
console.print()
|
|
739
|
+
console.print(f"[cyan]🧪 Generating TestQL scenarios...[/cyan]")
|
|
740
|
+
scenarios_output = Path(output_scenarios) if output_scenarios else None
|
|
741
|
+
testql_generator = TestQLCLIGenerator(str(project_path))
|
|
742
|
+
generated_files = testql_generator.generate(
|
|
743
|
+
output_dir=scenarios_output,
|
|
744
|
+
infer_args=infer_args,
|
|
745
|
+
)
|
|
746
|
+
testql_generator.print_summary(generated_files)
|
|
747
|
+
|
|
748
|
+
console.print()
|
|
749
|
+
console.print("[bold green]✅ CLI testing setup complete![/bold green]")
|
|
750
|
+
console.print()
|
|
751
|
+
console.print("[dim]Next steps:[/dim]")
|
|
752
|
+
console.print(" 1. Review generated wup.yaml")
|
|
753
|
+
console.print(" 2. Review testql-scenarios/*.testql.toon.yaml")
|
|
754
|
+
console.print(" 3. Run: wup watch . --mode testql")
|
|
755
|
+
console.print(" 4. Or run individual scenario: testql run testql-scenarios/cli-smoke.testql.toon.yaml")
|
|
756
|
+
|
|
757
|
+
except Exception as e:
|
|
758
|
+
console.print(f"[red]Error: {e}[/red]")
|
|
759
|
+
raise typer.Exit(1)
|
|
760
|
+
|
|
761
|
+
|
|
681
762
|
if __name__ == "__main__":
|
|
682
763
|
app()
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"""Generator for wup.yaml configuration for CLI/shell services."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Dict, List, Optional
|
|
7
|
+
|
|
8
|
+
import yaml
|
|
9
|
+
|
|
10
|
+
from .cli_scanner import CLIScanner, CLIPackage, CLICommand
|
|
11
|
+
from .models.config import (
|
|
12
|
+
ProjectConfig,
|
|
13
|
+
ServiceConfig,
|
|
14
|
+
ServiceTestConfig,
|
|
15
|
+
TestQLConfig,
|
|
16
|
+
TestStrategyConfig,
|
|
17
|
+
WatchConfig,
|
|
18
|
+
WupConfig,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class CLIConfigGenerator:
|
|
23
|
+
"""Generate wup.yaml configuration for CLI/shell services."""
|
|
24
|
+
|
|
25
|
+
def __init__(self, project_root: str):
|
|
26
|
+
self.project_root = Path(project_root).resolve()
|
|
27
|
+
self.scanner = CLIScanner(project_root)
|
|
28
|
+
|
|
29
|
+
def generate(
|
|
30
|
+
self,
|
|
31
|
+
output_path: Optional[Path] = None,
|
|
32
|
+
merge_existing: bool = False,
|
|
33
|
+
) -> WupConfig:
|
|
34
|
+
"""Generate wup.yaml configuration for CLI services.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
output_path: Path to save the configuration (default: wup.yaml)
|
|
38
|
+
merge_existing: If True, merge with existing wup.yaml
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
Generated WupConfig object
|
|
42
|
+
"""
|
|
43
|
+
# Scan for CLI commands
|
|
44
|
+
packages = self.scanner.scan()
|
|
45
|
+
|
|
46
|
+
if not packages:
|
|
47
|
+
raise ValueError("No CLI packages found in project")
|
|
48
|
+
|
|
49
|
+
# Load existing config if merging
|
|
50
|
+
existing_config = None
|
|
51
|
+
if merge_existing:
|
|
52
|
+
from .config import load_config
|
|
53
|
+
existing_config = load_config(self.project_root)
|
|
54
|
+
|
|
55
|
+
# Generate configuration
|
|
56
|
+
config = self._generate_config(packages, existing_config)
|
|
57
|
+
|
|
58
|
+
# Save configuration
|
|
59
|
+
if output_path is None:
|
|
60
|
+
output_path = self.project_root / "wup.yaml"
|
|
61
|
+
|
|
62
|
+
self._save_config(config, output_path)
|
|
63
|
+
|
|
64
|
+
return config
|
|
65
|
+
|
|
66
|
+
def _generate_config(
|
|
67
|
+
self,
|
|
68
|
+
packages: List[CLIPackage],
|
|
69
|
+
existing_config: Optional[WupConfig] = None,
|
|
70
|
+
) -> WupConfig:
|
|
71
|
+
"""Generate WupConfig from scanned packages."""
|
|
72
|
+
if existing_config:
|
|
73
|
+
config = existing_config
|
|
74
|
+
else:
|
|
75
|
+
config = WupConfig(
|
|
76
|
+
project=ProjectConfig(
|
|
77
|
+
name=self.project_root.name,
|
|
78
|
+
description=f"CLI testing for {self.project_root.name}",
|
|
79
|
+
),
|
|
80
|
+
watch=WatchConfig(
|
|
81
|
+
paths=["**/*.py"],
|
|
82
|
+
exclude_patterns=["*.md", "tests/**", ".venv/**", "venv/**"],
|
|
83
|
+
file_types=[".py"],
|
|
84
|
+
),
|
|
85
|
+
test_strategy=TestStrategyConfig(
|
|
86
|
+
quick={"debounce_s": 2, "max_queue": 5, "timeout_s": 30},
|
|
87
|
+
detail={"debounce_s": 10, "max_queue": 1, "timeout_s": 60},
|
|
88
|
+
),
|
|
89
|
+
testql=TestQLConfig(
|
|
90
|
+
scenario_dir="testql-scenarios",
|
|
91
|
+
smoke_scenario="cli-smoke.testql.toon.yaml",
|
|
92
|
+
output_format="json",
|
|
93
|
+
probe_interval_s=60,
|
|
94
|
+
),
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
# Add shell services for each package
|
|
98
|
+
for package in packages:
|
|
99
|
+
service = self._create_shell_service(package)
|
|
100
|
+
|
|
101
|
+
# Check if service already exists
|
|
102
|
+
existing_service = next(
|
|
103
|
+
(s for s in config.services if s.name == service.name),
|
|
104
|
+
None,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
if existing_service:
|
|
108
|
+
# Update existing service
|
|
109
|
+
existing_service.type = service.type
|
|
110
|
+
existing_service.quick_tests = service.quick_tests
|
|
111
|
+
existing_service.detail_tests = service.detail_tests
|
|
112
|
+
else:
|
|
113
|
+
# Add new service
|
|
114
|
+
config.services.append(service)
|
|
115
|
+
|
|
116
|
+
return config
|
|
117
|
+
|
|
118
|
+
def _create_shell_service(self, package: CLIPackage) -> ServiceConfig:
|
|
119
|
+
"""Create a shell service configuration from a CLI package."""
|
|
120
|
+
# Calculate max_endpoints based on number of commands
|
|
121
|
+
command_count = len(package.commands)
|
|
122
|
+
quick_max = min(command_count, 5)
|
|
123
|
+
detail_max = min(command_count * 2, 20)
|
|
124
|
+
|
|
125
|
+
service = ServiceConfig(
|
|
126
|
+
name=f"{package.name}-shell",
|
|
127
|
+
type="shell",
|
|
128
|
+
paths=[], # Auto-detect
|
|
129
|
+
root=str(self.project_root),
|
|
130
|
+
quick_tests=ServiceTestConfig(
|
|
131
|
+
scope="all",
|
|
132
|
+
max_endpoints=quick_max,
|
|
133
|
+
),
|
|
134
|
+
detail_tests=ServiceTestConfig(
|
|
135
|
+
scope="all",
|
|
136
|
+
max_endpoints=detail_max,
|
|
137
|
+
),
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
return service
|
|
141
|
+
|
|
142
|
+
def _save_config(self, config: WupConfig, output_path: Path) -> None:
|
|
143
|
+
"""Save configuration to YAML file."""
|
|
144
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
145
|
+
|
|
146
|
+
# Convert to dict
|
|
147
|
+
config_dict = {
|
|
148
|
+
"project": {
|
|
149
|
+
"name": config.project.name,
|
|
150
|
+
"description": config.project.description,
|
|
151
|
+
},
|
|
152
|
+
"watch": {
|
|
153
|
+
"paths": config.watch.paths,
|
|
154
|
+
"exclude_patterns": config.watch.exclude_patterns,
|
|
155
|
+
"file_types": config.watch.file_types,
|
|
156
|
+
},
|
|
157
|
+
"services": [
|
|
158
|
+
{
|
|
159
|
+
"name": svc.name,
|
|
160
|
+
"type": svc.type,
|
|
161
|
+
"paths": svc.paths,
|
|
162
|
+
"root": svc.root,
|
|
163
|
+
"quick_tests": {
|
|
164
|
+
"scope": svc.quick_tests.scope,
|
|
165
|
+
"max_endpoints": svc.quick_tests.max_endpoints,
|
|
166
|
+
},
|
|
167
|
+
"detail_tests": {
|
|
168
|
+
"scope": svc.detail_tests.scope,
|
|
169
|
+
"max_endpoints": svc.detail_tests.max_endpoints,
|
|
170
|
+
},
|
|
171
|
+
}
|
|
172
|
+
for svc in config.services
|
|
173
|
+
],
|
|
174
|
+
"test_strategy": {
|
|
175
|
+
"quick": config.test_strategy.quick,
|
|
176
|
+
"detail": config.test_strategy.detail,
|
|
177
|
+
},
|
|
178
|
+
"testql": {
|
|
179
|
+
"scenario_dir": config.testql.scenario_dir,
|
|
180
|
+
"smoke_scenario": config.testql.smoke_scenario,
|
|
181
|
+
"output_format": config.testql.output_format,
|
|
182
|
+
"probe_interval_s": config.testql.probe_interval_s,
|
|
183
|
+
},
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
# Add header
|
|
187
|
+
header = f"""# WUP Configuration for CLI Testing
|
|
188
|
+
# Generated automatically by wup init-cli
|
|
189
|
+
# Project: {config.project.name}
|
|
190
|
+
|
|
191
|
+
"""
|
|
192
|
+
|
|
193
|
+
with open(output_path, "w", encoding="utf-8") as f:
|
|
194
|
+
f.write(header)
|
|
195
|
+
yaml.dump(config_dict, f, default_flow_style=False, sort_keys=False)
|
|
196
|
+
|
|
197
|
+
def print_summary(self, config: WupConfig) -> None:
|
|
198
|
+
"""Print summary of generated configuration."""
|
|
199
|
+
from rich.console import Console
|
|
200
|
+
from rich.table import Table
|
|
201
|
+
|
|
202
|
+
console = Console()
|
|
203
|
+
|
|
204
|
+
console.print("\n[bold green]✓ Generated wup.yaml configuration[/bold green]\n")
|
|
205
|
+
|
|
206
|
+
table = Table(title="Shell Services")
|
|
207
|
+
table.add_column("Service", style="cyan")
|
|
208
|
+
table.add_column("Type", style="green")
|
|
209
|
+
table.add_column("Quick Tests", style="yellow")
|
|
210
|
+
table.add_column("Detail Tests", style="yellow")
|
|
211
|
+
|
|
212
|
+
for svc in config.services:
|
|
213
|
+
if svc.type == "shell":
|
|
214
|
+
table.add_row(
|
|
215
|
+
svc.name,
|
|
216
|
+
svc.type,
|
|
217
|
+
str(svc.quick_tests.max_endpoints),
|
|
218
|
+
str(svc.detail_tests.max_endpoints),
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
console.print(table)
|
|
222
|
+
console.print(f"\nTestQL scenarios directory: {config.testql.scenario_dir}")
|
|
223
|
+
console.print(f"Smoke scenario: {config.testql.smoke_scenario}")
|