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.
Files changed (33) hide show
  1. great_expectations_cloud/agent/__init__.py +3 -0
  2. great_expectations_cloud/agent/actions/__init__.py +8 -5
  3. great_expectations_cloud/agent/actions/agent_action.py +21 -6
  4. great_expectations_cloud/agent/actions/draft_datasource_config_action.py +45 -24
  5. great_expectations_cloud/agent/actions/generate_data_quality_check_expectations_action.py +557 -0
  6. great_expectations_cloud/agent/actions/list_asset_names.py +65 -0
  7. great_expectations_cloud/agent/actions/run_checkpoint.py +74 -27
  8. great_expectations_cloud/agent/actions/run_metric_list_action.py +11 -5
  9. great_expectations_cloud/agent/actions/run_scheduled_checkpoint.py +67 -0
  10. great_expectations_cloud/agent/actions/run_window_checkpoint.py +66 -0
  11. great_expectations_cloud/agent/actions/utils.py +35 -0
  12. great_expectations_cloud/agent/agent.py +444 -101
  13. great_expectations_cloud/agent/cli.py +2 -2
  14. great_expectations_cloud/agent/config.py +19 -5
  15. great_expectations_cloud/agent/event_handler.py +49 -12
  16. great_expectations_cloud/agent/exceptions.py +9 -0
  17. great_expectations_cloud/agent/message_service/asyncio_rabbit_mq_client.py +80 -14
  18. great_expectations_cloud/agent/message_service/subscriber.py +8 -5
  19. great_expectations_cloud/agent/models.py +197 -20
  20. great_expectations_cloud/agent/utils.py +84 -0
  21. great_expectations_cloud/logging/logging_cfg.py +20 -4
  22. great_expectations_cloud/py.typed +0 -0
  23. {great_expectations_cloud-20240523.0.dev0.dist-info → great_expectations_cloud-20251124.0.dev1.dist-info}/METADATA +54 -46
  24. great_expectations_cloud-20251124.0.dev1.dist-info/RECORD +34 -0
  25. {great_expectations_cloud-20240523.0.dev0.dist-info → great_expectations_cloud-20251124.0.dev1.dist-info}/WHEEL +1 -1
  26. great_expectations_cloud/agent/actions/data_assistants/__init__.py +0 -8
  27. great_expectations_cloud/agent/actions/data_assistants/run_missingness_data_assistant.py +0 -45
  28. great_expectations_cloud/agent/actions/data_assistants/run_onboarding_data_assistant.py +0 -45
  29. great_expectations_cloud/agent/actions/data_assistants/utils.py +0 -123
  30. great_expectations_cloud/agent/actions/list_table_names.py +0 -76
  31. great_expectations_cloud-20240523.0.dev0.dist-info/RECORD +0 -32
  32. {great_expectations_cloud-20240523.0.dev0.dist-info → great_expectations_cloud-20251124.0.dev1.dist-info}/entry_points.txt +0 -0
  33. {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.list_table_names import ListTableNamesAction
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 typing import TYPE_CHECKING, Generic, Sequence, TypeVar
5
+ from collections.abc import Sequence
6
+ from typing import TYPE_CHECKING, Generic, Optional, TypeVar, Union
5
7
 
6
- from great_expectations.compatibility.pydantic import BaseModel
8
+ from pydantic.v1 import BaseModel
7
9
 
8
- from great_expectations_cloud.agent.models import CreatedResource, Event
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): # type: ignore[misc] # BaseSettings is has Any type
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=Event)
30
+ _EventT = TypeVar("_EventT", bound=Union[AgentBaseExtraForbid, AgentBaseExtraIgnore])
21
31
 
22
32
 
23
33
  class AgentAction(Generic[_EventT]):
24
- def __init__(self, context: CloudDataContext):
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.config import (
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.sources.type_lookup[datasource_type]
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
- def get_draft_config(self, config_id: UUID) -> dict[str, Any]:
61
- try:
62
- config = GxAgentEnvVars()
63
- except pydantic.ValidationError as validation_err:
64
- raise RuntimeError(
65
- generate_config_validation_error_text(validation_err)
66
- ) from validation_err
67
- resource_url = (
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
- session = create_session(access_token=config.gx_cloud_access_token)
72
- response = session.get(resource_url)
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 " "connecting to GX Cloud"
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"]["attributes"]["draft_config"] # type: ignore[no-any-return]
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("0", DraftDatasourceConfigEvent, DraftDatasourceConfigAction)
107
+ register_event_action("1", DraftDatasourceConfigEvent, DraftDatasourceConfigAction)