duckrun 0.2.10__tar.gz → 0.2.10.dev1__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 duckrun might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: duckrun
3
- Version: 0.2.10
3
+ Version: 0.2.10.dev1
4
4
  Summary: Lakehouse task runner powered by DuckDB for Microsoft Fabric
5
5
  Author: mim
6
6
  License: MIT
@@ -94,6 +94,7 @@ class Duckrun:
94
94
  pass # Not in Colab, use default transport
95
95
 
96
96
  self._attach_lakehouse()
97
+ self._register_lookup_functions()
97
98
 
98
99
  @classmethod
99
100
  def connect(cls, connection_string: str, sql_folder: Optional[str] = None,
@@ -457,6 +458,151 @@ class Duckrun:
457
458
  print(f"❌ Error attaching lakehouse: {e}")
458
459
  print("Continuing without pre-attached tables.")
459
460
 
461
+ def _register_lookup_functions(self):
462
+ """
463
+ Register Fabric API lookup functions as DuckDB UDFs.
464
+ Allows SQL queries to resolve workspace/lakehouse names from IDs and vice versa.
465
+
466
+ Functions registered:
467
+ - get_workspace_name(workspace_id) -> str
468
+ - get_lakehouse_name(workspace_id, lakehouse_id) -> str
469
+ - get_workspace_id_from_name(workspace_name) -> str
470
+ - get_lakehouse_id_from_name(workspace_id, lakehouse_name) -> str
471
+ """
472
+ # Cache to avoid repeated API calls
473
+ self._name_cache = {
474
+ 'workspace_id_to_name': {},
475
+ 'workspace_name_to_id': {},
476
+ 'lakehouse_id_to_name': {},
477
+ 'lakehouse_name_to_id': {}
478
+ }
479
+
480
+ def get_workspace_name(workspace_id: str) -> str:
481
+ """Get workspace display name from workspace ID (GUID)"""
482
+ if workspace_id in self._name_cache['workspace_id_to_name']:
483
+ return self._name_cache['workspace_id_to_name'][workspace_id]
484
+
485
+ try:
486
+ from .auth import get_fabric_api_token
487
+ token = get_fabric_api_token()
488
+ if not token:
489
+ return None
490
+
491
+ url = "https://api.fabric.microsoft.com/v1/workspaces"
492
+ headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
493
+ response = requests.get(url, headers=headers)
494
+ response.raise_for_status()
495
+
496
+ workspaces = response.json().get("value", [])
497
+ for workspace in workspaces:
498
+ if workspace.get("id") == workspace_id:
499
+ name = workspace.get("displayName", "")
500
+ self._name_cache['workspace_id_to_name'][workspace_id] = name
501
+ self._name_cache['workspace_name_to_id'][name] = workspace_id
502
+ return name
503
+
504
+ return None
505
+ except Exception as e:
506
+ return None
507
+
508
+ def get_lakehouse_name(workspace_id: str, lakehouse_id: str) -> str:
509
+ """Get lakehouse display name from workspace ID and lakehouse ID (GUIDs)"""
510
+ cache_key = f"{workspace_id}/{lakehouse_id}"
511
+ if cache_key in self._name_cache['lakehouse_id_to_name']:
512
+ return self._name_cache['lakehouse_id_to_name'][cache_key]
513
+
514
+ try:
515
+ from .auth import get_fabric_api_token
516
+ token = get_fabric_api_token()
517
+ if not token:
518
+ return None
519
+
520
+ url = f"https://api.fabric.microsoft.com/v1/workspaces/{workspace_id}/lakehouses"
521
+ headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
522
+ response = requests.get(url, headers=headers)
523
+ response.raise_for_status()
524
+
525
+ lakehouses = response.json().get("value", [])
526
+ for lakehouse in lakehouses:
527
+ if lakehouse.get("id") == lakehouse_id:
528
+ name = lakehouse.get("displayName", "")
529
+ self._name_cache['lakehouse_id_to_name'][cache_key] = name
530
+ lh_cache_key = f"{workspace_id}/{name}"
531
+ self._name_cache['lakehouse_name_to_id'][lh_cache_key] = lakehouse_id
532
+ return name
533
+
534
+ return None
535
+ except Exception as e:
536
+ return None
537
+
538
+ def get_workspace_id_from_name(workspace_name: str) -> str:
539
+ """Get workspace ID (GUID) from workspace display name"""
540
+ if workspace_name in self._name_cache['workspace_name_to_id']:
541
+ return self._name_cache['workspace_name_to_id'][workspace_name]
542
+
543
+ try:
544
+ from .auth import get_fabric_api_token
545
+ token = get_fabric_api_token()
546
+ if not token:
547
+ return None
548
+
549
+ url = "https://api.fabric.microsoft.com/v1/workspaces"
550
+ headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
551
+ response = requests.get(url, headers=headers)
552
+ response.raise_for_status()
553
+
554
+ workspaces = response.json().get("value", [])
555
+ for workspace in workspaces:
556
+ if workspace.get("displayName") == workspace_name:
557
+ workspace_id = workspace.get("id", "")
558
+ self._name_cache['workspace_name_to_id'][workspace_name] = workspace_id
559
+ self._name_cache['workspace_id_to_name'][workspace_id] = workspace_name
560
+ return workspace_id
561
+
562
+ return None
563
+ except Exception as e:
564
+ return None
565
+
566
+ def get_lakehouse_id_from_name(workspace_id: str, lakehouse_name: str) -> str:
567
+ """Get lakehouse ID (GUID) from workspace ID and lakehouse display name"""
568
+ cache_key = f"{workspace_id}/{lakehouse_name}"
569
+ if cache_key in self._name_cache['lakehouse_name_to_id']:
570
+ return self._name_cache['lakehouse_name_to_id'][cache_key]
571
+
572
+ try:
573
+ from .auth import get_fabric_api_token
574
+ token = get_fabric_api_token()
575
+ if not token:
576
+ return None
577
+
578
+ url = f"https://api.fabric.microsoft.com/v1/workspaces/{workspace_id}/lakehouses"
579
+ headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
580
+ response = requests.get(url, headers=headers)
581
+ response.raise_for_status()
582
+
583
+ lakehouses = response.json().get("value", [])
584
+ for lakehouse in lakehouses:
585
+ if lakehouse.get("displayName") == lakehouse_name:
586
+ lakehouse_id = lakehouse.get("id", "")
587
+ self._name_cache['lakehouse_name_to_id'][cache_key] = lakehouse_id
588
+ id_cache_key = f"{workspace_id}/{lakehouse_id}"
589
+ self._name_cache['lakehouse_id_to_name'][id_cache_key] = lakehouse_name
590
+ return lakehouse_id
591
+
592
+ return None
593
+ except Exception as e:
594
+ return None
595
+
596
+ # Register functions in DuckDB
597
+ try:
598
+ self.con.create_function("get_workspace_name", get_workspace_name)
599
+ self.con.create_function("get_lakehouse_name", get_lakehouse_name)
600
+ self.con.create_function("get_workspace_id_from_name", get_workspace_id_from_name)
601
+ self.con.create_function("get_lakehouse_id_from_name", get_lakehouse_id_from_name)
602
+ print("✅ Registered lookup functions: get_workspace_name, get_lakehouse_name, get_workspace_id_from_name, get_lakehouse_id_from_name")
603
+ except Exception as e:
604
+ print(f"⚠️ Warning: Could not register lookup functions: {e}")
605
+
460
606
  def get_workspace_id(self) -> str:
461
607
  """
462
608
  Get the workspace ID (GUID or name without spaces).
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: duckrun
3
- Version: 0.2.10
3
+ Version: 0.2.10.dev1
4
4
  Summary: Lakehouse task runner powered by DuckDB for Microsoft Fabric
5
5
  Author: mim
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "duckrun"
7
- version = "0.2.10"
7
+ version = "0.2.10.dev1"
8
8
  description = "Lakehouse task runner powered by DuckDB for Microsoft Fabric"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes