moose-lib 0.6.151__tar.gz → 0.6.153__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.151 → moose_lib-0.6.153}/PKG-INFO +1 -1
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/data_models.py +59 -4
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/dmv2/olap_table.py +2 -2
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib.egg-info/PKG-INFO +1 -1
- {moose_lib-0.6.151 → moose_lib-0.6.153}/README.md +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/__init__.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/blocks.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/clients/__init__.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/clients/redis_client.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/commons.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/config/__init__.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/config/config_file.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/config/runtime.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/dmv2/__init__.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/dmv2/_registry.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/dmv2/consumption.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/dmv2/ingest_api.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/dmv2/ingest_pipeline.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/dmv2/life_cycle.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/dmv2/materialized_view.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/dmv2/registry.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/dmv2/sql_resource.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/dmv2/stream.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/dmv2/types.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/dmv2/view.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/dmv2/web_app.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/dmv2/web_app_helpers.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/dmv2/workflow.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/dmv2_serializer.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/internal.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/main.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/query_builder.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/query_param.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/streaming/__init__.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/streaming/streaming_function_runner.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/utilities/__init__.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib/utilities/sql.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib.egg-info/SOURCES.txt +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib.egg-info/dependency_links.txt +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib.egg-info/requires.txt +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/moose_lib.egg-info/top_level.txt +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/setup.cfg +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/setup.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/tests/__init__.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/tests/conftest.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/tests/test_moose.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/tests/test_olap_table_versioning.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/tests/test_query_builder.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/tests/test_redis_client.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/tests/test_s3queue_config.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/tests/test_simple_aggregate.py +0 -0
- {moose_lib-0.6.151 → moose_lib-0.6.153}/tests/test_web_app.py +0 -0
|
@@ -40,6 +40,14 @@ class ClickHouseTTL:
|
|
|
40
40
|
expression: str
|
|
41
41
|
|
|
42
42
|
|
|
43
|
+
@dataclasses.dataclass(frozen=True)
|
|
44
|
+
class ClickHouseJson:
|
|
45
|
+
max_dynamic_paths: int | None = None
|
|
46
|
+
max_dynamic_types: int | None = None
|
|
47
|
+
skip_paths: tuple[str, ...] = ()
|
|
48
|
+
skip_regexps: tuple[str, ...] = ()
|
|
49
|
+
|
|
50
|
+
|
|
43
51
|
def clickhouse_decimal(precision: int, scale: int) -> Type[Decimal]:
|
|
44
52
|
return Annotated[Decimal, Field(max_digits=precision, decimal_places=scale)]
|
|
45
53
|
|
|
@@ -160,7 +168,15 @@ class MapType(BaseModel):
|
|
|
160
168
|
value_type: "DataType"
|
|
161
169
|
|
|
162
170
|
|
|
163
|
-
|
|
171
|
+
class JsonOptions(BaseModel):
|
|
172
|
+
max_dynamic_paths: int | None = None
|
|
173
|
+
max_dynamic_types: int | None = None
|
|
174
|
+
typed_paths: list[tuple[str, "DataType"]] = []
|
|
175
|
+
skip_paths: list[str] = []
|
|
176
|
+
skip_regexps: list[str] = []
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
type DataType = str | DataEnum | ArrayType | Nested | NamedTupleType | MapType | JsonOptions
|
|
164
180
|
|
|
165
181
|
|
|
166
182
|
def handle_jwt(field_type: type) -> Tuple[bool, type]:
|
|
@@ -244,8 +260,8 @@ def _validate_geometry_type(requested: str, t: type) -> None:
|
|
|
244
260
|
)
|
|
245
261
|
case "MultiPolygon":
|
|
246
262
|
if not _is_list_of(
|
|
247
|
-
|
|
248
|
-
|
|
263
|
+
lambda x: _is_list_of(lambda y: _is_list_of(_is_point_type, y), x),
|
|
264
|
+
t,
|
|
249
265
|
):
|
|
250
266
|
raise ValueError(
|
|
251
267
|
"MultiPolygon must be typed as list[list[list[tuple[float, float]]]]"
|
|
@@ -314,7 +330,7 @@ def py_type_to_column_type(t: type, mds: list[Any]) -> Tuple[bool, list[Any], Da
|
|
|
314
330
|
data_type = "IPv4"
|
|
315
331
|
elif t is ipaddress.IPv6Address:
|
|
316
332
|
data_type = "IPv6"
|
|
317
|
-
elif any(md in [
|
|
333
|
+
elif any(md in [ # this check has to happen before t is matched against tuple/list
|
|
318
334
|
"Point",
|
|
319
335
|
"Ring",
|
|
320
336
|
"LineString",
|
|
@@ -347,6 +363,45 @@ def py_type_to_column_type(t: type, mds: list[Any]) -> Tuple[bool, list[Any], Da
|
|
|
347
363
|
data_type = "UUID"
|
|
348
364
|
elif t is Any:
|
|
349
365
|
data_type = "Json"
|
|
366
|
+
elif any(isinstance(md, ClickHouseJson) for md in mds) and issubclass(t, BaseModel):
|
|
367
|
+
# Annotated[SomePydanticClass, ClickHouseJson(...)]
|
|
368
|
+
columns = _to_columns(t)
|
|
369
|
+
for c in columns:
|
|
370
|
+
if c.default is not None:
|
|
371
|
+
raise ValueError(
|
|
372
|
+
"Default in inner field. Put ClickHouseDefault in top level field."
|
|
373
|
+
)
|
|
374
|
+
# Enforce extra='allow' for JSON-mapped models
|
|
375
|
+
if t.model_config.get('extra') != 'allow':
|
|
376
|
+
raise ValueError(
|
|
377
|
+
f"Model {t.__name__} with ClickHouseJson must have model_config with extra='allow'. "
|
|
378
|
+
"Add: model_config = ConfigDict(extra='allow')"
|
|
379
|
+
)
|
|
380
|
+
opts = next(md for md in mds if isinstance(md, ClickHouseJson))
|
|
381
|
+
|
|
382
|
+
# Build typed_paths from fields as tuples of (name, type)
|
|
383
|
+
typed_paths: list[tuple[str, DataType]] = []
|
|
384
|
+
for c in columns:
|
|
385
|
+
typed_paths.append((c.name, c.data_type))
|
|
386
|
+
|
|
387
|
+
has_any_option = (
|
|
388
|
+
opts.max_dynamic_paths is not None or
|
|
389
|
+
opts.max_dynamic_types is not None or
|
|
390
|
+
len(typed_paths) > 0 or
|
|
391
|
+
len(opts.skip_paths) > 0 or
|
|
392
|
+
len(opts.skip_regexps) > 0
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
if not has_any_option:
|
|
396
|
+
data_type = "Json"
|
|
397
|
+
else:
|
|
398
|
+
data_type = JsonOptions(
|
|
399
|
+
max_dynamic_paths=opts.max_dynamic_paths,
|
|
400
|
+
max_dynamic_types=opts.max_dynamic_types,
|
|
401
|
+
typed_paths=typed_paths,
|
|
402
|
+
skip_paths=list(opts.skip_paths),
|
|
403
|
+
skip_regexps=list(opts.skip_regexps),
|
|
404
|
+
)
|
|
350
405
|
elif get_origin(t) is Literal and all(isinstance(arg, str) for arg in get_args(t)):
|
|
351
406
|
data_type = "String"
|
|
352
407
|
mds.append("LowCardinality")
|
|
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
|