moose-lib 0.6.172__tar.gz → 0.6.173__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.

Files changed (55) hide show
  1. {moose_lib-0.6.172 → moose_lib-0.6.173}/PKG-INFO +1 -1
  2. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/__init__.py +1 -1
  3. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/data_models.py +48 -3
  4. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib.egg-info/PKG-INFO +1 -1
  5. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib.egg-info/SOURCES.txt +1 -0
  6. moose_lib-0.6.173/tests/test_fixedstring.py +43 -0
  7. {moose_lib-0.6.172 → moose_lib-0.6.173}/README.md +0 -0
  8. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/blocks.py +0 -0
  9. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/clients/__init__.py +0 -0
  10. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/clients/redis_client.py +0 -0
  11. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/commons.py +0 -0
  12. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/config/__init__.py +0 -0
  13. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/config/config_file.py +0 -0
  14. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/config/runtime.py +0 -0
  15. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/dmv2/__init__.py +0 -0
  16. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/dmv2/_registry.py +0 -0
  17. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/dmv2/consumption.py +0 -0
  18. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/dmv2/ingest_api.py +0 -0
  19. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/dmv2/ingest_pipeline.py +0 -0
  20. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/dmv2/life_cycle.py +0 -0
  21. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/dmv2/materialized_view.py +0 -0
  22. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/dmv2/olap_table.py +0 -0
  23. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/dmv2/registry.py +0 -0
  24. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/dmv2/sql_resource.py +0 -0
  25. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/dmv2/stream.py +0 -0
  26. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/dmv2/types.py +0 -0
  27. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/dmv2/view.py +0 -0
  28. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/dmv2/web_app.py +0 -0
  29. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/dmv2/web_app_helpers.py +0 -0
  30. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/dmv2/workflow.py +0 -0
  31. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/dmv2_serializer.py +0 -0
  32. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/internal.py +0 -0
  33. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/main.py +0 -0
  34. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/query_builder.py +0 -0
  35. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/query_param.py +0 -0
  36. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/secrets.py +0 -0
  37. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/streaming/__init__.py +0 -0
  38. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/streaming/streaming_function_runner.py +0 -0
  39. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/utilities/__init__.py +0 -0
  40. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib/utilities/sql.py +0 -0
  41. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib.egg-info/dependency_links.txt +0 -0
  42. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib.egg-info/requires.txt +0 -0
  43. {moose_lib-0.6.172 → moose_lib-0.6.173}/moose_lib.egg-info/top_level.txt +0 -0
  44. {moose_lib-0.6.172 → moose_lib-0.6.173}/setup.cfg +0 -0
  45. {moose_lib-0.6.172 → moose_lib-0.6.173}/setup.py +0 -0
  46. {moose_lib-0.6.172 → moose_lib-0.6.173}/tests/__init__.py +0 -0
  47. {moose_lib-0.6.172 → moose_lib-0.6.173}/tests/conftest.py +0 -0
  48. {moose_lib-0.6.172 → moose_lib-0.6.173}/tests/test_moose.py +0 -0
  49. {moose_lib-0.6.172 → moose_lib-0.6.173}/tests/test_olap_table_versioning.py +0 -0
  50. {moose_lib-0.6.172 → moose_lib-0.6.173}/tests/test_query_builder.py +0 -0
  51. {moose_lib-0.6.172 → moose_lib-0.6.173}/tests/test_redis_client.py +0 -0
  52. {moose_lib-0.6.172 → moose_lib-0.6.173}/tests/test_s3queue_config.py +0 -0
  53. {moose_lib-0.6.172 → moose_lib-0.6.173}/tests/test_secrets.py +0 -0
  54. {moose_lib-0.6.172 → moose_lib-0.6.173}/tests/test_simple_aggregate.py +0 -0
  55. {moose_lib-0.6.172 → moose_lib-0.6.173}/tests/test_web_app.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: moose_lib
3
- Version: 0.6.172
3
+ Version: 0.6.173
4
4
  Home-page: https://www.fiveonefour.com/moose
5
5
  Author: Fiveonefour Labs Inc.
6
6
  Author-email: support@fiveonefour.com
@@ -30,7 +30,7 @@ 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 Key, AggregateFunction, StringToEnumMixin
33
+ from .data_models import Key, AggregateFunction, StringToEnumMixin, FixedString, ClickhouseFixedStringSize
34
34
  from .commons import Logger
35
35
 
36
36
  from .query_builder import *
@@ -26,6 +26,11 @@ class ClickhouseSize:
26
26
  size: int
27
27
 
28
28
 
29
+ @dataclasses.dataclass(frozen=True)
30
+ class ClickhouseFixedStringSize:
31
+ size: int
32
+
33
+
29
34
  @dataclasses.dataclass(frozen=True)
30
35
  class ClickhouseDefault:
31
36
  expression: str
@@ -61,6 +66,23 @@ def clickhouse_datetime64(precision: int) -> Type[datetime]:
61
66
  return Annotated[datetime, ClickhousePrecision(precision=precision)]
62
67
 
63
68
 
69
+ def FixedString(size: int) -> ClickhouseFixedStringSize:
70
+ """
71
+ Creates a FixedString(N) annotation for fixed-length strings.
72
+
73
+ ClickHouse stores exactly N bytes, padding shorter values with null bytes.
74
+ Values exceeding N bytes will raise an exception.
75
+
76
+ Use for fixed-length data like hashes, IPs, UUIDs, MAC addresses.
77
+
78
+ Example:
79
+ md5_hash: Annotated[str, FixedString(16)] # 16-byte MD5
80
+ sha256: Annotated[str, FixedString(32)] # 32-byte SHA256
81
+ ipv6: Annotated[str, FixedString(16)] # 16-byte IPv6
82
+ """
83
+ return ClickhouseFixedStringSize(size=size)
84
+
85
+
64
86
  type Point = Annotated[tuple[float, float], "Point"]
65
87
  type Ring = Annotated[list[tuple[float, float]], "Ring"]
66
88
  type LineString = Annotated[list[tuple[float, float]], "LineString"]
@@ -279,7 +301,26 @@ def py_type_to_column_type(t: type, mds: list[Any]) -> Tuple[bool, list[Any], Da
279
301
  data_type: DataType
280
302
 
281
303
  if t is str:
282
- data_type = "String"
304
+ # Check for FixedString annotation
305
+ fixed_string_size = next(
306
+ (md.size for md in mds if isinstance(md, ClickhouseFixedStringSize)),
307
+ None
308
+ )
309
+ if fixed_string_size:
310
+ data_type = f"FixedString({fixed_string_size})"
311
+ else:
312
+ data_type = "String"
313
+ elif t is bytes:
314
+ # Check for FixedString annotation
315
+ fixed_string_size = next(
316
+ (md.size for md in mds if isinstance(md, ClickhouseFixedStringSize)),
317
+ None
318
+ )
319
+ if fixed_string_size:
320
+ data_type = f"FixedString({fixed_string_size})"
321
+ else:
322
+ # Regular bytes without FixedString annotation
323
+ data_type = "String"
283
324
  elif t is int:
284
325
  # Check for int size annotations
285
326
  int_size = next((md for md in mds if isinstance(md, str) and re.match(r'^u?int\d+$', md)), None)
@@ -437,9 +478,13 @@ def py_type_to_column_type(t: type, mds: list[Any]) -> Tuple[bool, list[Any], Da
437
478
  def _to_columns(model: type[BaseModel]) -> list[Column]:
438
479
  """Convert Pydantic model fields to Column definitions."""
439
480
  columns = []
481
+ # Get raw annotations from the model class to preserve type aliases
482
+ raw_annotations = getattr(model, '__annotations__', {})
483
+
440
484
  for field_name, field_info in model.model_fields.items():
441
- # Get the field type annotation
442
- field_type = field_info.annotation
485
+ # Use raw annotation if available (preserves type aliases and their metadata)
486
+ # Fall back to field_info.annotation if not found in __annotations__
487
+ field_type = raw_annotations.get(field_name, field_info.annotation)
443
488
  if field_type is None:
444
489
  raise ValueError(f"Missing type for {field_name}")
445
490
  primary_key, field_type = handle_key(field_type)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: moose_lib
3
- Version: 0.6.172
3
+ Version: 0.6.173
4
4
  Home-page: https://www.fiveonefour.com/moose
5
5
  Author: Fiveonefour Labs Inc.
6
6
  Author-email: support@fiveonefour.com
@@ -42,6 +42,7 @@ moose_lib/utilities/__init__.py
42
42
  moose_lib/utilities/sql.py
43
43
  tests/__init__.py
44
44
  tests/conftest.py
45
+ tests/test_fixedstring.py
45
46
  tests/test_moose.py
46
47
  tests/test_olap_table_versioning.py
47
48
  tests/test_query_builder.py
@@ -0,0 +1,43 @@
1
+ from datetime import datetime
2
+ from typing import Annotated
3
+ from pydantic import BaseModel
4
+ from moose_lib import Key, FixedString
5
+ from moose_lib.data_models import _to_columns
6
+
7
+
8
+ def test_fixedstring_annotation():
9
+ """Test FixedString annotation converts to correct ClickHouse type with str base type."""
10
+
11
+ class FixedStringTest(BaseModel):
12
+ id: Key[str]
13
+ created_at: datetime
14
+ md5_hash: Annotated[str, FixedString(16)]
15
+ sha256_hash: Annotated[str, FixedString(32)]
16
+ ipv6_address: Annotated[str, FixedString(16)]
17
+
18
+ columns = _to_columns(FixedStringTest)
19
+ by_name = {col.name: col for col in columns}
20
+
21
+ assert by_name["md5_hash"].data_type == "FixedString(16)"
22
+ assert by_name["sha256_hash"].data_type == "FixedString(32)"
23
+ assert by_name["ipv6_address"].data_type == "FixedString(16)"
24
+
25
+ # Verify other fields still work
26
+ assert by_name["id"].data_type == "String"
27
+ assert by_name["created_at"].data_type == "DateTime"
28
+
29
+
30
+ def test_fixedstring_different_sizes():
31
+ """Test various FixedString sizes."""
32
+
33
+ class FixedStringSizes(BaseModel):
34
+ mac_address: Annotated[str, FixedString(6)]
35
+ uuid_binary: Annotated[str, FixedString(16)]
36
+ sha512_hash: Annotated[str, FixedString(64)]
37
+
38
+ columns = _to_columns(FixedStringSizes)
39
+ by_name = {col.name: col for col in columns}
40
+
41
+ assert by_name["mac_address"].data_type == "FixedString(6)"
42
+ assert by_name["uuid_binary"].data_type == "FixedString(16)"
43
+ assert by_name["sha512_hash"].data_type == "FixedString(64)"
File without changes
File without changes
File without changes