wup 0.2.75__tar.gz → 0.2.76__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.75/wup.egg-info → wup-0.2.76}/PKG-INFO +6 -6
- {wup-0.2.75 → wup-0.2.76}/README.md +5 -5
- {wup-0.2.75 → wup-0.2.76}/pyproject.toml +1 -1
- {wup-0.2.75 → wup-0.2.76}/tests/test_genericity.py +26 -0
- {wup-0.2.75 → wup-0.2.76}/wup/__init__.py +1 -1
- {wup-0.2.75 → wup-0.2.76}/wup/config.py +2 -0
- {wup-0.2.75 → wup-0.2.76}/wup/core.py +19 -4
- {wup-0.2.75 → wup-0.2.76}/wup/models/config.py +3 -0
- {wup-0.2.75 → wup-0.2.76/wup.egg-info}/PKG-INFO +6 -6
- {wup-0.2.75 → wup-0.2.76}/LICENSE +0 -0
- {wup-0.2.75 → wup-0.2.76}/setup.cfg +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_aql.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_assistant.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_auto_detection.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_cli_bridge.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_cli_filtering.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_control.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_discovery_adapters.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_e2e.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_endpoints_init_cli.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_health_summary_passed.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_monitoring_manifest.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_multi_project.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_oql.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_planfile_reporter_dedupe.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_probe_mutex.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_service_inference.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_status_data.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_sync.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_testql_monitor.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_testql_watcher.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_visual_diff_periodic_skip.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_visual_diff_progress.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_watch_exclude.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_watch_no_paths_exit.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_web_client.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_wup.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/tests/test_wup_generate.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/_ast_detector.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/_base_detector.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/_hash_detector.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/_yaml_detector.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/anomaly_detector.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/anomaly_models.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/aql.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/assistant.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/assistant_discovery.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/assistant_validator.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/bus.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/cli.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/cli_bridge.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/cli_config_generator.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/cli_scanner.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/control.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/dependency_mapper.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/discovery.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/endpoints.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/event_store.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/file_watcher/events/file_events.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/generate.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/init_cli.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/models/__init__.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/models/target.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/monitoring_manifest.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/multi.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/oql.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/paths.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/planfile_reporter.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/status_data.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/sync.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/testing/events/health_events.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/testing/events/test_results.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/testing/handlers/event_handlers.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/testing/handlers/health_handlers.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/testing/queries/health_queries.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/testql_cli_generator.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/testql_discovery.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/testql_monitor.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/testql_watcher.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/validate.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/visual_diff.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup/web_client.py +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup.egg-info/SOURCES.txt +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup.egg-info/dependency_links.txt +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup.egg-info/entry_points.txt +0 -0
- {wup-0.2.75 → wup-0.2.76}/wup.egg-info/requires.txt +0 -0
- {wup-0.2.75 → wup-0.2.76}/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.76
|
|
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
|
|
@@ -42,17 +42,17 @@ Dynamic: license-file
|
|
|
42
42
|
|
|
43
43
|
## AI Cost Tracking
|
|
44
44
|
|
|
45
|
-
    
|
|
46
|
+
  
|
|
47
47
|
|
|
48
|
-
- 🤖 **LLM usage:** $6.
|
|
49
|
-
- 👤 **Human dev:** ~$
|
|
48
|
+
- 🤖 **LLM usage:** $6.7652 (105 commits)
|
|
49
|
+
- 👤 **Human dev:** ~$5295 (53.0h @ $100/h, 30min dedup)
|
|
50
50
|
|
|
51
51
|
Generated on 2026-07-17 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
52
52
|
|
|
53
53
|
---
|
|
54
54
|
|
|
55
|
-
    
|
|
56
56
|
|
|
57
57
|
**WUP (What's Up)** - Intelligent file watcher for regression testing in large projects.
|
|
58
58
|
|
|
@@ -3,17 +3,17 @@
|
|
|
3
3
|
|
|
4
4
|
## AI Cost Tracking
|
|
5
5
|
|
|
6
|
-
    
|
|
7
|
+
  
|
|
8
8
|
|
|
9
|
-
- 🤖 **LLM usage:** $6.
|
|
10
|
-
- 👤 **Human dev:** ~$
|
|
9
|
+
- 🤖 **LLM usage:** $6.7652 (105 commits)
|
|
10
|
+
- 👤 **Human dev:** ~$5295 (53.0h @ $100/h, 30min dedup)
|
|
11
11
|
|
|
12
12
|
Generated on 2026-07-17 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
|
|
|
@@ -96,6 +96,32 @@ def test_reject_prefixes_explicit_override() -> None:
|
|
|
96
96
|
assert reject_prefixes_for_config(cfg) == ("/internal",)
|
|
97
97
|
|
|
98
98
|
|
|
99
|
+
def _prefix_matches(cfg, top: str) -> bool:
|
|
100
|
+
import re
|
|
101
|
+
from wup.core import WupWatcher
|
|
102
|
+
|
|
103
|
+
watcher = WupWatcher(project_root=".", config=cfg)
|
|
104
|
+
pat = "|".join(re.escape(p) for p in watcher._service_name_prefixes())
|
|
105
|
+
return bool(re.match(rf"^({pat})[-_]", top))
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def test_service_prefix_generic_default() -> None:
|
|
109
|
+
cfg = validate_config({"project": {"name": "p"}})
|
|
110
|
+
assert _prefix_matches(cfg, "api-gateway") # generic prefix
|
|
111
|
+
assert not _prefix_matches(cfg, "connect-foo") # fleet prefix is opt-in
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def test_service_prefix_connect_profile() -> None:
|
|
115
|
+
cfg = validate_config({"project": {"name": "p"}, "testql": {"service_map_profile": "connect"}})
|
|
116
|
+
assert _prefix_matches(cfg, "connect-foo")
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def test_service_prefix_custom() -> None:
|
|
120
|
+
cfg = validate_config({"project": {"name": "p"}, "testql": {"service_name_prefixes": ["svc"]}})
|
|
121
|
+
assert _prefix_matches(cfg, "svc-auth")
|
|
122
|
+
assert not _prefix_matches(cfg, "connect-foo")
|
|
123
|
+
|
|
124
|
+
|
|
99
125
|
def test_config_roundtrips_docker_service_map() -> None:
|
|
100
126
|
raw = {
|
|
101
127
|
"project": {"name": "p"},
|
|
@@ -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.76"
|
|
11
11
|
__author__ = "Tom Sapletta"
|
|
12
12
|
|
|
13
13
|
from .config import load_config, save_config, get_default_config
|
|
@@ -233,6 +233,7 @@ def _parse_testql_config(raw: dict) -> TestQLConfig:
|
|
|
233
233
|
docker_service_map=testql_raw.get("docker_service_map", {}),
|
|
234
234
|
service_map_profile=testql_raw.get("service_map_profile", ""),
|
|
235
235
|
monitoring_reject_prefixes=testql_raw.get("monitoring_reject_prefixes", []),
|
|
236
|
+
service_name_prefixes=testql_raw.get("service_name_prefixes", []),
|
|
236
237
|
base_url=testql_raw.get("base_url", ""),
|
|
237
238
|
api_base_url=testql_raw.get("api_base_url", ""),
|
|
238
239
|
base_url_env=testql_raw.get("base_url_env", "WUP_BASE_URL"),
|
|
@@ -499,6 +500,7 @@ def save_config(config: WupConfig, output_path: Path):
|
|
|
499
500
|
"docker_service_map": config.testql.docker_service_map,
|
|
500
501
|
"service_map_profile": config.testql.service_map_profile,
|
|
501
502
|
"monitoring_reject_prefixes": config.testql.monitoring_reject_prefixes,
|
|
503
|
+
"service_name_prefixes": config.testql.service_name_prefixes,
|
|
502
504
|
"base_url": config.testql.base_url,
|
|
503
505
|
"api_base_url": config.testql.api_base_url,
|
|
504
506
|
"base_url_env": config.testql.base_url_env,
|
|
@@ -115,10 +115,22 @@ class WupWatcher:
|
|
|
115
115
|
except ValueError:
|
|
116
116
|
return file_path_obj
|
|
117
117
|
|
|
118
|
+
# Generic top-level directory prefixes that name a service on their own.
|
|
119
|
+
_GENERIC_SERVICE_PREFIXES = ("backend", "frontend", "api", "app", "worker", "service")
|
|
120
|
+
|
|
121
|
+
def _service_name_prefixes(self) -> List[str]:
|
|
122
|
+
"""Effective service-name prefixes: generic set + config + profile."""
|
|
123
|
+
prefixes = list(self._GENERIC_SERVICE_PREFIXES)
|
|
124
|
+
testql = getattr(self.config, "testql", None)
|
|
125
|
+
prefixes.extend(getattr(testql, "service_name_prefixes", None) or [])
|
|
126
|
+
if (getattr(testql, "service_map_profile", "") or "").lower() == "connect":
|
|
127
|
+
prefixes.append("connect")
|
|
128
|
+
return prefixes
|
|
129
|
+
|
|
118
130
|
def infer_service(self, file_path: str) -> Optional[str]:
|
|
119
131
|
"""
|
|
120
132
|
Infer service name from file path.
|
|
121
|
-
|
|
133
|
+
|
|
122
134
|
Uses config services first, then dependency mapper, then heuristics.
|
|
123
135
|
"""
|
|
124
136
|
rel_path = self._to_relative_path(file_path)
|
|
@@ -144,12 +156,15 @@ class WupWatcher:
|
|
|
144
156
|
if re.search(pattern, path_lower):
|
|
145
157
|
return svc.name
|
|
146
158
|
|
|
147
|
-
# Heuristic: if top-level directory
|
|
148
|
-
# use it directly
|
|
159
|
+
# Heuristic: if the top-level directory starts with a known service prefix
|
|
160
|
+
# (e.g. api-*, worker-*), use it directly — takes priority over stale
|
|
161
|
+
# deps.json. Prefixes are generic by default; projects add their own via
|
|
162
|
+
# testql.service_name_prefixes, and the "connect" profile adds connect-*.
|
|
149
163
|
if parts:
|
|
150
164
|
top = parts[0]
|
|
151
165
|
import re as _re
|
|
152
|
-
|
|
166
|
+
prefixes = "|".join(_re.escape(p) for p in self._service_name_prefixes())
|
|
167
|
+
if prefixes and _re.match(rf'^({prefixes})[-_]', top):
|
|
153
168
|
return top
|
|
154
169
|
|
|
155
170
|
# Use dependency mapper if available
|
|
@@ -79,6 +79,9 @@ class TestQLConfig:
|
|
|
79
79
|
# URL path prefixes that are NOT valid health probes (rejected in probe
|
|
80
80
|
# discovery). Empty = accept everything (generic). Overrides the profile.
|
|
81
81
|
monitoring_reject_prefixes: List[str] = field(default_factory=list)
|
|
82
|
+
# Extra top-level directory prefixes treated as a service name (added to the
|
|
83
|
+
# generic backend/frontend/api/app/worker/service set). Empty = generic only.
|
|
84
|
+
service_name_prefixes: List[str] = field(default_factory=list)
|
|
82
85
|
base_url: str = ""
|
|
83
86
|
api_base_url: str = "" # Core API (c2004: http://localhost:8101) — used for backend probes
|
|
84
87
|
base_url_env: str = "WUP_BASE_URL"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wup
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.76
|
|
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
|
|
@@ -42,17 +42,17 @@ Dynamic: license-file
|
|
|
42
42
|
|
|
43
43
|
## AI Cost Tracking
|
|
44
44
|
|
|
45
|
-
    
|
|
46
|
+
  
|
|
47
47
|
|
|
48
|
-
- 🤖 **LLM usage:** $6.
|
|
49
|
-
- 👤 **Human dev:** ~$
|
|
48
|
+
- 🤖 **LLM usage:** $6.7652 (105 commits)
|
|
49
|
+
- 👤 **Human dev:** ~$5295 (53.0h @ $100/h, 30min dedup)
|
|
50
50
|
|
|
51
51
|
Generated on 2026-07-17 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
52
52
|
|
|
53
53
|
---
|
|
54
54
|
|
|
55
|
-
    
|
|
56
56
|
|
|
57
57
|
**WUP (What's Up)** - Intelligent file watcher for regression testing in large projects.
|
|
58
58
|
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|