sqlmodel-object-helpers 0.0.5__tar.gz → 0.0.6__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.
Files changed (42) hide show
  1. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/PKG-INFO +126 -2
  2. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/README.md +125 -1
  3. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/src/sqlmodel_object_helpers/__init__.py +15 -3
  4. sqlmodel_object_helpers-0.0.6/src/sqlmodel_object_helpers/dynamic_meta.py +468 -0
  5. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/src/sqlmodel_object_helpers/standalone.py +35 -0
  6. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/tests/conftest.py +5 -1
  7. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/tests/test_datetime_range.py +51 -46
  8. sqlmodel_object_helpers-0.0.6/tests/test_dynamic_meta.py +1037 -0
  9. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/tests/test_query.py +37 -0
  10. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/tests/test_standalone.py +22 -0
  11. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/.github/workflows/publish.yml +0 -0
  12. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/.gitignore +0 -0
  13. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/LICENSE +0 -0
  14. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/pyproject.toml +0 -0
  15. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/src/sqlmodel_object_helpers/constants.py +0 -0
  16. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/src/sqlmodel_object_helpers/exceptions.py +0 -0
  17. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/src/sqlmodel_object_helpers/filters.py +0 -0
  18. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/src/sqlmodel_object_helpers/loaders.py +0 -0
  19. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/src/sqlmodel_object_helpers/mutations.py +0 -0
  20. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/src/sqlmodel_object_helpers/operators.py +0 -0
  21. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/src/sqlmodel_object_helpers/query.py +0 -0
  22. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/src/sqlmodel_object_helpers/session.py +0 -0
  23. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/src/sqlmodel_object_helpers/types/__init__.py +0 -0
  24. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/src/sqlmodel_object_helpers/types/columns.py +0 -0
  25. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/src/sqlmodel_object_helpers/types/datetime.py +0 -0
  26. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/src/sqlmodel_object_helpers/types/filters.py +0 -0
  27. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/src/sqlmodel_object_helpers/types/pagination.py +0 -0
  28. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/src/sqlmodel_object_helpers/types/projections.py +0 -0
  29. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/tests/test_bulk_mutations.py +0 -0
  30. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/tests/test_column_meta.py +0 -0
  31. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/tests/test_computed_columns.py +0 -0
  32. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/tests/test_count_exists.py +0 -0
  33. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/tests/test_exceptions.py +0 -0
  34. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/tests/test_filters.py +0 -0
  35. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/tests/test_for_update.py +0 -0
  36. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/tests/test_generated_columns_pg.py +0 -0
  37. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/tests/test_loaders.py +0 -0
  38. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/tests/test_mutations.py +0 -0
  39. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/tests/test_operators.py +0 -0
  40. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/tests/test_settings.py +0 -0
  41. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/tests/test_time_filter.py +0 -0
  42. {sqlmodel_object_helpers-0.0.5 → sqlmodel_object_helpers-0.0.6}/tests/test_types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlmodel-object-helpers
3
- Version: 0.0.5
3
+ Version: 0.0.6
4
4
  Summary: Generic async query helpers for SQLModel: filtering, eager loading, pagination
5
5
  Project-URL: Homepage, https://github.com/itstandart/sqlmodel-object-helpers
6
6
  Project-URL: Repository, https://github.com/itstandart/sqlmodel-object-helpers
@@ -55,6 +55,7 @@ Generic async query helpers for [SQLModel](https://sqlmodel.tiangolo.com/): filt
55
55
  - **Relationship Safety Check** - `check_for_related_records` pre-deletion inspection of ONETOMANY dependencies
56
56
  - **Security Limits** - Configurable depth, list size, and pagination caps to prevent abuse
57
57
  - **Type Safety** - Full type annotations with PEP 695 generics and `py.typed` marker (PEP 561)
58
+ - **Dynamic Table Metadata** - `build_dynamic_meta` derives `TableMeta` + `list[ColumnMeta]` from a SQLModel class by reading PostgreSQL `pg_description` with fallback to `Column(comment=...)`. Supports per-role label/row_link overrides via `||` comment format, TTL-cached
58
59
  - **Standalone Mode** - `configure()` + `import sqlmodel_object_helpers.standalone` for auto-session usage without DI
59
60
  - **Session Lifecycle Logging** - Transparent session open/commit/rollback logging with hex session IDs and timing
60
61
 
@@ -619,6 +620,117 @@ order = soh.OrderBy(sorts=[
619
620
  result = await soh.get_objects(session, User, order_by=order)
620
621
  ```
621
622
 
623
+ ## Dynamic Table Metadata
624
+
625
+ `build_dynamic_meta` builds `TableMeta` + `list[ColumnMeta]` from a SQLModel class at runtime, reading PostgreSQL `pg_description` (TTL-cached) with fallback to `Column(comment=...)` model defaults.
626
+
627
+ ```python
628
+ import sqlmodel_object_helpers as soh
629
+
630
+ # Physical columns — label, type, lookup derived automatically
631
+ table_meta, columns = await soh.build_dynamic_meta(
632
+ session,
633
+ EmailMessage,
634
+ name="email_messages",
635
+ columns=[
636
+ "id", # physical column — everything derived
637
+ "email_type_id", # FK on *_lkp → lookup_dict auto-derived
638
+ "updated_at",
639
+ soh.ColumnMeta( # virtual column — fully specified
640
+ json_path="last_editor.user_name",
641
+ label="Редактор",
642
+ type=soh.ColumnType.STRING,
643
+ ),
644
+ ],
645
+ role_type="operator", # per-role label/row_link overrides
646
+ )
647
+
648
+ # Returns (TableMeta, list[ColumnMeta]) ready for GetAllPagination
649
+ return soh.GetAllPagination(
650
+ table=table_meta,
651
+ columns=columns,
652
+ data=items,
653
+ pagination=pagination_r,
654
+ )
655
+ ```
656
+
657
+ ### Type derivation (SA type → ColumnType)
658
+
659
+ Physical column types are mapped automatically. Unknown types fall back to `string`.
660
+
661
+ | SQLAlchemy type | ColumnType |
662
+ |---|---|
663
+ | `Boolean` | `boolean` |
664
+ | `DateTime` | `datetime` |
665
+ | `Date` | `date` |
666
+ | `Integer`, `BigInteger`, `SmallInteger` | `integer` |
667
+ | `Numeric`, `Float` | `float` |
668
+ | `String`, `Text`, `Enum`, `Interval`, `ARRAY`, `Uuid` | `string` |
669
+ | Any other type | `string` (fallback) |
670
+
671
+ ### Label precedence (per physical column)
672
+
673
+ 1. `pg_description` — DBA edit via `COMMENT ON COLUMN` (supports per-role `||` overrides)
674
+ 2. `Column(comment=...)` — Python-side default in the model
675
+ 3. `ValueError` — fail-loud if both are missing
676
+
677
+ ### Per-role overrides via `||` format
678
+
679
+ DBAs can set role-specific labels and row links in PostgreSQL comments:
680
+
681
+ ```sql
682
+ COMMENT ON COLUMN emails.email_type_id IS 'Тип письма||operator=Категория||buh=Реквизит';
683
+ COMMENT ON TABLE emails IS 'Письма||row_link=/email/$id||row_link.operator=/op/email/$id';
684
+ ```
685
+
686
+ ### TTL cache
687
+
688
+ `pg_description` queries are cached per `(schema, table)` with a configurable TTL (default 60s):
689
+
690
+ ```python
691
+ soh.configure_meta_cache_ttl(120) # change TTL to 120 seconds
692
+ soh.invalidate_meta_cache() # clear entire cache
693
+ soh.invalidate_meta_cache(schema="lead") # clear all entries for a schema
694
+ soh.invalidate_meta_cache("lead", "emails") # clear one entry
695
+ ```
696
+
697
+ ### Standalone mode
698
+
699
+ ```python
700
+ import sqlmodel_object_helpers.standalone as soh_sa
701
+
702
+ table_meta, columns = await soh_sa.build_dynamic_meta(
703
+ EmailMessage,
704
+ name="email_messages",
705
+ columns=["id", "email_type_id"],
706
+ )
707
+ ```
708
+
709
+ ### Backward compatibility and migration
710
+
711
+ `GetAllPagination` is fully backward compatible — `table` and `columns` default to `None`, so existing endpoints continue to work without changes:
712
+
713
+ ```python
714
+ # Before (still works as-is)
715
+ return soh.GetAllPagination(data=items, pagination=pagination_r)
716
+
717
+ # After (meta added when ready)
718
+ return soh.GetAllPagination(
719
+ table=table_meta,
720
+ columns=columns,
721
+ data=items,
722
+ pagination=pagination_r,
723
+ )
724
+ ```
725
+
726
+ Endpoints can be migrated one at a time. Three strategies per endpoint:
727
+
728
+ | Strategy | `table`/`columns` | Use case |
729
+ |---|---|---|
730
+ | **No meta** | Always `None` | Endpoint not yet migrated, frontend uses hardcoded table |
731
+ | **Always meta** | Sent on every request | Simple, no frontend caching logic needed |
732
+ | **Meta on first page** | Sent when `page=1`, `None` on pages 2+ | Saves traffic, frontend caches meta from first response |
733
+
622
734
  ## API Reference
623
735
 
624
736
  ### Session Management
@@ -629,7 +741,7 @@ result = await soh.get_objects(session, User, order_by=order)
629
741
 
630
742
  ### Standalone Wrappers
631
743
 
632
- - `import sqlmodel_object_helpers.standalone as soh_sa` -- All 12 query/mutation functions without `session` parameter
744
+ - `import sqlmodel_object_helpers.standalone as soh_sa` -- All 12 query/mutation functions plus `build_dynamic_meta` without `session` parameter
633
745
 
634
746
  ### Settings
635
747
 
@@ -654,6 +766,14 @@ result = await soh.get_objects(session, User, order_by=order)
654
766
  - `soh.delete_objects(session, model, filters)` -- Bulk delete via single `DELETE ... WHERE`
655
767
  - `soh.check_for_related_records(session, model, pk)` -- Pre-deletion dependency check
656
768
 
769
+ ### Dynamic Meta
770
+
771
+ - `soh.build_dynamic_meta(session, model, *, name, columns, header, row_link, role_type)` -- Build `TableMeta` + `list[ColumnMeta]` from model + `pg_description`
772
+ - `soh.load_pg_comments(session, schema, table)` -- Read `(table_comment, {col: comment})` from `pg_description` (TTL-cached)
773
+ - `soh.configure_meta_cache_ttl(seconds)` -- Override default `pg_description` cache TTL (default: 60s)
774
+ - `soh.invalidate_meta_cache(schema, table)` -- Manually invalidate the `pg_description` cache (full, by-schema, or by-table)
775
+ - `soh.ColumnEntry` -- Type alias: `str | ColumnMeta` (element of `columns` list in `build_dynamic_meta`)
776
+
657
777
  ### Filter Builders
658
778
 
659
779
  - `soh.build_filter(model, filters, ...)` -- Build SQLAlchemy expression from LogicalFilter dict
@@ -762,6 +882,10 @@ This project follows [Semantic Versioning](https://semver.org/) (MAJOR.MINOR.PAT
762
882
 
763
883
  ## Changelog
764
884
 
885
+ ### 0.0.6
886
+
887
+ - **build_dynamic_meta** / **load_pg_comments** / **configure_meta_cache_ttl** / **invalidate_meta_cache** — dynamic UI metadata reader. Builds `TableMeta` and `list[ColumnMeta]` from a SQLModel class by reading PostgreSQL `pg_description` (TTL-cached, default 60s) with fallback to `Column(comment=...)` defaults from the model. Supports per-role label/row_link overrides via extended `||` comment format. For physical columns the label precedence is `pg_description` > `Column(comment=...)` model default. For virtual columns (paths with `.` traversing relationships) and full overrides — pass a fully-specified `ColumnMeta` instance directly in the `columns` list (used as-is, no derivation). Lookup `lookup_dict`/`lookup_path` are derived from FK on `*_lkp` tables by `{schema}_{base}` convention. Type derived from SA column type. DBAs can edit labels via `COMMENT ON COLUMN/TABLE` SQL — frontend reflects changes within cache TTL without redeploy. No sync block, no schema migrations introduced; the application's `db.py` is not touched.
888
+
765
889
  ### 0.0.5
766
890
 
767
891
  - **FilterDatetimeRange** / **FilterNaiveDatetimeRange** — range filters that parse comma-separated date strings (`"2026-04-01,2026-05-06"`) into `gt`/`lt` operators for SQL filtering
@@ -21,6 +21,7 @@ Generic async query helpers for [SQLModel](https://sqlmodel.tiangolo.com/): filt
21
21
  - **Relationship Safety Check** - `check_for_related_records` pre-deletion inspection of ONETOMANY dependencies
22
22
  - **Security Limits** - Configurable depth, list size, and pagination caps to prevent abuse
23
23
  - **Type Safety** - Full type annotations with PEP 695 generics and `py.typed` marker (PEP 561)
24
+ - **Dynamic Table Metadata** - `build_dynamic_meta` derives `TableMeta` + `list[ColumnMeta]` from a SQLModel class by reading PostgreSQL `pg_description` with fallback to `Column(comment=...)`. Supports per-role label/row_link overrides via `||` comment format, TTL-cached
24
25
  - **Standalone Mode** - `configure()` + `import sqlmodel_object_helpers.standalone` for auto-session usage without DI
25
26
  - **Session Lifecycle Logging** - Transparent session open/commit/rollback logging with hex session IDs and timing
26
27
 
@@ -585,6 +586,117 @@ order = soh.OrderBy(sorts=[
585
586
  result = await soh.get_objects(session, User, order_by=order)
586
587
  ```
587
588
 
589
+ ## Dynamic Table Metadata
590
+
591
+ `build_dynamic_meta` builds `TableMeta` + `list[ColumnMeta]` from a SQLModel class at runtime, reading PostgreSQL `pg_description` (TTL-cached) with fallback to `Column(comment=...)` model defaults.
592
+
593
+ ```python
594
+ import sqlmodel_object_helpers as soh
595
+
596
+ # Physical columns — label, type, lookup derived automatically
597
+ table_meta, columns = await soh.build_dynamic_meta(
598
+ session,
599
+ EmailMessage,
600
+ name="email_messages",
601
+ columns=[
602
+ "id", # physical column — everything derived
603
+ "email_type_id", # FK on *_lkp → lookup_dict auto-derived
604
+ "updated_at",
605
+ soh.ColumnMeta( # virtual column — fully specified
606
+ json_path="last_editor.user_name",
607
+ label="Редактор",
608
+ type=soh.ColumnType.STRING,
609
+ ),
610
+ ],
611
+ role_type="operator", # per-role label/row_link overrides
612
+ )
613
+
614
+ # Returns (TableMeta, list[ColumnMeta]) ready for GetAllPagination
615
+ return soh.GetAllPagination(
616
+ table=table_meta,
617
+ columns=columns,
618
+ data=items,
619
+ pagination=pagination_r,
620
+ )
621
+ ```
622
+
623
+ ### Type derivation (SA type → ColumnType)
624
+
625
+ Physical column types are mapped automatically. Unknown types fall back to `string`.
626
+
627
+ | SQLAlchemy type | ColumnType |
628
+ |---|---|
629
+ | `Boolean` | `boolean` |
630
+ | `DateTime` | `datetime` |
631
+ | `Date` | `date` |
632
+ | `Integer`, `BigInteger`, `SmallInteger` | `integer` |
633
+ | `Numeric`, `Float` | `float` |
634
+ | `String`, `Text`, `Enum`, `Interval`, `ARRAY`, `Uuid` | `string` |
635
+ | Any other type | `string` (fallback) |
636
+
637
+ ### Label precedence (per physical column)
638
+
639
+ 1. `pg_description` — DBA edit via `COMMENT ON COLUMN` (supports per-role `||` overrides)
640
+ 2. `Column(comment=...)` — Python-side default in the model
641
+ 3. `ValueError` — fail-loud if both are missing
642
+
643
+ ### Per-role overrides via `||` format
644
+
645
+ DBAs can set role-specific labels and row links in PostgreSQL comments:
646
+
647
+ ```sql
648
+ COMMENT ON COLUMN emails.email_type_id IS 'Тип письма||operator=Категория||buh=Реквизит';
649
+ COMMENT ON TABLE emails IS 'Письма||row_link=/email/$id||row_link.operator=/op/email/$id';
650
+ ```
651
+
652
+ ### TTL cache
653
+
654
+ `pg_description` queries are cached per `(schema, table)` with a configurable TTL (default 60s):
655
+
656
+ ```python
657
+ soh.configure_meta_cache_ttl(120) # change TTL to 120 seconds
658
+ soh.invalidate_meta_cache() # clear entire cache
659
+ soh.invalidate_meta_cache(schema="lead") # clear all entries for a schema
660
+ soh.invalidate_meta_cache("lead", "emails") # clear one entry
661
+ ```
662
+
663
+ ### Standalone mode
664
+
665
+ ```python
666
+ import sqlmodel_object_helpers.standalone as soh_sa
667
+
668
+ table_meta, columns = await soh_sa.build_dynamic_meta(
669
+ EmailMessage,
670
+ name="email_messages",
671
+ columns=["id", "email_type_id"],
672
+ )
673
+ ```
674
+
675
+ ### Backward compatibility and migration
676
+
677
+ `GetAllPagination` is fully backward compatible — `table` and `columns` default to `None`, so existing endpoints continue to work without changes:
678
+
679
+ ```python
680
+ # Before (still works as-is)
681
+ return soh.GetAllPagination(data=items, pagination=pagination_r)
682
+
683
+ # After (meta added when ready)
684
+ return soh.GetAllPagination(
685
+ table=table_meta,
686
+ columns=columns,
687
+ data=items,
688
+ pagination=pagination_r,
689
+ )
690
+ ```
691
+
692
+ Endpoints can be migrated one at a time. Three strategies per endpoint:
693
+
694
+ | Strategy | `table`/`columns` | Use case |
695
+ |---|---|---|
696
+ | **No meta** | Always `None` | Endpoint not yet migrated, frontend uses hardcoded table |
697
+ | **Always meta** | Sent on every request | Simple, no frontend caching logic needed |
698
+ | **Meta on first page** | Sent when `page=1`, `None` on pages 2+ | Saves traffic, frontend caches meta from first response |
699
+
588
700
  ## API Reference
589
701
 
590
702
  ### Session Management
@@ -595,7 +707,7 @@ result = await soh.get_objects(session, User, order_by=order)
595
707
 
596
708
  ### Standalone Wrappers
597
709
 
598
- - `import sqlmodel_object_helpers.standalone as soh_sa` -- All 12 query/mutation functions without `session` parameter
710
+ - `import sqlmodel_object_helpers.standalone as soh_sa` -- All 12 query/mutation functions plus `build_dynamic_meta` without `session` parameter
599
711
 
600
712
  ### Settings
601
713
 
@@ -620,6 +732,14 @@ result = await soh.get_objects(session, User, order_by=order)
620
732
  - `soh.delete_objects(session, model, filters)` -- Bulk delete via single `DELETE ... WHERE`
621
733
  - `soh.check_for_related_records(session, model, pk)` -- Pre-deletion dependency check
622
734
 
735
+ ### Dynamic Meta
736
+
737
+ - `soh.build_dynamic_meta(session, model, *, name, columns, header, row_link, role_type)` -- Build `TableMeta` + `list[ColumnMeta]` from model + `pg_description`
738
+ - `soh.load_pg_comments(session, schema, table)` -- Read `(table_comment, {col: comment})` from `pg_description` (TTL-cached)
739
+ - `soh.configure_meta_cache_ttl(seconds)` -- Override default `pg_description` cache TTL (default: 60s)
740
+ - `soh.invalidate_meta_cache(schema, table)` -- Manually invalidate the `pg_description` cache (full, by-schema, or by-table)
741
+ - `soh.ColumnEntry` -- Type alias: `str | ColumnMeta` (element of `columns` list in `build_dynamic_meta`)
742
+
623
743
  ### Filter Builders
624
744
 
625
745
  - `soh.build_filter(model, filters, ...)` -- Build SQLAlchemy expression from LogicalFilter dict
@@ -728,6 +848,10 @@ This project follows [Semantic Versioning](https://semver.org/) (MAJOR.MINOR.PAT
728
848
 
729
849
  ## Changelog
730
850
 
851
+ ### 0.0.6
852
+
853
+ - **build_dynamic_meta** / **load_pg_comments** / **configure_meta_cache_ttl** / **invalidate_meta_cache** — dynamic UI metadata reader. Builds `TableMeta` and `list[ColumnMeta]` from a SQLModel class by reading PostgreSQL `pg_description` (TTL-cached, default 60s) with fallback to `Column(comment=...)` defaults from the model. Supports per-role label/row_link overrides via extended `||` comment format. For physical columns the label precedence is `pg_description` > `Column(comment=...)` model default. For virtual columns (paths with `.` traversing relationships) and full overrides — pass a fully-specified `ColumnMeta` instance directly in the `columns` list (used as-is, no derivation). Lookup `lookup_dict`/`lookup_path` are derived from FK on `*_lkp` tables by `{schema}_{base}` convention. Type derived from SA column type. DBAs can edit labels via `COMMENT ON COLUMN/TABLE` SQL — frontend reflects changes within cache TTL without redeploy. No sync block, no schema migrations introduced; the application's `db.py` is not touched.
854
+
731
855
  ### 0.0.5
732
856
 
733
857
  - **FilterDatetimeRange** / **FilterNaiveDatetimeRange** — range filters that parse comma-separated date strings (`"2026-04-01,2026-05-06"`) into `gt`/`lt` operators for SQL filtering
@@ -1,8 +1,15 @@
1
1
  """sqlmodel-object-helpers — reusable query helpers for SQLModel projects."""
2
2
 
3
- __version__ = "0.0.5"
3
+ __version__ = "0.0.6"
4
4
 
5
5
  from .constants import QueryHelperSettings, settings
6
+ from .dynamic_meta import (
7
+ ColumnEntry,
8
+ build_dynamic_meta,
9
+ configure_meta_cache_ttl,
10
+ invalidate_meta_cache,
11
+ load_pg_comments,
12
+ )
6
13
  from .exceptions import (
7
14
  DatabaseError,
8
15
  InvalidFilterError,
@@ -13,7 +20,6 @@ from .exceptions import (
13
20
  )
14
21
  from .filters import build_filter, build_flat_filter, flatten_filters
15
22
  from .loaders import build_load_chain, build_load_options
16
- from .operators import SPECIAL_OPERATORS, SUPPORTED_OPERATORS, Operator
17
23
  from .mutations import (
18
24
  add_object,
19
25
  add_objects,
@@ -23,8 +29,10 @@ from .mutations import (
23
29
  update_object,
24
30
  update_objects,
25
31
  )
32
+ from .operators import SPECIAL_OPERATORS, SUPPORTED_OPERATORS, Operator
26
33
  from .query import count_objects, exists_object, get_object, get_objects, get_projection
27
34
  from .session import auto_session, configure, create_session_dependency
35
+ from .types.columns import BoolLabels, ColumnMeta, ColumnType, TableMeta
28
36
  from .types.datetime import UTCDatetime
29
37
  from .types.filters import (
30
38
  FilterBool,
@@ -43,7 +51,6 @@ from .types.filters import (
43
51
  OrderDesc,
44
52
  TimeFilter,
45
53
  )
46
- from .types.columns import BoolLabels, ColumnMeta, ColumnType, TableMeta
47
54
  from .types.pagination import (
48
55
  GetAllPagination,
49
56
  LookupMeta,
@@ -57,16 +64,19 @@ __all__ = [
57
64
  "add_object",
58
65
  "add_objects",
59
66
  "auto_session",
67
+ "build_dynamic_meta",
60
68
  "build_filter",
61
69
  "build_flat_filter",
62
70
  "build_load_chain",
63
71
  "build_load_options",
64
72
  "check_for_related_records",
65
73
  "BoolLabels",
74
+ "ColumnEntry",
66
75
  "ColumnMeta",
67
76
  "ColumnSpec",
68
77
  "ColumnType",
69
78
  "configure",
79
+ "configure_meta_cache_ttl",
70
80
  "count_objects",
71
81
  "create_session_dependency",
72
82
  "DatabaseError",
@@ -88,8 +98,10 @@ __all__ = [
88
98
  "get_objects",
89
99
  "get_projection",
90
100
  "GetAllPagination",
101
+ "invalidate_meta_cache",
91
102
  "InvalidFilterError",
92
103
  "InvalidLoadPathError",
104
+ "load_pg_comments",
93
105
  "LogicalFilter",
94
106
  "LookupMeta",
95
107
  "LookupResponse",