ml-analytics-tools 0.4.2__tar.gz → 0.4.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.
Files changed (33) hide show
  1. {ml_analytics_tools-0.4.2/ml_analytics_tools.egg-info → ml_analytics_tools-0.4.3}/PKG-INFO +1 -1
  2. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/ml_analytics/utils.py +68 -11
  3. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3/ml_analytics_tools.egg-info}/PKG-INFO +1 -1
  4. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/pyproject.toml +1 -1
  5. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/tests/test_utils.py +28 -1
  6. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/LICENSE +0 -0
  7. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/README.md +0 -0
  8. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/ml_analytics/__init__.py +0 -0
  9. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/ml_analytics/aws_auth.py +0 -0
  10. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/ml_analytics/cli.py +0 -0
  11. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/ml_analytics/data_connector.py +0 -0
  12. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/ml_analytics/gsheet_connector.py +0 -0
  13. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/ml_analytics/model_manager.py +0 -0
  14. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/ml_analytics/model_tools.py +0 -0
  15. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/ml_analytics/s3_connector.py +0 -0
  16. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/ml_analytics/sf_connector.py +0 -0
  17. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/ml_analytics/slack_connector.py +0 -0
  18. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/ml_analytics/tunnel_manager.py +0 -0
  19. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/ml_analytics_tools.egg-info/SOURCES.txt +0 -0
  20. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/ml_analytics_tools.egg-info/dependency_links.txt +0 -0
  21. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/ml_analytics_tools.egg-info/entry_points.txt +0 -0
  22. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/ml_analytics_tools.egg-info/requires.txt +0 -0
  23. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/ml_analytics_tools.egg-info/top_level.txt +0 -0
  24. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/setup.cfg +0 -0
  25. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/tests/test_aws_auth.py +0 -0
  26. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/tests/test_db_s3.py +0 -0
  27. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/tests/test_gsheet_connector.py +0 -0
  28. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/tests/test_identity_column.py +0 -0
  29. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/tests/test_model_manager.py +0 -0
  30. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/tests/test_model_tools.py +0 -0
  31. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/tests/test_s3_redshift_validation.py +0 -0
  32. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/tests/test_sf_connector.py +0 -0
  33. {ml_analytics_tools-0.4.2 → ml_analytics_tools-0.4.3}/tests/test_tunnel_manager.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ml-analytics-tools
3
- Version: 0.4.2
3
+ Version: 0.4.3
4
4
  Summary: Tools for ML projects and data management
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -68,6 +68,24 @@ def _get_dbutils():
68
68
  return _DBUTILS
69
69
 
70
70
  _DBUTILS_RESOLVED = True
71
+ try:
72
+ import builtins
73
+
74
+ _DBUTILS = getattr(builtins, "dbutils", None)
75
+ if _DBUTILS is not None:
76
+ return _DBUTILS
77
+ except Exception:
78
+ pass
79
+
80
+ try:
81
+ import __main__
82
+
83
+ _DBUTILS = getattr(__main__, "dbutils", None)
84
+ if _DBUTILS is not None:
85
+ return _DBUTILS
86
+ except Exception:
87
+ pass
88
+
71
89
  try:
72
90
  from databricks.sdk.runtime import dbutils
73
91
 
@@ -89,6 +107,29 @@ def _get_dbutils():
89
107
  return _DBUTILS
90
108
 
91
109
 
110
+ def _databricks_notebook_dir() -> Path | None:
111
+ """
112
+ Return the active Databricks notebook's workspace filesystem directory.
113
+
114
+ Databricks sets Python's cwd to the driver directory in many notebook/job
115
+ contexts, so relative workspace files need the notebook path as an anchor.
116
+ """
117
+ dbutils = _get_dbutils()
118
+ if dbutils is None:
119
+ return None
120
+
121
+ try:
122
+ ctx = dbutils.notebook.entry_point.getDbutils().notebook().getContext()
123
+ notebook_path = ctx.notebookPath().get()
124
+ except Exception:
125
+ return None
126
+
127
+ if not notebook_path:
128
+ return None
129
+
130
+ return (Path("/Workspace") / str(notebook_path).lstrip("/")).parent
131
+
132
+
92
133
  def get_credential_value(name, scope="ml"):
93
134
  """
94
135
  Get the value of the credential or variable called "name" in different environments.
@@ -367,21 +408,37 @@ def get_sql_files(relative_folder: str, pipeline: str | None = None) -> dict[str
367
408
 
368
409
  def load_sql_query(query_path: str, **kwargs) -> str | None:
369
410
  """
370
- Load a SQL query from a file relative to the project root.
411
+ Load a SQL query from a file.
412
+
413
+ Relative paths are resolved from the project root first, then the current
414
+ working directory, then the active Databricks notebook directory when
415
+ available.
371
416
  """
372
417
  logger = get_logger("ml_analytics.utils.load_sql_query")
373
418
 
374
419
  try:
375
- project_root = find_project_root()
376
- absolute_file_path = project_root / query_path
377
- if not absolute_file_path.exists():
378
- logger.error(f"SQL file '{query_path}' not found at '{absolute_file_path}'.")
379
- return None
380
- with open(absolute_file_path) as file:
381
- sql_query = file.read().format(**kwargs)
382
- return sql_query
383
- except FileNotFoundError:
384
- logger.error("Could not load SQL query because project root was not found.")
420
+ path = Path(query_path).expanduser()
421
+ if path.is_absolute():
422
+ candidate_paths = [path]
423
+ else:
424
+ candidate_paths = []
425
+ project_root = find_project_root(required=False)
426
+ if project_root is not None:
427
+ candidate_paths.append(project_root / path)
428
+ candidate_paths.append(Path.cwd() / path)
429
+ notebook_dir = _databricks_notebook_dir()
430
+ if notebook_dir is not None:
431
+ candidate_paths.append(notebook_dir / path)
432
+
433
+ checked_paths = []
434
+ for absolute_file_path in dict.fromkeys(candidate_paths):
435
+ checked_paths.append(str(absolute_file_path))
436
+ if not absolute_file_path.exists():
437
+ continue
438
+ with open(absolute_file_path) as file:
439
+ return file.read().format(**kwargs)
440
+
441
+ logger.error(f"SQL file '{query_path}' not found. Checked: {checked_paths}.")
385
442
  return None
386
443
  except Exception as e:
387
444
  logger.error(f"Error loading SQL query {query_path}: {e}", exc_info=True)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ml-analytics-tools
3
- Version: 0.4.2
3
+ Version: 0.4.3
4
4
  Summary: Tools for ML projects and data management
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ml-analytics-tools"
3
- version = "0.4.2"
3
+ version = "0.4.3"
4
4
  description = "Tools for ML projects and data management"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -4,7 +4,7 @@ from unittest.mock import MagicMock, patch
4
4
 
5
5
  import pytest
6
6
 
7
- from ml_analytics.utils import execute_sql_scripts, get_sql_files
7
+ from ml_analytics.utils import execute_sql_scripts, get_sql_files, load_sql_query
8
8
 
9
9
  SQL_FOLDER_NAME = "queries"
10
10
 
@@ -130,6 +130,33 @@ class TestGetSqlFilesYamlMode:
130
130
  assert result["alpha"] == sql_folder / "alpha.sql"
131
131
 
132
132
 
133
+ class TestLoadSqlQuery:
134
+ def test_relative_path_falls_back_to_cwd_without_project_root(self, monkeypatch, tmp_path):
135
+ sql_file = tmp_path / "sql" / "experiment.sql"
136
+ sql_file.parent.mkdir()
137
+ sql_file.write_text("SELECT {n} AS n")
138
+
139
+ monkeypatch.chdir(tmp_path)
140
+ monkeypatch.setattr("ml_analytics.utils.find_project_root", lambda *args, **kwargs: None)
141
+ monkeypatch.setattr("ml_analytics.utils._databricks_notebook_dir", lambda: None)
142
+
143
+ assert load_sql_query("sql/experiment.sql", n=7) == "SELECT 7 AS n"
144
+
145
+ def test_relative_path_falls_back_to_databricks_notebook_dir(self, monkeypatch, tmp_path):
146
+ driver_dir = tmp_path / "driver"
147
+ notebook_dir = tmp_path / "Workspace" / "Users" / "me" / "exploring"
148
+ sql_file = notebook_dir / "sql" / "experiment.sql"
149
+ driver_dir.mkdir()
150
+ sql_file.parent.mkdir(parents=True)
151
+ sql_file.write_text("SELECT 1")
152
+
153
+ monkeypatch.chdir(driver_dir)
154
+ monkeypatch.setattr("ml_analytics.utils.find_project_root", lambda *args, **kwargs: None)
155
+ monkeypatch.setattr("ml_analytics.utils._databricks_notebook_dir", lambda: notebook_dir)
156
+
157
+ assert load_sql_query("sql/experiment.sql") == "SELECT 1"
158
+
159
+
133
160
  # ---------------------------------------------------------------------------
134
161
  # execute_sql_scripts — folder path inputs
135
162
  # ---------------------------------------------------------------------------