satisfactoscript 0.5.9__tar.gz → 0.5.10__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 (32) hide show
  1. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/PKG-INFO +1 -1
  2. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/pyproject.toml +1 -1
  3. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/src/satisfactoscript/__init__.py +2 -1
  4. satisfactoscript-0.5.10/src/satisfactoscript/registry.py +7 -0
  5. satisfactoscript-0.5.10/src/satisfactoscript/utils.py +29 -0
  6. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/src/satisfactoscript.egg-info/PKG-INFO +1 -1
  7. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/src/satisfactoscript.egg-info/SOURCES.txt +5 -1
  8. satisfactoscript-0.5.10/tests/test_registry_import_paths.py +26 -0
  9. satisfactoscript-0.5.10/tests/test_utils_safe_columns.py +46 -0
  10. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/README.md +0 -0
  11. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/setup.cfg +0 -0
  12. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/src/satisfactoscript/agentic/__init__.py +0 -0
  13. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/src/satisfactoscript/agentic/agent.py +0 -0
  14. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/src/satisfactoscript/core/__init__.py +0 -0
  15. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/src/satisfactoscript/core/config.py +0 -0
  16. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/src/satisfactoscript/core/core.py +0 -0
  17. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/src/satisfactoscript/core/loaders.py +0 -0
  18. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/src/satisfactoscript/core/registry.py +0 -0
  19. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/src/satisfactoscript/semantic/__init__.py +0 -0
  20. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/src/satisfactoscript/semantic/semantic.py +0 -0
  21. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/src/satisfactoscript.egg-info/dependency_links.txt +0 -0
  22. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/src/satisfactoscript.egg-info/requires.txt +0 -0
  23. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/src/satisfactoscript.egg-info/top_level.txt +0 -0
  24. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/tests/test_config.py +0 -0
  25. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/tests/test_core.py +0 -0
  26. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/tests/test_core_connect_patch.py +0 -0
  27. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/tests/test_core_env_detection.py +0 -0
  28. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/tests/test_core_join.py +0 -0
  29. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/tests/test_core_username.py +0 -0
  30. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/tests/test_dummy.py +0 -0
  31. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/tests/test_loaders.py +0 -0
  32. {satisfactoscript-0.5.9 → satisfactoscript-0.5.10}/tests/test_registry.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: satisfactoscript
3
- Version: 0.5.9
3
+ Version: 0.5.10
4
4
  Summary: An Enterprise-Ready, Declarative Data Engineering Framework for Databricks Lakehouse.
5
5
  Author: julhouba
6
6
  Classifier: Programming Language :: Python :: 3
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "satisfactoscript"
7
- version = "0.5.9"
7
+ version = "0.5.10"
8
8
  description = "An Enterprise-Ready, Declarative Data Engineering Framework for Databricks Lakehouse."
9
9
  readme = "README.md"
10
10
  authors = [
@@ -1,5 +1,6 @@
1
1
  from .core.core import SatisfactoEngine
2
2
  from .core.registry import RuleRegistry
3
3
  from .core.config import ConfigurationManager
4
+ from .utils import safe_columns
4
5
 
5
- __all__ = ["SatisfactoEngine", "RuleRegistry", "ConfigurationManager"]
6
+ __all__ = ["SatisfactoEngine", "RuleRegistry", "ConfigurationManager", "safe_columns"]
@@ -0,0 +1,7 @@
1
+ """
2
+ Compatibility shim — keeps `from satisfactoscript.registry import RuleRegistry` working.
3
+ The canonical location is satisfactoscript.core.registry.
4
+ """
5
+ from satisfactoscript.core.registry import RuleRegistry
6
+
7
+ __all__ = ["RuleRegistry"]
@@ -0,0 +1,29 @@
1
+ """
2
+ Utility helpers for rule authoring — compatible with Databricks Connect v2.
3
+ """
4
+
5
+
6
+ def safe_columns(df):
7
+ """
8
+ Returns the column names of a DataFrame without triggering a failing AnalyzePlan RPC.
9
+
10
+ On native Databricks (cluster / notebook), this delegates to ``df.columns`` as normal.
11
+ On Databricks Connect v2 from local environments (PyCharm / VS Code on Windows), the
12
+ ``AnalyzePlan`` gRPC call that backs ``df.columns`` can fail with
13
+ ``Missing required field 'UserContext'``. In that case this function returns an empty
14
+ list so that optional-column branches in business rules are silently skipped rather than
15
+ crashing. Core transformations (withColumn, filter, write …) are unaffected because they
16
+ go through ``ExecutePlan``, not ``AnalyzePlan``.
17
+
18
+ Args:
19
+ df: A PySpark DataFrame.
20
+
21
+ Returns:
22
+ list[str]: Column names, or ``[]`` when schema inspection fails locally.
23
+ """
24
+ try:
25
+ return df.columns
26
+ except Exception as e:
27
+ if "UserContext" in str(e) or "INVALID_ARGUMENT" in str(e):
28
+ return []
29
+ raise
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: satisfactoscript
3
- Version: 0.5.9
3
+ Version: 0.5.10
4
4
  Summary: An Enterprise-Ready, Declarative Data Engineering Framework for Databricks Lakehouse.
5
5
  Author: julhouba
6
6
  Classifier: Programming Language :: Python :: 3
@@ -1,6 +1,8 @@
1
1
  README.md
2
2
  pyproject.toml
3
3
  src/satisfactoscript/__init__.py
4
+ src/satisfactoscript/registry.py
5
+ src/satisfactoscript/utils.py
4
6
  src/satisfactoscript.egg-info/PKG-INFO
5
7
  src/satisfactoscript.egg-info/SOURCES.txt
6
8
  src/satisfactoscript.egg-info/dependency_links.txt
@@ -23,4 +25,6 @@ tests/test_core_join.py
23
25
  tests/test_core_username.py
24
26
  tests/test_dummy.py
25
27
  tests/test_loaders.py
26
- tests/test_registry.py
28
+ tests/test_registry.py
29
+ tests/test_registry_import_paths.py
30
+ tests/test_utils_safe_columns.py
@@ -0,0 +1,26 @@
1
+ """
2
+ Tests for RuleRegistry import path compatibility.
3
+ All import paths must resolve to the same singleton class.
4
+ """
5
+ from satisfactoscript.core.registry import RuleRegistry as RR_core
6
+ from satisfactoscript.registry import RuleRegistry as RR_shim
7
+ from satisfactoscript import RuleRegistry as RR_top
8
+
9
+
10
+ def test_all_import_paths_resolve_to_same_class():
11
+ """All three import paths must return the exact same class (same singleton)."""
12
+ assert RR_core is RR_shim
13
+ assert RR_core is RR_top
14
+
15
+
16
+ def test_rule_registered_via_shim_is_visible_everywhere():
17
+ """A rule registered using the shim import must be retrievable from all paths."""
18
+ @RR_shim.register_rule(name="__test_shim_rule__")
19
+ def _my_rule(df):
20
+ return df
21
+
22
+ assert RR_core.get_rule("__test_shim_rule__") is _my_rule
23
+ assert RR_top.get_rule("__test_shim_rule__") is _my_rule
24
+
25
+ # Cleanup
26
+ RR_core._rules.pop("__test_shim_rule__", None)
@@ -0,0 +1,46 @@
1
+ """
2
+ Tests for satisfactoscript.utils.safe_columns.
3
+ """
4
+ import pytest
5
+ from unittest.mock import MagicMock, PropertyMock
6
+ from satisfactoscript import safe_columns
7
+
8
+
9
+ class TestSafeColumns:
10
+
11
+ def test_returns_df_columns_normally(self):
12
+ df = MagicMock()
13
+ type(df).columns = PropertyMock(return_value=["id", "name", "value"])
14
+
15
+ assert safe_columns(df) == ["id", "name", "value"]
16
+
17
+ def test_returns_empty_list_on_usercontext_grpc_error(self):
18
+ df = MagicMock()
19
+ type(df).columns = PropertyMock(
20
+ side_effect=Exception("gRPC: Missing required field 'UserContext' in the request.")
21
+ )
22
+
23
+ result = safe_columns(df)
24
+
25
+ assert result == []
26
+
27
+ def test_returns_empty_list_on_invalid_argument_grpc_error(self):
28
+ df = MagicMock()
29
+ type(df).columns = PropertyMock(
30
+ side_effect=Exception("StatusCode.INVALID_ARGUMENT details: something")
31
+ )
32
+
33
+ result = safe_columns(df)
34
+
35
+ assert result == []
36
+
37
+ def test_reraises_unrelated_exceptions(self):
38
+ df = MagicMock()
39
+ type(df).columns = PropertyMock(side_effect=RuntimeError("disk full"))
40
+
41
+ with pytest.raises(RuntimeError, match="disk full"):
42
+ safe_columns(df)
43
+
44
+ def test_importable_from_satisfactoscript_top_level(self):
45
+ from satisfactoscript import safe_columns as sc
46
+ assert callable(sc)