great-expectations-cloud 20240523.0.dev0__py3-none-any.whl → 20251124.0.dev1__py3-none-any.whl
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.
- great_expectations_cloud/agent/__init__.py +3 -0
- great_expectations_cloud/agent/actions/__init__.py +8 -5
- great_expectations_cloud/agent/actions/agent_action.py +21 -6
- great_expectations_cloud/agent/actions/draft_datasource_config_action.py +45 -24
- great_expectations_cloud/agent/actions/generate_data_quality_check_expectations_action.py +557 -0
- great_expectations_cloud/agent/actions/list_asset_names.py +65 -0
- great_expectations_cloud/agent/actions/run_checkpoint.py +74 -27
- great_expectations_cloud/agent/actions/run_metric_list_action.py +11 -5
- great_expectations_cloud/agent/actions/run_scheduled_checkpoint.py +67 -0
- great_expectations_cloud/agent/actions/run_window_checkpoint.py +66 -0
- great_expectations_cloud/agent/actions/utils.py +35 -0
- great_expectations_cloud/agent/agent.py +444 -101
- great_expectations_cloud/agent/cli.py +2 -2
- great_expectations_cloud/agent/config.py +19 -5
- great_expectations_cloud/agent/event_handler.py +49 -12
- great_expectations_cloud/agent/exceptions.py +9 -0
- great_expectations_cloud/agent/message_service/asyncio_rabbit_mq_client.py +80 -14
- great_expectations_cloud/agent/message_service/subscriber.py +8 -5
- great_expectations_cloud/agent/models.py +197 -20
- great_expectations_cloud/agent/utils.py +84 -0
- great_expectations_cloud/logging/logging_cfg.py +20 -4
- great_expectations_cloud/py.typed +0 -0
- {great_expectations_cloud-20240523.0.dev0.dist-info → great_expectations_cloud-20251124.0.dev1.dist-info}/METADATA +54 -46
- great_expectations_cloud-20251124.0.dev1.dist-info/RECORD +34 -0
- {great_expectations_cloud-20240523.0.dev0.dist-info → great_expectations_cloud-20251124.0.dev1.dist-info}/WHEEL +1 -1
- great_expectations_cloud/agent/actions/data_assistants/__init__.py +0 -8
- great_expectations_cloud/agent/actions/data_assistants/run_missingness_data_assistant.py +0 -45
- great_expectations_cloud/agent/actions/data_assistants/run_onboarding_data_assistant.py +0 -45
- great_expectations_cloud/agent/actions/data_assistants/utils.py +0 -123
- great_expectations_cloud/agent/actions/list_table_names.py +0 -76
- great_expectations_cloud-20240523.0.dev0.dist-info/RECORD +0 -32
- {great_expectations_cloud-20240523.0.dev0.dist-info → great_expectations_cloud-20251124.0.dev1.dist-info}/entry_points.txt +0 -0
- {great_expectations_cloud-20240523.0.dev0.dist-info → great_expectations_cloud-20251124.0.dev1.dist-info/licenses}/LICENSE +0 -0
|
@@ -2,4 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import great_expectations_cloud.agent.actions # import actions to register them
|
|
4
4
|
from great_expectations_cloud.agent.agent import GXAgent
|
|
5
|
+
from great_expectations_cloud.agent.event_handler import register_event_action
|
|
6
|
+
from great_expectations_cloud.agent.models import Event, EventType
|
|
5
7
|
from great_expectations_cloud.agent.run import get_version, run_agent
|
|
8
|
+
from great_expectations_cloud.agent.utils import triangular_interpolation
|
|
@@ -7,13 +7,16 @@ from great_expectations_cloud.agent.actions.agent_action import (
|
|
|
7
7
|
)
|
|
8
8
|
|
|
9
9
|
# Import all actions to register them:
|
|
10
|
-
from great_expectations_cloud.agent.actions.data_assistants import (
|
|
11
|
-
RunMissingnessDataAssistantAction,
|
|
12
|
-
RunOnboardingDataAssistantAction,
|
|
13
|
-
)
|
|
14
10
|
from great_expectations_cloud.agent.actions.draft_datasource_config_action import (
|
|
15
11
|
DraftDatasourceConfigAction,
|
|
16
12
|
)
|
|
17
|
-
from great_expectations_cloud.agent.actions.
|
|
13
|
+
from great_expectations_cloud.agent.actions.generate_data_quality_check_expectations_action import (
|
|
14
|
+
GenerateDataQualityCheckExpectationsAction,
|
|
15
|
+
)
|
|
16
|
+
from great_expectations_cloud.agent.actions.list_asset_names import ListAssetNamesAction
|
|
18
17
|
from great_expectations_cloud.agent.actions.run_checkpoint import RunCheckpointAction
|
|
19
18
|
from great_expectations_cloud.agent.actions.run_metric_list_action import MetricListAction
|
|
19
|
+
from great_expectations_cloud.agent.actions.run_scheduled_checkpoint import (
|
|
20
|
+
RunScheduledCheckpointAction,
|
|
21
|
+
)
|
|
22
|
+
from great_expectations_cloud.agent.actions.run_window_checkpoint import RunWindowCheckpointAction
|
|
@@ -1,28 +1,43 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import datetime
|
|
3
4
|
from abc import abstractmethod
|
|
4
|
-
from
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
from typing import TYPE_CHECKING, Generic, Optional, TypeVar, Union
|
|
5
7
|
|
|
6
|
-
from
|
|
8
|
+
from pydantic.v1 import BaseModel
|
|
7
9
|
|
|
8
|
-
from great_expectations_cloud.agent.models import
|
|
10
|
+
from great_expectations_cloud.agent.models import (
|
|
11
|
+
AgentBaseExtraForbid,
|
|
12
|
+
AgentBaseExtraIgnore,
|
|
13
|
+
CreatedResource,
|
|
14
|
+
DomainContext,
|
|
15
|
+
)
|
|
9
16
|
|
|
10
17
|
if TYPE_CHECKING:
|
|
11
18
|
from great_expectations.data_context import CloudDataContext
|
|
12
19
|
|
|
13
20
|
|
|
14
|
-
class ActionResult(BaseModel):
|
|
21
|
+
class ActionResult(BaseModel):
|
|
15
22
|
id: str
|
|
16
23
|
type: str
|
|
17
24
|
created_resources: Sequence[CreatedResource]
|
|
25
|
+
job_duration: Optional[datetime.timedelta] = ( # noqa: UP045
|
|
26
|
+
None # Python 3.8 doesn't support `X | Y` for type annotation
|
|
27
|
+
)
|
|
18
28
|
|
|
19
29
|
|
|
20
|
-
_EventT = TypeVar("_EventT", bound=
|
|
30
|
+
_EventT = TypeVar("_EventT", bound=Union[AgentBaseExtraForbid, AgentBaseExtraIgnore])
|
|
21
31
|
|
|
22
32
|
|
|
23
33
|
class AgentAction(Generic[_EventT]):
|
|
24
|
-
def __init__(
|
|
34
|
+
def __init__(
|
|
35
|
+
self, context: CloudDataContext, base_url: str, domain_context: DomainContext, auth_key: str
|
|
36
|
+
):
|
|
25
37
|
self._context = context
|
|
38
|
+
self._base_url = base_url
|
|
39
|
+
self._domain_context = domain_context
|
|
40
|
+
self._auth_key = auth_key
|
|
26
41
|
|
|
27
42
|
@abstractmethod
|
|
28
43
|
def run(self, event: _EventT, id: str) -> ActionResult: ...
|
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from typing import Any
|
|
4
|
+
from urllib.parse import urljoin
|
|
4
5
|
from uuid import UUID
|
|
5
6
|
|
|
6
|
-
from great_expectations.compatibility import pydantic
|
|
7
7
|
from great_expectations.core.http import create_session
|
|
8
|
+
from great_expectations.datasource.fluent import SQLDatasource
|
|
8
9
|
from great_expectations.datasource.fluent.interfaces import TestConnectionError
|
|
9
10
|
from typing_extensions import override
|
|
10
11
|
|
|
11
12
|
from great_expectations_cloud.agent.actions import ActionResult, AgentAction
|
|
12
|
-
from great_expectations_cloud.agent.
|
|
13
|
-
GxAgentEnvVars,
|
|
14
|
-
generate_config_validation_error_text,
|
|
15
|
-
)
|
|
13
|
+
from great_expectations_cloud.agent.actions.utils import get_asset_names
|
|
16
14
|
from great_expectations_cloud.agent.event_handler import register_event_action
|
|
17
15
|
from great_expectations_cloud.agent.exceptions import ErrorCode, raise_with_error_code
|
|
18
16
|
from great_expectations_cloud.agent.models import DraftDatasourceConfigEvent
|
|
19
17
|
|
|
20
18
|
|
|
21
19
|
class DraftDatasourceConfigAction(AgentAction[DraftDatasourceConfigEvent]):
|
|
20
|
+
# TODO: New actions need to be created that are compatible with GX v1 and registered for v1.
|
|
21
|
+
# This action is registered for v0, see register_event_action()
|
|
22
|
+
|
|
22
23
|
@override
|
|
23
24
|
def run(self, event: DraftDatasourceConfigEvent, id: str) -> ActionResult:
|
|
24
25
|
try:
|
|
@@ -43,11 +44,10 @@ class DraftDatasourceConfigAction(AgentAction[DraftDatasourceConfigEvent]):
|
|
|
43
44
|
datasource_type = draft_config.get("type", None)
|
|
44
45
|
if datasource_type is None:
|
|
45
46
|
raise TypeError( # noqa: TRY003 # one off error
|
|
46
|
-
"The DraftDatasourceConfigAction can only be used with a "
|
|
47
|
-
"fluent-style Data Source."
|
|
47
|
+
"The DraftDatasourceConfigAction can only be used with a fluent-style Data Source."
|
|
48
48
|
)
|
|
49
49
|
try:
|
|
50
|
-
datasource_cls = self._context.
|
|
50
|
+
datasource_cls = self._context.data_sources.type_lookup[datasource_type]
|
|
51
51
|
except LookupError as exc:
|
|
52
52
|
raise TypeError( # noqa: TRY003 # one off error
|
|
53
53
|
"DraftDatasourceConfigAction received an unknown Data Source type."
|
|
@@ -55,32 +55,53 @@ class DraftDatasourceConfigAction(AgentAction[DraftDatasourceConfigEvent]):
|
|
|
55
55
|
datasource = datasource_cls(**draft_config)
|
|
56
56
|
datasource._data_context = self._context
|
|
57
57
|
datasource.test_connection(test_assets=True) # raises `TestConnectionError` on failure
|
|
58
|
-
return ActionResult(id=id, type=event.type, created_resources=[])
|
|
59
58
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
f"{config.gx_cloud_base_url}/organizations/"
|
|
69
|
-
f"{config.gx_cloud_organization_id}/datasources/drafts/{config_id}"
|
|
59
|
+
if isinstance(datasource, SQLDatasource):
|
|
60
|
+
asset_names = get_asset_names(datasource)
|
|
61
|
+
self._update_asset_names_list(config_id=event.config_id, asset_names=asset_names)
|
|
62
|
+
|
|
63
|
+
return ActionResult(
|
|
64
|
+
id=id,
|
|
65
|
+
type=event.type,
|
|
66
|
+
created_resources=[],
|
|
70
67
|
)
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
|
|
69
|
+
def _update_asset_names_list(self, config_id: UUID, asset_names: list[str]) -> None:
|
|
70
|
+
with create_session(access_token=self._auth_key) as session:
|
|
71
|
+
url = urljoin(
|
|
72
|
+
base=self._base_url,
|
|
73
|
+
url=f"/api/v1/organizations/{self._domain_context.organization_id}/workspaces/{self._domain_context.workspace_id}/draft-table-names/{config_id}",
|
|
74
|
+
)
|
|
75
|
+
response = session.put(
|
|
76
|
+
url=url,
|
|
77
|
+
json={"data": {"table_names": asset_names}},
|
|
78
|
+
)
|
|
73
79
|
if not response.ok:
|
|
74
80
|
raise RuntimeError( # noqa: TRY003 # one off error
|
|
75
|
-
"DraftDatasourceConfigAction encountered an error while
|
|
81
|
+
f"DraftDatasourceConfigAction encountered an error while connecting to GX Cloud. "
|
|
82
|
+
f"Unable to update "
|
|
83
|
+
f"table_names for Draft Config with ID"
|
|
84
|
+
f"={config_id}.",
|
|
76
85
|
)
|
|
86
|
+
|
|
87
|
+
def get_draft_config(self, config_id: UUID) -> dict[str, Any]:
|
|
88
|
+
resource_url = urljoin(
|
|
89
|
+
base=self._base_url,
|
|
90
|
+
url=f"/api/v1/organizations/{self._domain_context.organization_id}/workspaces/{self._domain_context.workspace_id}/draft-datasources/{config_id}",
|
|
91
|
+
)
|
|
92
|
+
with create_session(access_token=self._auth_key) as session:
|
|
93
|
+
response = session.get(resource_url)
|
|
94
|
+
if not response.ok:
|
|
95
|
+
raise RuntimeError( # noqa: TRY003 # one off error
|
|
96
|
+
"DraftDatasourceConfigAction encountered an error while connecting to GX Cloud"
|
|
97
|
+
)
|
|
77
98
|
data = response.json()
|
|
78
99
|
try:
|
|
79
|
-
return data["data"]["
|
|
100
|
+
return data["data"]["config"] # type: ignore[no-any-return]
|
|
80
101
|
except KeyError as e:
|
|
81
102
|
raise RuntimeError( # noqa: TRY003 # one off error
|
|
82
103
|
"Malformed response received from GX Cloud"
|
|
83
104
|
) from e
|
|
84
105
|
|
|
85
106
|
|
|
86
|
-
register_event_action("
|
|
107
|
+
register_event_action("1", DraftDatasourceConfigEvent, DraftDatasourceConfigAction)
|