moose-lib 0.6.137__tar.gz → 0.6.138__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.
- {moose_lib-0.6.137 → moose_lib-0.6.138}/PKG-INFO +1 -1
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/dmv2/web_app.py +24 -12
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib.egg-info/PKG-INFO +1 -1
- {moose_lib-0.6.137 → moose_lib-0.6.138}/tests/test_web_app.py +19 -19
- {moose_lib-0.6.137 → moose_lib-0.6.138}/README.md +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/__init__.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/blocks.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/clients/__init__.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/clients/redis_client.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/commons.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/config/__init__.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/config/config_file.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/config/runtime.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/data_models.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/dmv2/__init__.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/dmv2/_registry.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/dmv2/consumption.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/dmv2/ingest_api.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/dmv2/ingest_pipeline.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/dmv2/life_cycle.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/dmv2/materialized_view.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/dmv2/olap_table.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/dmv2/registry.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/dmv2/sql_resource.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/dmv2/stream.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/dmv2/types.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/dmv2/view.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/dmv2/web_app_helpers.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/dmv2/workflow.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/dmv2_serializer.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/internal.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/main.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/query_builder.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/query_param.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/streaming/__init__.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/streaming/streaming_function_runner.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/utilities/__init__.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib/utilities/sql.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib.egg-info/SOURCES.txt +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib.egg-info/dependency_links.txt +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib.egg-info/requires.txt +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/moose_lib.egg-info/top_level.txt +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/setup.cfg +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/setup.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/tests/__init__.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/tests/conftest.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/tests/test_moose.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/tests/test_olap_table_versioning.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/tests/test_query_builder.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/tests/test_redis_client.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/tests/test_s3queue_config.py +0 -0
- {moose_lib-0.6.137 → moose_lib-0.6.138}/tests/test_simple_aggregate.py +0 -0
|
@@ -37,15 +37,15 @@ class WebAppConfig:
|
|
|
37
37
|
"""Configuration for a WebApp.
|
|
38
38
|
|
|
39
39
|
Attributes:
|
|
40
|
-
mount_path: The URL path where the WebApp will be mounted.
|
|
41
|
-
|
|
42
|
-
Cannot end with "/" (
|
|
40
|
+
mount_path: The URL path where the WebApp will be mounted (required).
|
|
41
|
+
Cannot be "/" (root path).
|
|
42
|
+
Cannot end with "/" (trailing slash).
|
|
43
43
|
Cannot start with reserved paths.
|
|
44
44
|
metadata: Optional metadata for documentation purposes.
|
|
45
45
|
inject_moose_utils: Whether to inject MooseClient utilities into requests.
|
|
46
46
|
Defaults to True.
|
|
47
47
|
"""
|
|
48
|
-
mount_path:
|
|
48
|
+
mount_path: str
|
|
49
49
|
metadata: Optional[WebAppMetadata] = None
|
|
50
50
|
inject_moose_utils: bool = True
|
|
51
51
|
|
|
@@ -85,7 +85,7 @@ class WebApp:
|
|
|
85
85
|
Args:
|
|
86
86
|
name: Unique name for this WebApp.
|
|
87
87
|
app: The FastAPI application instance.
|
|
88
|
-
config:
|
|
88
|
+
config: Configuration for the WebApp (required, must include mount_path).
|
|
89
89
|
|
|
90
90
|
Raises:
|
|
91
91
|
ValueError: If validation fails (duplicate name, invalid mount path, etc.)
|
|
@@ -95,11 +95,11 @@ class WebApp:
|
|
|
95
95
|
self,
|
|
96
96
|
name: str,
|
|
97
97
|
app: Any, # FastAPI app, typed as Any to avoid import dependency
|
|
98
|
-
config:
|
|
98
|
+
config: WebAppConfig,
|
|
99
99
|
):
|
|
100
100
|
self.name = name
|
|
101
101
|
self.app = app
|
|
102
|
-
self.config = config
|
|
102
|
+
self.config = config
|
|
103
103
|
|
|
104
104
|
# Import the registry here to avoid circular dependency
|
|
105
105
|
from ._registry import _web_apps
|
|
@@ -126,10 +126,23 @@ class WebApp:
|
|
|
126
126
|
if name in existing_web_apps:
|
|
127
127
|
raise ValueError(f"WebApp with name '{name}' already exists")
|
|
128
128
|
|
|
129
|
-
|
|
129
|
+
# Validate mountPath - it is required
|
|
130
|
+
if not config.mount_path:
|
|
131
|
+
raise ValueError(
|
|
132
|
+
f"mountPath is required. Please specify a mount path for your WebApp (e.g., \"/myapi\")."
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
mount_path = config.mount_path
|
|
136
|
+
|
|
137
|
+
# Check for root path - not allowed as it would overlap reserved paths
|
|
138
|
+
if mount_path == "/":
|
|
139
|
+
raise ValueError(
|
|
140
|
+
f"mountPath cannot be \"/\" as it would allow routes to overlap with reserved paths: "
|
|
141
|
+
f"{', '.join(RESERVED_MOUNT_PATHS)}"
|
|
142
|
+
)
|
|
130
143
|
|
|
131
144
|
# Validate mount path format
|
|
132
|
-
if mount_path
|
|
145
|
+
if mount_path.endswith("/"):
|
|
133
146
|
raise ValueError(
|
|
134
147
|
f"mountPath cannot end with a trailing slash. "
|
|
135
148
|
f"Remove the '/' from: \"{mount_path}\""
|
|
@@ -146,7 +159,7 @@ class WebApp:
|
|
|
146
159
|
|
|
147
160
|
# Check for duplicate mount path
|
|
148
161
|
for existing_name, existing_app in existing_web_apps.items():
|
|
149
|
-
existing_mount = existing_app.config.mount_path
|
|
162
|
+
existing_mount = existing_app.config.mount_path
|
|
150
163
|
if existing_mount == mount_path:
|
|
151
164
|
raise ValueError(
|
|
152
165
|
f"WebApp with mountPath \"{mount_path}\" already exists "
|
|
@@ -154,5 +167,4 @@ class WebApp:
|
|
|
154
167
|
)
|
|
155
168
|
|
|
156
169
|
def __repr__(self) -> str:
|
|
157
|
-
|
|
158
|
-
return f"WebApp(name='{self.name}', mount_path='{mount}')"
|
|
170
|
+
return f"WebApp(name='{self.name}', mount_path='{self.config.mount_path}')"
|
|
@@ -21,13 +21,14 @@ def clear_registry():
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
def test_webapp_basic_creation():
|
|
24
|
-
"""Test basic WebApp creation with
|
|
24
|
+
"""Test basic WebApp creation with required mount_path."""
|
|
25
25
|
app = MockFastAPIApp()
|
|
26
|
-
|
|
26
|
+
config = WebAppConfig(mount_path="/test")
|
|
27
|
+
webapp = WebApp("test_app", app, config)
|
|
27
28
|
|
|
28
29
|
assert webapp.name == "test_app"
|
|
29
30
|
assert webapp.app is app
|
|
30
|
-
assert webapp.config.mount_path
|
|
31
|
+
assert webapp.config.mount_path == "/test"
|
|
31
32
|
assert webapp.config.inject_moose_utils is True
|
|
32
33
|
assert "test_app" in _web_apps
|
|
33
34
|
|
|
@@ -63,10 +64,10 @@ def test_webapp_duplicate_name():
|
|
|
63
64
|
app1 = MockFastAPIApp()
|
|
64
65
|
app2 = MockFastAPIApp()
|
|
65
66
|
|
|
66
|
-
WebApp("test_app", app1)
|
|
67
|
+
WebApp("test_app", app1, WebAppConfig(mount_path="/test1"))
|
|
67
68
|
|
|
68
69
|
with pytest.raises(ValueError, match="WebApp with name 'test_app' already exists"):
|
|
69
|
-
WebApp("test_app", app2)
|
|
70
|
+
WebApp("test_app", app2, WebAppConfig(mount_path="/test2"))
|
|
70
71
|
|
|
71
72
|
|
|
72
73
|
def test_webapp_trailing_slash_validation():
|
|
@@ -78,13 +79,13 @@ def test_webapp_trailing_slash_validation():
|
|
|
78
79
|
WebApp("test_app", app, config)
|
|
79
80
|
|
|
80
81
|
|
|
81
|
-
def
|
|
82
|
-
"""Test that root path '/' is
|
|
82
|
+
def test_webapp_root_path_rejected():
|
|
83
|
+
"""Test that root path '/' is rejected to prevent overlap with reserved paths."""
|
|
83
84
|
app = MockFastAPIApp()
|
|
84
85
|
config = WebAppConfig(mount_path="/")
|
|
85
|
-
webapp = WebApp("test_app", app, config)
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
with pytest.raises(ValueError, match='mountPath cannot be "/" as it would allow routes to overlap with reserved paths'):
|
|
88
|
+
WebApp("test_app", app, config)
|
|
88
89
|
|
|
89
90
|
|
|
90
91
|
def test_webapp_reserved_paths():
|
|
@@ -144,7 +145,7 @@ def test_webapp_different_mount_paths():
|
|
|
144
145
|
def test_webapp_inject_moose_utils_false():
|
|
145
146
|
"""Test WebApp with inject_moose_utils disabled."""
|
|
146
147
|
app = MockFastAPIApp()
|
|
147
|
-
config = WebAppConfig(inject_moose_utils=False)
|
|
148
|
+
config = WebAppConfig(mount_path="/test", inject_moose_utils=False)
|
|
148
149
|
webapp = WebApp("test_app", app, config)
|
|
149
150
|
|
|
150
151
|
assert webapp.config.inject_moose_utils is False
|
|
@@ -159,13 +160,12 @@ def test_webapp_repr():
|
|
|
159
160
|
assert "/myapi" in repr(webapp)
|
|
160
161
|
|
|
161
162
|
|
|
162
|
-
def
|
|
163
|
-
"""Test
|
|
163
|
+
def test_webapp_mount_path_required():
|
|
164
|
+
"""Test that mount_path is required."""
|
|
164
165
|
app = MockFastAPIApp()
|
|
165
|
-
webapp = WebApp("test_app", app)
|
|
166
166
|
|
|
167
|
-
|
|
168
|
-
|
|
167
|
+
with pytest.raises(ValueError, match="mountPath is required"):
|
|
168
|
+
WebApp("test_app", app, WebAppConfig(mount_path=""))
|
|
169
169
|
|
|
170
170
|
|
|
171
171
|
def test_webapp_serialization():
|
|
@@ -197,16 +197,16 @@ def test_webapp_serialization():
|
|
|
197
197
|
assert infra_map["webApps"]["test_app"]["metadata"]["description"] == "Test API"
|
|
198
198
|
|
|
199
199
|
|
|
200
|
-
def
|
|
201
|
-
"""Test WebApp serialization with
|
|
200
|
+
def test_webapp_serialization_with_mount_path():
|
|
201
|
+
"""Test WebApp serialization with explicit mount path."""
|
|
202
202
|
from moose_lib.internal import to_infra_map
|
|
203
203
|
|
|
204
204
|
app = MockFastAPIApp()
|
|
205
|
-
WebApp("test_app", app)
|
|
205
|
+
WebApp("test_app", app, WebAppConfig(mount_path="/testpath"))
|
|
206
206
|
|
|
207
207
|
infra_map = to_infra_map()
|
|
208
208
|
|
|
209
|
-
assert infra_map["webApps"]["test_app"]["mountPath"] == "/"
|
|
209
|
+
assert infra_map["webApps"]["test_app"]["mountPath"] == "/testpath"
|
|
210
210
|
|
|
211
211
|
|
|
212
212
|
def test_webapp_serialization_no_metadata():
|
|
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
|