dasl-client 1.0.7__tar.gz → 1.0.11__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 dasl-client might be problematic. Click here for more details.

Files changed (39) hide show
  1. {dasl_client-1.0.7 → dasl_client-1.0.11}/PKG-INFO +3 -2
  2. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client/auth/auth.py +6 -5
  3. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client/client.py +45 -9
  4. dasl_client-1.0.11/dasl_client/preset_development/__init__.py +4 -0
  5. dasl_client-1.0.11/dasl_client/preset_development/errors.py +159 -0
  6. dasl_client-1.0.11/dasl_client/preset_development/preview_engine.py +344 -0
  7. dasl_client-1.0.11/dasl_client/preset_development/preview_parameters.py +386 -0
  8. dasl_client-1.0.11/dasl_client/preset_development/stage.py +559 -0
  9. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client/types/__init__.py +1 -0
  10. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client/types/admin_config.py +10 -7
  11. dasl_client-1.0.11/dasl_client/types/content.py +235 -0
  12. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client/types/datasource.py +177 -138
  13. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client/types/dbui.py +46 -34
  14. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client/types/rule.py +91 -65
  15. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client/types/types.py +67 -54
  16. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client/types/workspace_config.py +90 -74
  17. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client.egg-info/PKG-INFO +3 -2
  18. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client.egg-info/SOURCES.txt +6 -0
  19. dasl_client-1.0.11/dasl_client.egg-info/requires.txt +4 -0
  20. {dasl_client-1.0.7 → dasl_client-1.0.11}/pyproject.toml +4 -3
  21. dasl_client-1.0.7/dasl_client.egg-info/requires.txt +0 -3
  22. {dasl_client-1.0.7 → dasl_client-1.0.11}/LICENSE +0 -0
  23. {dasl_client-1.0.7 → dasl_client-1.0.11}/README.md +0 -0
  24. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client/__init__.py +0 -0
  25. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client/auth/__init__.py +0 -0
  26. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client/conn/__init__.py +0 -0
  27. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client/conn/client_identifier.py +0 -0
  28. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client/conn/conn.py +0 -0
  29. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client/errors/__init__.py +0 -0
  30. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client/errors/errors.py +0 -0
  31. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client/helpers.py +0 -0
  32. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client/types/helpers.py +0 -0
  33. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client.egg-info/dependency_links.txt +0 -0
  34. {dasl_client-1.0.7 → dasl_client-1.0.11}/dasl_client.egg-info/top_level.txt +0 -0
  35. {dasl_client-1.0.7 → dasl_client-1.0.11}/setup.cfg +0 -0
  36. {dasl_client-1.0.7 → dasl_client-1.0.11}/setup.py +0 -0
  37. {dasl_client-1.0.7 → dasl_client-1.0.11}/test/test_api_changes.py +0 -0
  38. {dasl_client-1.0.7 → dasl_client-1.0.11}/test/test_api_surface.py +0 -0
  39. {dasl_client-1.0.7 → dasl_client-1.0.11}/test/test_marshaling.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dasl_client
3
- Version: 1.0.7
3
+ Version: 1.0.11
4
4
  Summary: The DASL client library used for interacting with the DASL workspace
5
5
  Home-page: https://github.com/antimatter/asl
6
6
  Author: Antimatter Team
@@ -8,9 +8,10 @@ Author-email: Antimatter Team <support@antimatter.io>
8
8
  Requires-Python: >=3.8
9
9
  Description-Content-Type: text/markdown
10
10
  License-File: LICENSE
11
- Requires-Dist: dasl_api==0.1.12
11
+ Requires-Dist: dasl_api==0.1.14
12
12
  Requires-Dist: databricks-sdk>=0.41.0
13
13
  Requires-Dist: pydantic>=2
14
+ Requires-Dist: typing_extensions==4.10.0
14
15
 
15
16
  # DASL Client Library
16
17
 
@@ -1,4 +1,5 @@
1
1
  import abc
2
+ import base64
2
3
  import time
3
4
  from datetime import datetime
4
5
 
@@ -176,15 +177,15 @@ class DatabricksSecretAuth(Authorization):
176
177
  principalName=self._principal,
177
178
  )
178
179
  handler = api.WorkspaceV1Api(api_client=self._client)
179
- resp = handler.workspace_v1_begin_authentication(
180
- workspace=self._workspace, workspace_v1_begin_authenticate_request=req
180
+ resp = handler.workspace_v1_request_secret(
181
+ workspace=self._workspace, workspace_v1_request_secret_request=req
181
182
  )
182
183
  secret_name = resp.secret_name
183
184
  secret_value = ""
184
185
  for tries in range(3):
185
186
  try:
186
- secret_value = WorkspaceClient().secrets.get_secret(
187
- secret_name, "token"
187
+ secret_value = (
188
+ WorkspaceClient().secrets.get_secret(secret_name, "token").value
188
189
  )
189
190
  break
190
191
  except ResourceDoesNotExist:
@@ -194,7 +195,7 @@ class DatabricksSecretAuth(Authorization):
194
195
  raise RuntimeError(f"failed to complete secret auth")
195
196
 
196
197
  req = WorkspaceV1AuthenticateRequest(
197
- databricks_secret=secret_value,
198
+ databricks_secret=base64.b64decode(secret_value).decode("utf-8"),
198
199
  )
199
200
  handler = api.WorkspaceV1Api(api_client=self._client)
200
201
 
@@ -3,8 +3,8 @@ from typing import Any, Callable, Iterator, List, Optional, TypeVar
3
3
 
4
4
  from dasl_api import (
5
5
  CoreV1Api,
6
- CoreV1DataSourceAutoloaderSpec,
7
6
  DbuiV1Api,
7
+ ContentV1Api,
8
8
  WorkspaceV1Api,
9
9
  WorkspaceV1CreateWorkspaceRequest,
10
10
  api,
@@ -13,6 +13,7 @@ from pydantic import Field
13
13
 
14
14
  from dasl_client.auth.auth import (
15
15
  Authorization,
16
+ DatabricksSecretAuth,
16
17
  DatabricksTokenAuth,
17
18
  ServiceAccountKeyAuth,
18
19
  )
@@ -29,6 +30,8 @@ from .types import (
29
30
  WorkspaceConfig,
30
31
  TransformRequest,
31
32
  TransformResponse,
33
+ DataSourcePresetsList,
34
+ DataSourcePreset,
32
35
  )
33
36
 
34
37
 
@@ -51,7 +54,7 @@ class Client:
51
54
 
52
55
  :param auth: Authorization instance for authorizing requests to
53
56
  the dasl control plane.
54
- :returns Client
57
+ :returns: Client
55
58
  """
56
59
  self.auth = auth
57
60
 
@@ -83,7 +86,7 @@ class Client:
83
86
  :param dasl_host: The URL of the DASL server. This value should
84
87
  not generally be specified unless you are testing against
85
88
  an alternative environment.
86
- :returns Client
89
+ :returns: Client for the newly created workspace.
87
90
  """
88
91
  with error_handler():
89
92
  if workspace_url is None:
@@ -131,7 +134,7 @@ class Client:
131
134
  :param dasl_host: The URL of the DASL server. This value should
132
135
  not generally be specified unless you are testing against
133
136
  an alternative environment.
134
- :returns Client
137
+ :returns: Client for the existing workspace.
135
138
  """
136
139
  with error_handler():
137
140
  if workspace_url is None:
@@ -195,7 +198,7 @@ class Client:
195
198
  :param dasl_host: The URL of the DASL server. This value should
196
199
  not generally be specified unless you are testing against
197
200
  an alternative environment.
198
- :returns Client
201
+ :returns: Client for the newly created or existing workspace.
199
202
  """
200
203
  try:
201
204
  return Client.new_workspace(
@@ -229,6 +232,9 @@ class Client:
229
232
  def _dbui_client(self) -> DbuiV1Api:
230
233
  return DbuiV1Api(self.auth.client())
231
234
 
235
+ def _content_client(self) -> ContentV1Api:
236
+ return ContentV1Api(self.auth.client())
237
+
232
238
  def _workspace(self) -> str:
233
239
  return self.auth.workspace()
234
240
 
@@ -274,7 +280,7 @@ class Client:
274
280
  you will need to repopulate the service_principal_secret correctly
275
281
  before passing the result back to put_admin_config.
276
282
 
277
- :returns AdminConfig
283
+ :returns: AdminConfig containing the current settings.
278
284
  """
279
285
  with error_handler():
280
286
  return AdminConfig.from_api_obj(
@@ -306,6 +312,8 @@ class Client:
306
312
  Retrieve the WorkspaceConfig from the DASL server. The returned
307
313
  value can be updated directly and passed to put_config in order
308
314
  to make changes.
315
+
316
+ :returns: WorkspaceConfig containing the current configuration.
309
317
  """
310
318
  with error_handler():
311
319
  return WorkspaceConfig.from_api_obj(
@@ -348,7 +356,7 @@ class Client:
348
356
  in order to make changes.
349
357
 
350
358
  :param name: The unique name of the DataSource within this workspace
351
- :returns DataSource
359
+ :returns: DataSource
352
360
  """
353
361
  with error_handler():
354
362
  return DataSource.from_api_obj(
@@ -459,7 +467,7 @@ class Client:
459
467
  in order to make changes.
460
468
 
461
469
  :param name: The unique name of the Rule within this workspace
462
- :returns Rule
470
+ :returns: Rule
463
471
  """
464
472
  with error_handler():
465
473
  return Rule.from_api_obj(
@@ -601,7 +609,7 @@ class Client:
601
609
  :param value: The observable value
602
610
  :param cursor: A cursor to be used when paginating results
603
611
  :param limit: A limit of the number of results to return
604
- :returns EventsList
612
+ :returns: EventsList
605
613
  """
606
614
  with error_handler():
607
615
  return Dbui.ObservableEvents.EventsList.from_api_obj(
@@ -614,3 +622,31 @@ class Client:
614
622
  limit=limit,
615
623
  )
616
624
  )
625
+
626
+ def list_presets(self) -> DataSourcePresetsList:
627
+ """
628
+ List the Presets in this workspace. This will include any user defined
629
+ presets if a custom presets path has been configured in the workspace.
630
+
631
+ :returns: DataSourcePresetsList
632
+ """
633
+ with error_handler():
634
+ return DataSourcePresetsList.from_api_obj(
635
+ self._content_client().content_v1_get_preset_data_sources(
636
+ self._workspace(),
637
+ )
638
+ )
639
+
640
+ def get_preset(self, name: str) -> DataSourcePreset:
641
+ """
642
+ Get the preset with the argument name from the DASL server. If the preset name
643
+ begins with 'internal_' it will instead be collected from the user catalog,
644
+ provided a preset path is set in the workspace config.
645
+
646
+ :param name: The unique name of the DataSource preset within this workspace.
647
+ :returns: DataSourcePreset
648
+ """
649
+ with error_handler():
650
+ return DataSourcePreset.from_api_obj(
651
+ self._content_client().content_v1_get_preset_datasource(self._workspace(), name)
652
+ )
@@ -0,0 +1,4 @@
1
+ # dasl_client/preset_development/__init__.py
2
+ from .preview_parameters import *
3
+ from .errors import *
4
+ from .preview_engine import *
@@ -0,0 +1,159 @@
1
+ from pyspark.sql import DataFrame, SparkSession
2
+ from pyspark.sql.types import *
3
+ from pyspark.sql.dataframe import DataFrame
4
+ from typing import Dict, Any, List, Mapping, Tuple
5
+ from IPython import get_ipython
6
+
7
+
8
+ class PresetError(Exception):
9
+ pass
10
+
11
+
12
+ class InvalidGoldTableSchemaError(PresetError):
13
+ def __init__(self, schema: str, additional_message: str = ""):
14
+ self.schema = schema
15
+ message = (
16
+ f"Malformed gold schema provided {schema}. {additional_message}".strip()
17
+ )
18
+ super().__init__(message)
19
+
20
+
21
+ class NoSilverStageProvdedError(PresetError):
22
+ def __init__(self, additional_msg: str = ""):
23
+ message = f"No silver stage provided{additional_msg}."
24
+ super().__init__(message)
25
+
26
+
27
+ class NoSilverTransformStageProvdedError(PresetError):
28
+ def __init__(
29
+ self,
30
+ message: str = "No silver transform stage provided, but gold stage is present.",
31
+ ):
32
+ super().__init__(message)
33
+
34
+
35
+ class PreTransformNotFound(PresetError):
36
+ def __init__(
37
+ self,
38
+ message: str = "Requested silver pretransform name not found in preset's silver pretransforms.",
39
+ ):
40
+ super().__init__(message)
41
+
42
+
43
+ class NoSilverPreTransformStageProvdedError(PresetError):
44
+ def __init__(
45
+ self,
46
+ message: str = "No silver transform stage provided, but prestransform name provided.",
47
+ ):
48
+ super().__init__(message)
49
+
50
+
51
+ class MissingTableFieldError(PresetError):
52
+ def __init__(self, layer: str, table_name: str, field_name: str):
53
+ self.layer = layer
54
+ self.table_name = table_name
55
+ self.field_name = field_name
56
+ message = f"{layer} stage {table_name} is missing {field_name} field."
57
+ super().__init__(message)
58
+
59
+
60
+ class DuplicateFieldNameError(PresetError):
61
+ def __init__(self, stage: str, stage_name: str, field_name: str):
62
+ self.stage = stage
63
+ self.stage_name = stage_name
64
+ self.field_name = field_name
65
+ message = f"Duplicate field specification name found in {stage} stage {stage_name} named {field_name}."
66
+ super().__init__(message)
67
+
68
+
69
+ class MalformedFieldError(PresetError):
70
+ def __init__(self, stage: str, stage_name: str, field_name: str):
71
+ self.stage = stage
72
+ self.stage_name = stage_name
73
+ self.field_name = field_name
74
+ message = f"Please provide 1 operation only in {stage} stage {stage_name}'s field specification named {field_name}."
75
+ super().__init__(message)
76
+
77
+
78
+ class MissingFieldNameError(PresetError):
79
+ def __init__(self, stage: str, stage_name: str):
80
+ self.stage = stage
81
+ self.stage_name = stage_name
82
+ message = (
83
+ f"Field specification in {stage} stage {stage_name} missing name field."
84
+ )
85
+ super().__init__(message)
86
+
87
+
88
+ class MissingSilverKeysError(PresetError):
89
+ def __init__(self, missing_keys: str):
90
+ self.missing_keys = missing_keys
91
+ message = f"Gold table/s have no corresponding input from silver table/s: {missing_keys}"
92
+ super().__init__(message)
93
+
94
+
95
+ class MissingAutoloaderConfigError(PresetError):
96
+ def __init__(
97
+ self,
98
+ message: str = "Autoloader mode selected, but no autoloader configuration found in preset.autoloader.",
99
+ ):
100
+ super().__init__(message)
101
+
102
+
103
+ class AutoloaderMissingFieldError(PresetError):
104
+ def __init__(self, field_name: str):
105
+ self.field_name = field_name
106
+ message = f"Autoloader mode selected, but missing field {field_name} in preset."
107
+ super().__init__(message)
108
+
109
+
110
+ class UnknownGoldTableError(PresetError):
111
+ def __init__(self, table_name: str, schema: str):
112
+ self.table_name = table_name
113
+ self.schema = schema
114
+ message = (
115
+ f"The referenced Gold table name {table_name} does not exist in {schema}."
116
+ )
117
+ super().__init__(message)
118
+
119
+
120
+ class GoldTableCompatibilityError(PresetError):
121
+ def __init__(self, message: str):
122
+ super().__init__(message)
123
+
124
+
125
+ class ReferencedColumnMissingError(PresetError):
126
+ def __init__(self, operation: str, column_name: str):
127
+ self.operation = operation
128
+ self.column_name = column_name
129
+ message = f"The referenced column {column_name} was not found in the dataframe during {operation} operation."
130
+ super().__init__(message)
131
+
132
+
133
+ class MissingJoinFieldError(PresetError):
134
+ def __init__(self, field_name: str):
135
+ self.field_name = field_name
136
+ message = f"Join operation is missing required field {field_name}."
137
+ super().__init__(message)
138
+
139
+
140
+ class MissingUtilityConfigurationFieldError(PresetError):
141
+ def __init__(self, operation: str, field_name: str):
142
+ self.operation = operation
143
+ self.field_name = field_name
144
+ message = f"The required configuration field {field_name} was not suppled in the {operation} operation."
145
+ super().__init__(message)
146
+
147
+
148
+ class AssertionFailedError(PresetError):
149
+ def __init__(self, expr: str, assertion_message: str, df: DataFrame):
150
+ # Get the Databricks built-in functions out the namespace.
151
+ ipython = get_ipython()
152
+ display = ipython.user_ns["display"]
153
+
154
+ self.expr = expr
155
+ self.assertion_message = assertion_message
156
+ self.df = df
157
+ message = f"The above rows failed the assertion expression {expr} with reason: {assertion_message}\n"
158
+ display(df)
159
+ super().__init__(message)