moose-lib 0.6.174__tar.gz → 0.6.176__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.
Potentially problematic release.
This version of moose-lib might be problematic. Click here for more details.
- {moose_lib-0.6.174 → moose_lib-0.6.176}/PKG-INFO +1 -1
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/__init__.py +19 -1
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/data_models.py +14 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib.egg-info/PKG-INFO +1 -1
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib.egg-info/SOURCES.txt +1 -0
- moose_lib-0.6.176/tests/test_int_types.py +204 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/README.md +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/blocks.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/clients/__init__.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/clients/redis_client.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/commons.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/config/__init__.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/config/config_file.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/config/runtime.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/dmv2/__init__.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/dmv2/_registry.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/dmv2/consumption.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/dmv2/ingest_api.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/dmv2/ingest_pipeline.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/dmv2/life_cycle.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/dmv2/materialized_view.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/dmv2/olap_table.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/dmv2/registry.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/dmv2/sql_resource.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/dmv2/stream.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/dmv2/types.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/dmv2/view.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/dmv2/web_app.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/dmv2/web_app_helpers.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/dmv2/workflow.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/dmv2_serializer.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/internal.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/main.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/query_builder.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/query_param.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/secrets.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/streaming/__init__.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/streaming/streaming_function_runner.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/utilities/__init__.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib/utilities/sql.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib.egg-info/dependency_links.txt +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib.egg-info/requires.txt +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/moose_lib.egg-info/top_level.txt +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/setup.cfg +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/setup.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/tests/__init__.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/tests/conftest.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/tests/test_fixedstring.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/tests/test_moose.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/tests/test_olap_table_versioning.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/tests/test_query_builder.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/tests/test_redis_client.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/tests/test_s3queue_config.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/tests/test_secrets.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/tests/test_simple_aggregate.py +0 -0
- {moose_lib-0.6.174 → moose_lib-0.6.176}/tests/test_web_app.py +0 -0
|
@@ -30,7 +30,25 @@ from .blocks import (
|
|
|
30
30
|
# Legacy enum (already exported via .blocks import, but explicit for clarity)
|
|
31
31
|
ClickHouseEngines
|
|
32
32
|
)
|
|
33
|
-
from .data_models import
|
|
33
|
+
from .data_models import (
|
|
34
|
+
Key,
|
|
35
|
+
AggregateFunction,
|
|
36
|
+
StringToEnumMixin,
|
|
37
|
+
FixedString,
|
|
38
|
+
ClickhouseFixedStringSize,
|
|
39
|
+
# Integer types
|
|
40
|
+
Int8,
|
|
41
|
+
Int16,
|
|
42
|
+
Int32,
|
|
43
|
+
Int64,
|
|
44
|
+
UInt8,
|
|
45
|
+
UInt16,
|
|
46
|
+
UInt32,
|
|
47
|
+
UInt64,
|
|
48
|
+
# Float types
|
|
49
|
+
Float32,
|
|
50
|
+
Float64,
|
|
51
|
+
)
|
|
34
52
|
from .commons import Logger
|
|
35
53
|
|
|
36
54
|
from .query_builder import *
|
|
@@ -15,6 +15,20 @@ import ipaddress
|
|
|
15
15
|
type Key[T: (str, int)] = T
|
|
16
16
|
type JWT[T] = T
|
|
17
17
|
|
|
18
|
+
# Integer type aliases for ClickHouse integer types
|
|
19
|
+
type Int8 = Annotated[int, "int8"]
|
|
20
|
+
type Int16 = Annotated[int, "int16"]
|
|
21
|
+
type Int32 = Annotated[int, "int32"]
|
|
22
|
+
type Int64 = Annotated[int, "int64"]
|
|
23
|
+
type UInt8 = Annotated[int, "uint8"]
|
|
24
|
+
type UInt16 = Annotated[int, "uint16"]
|
|
25
|
+
type UInt32 = Annotated[int, "uint32"]
|
|
26
|
+
type UInt64 = Annotated[int, "uint64"]
|
|
27
|
+
|
|
28
|
+
# Float type aliases for ClickHouse float types
|
|
29
|
+
type Float32 = Annotated[float, "float32"]
|
|
30
|
+
type Float64 = Annotated[float, "float64"]
|
|
31
|
+
|
|
18
32
|
|
|
19
33
|
@dataclasses.dataclass(frozen=True) # a BaseModel in the annotations will confuse pydantic
|
|
20
34
|
class ClickhousePrecision:
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Annotated
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
from moose_lib import (
|
|
5
|
+
Key,
|
|
6
|
+
Int8, Int16, Int32, Int64,
|
|
7
|
+
UInt8, UInt16, UInt32, UInt64,
|
|
8
|
+
Float32, Float64,
|
|
9
|
+
)
|
|
10
|
+
from moose_lib.data_models import _to_columns
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_integer_type_aliases():
|
|
14
|
+
"""Test that integer type aliases convert to correct ClickHouse types."""
|
|
15
|
+
|
|
16
|
+
class IntegerTypesTest(BaseModel):
|
|
17
|
+
id: Key[str]
|
|
18
|
+
created_at: datetime
|
|
19
|
+
tiny_int: Int8
|
|
20
|
+
small_int: Int16
|
|
21
|
+
medium_int: Int32
|
|
22
|
+
big_int: Int64
|
|
23
|
+
tiny_uint: UInt8
|
|
24
|
+
small_uint: UInt16
|
|
25
|
+
medium_uint: UInt32
|
|
26
|
+
big_uint: UInt64
|
|
27
|
+
|
|
28
|
+
columns = _to_columns(IntegerTypesTest)
|
|
29
|
+
by_name = {col.name: col for col in columns}
|
|
30
|
+
|
|
31
|
+
# Verify signed integer types
|
|
32
|
+
assert by_name["tiny_int"].data_type == "Int8"
|
|
33
|
+
assert by_name["small_int"].data_type == "Int16"
|
|
34
|
+
assert by_name["medium_int"].data_type == "Int32"
|
|
35
|
+
assert by_name["big_int"].data_type == "Int64"
|
|
36
|
+
|
|
37
|
+
# Verify unsigned integer types
|
|
38
|
+
assert by_name["tiny_uint"].data_type == "UInt8"
|
|
39
|
+
assert by_name["small_uint"].data_type == "UInt16"
|
|
40
|
+
assert by_name["medium_uint"].data_type == "UInt32"
|
|
41
|
+
assert by_name["big_uint"].data_type == "UInt64"
|
|
42
|
+
|
|
43
|
+
# Verify other fields still work
|
|
44
|
+
assert by_name["id"].data_type == "String"
|
|
45
|
+
assert by_name["created_at"].data_type == "DateTime"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_float_type_aliases():
|
|
49
|
+
"""Test that float type aliases convert to correct ClickHouse types."""
|
|
50
|
+
|
|
51
|
+
class FloatTypesTest(BaseModel):
|
|
52
|
+
id: Key[str]
|
|
53
|
+
precision_float: Float32
|
|
54
|
+
double_precision_float: Float64
|
|
55
|
+
|
|
56
|
+
columns = _to_columns(FloatTypesTest)
|
|
57
|
+
by_name = {col.name: col for col in columns}
|
|
58
|
+
|
|
59
|
+
assert by_name["precision_float"].data_type == "Float32"
|
|
60
|
+
assert by_name["double_precision_float"].data_type == "Float64"
|
|
61
|
+
assert by_name["id"].data_type == "String"
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def test_combined_numeric_types():
|
|
65
|
+
"""Test combining integer and float types in a single model."""
|
|
66
|
+
|
|
67
|
+
class NumericTypesTest(BaseModel):
|
|
68
|
+
user_id: UInt64
|
|
69
|
+
age: UInt8
|
|
70
|
+
score: Int32
|
|
71
|
+
latitude: Float64
|
|
72
|
+
longitude: Float64
|
|
73
|
+
precision_value: Float32
|
|
74
|
+
|
|
75
|
+
columns = _to_columns(NumericTypesTest)
|
|
76
|
+
by_name = {col.name: col for col in columns}
|
|
77
|
+
|
|
78
|
+
assert by_name["user_id"].data_type == "UInt64"
|
|
79
|
+
assert by_name["age"].data_type == "UInt8"
|
|
80
|
+
assert by_name["score"].data_type == "Int32"
|
|
81
|
+
assert by_name["latitude"].data_type == "Float64"
|
|
82
|
+
assert by_name["longitude"].data_type == "Float64"
|
|
83
|
+
assert by_name["precision_value"].data_type == "Float32"
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def test_integer_types_as_keys():
|
|
87
|
+
"""Test that integer types can be used as primary keys."""
|
|
88
|
+
|
|
89
|
+
class IntegerKeyTest(BaseModel):
|
|
90
|
+
user_id: Key[UInt64]
|
|
91
|
+
event_id: Key[Int64]
|
|
92
|
+
name: str
|
|
93
|
+
|
|
94
|
+
columns = _to_columns(IntegerKeyTest)
|
|
95
|
+
by_name = {col.name: col for col in columns}
|
|
96
|
+
|
|
97
|
+
assert by_name["user_id"].data_type == "UInt64"
|
|
98
|
+
assert by_name["user_id"].primary_key is True
|
|
99
|
+
assert by_name["event_id"].data_type == "Int64"
|
|
100
|
+
assert by_name["event_id"].primary_key is True
|
|
101
|
+
assert by_name["name"].data_type == "String"
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def test_optional_integer_types():
|
|
105
|
+
"""Test that optional integer types work correctly."""
|
|
106
|
+
from typing import Optional
|
|
107
|
+
|
|
108
|
+
class OptionalIntTest(BaseModel):
|
|
109
|
+
required_count: UInt32
|
|
110
|
+
optional_count: Optional[UInt32]
|
|
111
|
+
optional_score: Optional[Int16]
|
|
112
|
+
|
|
113
|
+
columns = _to_columns(OptionalIntTest)
|
|
114
|
+
by_name = {col.name: col for col in columns}
|
|
115
|
+
|
|
116
|
+
assert by_name["required_count"].data_type == "UInt32"
|
|
117
|
+
assert by_name["required_count"].required is True
|
|
118
|
+
|
|
119
|
+
assert by_name["optional_count"].data_type == "UInt32"
|
|
120
|
+
assert by_name["optional_count"].required is False
|
|
121
|
+
|
|
122
|
+
assert by_name["optional_score"].data_type == "Int16"
|
|
123
|
+
assert by_name["optional_score"].required is False
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def test_uint_common_use_cases():
|
|
127
|
+
"""Test common use cases for unsigned integers."""
|
|
128
|
+
|
|
129
|
+
class CommonUIntUseCases(BaseModel):
|
|
130
|
+
# User/entity IDs (always positive)
|
|
131
|
+
user_id: UInt64
|
|
132
|
+
# Counters (always positive or zero)
|
|
133
|
+
page_views: UInt32
|
|
134
|
+
click_count: UInt32
|
|
135
|
+
# Small enums/flags (0-255)
|
|
136
|
+
status_code: UInt8
|
|
137
|
+
# Port numbers (0-65535)
|
|
138
|
+
port: UInt16
|
|
139
|
+
# Timestamps as unix epoch
|
|
140
|
+
timestamp: UInt64
|
|
141
|
+
|
|
142
|
+
columns = _to_columns(CommonUIntUseCases)
|
|
143
|
+
by_name = {col.name: col for col in columns}
|
|
144
|
+
|
|
145
|
+
assert by_name["user_id"].data_type == "UInt64"
|
|
146
|
+
assert by_name["page_views"].data_type == "UInt32"
|
|
147
|
+
assert by_name["click_count"].data_type == "UInt32"
|
|
148
|
+
assert by_name["status_code"].data_type == "UInt8"
|
|
149
|
+
assert by_name["port"].data_type == "UInt16"
|
|
150
|
+
assert by_name["timestamp"].data_type == "UInt64"
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def test_int_common_use_cases():
|
|
154
|
+
"""Test common use cases for signed integers."""
|
|
155
|
+
|
|
156
|
+
class CommonIntUseCases(BaseModel):
|
|
157
|
+
# Temperature (can be negative)
|
|
158
|
+
temperature: Int16
|
|
159
|
+
# Financial amounts (can be negative for debits)
|
|
160
|
+
balance: Int64
|
|
161
|
+
# Deltas/differences
|
|
162
|
+
delta: Int32
|
|
163
|
+
# Small range values
|
|
164
|
+
offset: Int8
|
|
165
|
+
|
|
166
|
+
columns = _to_columns(CommonIntUseCases)
|
|
167
|
+
by_name = {col.name: col for col in columns}
|
|
168
|
+
|
|
169
|
+
assert by_name["temperature"].data_type == "Int16"
|
|
170
|
+
assert by_name["balance"].data_type == "Int64"
|
|
171
|
+
assert by_name["delta"].data_type == "Int32"
|
|
172
|
+
assert by_name["offset"].data_type == "Int8"
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def test_default_int_still_works():
|
|
176
|
+
"""Test that plain int without type annotation still works as before."""
|
|
177
|
+
|
|
178
|
+
class PlainIntTest(BaseModel):
|
|
179
|
+
plain_int: int
|
|
180
|
+
typed_int: UInt32
|
|
181
|
+
|
|
182
|
+
columns = _to_columns(PlainIntTest)
|
|
183
|
+
by_name = {col.name: col for col in columns}
|
|
184
|
+
|
|
185
|
+
# Plain int should still map to "Int" (default behavior)
|
|
186
|
+
assert by_name["plain_int"].data_type == "Int"
|
|
187
|
+
# Typed int should map to specific type
|
|
188
|
+
assert by_name["typed_int"].data_type == "UInt32"
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def test_default_float_still_works():
|
|
192
|
+
"""Test that plain float without type annotation still works as before."""
|
|
193
|
+
|
|
194
|
+
class PlainFloatTest(BaseModel):
|
|
195
|
+
plain_float: float
|
|
196
|
+
typed_float: Float32
|
|
197
|
+
|
|
198
|
+
columns = _to_columns(PlainFloatTest)
|
|
199
|
+
by_name = {col.name: col for col in columns}
|
|
200
|
+
|
|
201
|
+
# Plain float should still map to "Float64" (default behavior)
|
|
202
|
+
assert by_name["plain_float"].data_type == "Float64"
|
|
203
|
+
# Typed float should map to specific type
|
|
204
|
+
assert by_name["typed_float"].data_type == "Float32"
|
|
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
|