sibi-flux 2026.1.8__py3-none-any.whl → 2026.1.9__py3-none-any.whl

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.
sibi_flux/datacube/cli.py CHANGED
@@ -203,7 +203,7 @@ def set_context_defaults(
203
203
 
204
204
 
205
205
  def _get_db_url_callback(
206
- registry: DatacubeRegistry, db_url_map: Optional[str]
206
+ registry: DatacubeRegistry, db_url_map: Optional[str], params: Optional[Dict[str, Any]] = None
207
207
  ) -> Callable[[str], str]:
208
208
  """Helper to create a callback that resolves DB URLs from CLI overrides or registry."""
209
209
  cli_urls = json.loads(db_url_map) if db_url_map else {}
@@ -212,8 +212,24 @@ def _get_db_url_callback(
212
212
  # 1. CLI Override
213
213
  if conf_name in cli_urls:
214
214
  return cli_urls[conf_name]
215
+
215
216
  # 2. Dynamic Resolution
216
- url = resolve_db_url(conf_name, registry.global_imports)
217
+ imports = registry.global_imports
218
+
219
+ # Check specific import_spec from params
220
+ if params and "databases" in params:
221
+ for db in params.get("databases", []):
222
+ ref = db.get("connection_ref") or db.get("connection_obj")
223
+ if ref == conf_name:
224
+ spec = db.get("import_spec")
225
+ if spec and isinstance(spec, dict):
226
+ # Prepend specific module
227
+ imports = [spec.get("module")] + imports
228
+ elif db.get("global_import"):
229
+ imports = [db.get("global_import")] + imports
230
+ break
231
+
232
+ url = resolve_db_url(conf_name, imports)
217
233
  if url:
218
234
  return url
219
235
  raise ValueError(
@@ -283,9 +299,16 @@ def sync(
283
299
 
284
300
  flat_tables = {}
285
301
  for grp, tbls in existing_reg_data.items():
286
- if isinstance(tbls, dict):
302
+ if grp == "tables" and isinstance(tbls, dict):
303
+ # Modern format: tables are in 'tables' dict
304
+ for t, t_meta in tbls.items():
305
+ flat_tables[t] = t_meta
306
+ continue
307
+
308
+ if isinstance(tbls, dict) and grp != "global_imports":
309
+ # Legacy Scoped Format (grp is connection_obj)
287
310
  for t, t_meta in tbls.items():
288
- # Inject the config object (group key) so DatacubeRegistry knows the connection
311
+ # Inject/Overwrite connection_obj only if implied by scope
289
312
  t_meta["connection_obj"] = grp
290
313
  flat_tables[t] = t_meta
291
314
 
@@ -295,6 +318,11 @@ def sync(
295
318
  console.print(f"[yellow]Warning: Could not load existing registry: {e}[/yellow]")
296
319
 
297
320
  registry = DatacubeRegistry(config_data, params=context.params)
321
+
322
+ # Fix 2 Re-applied: Ensure global_imports are populated from params if registry loaded from file didn't have them
323
+ # This is critical for Clean Project + Force flows where registry might be partial or JIT
324
+ if not registry.global_imports and context.params.get("global_imports"):
325
+ registry.global_imports = context.params.get("global_imports")
298
326
 
299
327
  # --- Aggregation Phase ---
300
328
  # --- Aggregation Phase ---
@@ -453,7 +481,7 @@ def sync(
453
481
  registry.valid_paths = list(valid_paths)
454
482
  registry.valid_fieldmap_paths = context.valid_fieldmap_paths
455
483
 
456
- get_url = _get_db_url_callback(registry, db_url_map)
484
+ get_url = _get_db_url_callback(registry, db_url_map, params=context.params)
457
485
 
458
486
  # Group tables by target file
459
487
  file_groups = registry.group_tables_by_file()
@@ -770,8 +798,22 @@ def discover(
770
798
  if not wl_filename:
771
799
  # Default convention: discovery_whitelist_<db_name>.yaml
772
800
  wl_filename = f"discovery_whitelist_{conn_obj}.yaml"
801
+
773
802
  whitelist_path = config_path.parent / wl_filename
774
803
 
804
+ # Fallback 1: Auto-generated per-db (from scan/map fallback logic)
805
+ if not whitelist_path.exists():
806
+ fb = config_path.parent / f"discovery_whitelist_{conn_obj}.yaml"
807
+ if fb.exists():
808
+ whitelist_path = fb
809
+
810
+ # Fallback 2: Global whitelist.yaml (Generated by 'whitelist' command)
811
+ if not whitelist_path.exists():
812
+ global_wl = config_path.parent / "whitelist.yaml"
813
+ if global_wl.exists():
814
+ console.print(f"[dim]Fallback: Using global {global_wl.name} for {db_name}[/dim]")
815
+ whitelist_path = global_wl
816
+
775
817
  # Determine rules path
776
818
  rules_filename = db_config.get("rules_file")
777
819
  if not rules_filename:
@@ -1102,7 +1144,7 @@ def drift(
1102
1144
  config_data = _load_and_resolve_config(config_path)
1103
1145
 
1104
1146
  registry = DatacubeRegistry(config_data)
1105
- get_url = _get_db_url_callback(registry, db_url_map)
1147
+ get_url = _get_db_url_callback(registry, db_url_map, params=config_data)
1106
1148
  cli_urls = json.loads(db_url_map) if db_url_map else {}
1107
1149
 
1108
1150
  drift_table = Table(title="Schema Drift Analysis")
@@ -1566,6 +1608,15 @@ def workflow(
1566
1608
  dry_run=dry_run, # Preview rules if dry-running
1567
1609
  )
1568
1610
 
1611
+ console.print(f"\n[bold cyan]Step 0c: Generate Whitelist[/]")
1612
+ whitelist(
1613
+ config_file=config_file,
1614
+ db_name=db_name,
1615
+ db_url_map=db_url_map,
1616
+ env_file=env_file,
1617
+ force=force,
1618
+ )
1619
+
1569
1620
  # Step 1: Discover
1570
1621
  # Note: Discover currently runs for all DBs in config.
1571
1622
  console.print(f"\n[bold cyan]Step 1: Discovery[/]")
@@ -1582,17 +1633,10 @@ def workflow(
1582
1633
  force=False, # Discovery force is about fields usually?
1583
1634
  )
1584
1635
 
1585
- # Step 2: Map
1586
- console.print(f"\n[bold cyan]Step 2: Map Generation[/]")
1587
- map(
1588
- config_file=config_file,
1589
- db_url_map=db_url_map,
1590
- env_file=env_file,
1591
- db_name=db_name,
1592
- force=force,
1593
- )
1594
-
1595
- # Step 3: Sync
1636
+ # Step 2: Map (Skipped - Handled by Sync)
1637
+ # console.print(f"\n[bold cyan]Step 2: Map Generation (Integrated into Sync)[/]")
1638
+
1639
+ # Step 3: Sync -> Generates Code + Field Maps
1596
1640
  console.print(f"\n[bold cyan]Step 3: Sync (Code Generation)[/]")
1597
1641
  sync(
1598
1642
  config_file=config_file,
@@ -778,6 +778,32 @@ def generate_datacube_module_code(
778
778
  else:
779
779
  imports.add(base_imp)
780
780
 
781
+ # Config Object Import
782
+ # We need to resolve import for conf_obj (e.g. clickhouse_conf)
783
+ # Using registry.params which contains databases list with import_spec
784
+ params = registry.params
785
+ dbs = params.get("databases", [])
786
+ for db in dbs:
787
+ ref = db.get("connection_ref") or db.get("connection_obj")
788
+ if ref == conf_obj:
789
+ spec = db.get("import_spec")
790
+ if spec and isinstance(spec, dict):
791
+ mod = spec.get("module")
792
+ sym = spec.get("symbol")
793
+ if mod and sym:
794
+ imports.add(f"from {mod} import {sym}")
795
+ elif db.get("global_import"):
796
+ # Legacy or simple string import
797
+ imp_str = db.get("global_import")
798
+ if imp_str and sym and sym in imp_str:
799
+ imports.add(imp_str)
800
+ elif imp_str: # Fallback to add specific object if simple import
801
+ # Try to parse or just add "from ... import conf_obj" logic?
802
+ # If global_import is "from conf.credentials import *" -> hard to know
803
+ # If it is "from conf.credentials import replica_conf" -> easy
804
+ imports.add(imp_str)
805
+ break
806
+
781
807
  details = registry.get_table_details(table_name)
782
808
  field_map_str = details.get("field_map")
783
809
  sticky_filters = details.get("sticky_filters")
@@ -56,6 +56,8 @@ def propose_cubes(db_domain: str, app_name: str) -> None:
56
56
 
57
57
  # Registry Structure: {conf_obj: {table_name: {class_name: ..., path: ...}}}
58
58
  for conf_obj, tables in global_data.items():
59
+ if not isinstance(tables, dict):
60
+ continue
59
61
  for table_name, meta in tables.items():
60
62
  path_str = meta.get("path", "")
61
63
  class_name = meta.get("class_name")
@@ -100,14 +102,16 @@ def propose_cubes(db_domain: str, app_name: str) -> None:
100
102
 
101
103
  # 4. Update App Registry
102
104
 
103
- # Load existing
104
105
  current_config = {"cubes": []}
105
106
  if registry_path.exists():
106
107
  try:
107
108
  with open(registry_path, "r") as f:
108
109
  loaded = yaml.safe_load(f)
109
- if loaded and "cubes" in loaded:
110
- current_config = loaded
110
+ if loaded:
111
+ current_config = loaded
112
+ if "cubes" not in current_config or current_config["cubes"] is None:
113
+ current_config["cubes"] = []
114
+
111
115
  except Exception:
112
116
  pass
113
117
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sibi-flux
3
- Version: 2026.1.8
3
+ Version: 2026.1.9
4
4
  Summary: Sibi Toolkit: A collection of tools for Data Analysis/Engineering.
5
5
  Author: Luis Valverde
6
6
  Author-email: Luis Valverde <lvalverdeb@gmail.com>
@@ -23,12 +23,12 @@ sibi_flux/dask_cluster/exceptions.py,sha256=apQZaUMgac8k2ZTTsvUd-VlWdo9-Nrh5b6St
23
23
  sibi_flux/dask_cluster/utils.py,sha256=Pr2qaow6GVyvM0hqKSM0ZQpe2Ot5ayfGYQiNhNpYA8Y,1342
24
24
  sibi_flux/datacube/__init__.py,sha256=ODEoa4r5RtzynIp-PdVDaJ-4BcPBj1L9VkLIF7RYSPE,91
25
25
  sibi_flux/datacube/_data_cube.py,sha256=Ofgy3JlR7N0eKijpUzI-ixFlISUd3CFsxnKd6a4fguE,12629
26
- sibi_flux/datacube/cli.py,sha256=LoEa1lyKyCclAFZ4OEC9rFy6cyTtGoQ55xgSEQzMMDM,101107
26
+ sibi_flux/datacube/cli.py,sha256=z3NxwkGd44v58X3pxsOWcvYyvXOW_4_61V-gD_Kkzqs,103410
27
27
  sibi_flux/datacube/config_engine.py,sha256=3cmxycCqMzjYJ1fWn8IWrHTNwSQmRqxnPoOzc1lUtDk,8340
28
28
  sibi_flux/datacube/field_factory.py,sha256=Z3Yp6tGzrZ13rvKSjMFr9jvW7fazeNi4K1fAalxLujM,6376
29
29
  sibi_flux/datacube/field_mapper.py,sha256=V6aFYunl28DI7gSvrF7tcidPNX9QtOYymVxbumzQqPs,9334
30
30
  sibi_flux/datacube/field_registry.py,sha256=VBTqxNIn2-eWMiZi1oQK-719oyJfn3yhfV7Bz_0iNyU,4355
31
- sibi_flux/datacube/generator.py,sha256=gPGQW114N7jfyGwsSXc-jsJup_C4qSj75oM_CoWuP7Y,36943
31
+ sibi_flux/datacube/generator.py,sha256=oDkJozogn_wf-jrOPvtgtw_8rew9AviNQIM1MbSFQa0,38274
32
32
  sibi_flux/datacube/orchestrator.py,sha256=ZS2kh1Q6FF1sPtDaTkIvo8Q2S33OrYogjOWDl15-u-k,25254
33
33
  sibi_flux/datacube/router.py,sha256=SdG0J4O9CSZeUkHjyWHFC8B3oH83fSdDHfMXZfmHfi0,10914
34
34
  sibi_flux/dataset/__init__.py,sha256=zYpf4-nalcQNSUIOCDG0CqQu2SKkm89I9AF6Zy6z1sE,53
@@ -68,7 +68,7 @@ sibi_flux/init/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
68
68
  sibi_flux/init/app.py,sha256=Ofx_Sowvv6Ri-tDhLYkYllB_e1-4227J-MqhURTAmhI,3678
69
69
  sibi_flux/init/core.py,sha256=ahl4wVAyOrl1ko-f2NcYxeX9yQBQceYnobqeH_Gfp98,7785
70
70
  sibi_flux/init/cube_extender.py,sha256=wQPM0zncr97AiGCVM2BYo7dyaLKWIndV-0GvGNXvAMA,5269
71
- sibi_flux/init/cube_proposer.py,sha256=VA7WF-pDtto9-UdN1IlB7u6TiuxgMbgy79TRooyBPro,5071
71
+ sibi_flux/init/cube_proposer.py,sha256=FdcSbdgV7z2a2omeCJAhlM7zcnix440oMAz1bzl6LlE,5242
72
72
  sibi_flux/init/discovery_updater.py,sha256=3WONU50EnaIItaLncumd3hC6h059ykvoqMfRC5NAvi8,5652
73
73
  sibi_flux/init/env.py,sha256=WMczkJqdaCejSbkjcpW8a44GZdKicdh5GVfUqKYltBI,3792
74
74
  sibi_flux/init/env_engine.py,sha256=HYBik80qgp-_2RgnQY2edaKA30VY1k_3uAZ4TqIID2M,6247
@@ -123,7 +123,7 @@ sibi_flux/utils/file_utils.py,sha256=7OHUW65OTe6HlQ6wkDagDd7d0SCQ_-NEGmHlOJguKYw
123
123
  sibi_flux/utils/filepath_generator/__init__.py,sha256=YVFJhIewjwksb9E2t43ojNC-W_AqUDhkKxQVBIBMkY8,91
124
124
  sibi_flux/utils/filepath_generator/_filepath_generator.py,sha256=4HG-Ubvjtv6luL0z-A-8B6_r3o9YqBwATFXhOXiTbKc,6789
125
125
  sibi_flux/utils/retry.py,sha256=45t0MF2IoMayN9xkn5_FtakMq4HwZlGvHVd6qv8x1AY,1227
126
- sibi_flux-2026.1.8.dist-info/WHEEL,sha256=ZyFSCYkV2BrxH6-HRVRg3R9Fo7MALzer9KiPYqNxSbo,79
127
- sibi_flux-2026.1.8.dist-info/entry_points.txt,sha256=6xrq5zuz_8wodJj4s49raopnuC3Owy_leZRkWtcXpTk,49
128
- sibi_flux-2026.1.8.dist-info/METADATA,sha256=Jm2z9nxpK77TbqwAxWvA_s8fy5y_N71LJzfNnAwkLFM,9886
129
- sibi_flux-2026.1.8.dist-info/RECORD,,
126
+ sibi_flux-2026.1.9.dist-info/WHEEL,sha256=ZyFSCYkV2BrxH6-HRVRg3R9Fo7MALzer9KiPYqNxSbo,79
127
+ sibi_flux-2026.1.9.dist-info/entry_points.txt,sha256=6xrq5zuz_8wodJj4s49raopnuC3Owy_leZRkWtcXpTk,49
128
+ sibi_flux-2026.1.9.dist-info/METADATA,sha256=vaMygw_hUTc3ORvTh4kYbt_5v5Ovvtdm3dchFZxOGF8,9886
129
+ sibi_flux-2026.1.9.dist-info/RECORD,,