satisfactoscript 0.6.1__tar.gz → 0.6.3__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.
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/PKG-INFO +1 -1
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/pyproject.toml +1 -1
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/src/satisfactoscript/core/core.py +54 -6
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/src/satisfactoscript.egg-info/PKG-INFO +1 -1
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/README.md +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/setup.cfg +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/src/satisfactoscript/__init__.py +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/src/satisfactoscript/agentic/__init__.py +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/src/satisfactoscript/agentic/agent.py +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/src/satisfactoscript/core/__init__.py +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/src/satisfactoscript/core/config.py +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/src/satisfactoscript/core/loaders.py +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/src/satisfactoscript/core/registry.py +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/src/satisfactoscript/registry.py +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/src/satisfactoscript/semantic/__init__.py +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/src/satisfactoscript/semantic/semantic.py +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/src/satisfactoscript/utils.py +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/src/satisfactoscript.egg-info/SOURCES.txt +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/src/satisfactoscript.egg-info/dependency_links.txt +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/src/satisfactoscript.egg-info/requires.txt +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/src/satisfactoscript.egg-info/top_level.txt +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/tests/test_config.py +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/tests/test_core.py +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/tests/test_core_connect_patch.py +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/tests/test_core_env_detection.py +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/tests/test_core_join.py +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/tests/test_core_username.py +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/tests/test_dummy.py +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/tests/test_loaders.py +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/tests/test_registry.py +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/tests/test_registry_import_paths.py +0 -0
- {satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/tests/test_utils_safe_columns.py +0 -0
|
@@ -210,6 +210,7 @@ class SatisfactoEngine:
|
|
|
210
210
|
raise RuntimeError("CRITICAL: Failed to initialize Spark Session.")
|
|
211
211
|
|
|
212
212
|
self._patch_connect_debugging()
|
|
213
|
+
self._patch_connect_user_context()
|
|
213
214
|
self.dbutils = DBUtils(self.spark)
|
|
214
215
|
|
|
215
216
|
# ======================================================================
|
|
@@ -279,6 +280,42 @@ class SatisfactoEngine:
|
|
|
279
280
|
except Exception:
|
|
280
281
|
pass
|
|
281
282
|
|
|
283
|
+
def _patch_connect_user_context(self):
|
|
284
|
+
"""
|
|
285
|
+
Patches SparkConnectClient._user_id when it is empty or missing.
|
|
286
|
+
|
|
287
|
+
Root cause: on Databricks Connect v2 from local environments (Windows/PyCharm),
|
|
288
|
+
the gRPC session is created successfully but _user_id is not populated from the
|
|
289
|
+
SDK config. PySpark's execute_command only injects user_context.user_id when
|
|
290
|
+
self._user_id is truthy — so every gRPC execution call (saveAsTable, collect,
|
|
291
|
+
execute_command for DDL) fails immediately with:
|
|
292
|
+
'Missing required field UserContext'
|
|
293
|
+
|
|
294
|
+
Fix: after session creation, if _user_id is absent on the SparkConnectClient,
|
|
295
|
+
fetch the current user's email via the Databricks SDK REST API (which is not
|
|
296
|
+
affected by the gRPC issue) and inject it directly into the client object.
|
|
297
|
+
This is a one-time init patch with no functional side effects.
|
|
298
|
+
"""
|
|
299
|
+
try:
|
|
300
|
+
client = getattr(self.spark, 'client', None)
|
|
301
|
+
if client is None:
|
|
302
|
+
return # Standard SparkSession (not a Connect session) — nothing to patch
|
|
303
|
+
|
|
304
|
+
if getattr(client, '_user_id', None):
|
|
305
|
+
return # Already properly set — no patch needed
|
|
306
|
+
|
|
307
|
+
from databricks.sdk import WorkspaceClient
|
|
308
|
+
host = os.getenv("DATABRICKS_HOST")
|
|
309
|
+
token = os.getenv("DATABRICKS_TOKEN")
|
|
310
|
+
if host and token:
|
|
311
|
+
w = WorkspaceClient(host=host, token=token)
|
|
312
|
+
email = w.current_user.me().user_name
|
|
313
|
+
if email:
|
|
314
|
+
client._user_id = email
|
|
315
|
+
print(f" [Init] ⚙️ Applied UserContext patch: user_id injected ('{email}').")
|
|
316
|
+
except Exception:
|
|
317
|
+
pass
|
|
318
|
+
|
|
282
319
|
def _find_file_upwards(self, filename):
|
|
283
320
|
"""
|
|
284
321
|
Searches for a file starting from current working directory and moving up.
|
|
@@ -546,10 +583,15 @@ class SatisfactoEngine:
|
|
|
546
583
|
fqn (str): The Fully Qualified Name of the target table.
|
|
547
584
|
label (str): A label to display in the logging output.
|
|
548
585
|
"""
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
586
|
+
try:
|
|
587
|
+
if df.isEmpty():
|
|
588
|
+
print(f" -> [Write] WARNING: Dataframe for {label} is empty. Skipping write.")
|
|
589
|
+
return
|
|
590
|
+
except Exception:
|
|
591
|
+
# isEmpty() triggers collect() via gRPC, which fails with UserContext on
|
|
592
|
+
# Databricks Connect v2 locally. Skip the check and proceed with the write.
|
|
593
|
+
pass
|
|
594
|
+
|
|
553
595
|
print(f" -> [Write] Writing data to: {fqn} ...")
|
|
554
596
|
df.write.format("delta").mode("overwrite").option("overwriteSchema", "true").saveAsTable(fqn)
|
|
555
597
|
print(f" -> [Success] Table {label} written successfully.")
|
|
@@ -846,5 +888,11 @@ class SatisfactoEngine:
|
|
|
846
888
|
print(f" -> [Success] Table {target_table_name} optimized successfully.")
|
|
847
889
|
|
|
848
890
|
except Exception as e:
|
|
849
|
-
|
|
850
|
-
|
|
891
|
+
# OPTIMIZE is a Databricks DDL command with no SDK REST equivalent.
|
|
892
|
+
# When running locally via Databricks Connect v2, gRPC DDL calls fail with
|
|
893
|
+
# 'Missing required field UserContext'. In that case, skip silently.
|
|
894
|
+
if "UserContext" in str(e) or "user_context" in str(e).lower():
|
|
895
|
+
print(f" -> ⚠️ [Optimize] Skipped: OPTIMIZE is not supported via Databricks Connect v2 locally.")
|
|
896
|
+
else:
|
|
897
|
+
print(f" -> ❌ [Error] Optimization failed on {full_target_fqn}: {e}")
|
|
898
|
+
raise e
|
|
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
|
{satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/src/satisfactoscript.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/src/satisfactoscript.egg-info/requires.txt
RENAMED
|
File without changes
|
{satisfactoscript-0.6.1 → satisfactoscript-0.6.3}/src/satisfactoscript.egg-info/top_level.txt
RENAMED
|
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
|