atlan-application-sdk-api 3.51.0__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.
- application_sdk/__init__.py +7 -0
- application_sdk/_build_info.py +62 -0
- application_sdk/_context_errors.py +65 -0
- application_sdk/_install.py +130 -0
- application_sdk/_logging.py +171 -0
- application_sdk/_runtime/__init__.py +29 -0
- application_sdk/_runtime/offload.py +1020 -0
- application_sdk/_runtime/progress.py +757 -0
- application_sdk/clients/__init__.py +63 -0
- application_sdk/clients/_interface.py +58 -0
- application_sdk/clients/_sql_failure_classifier.py +112 -0
- application_sdk/clients/base.py +565 -0
- application_sdk/clients/http_errors.py +28 -0
- application_sdk/clients/models.py +49 -0
- application_sdk/clients/sql.py +1218 -0
- application_sdk/clients/sql_errors.py +192 -0
- application_sdk/clients/sql_typecasters.py +431 -0
- application_sdk/clients/ssl_utils.py +247 -0
- application_sdk/common/__init__.py +53 -0
- application_sdk/common/_generated_tree.py +321 -0
- application_sdk/common/_listing.py +192 -0
- application_sdk/common/aws_utils.py +522 -0
- application_sdk/common/aws_utils_errors.py +88 -0
- application_sdk/common/build_identity.py +120 -0
- application_sdk/common/concurrency.py +45 -0
- application_sdk/common/errors.py +99 -0
- application_sdk/common/filter_matching.py +261 -0
- application_sdk/common/logger.py +11 -0
- application_sdk/common/models.py +31 -0
- application_sdk/common/sql_filters.py +719 -0
- application_sdk/common/sql_filters_errors.py +17 -0
- application_sdk/common/task_queue.py +431 -0
- application_sdk/common/types.py +51 -0
- application_sdk/common/utils.py +87 -0
- application_sdk/constants.py +1120 -0
- application_sdk/contracts/__init__.py +158 -0
- application_sdk/contracts/base.py +1178 -0
- application_sdk/contracts/events.py +251 -0
- application_sdk/contracts/types.py +801 -0
- application_sdk/contracts/types_errors.py +17 -0
- application_sdk/credentials/__init__.py +326 -0
- application_sdk/credentials/errors.py +226 -0
- application_sdk/credentials/extra.py +114 -0
- application_sdk/credentials/ingress.py +283 -0
- application_sdk/credentials/ref.py +376 -0
- application_sdk/credentials/spec.py +182 -0
- application_sdk/credentials/types.py +339 -0
- application_sdk/credentials/utils.py +257 -0
- application_sdk/errors/__init__.py +224 -0
- application_sdk/errors/base.py +504 -0
- application_sdk/errors/categories.py +118 -0
- application_sdk/errors/http.py +81 -0
- application_sdk/errors/leaves.py +526 -0
- application_sdk/errors/wire.py +124 -0
- application_sdk/handler/__init__.py +97 -0
- application_sdk/handler/_warmup.py +198 -0
- application_sdk/handler/asgi.py +252 -0
- application_sdk/handler/base.py +281 -0
- application_sdk/handler/context.py +212 -0
- application_sdk/handler/contracts.py +1166 -0
- application_sdk/handler/manifest.py +81 -0
- application_sdk/handler/metadata_routes.py +699 -0
- application_sdk/handler/object_routes.py +418 -0
- application_sdk/handler/request_contract.py +91 -0
- application_sdk/handler/routes.py +1118 -0
- application_sdk/handler/service_errors.py +37 -0
- application_sdk/server/__init__.py +15 -0
- application_sdk/server/fastapi/models.py +338 -0
- application_sdk/templates/__init__.py +52 -0
- application_sdk/templates/contracts/__init__.py +111 -0
- application_sdk/templates/contracts/base_metadata_extraction.py +32 -0
- application_sdk/templates/contracts/incremental_sql.py +563 -0
- application_sdk/templates/contracts/sql_metadata.py +824 -0
- application_sdk/templates/contracts/sql_query.py +105 -0
- application_sdk/version.py +40 -0
- atlan_application_sdk_api-3.51.0.dist-info/METADATA +230 -0
- atlan_application_sdk_api-3.51.0.dist-info/RECORD +78 -0
- atlan_application_sdk_api-3.51.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""Typed error leaves for the handler service module."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import ClassVar
|
|
7
|
+
|
|
8
|
+
from application_sdk.errors.leaves import InternalError, InvalidInputError
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(kw_only=True)
|
|
12
|
+
class TempPathEscapeError(InternalError):
|
|
13
|
+
"""A path escaped the system temp directory — invariant violation."""
|
|
14
|
+
|
|
15
|
+
code: ClassVar[str] = "INTERNAL_HANDLER_TEMP_PATH_ESCAPE"
|
|
16
|
+
message: str = "Temp file path escapes system temp directory"
|
|
17
|
+
component: str | None = "handler"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass(kw_only=True)
|
|
21
|
+
class InvalidConfigIdError(InvalidInputError):
|
|
22
|
+
"""config_id did not match the allowed character pattern."""
|
|
23
|
+
|
|
24
|
+
code: ClassVar[str] = "INVALID_INPUT_CONFIG_ID"
|
|
25
|
+
message: str = "Invalid config_id: must match allowed character pattern"
|
|
26
|
+
field: str | None = "config_id"
|
|
27
|
+
config_id: str | None = None
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass(kw_only=True)
|
|
31
|
+
class InvalidConfigTypeError(InvalidInputError):
|
|
32
|
+
"""config_type did not match the allowed character pattern."""
|
|
33
|
+
|
|
34
|
+
code: ClassVar[str] = "INVALID_INPUT_CONFIG_TYPE"
|
|
35
|
+
message: str = "Invalid config_type: must match allowed character pattern"
|
|
36
|
+
field: str | None = "config_type"
|
|
37
|
+
config_type: str | None = None
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""HTTP server layer — FastAPI app, MCP integration, middleware.
|
|
2
|
+
|
|
3
|
+
Import from the submodules (``application_sdk.server.middleware``,
|
|
4
|
+
``application_sdk.server.mcp``); nothing is re-exported here, and nothing is
|
|
5
|
+
imported at package scope so that reaching one submodule never pulls in the
|
|
6
|
+
others' dependencies.
|
|
7
|
+
|
|
8
|
+
This file is intentionally almost empty. It exists because a package without an
|
|
9
|
+
``__init__.py`` is an implicit namespace package, which static tools — griffe,
|
|
10
|
+
and therefore the capability manifest — do not descend into: the public surface
|
|
11
|
+
of ``server.mcp`` and ``server.middleware`` was invisible to every static reader
|
|
12
|
+
of this package while it was missing (FND-439). The previous ``__init__.py`` was
|
|
13
|
+
deleted wholesale with the v2 shim layer (b5ed0e49) because it held the
|
|
14
|
+
deprecated ``ServerInterface``; only the deprecated content was meant to go.
|
|
15
|
+
"""
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
# Request/Response DTOs for workflows
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from typing import Any, Callable, Coroutine, Dict, Optional, Union
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, Field, RootModel
|
|
7
|
+
|
|
8
|
+
from application_sdk.contracts.events import Event
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TestAuthRequest(RootModel[Dict[str, Any]]):
|
|
12
|
+
root: Dict[str, Any] = Field(
|
|
13
|
+
..., description="Root JSON object containing database credentials"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class TestAuthResponse(BaseModel):
|
|
18
|
+
success: bool
|
|
19
|
+
message: str
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class MetadataType(str, Enum):
|
|
23
|
+
DATABASE = "database"
|
|
24
|
+
SCHEMA = "schema"
|
|
25
|
+
ALL = "all"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class FetchMetadataRequest(RootModel[Dict[str, Any]]):
|
|
29
|
+
root: Dict[str, Any] = Field(
|
|
30
|
+
..., description="Root JSON object containing the metadata and credentials"
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class FetchMetadataResponse(BaseModel):
|
|
35
|
+
success: bool
|
|
36
|
+
data: Any
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class PreflightCheckRequest(BaseModel):
|
|
40
|
+
model_config = {
|
|
41
|
+
"json_schema_extra": {
|
|
42
|
+
"example": {
|
|
43
|
+
"credentials": {
|
|
44
|
+
"authType": "basic",
|
|
45
|
+
"host": "host",
|
|
46
|
+
"port": 5432,
|
|
47
|
+
"username": "username",
|
|
48
|
+
"password": "password",
|
|
49
|
+
"database": "databasename",
|
|
50
|
+
},
|
|
51
|
+
"metadata": {
|
|
52
|
+
"include-filter": '{"^dbengine$":["^public$","^airflow$"]}',
|
|
53
|
+
"exclude-filter": "{}",
|
|
54
|
+
"temp-table-regex": "",
|
|
55
|
+
},
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
credentials: Dict[str, Any] = Field(
|
|
61
|
+
..., description="Required JSON field containing database credentials"
|
|
62
|
+
)
|
|
63
|
+
metadata: Dict[str, Any] = Field(
|
|
64
|
+
...,
|
|
65
|
+
description="Required JSON field containing form data for filtering and configuration",
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class PreflightCheckResponse(BaseModel):
|
|
70
|
+
model_config = {
|
|
71
|
+
"json_schema_extra": {
|
|
72
|
+
"example": {
|
|
73
|
+
"success": True,
|
|
74
|
+
"data": {
|
|
75
|
+
"successMessage": "Successfully checked",
|
|
76
|
+
"failureMessage": "",
|
|
77
|
+
},
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
success: bool = Field(
|
|
83
|
+
..., description="Indicates if the overall operation was successful"
|
|
84
|
+
)
|
|
85
|
+
data: Dict[str, Any] = Field(..., description="Response data")
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class WorkflowRequest(RootModel[Dict[str, Any]]):
|
|
89
|
+
model_config = {
|
|
90
|
+
"json_schema_extra": {
|
|
91
|
+
"example": {
|
|
92
|
+
"miner_args": {},
|
|
93
|
+
"credentials": {
|
|
94
|
+
"authType": "basic",
|
|
95
|
+
"host": "",
|
|
96
|
+
"port": 5432,
|
|
97
|
+
"username": "username",
|
|
98
|
+
"password": "password",
|
|
99
|
+
"database": "databasename",
|
|
100
|
+
},
|
|
101
|
+
"connection": {"connection": "dev"},
|
|
102
|
+
"metadata": {
|
|
103
|
+
"include-filter": '{"^dbengine$":["^public$","^airflow$"]}',
|
|
104
|
+
"exclude-filter": "{}",
|
|
105
|
+
"temp-table-regex": "",
|
|
106
|
+
},
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
root: Dict[str, Any] = Field(
|
|
112
|
+
..., description="Root JSON object containing workflow configuration"
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class EventWorkflowRequest(BaseModel):
|
|
117
|
+
event: Event = Field(alias="data", description="Event object")
|
|
118
|
+
datacontenttype: str = Field(
|
|
119
|
+
alias="datacontenttype", description="Data content type"
|
|
120
|
+
)
|
|
121
|
+
id: str = Field(alias="id", description="Event ID")
|
|
122
|
+
source: str = Field(alias="source", description="Event source")
|
|
123
|
+
specversion: str = Field(alias="specversion", description="Event spec version")
|
|
124
|
+
time: str = Field(alias="time", description="Event time")
|
|
125
|
+
type: str = Field(alias="type", description="Event type")
|
|
126
|
+
topic: str = Field(alias="topic", description="Event topic")
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class WorkflowData(BaseModel):
|
|
130
|
+
workflow_id: str = Field(..., description="Unique identifier for the workflow")
|
|
131
|
+
run_id: str = Field(..., description="Unique identifier for the workflow run")
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class WorkflowResponse(BaseModel):
|
|
135
|
+
model_config = {
|
|
136
|
+
"json_schema_extra": {
|
|
137
|
+
"example": {
|
|
138
|
+
"success": True,
|
|
139
|
+
"message": "Workflow started successfully",
|
|
140
|
+
"data": {
|
|
141
|
+
"workflow_id": "4b805f36-48c5-4dd3-942f-650e06f75bbc",
|
|
142
|
+
"run_id": "efe16ffe-24b2-4391-a7ec-7000c32c5893",
|
|
143
|
+
},
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
success: bool = Field(
|
|
149
|
+
..., description="Indicates whether the operation was successful"
|
|
150
|
+
)
|
|
151
|
+
message: str = Field(
|
|
152
|
+
..., description="Message describing the result of the operation"
|
|
153
|
+
)
|
|
154
|
+
data: WorkflowData = Field(..., description="Details about the workflow and run")
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class EventWorkflowResponse(WorkflowResponse):
|
|
158
|
+
class Status(str, Enum):
|
|
159
|
+
SUCCESS = "SUCCESS"
|
|
160
|
+
RETRY = "RETRY"
|
|
161
|
+
DROP = "DROP"
|
|
162
|
+
|
|
163
|
+
# This should be a string enum of the status of the workflow, based on the Dapr docs
|
|
164
|
+
# https://docs.dapr.io/reference/api/pubsub_api/#expected-http-response
|
|
165
|
+
status: Status = Field(..., description="Status of the workflow")
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
class WorkflowConfigRequest(RootModel[Dict[str, Any]]):
|
|
169
|
+
root: Dict[str, Any] = Field(
|
|
170
|
+
..., description="Root JSON object containing workflow configuration"
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
class WorkflowConfigResponse(BaseModel):
|
|
175
|
+
model_config = {
|
|
176
|
+
"json_schema_extra": {
|
|
177
|
+
"example": {
|
|
178
|
+
"success": True,
|
|
179
|
+
"message": "Workflow configuration fetched successfully",
|
|
180
|
+
"data": {
|
|
181
|
+
"credential_guid": "credential_test-uuid",
|
|
182
|
+
"connection": {"connection": "dev"},
|
|
183
|
+
"metadata": {
|
|
184
|
+
"include-filter": '{"^dbengine$":["^public$","^airflow$"]}',
|
|
185
|
+
"exclude-filter": "{}",
|
|
186
|
+
"temp-table-regex": "",
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
success: bool = Field(
|
|
194
|
+
..., description="Indicates whether the operation was successful"
|
|
195
|
+
)
|
|
196
|
+
message: str = Field(
|
|
197
|
+
..., description="Message describing the result of the operation"
|
|
198
|
+
)
|
|
199
|
+
data: Dict[str, Any] = Field(..., description="Workflow configuration")
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
class ConfigMapResponse(BaseModel):
|
|
203
|
+
model_config = {
|
|
204
|
+
"json_schema_extra": {
|
|
205
|
+
"example": {
|
|
206
|
+
"success": True,
|
|
207
|
+
"message": "Configuration map fetched successfully",
|
|
208
|
+
"data": {
|
|
209
|
+
"config_map_id": "pikachu-config-001",
|
|
210
|
+
"name": "Pikachu Configuration",
|
|
211
|
+
"settings": {
|
|
212
|
+
"electric_type": True,
|
|
213
|
+
"level": 25,
|
|
214
|
+
"moves": ["Thunderbolt", "Quick Attack"],
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
success: bool = Field(
|
|
222
|
+
..., description="Indicates whether the operation was successful"
|
|
223
|
+
)
|
|
224
|
+
message: str = Field(
|
|
225
|
+
..., description="Message describing the result of the operation"
|
|
226
|
+
)
|
|
227
|
+
data: Dict[str, Any] = Field(..., description="Configuration map object")
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
class Subscription(BaseModel):
|
|
231
|
+
"""Subscription configuration for Dapr messaging.
|
|
232
|
+
|
|
233
|
+
Attributes:
|
|
234
|
+
component_name: Name of the Dapr pubsub component
|
|
235
|
+
topic: Topic to subscribe to
|
|
236
|
+
route: Route path for the message handler endpoint
|
|
237
|
+
handler: Required callback function to handle incoming messages
|
|
238
|
+
bulk_config: Optional bulk subscribe configuration
|
|
239
|
+
dead_letter_topic: Optional dead letter topic for failed messages
|
|
240
|
+
|
|
241
|
+
Nested Classes:
|
|
242
|
+
BulkConfig: Configuration for bulk message processing
|
|
243
|
+
MessageStatus: Status codes for handler responses (SUCCESS, RETRY, DROP)
|
|
244
|
+
"""
|
|
245
|
+
|
|
246
|
+
class BulkConfig(BaseModel):
|
|
247
|
+
"""Bulk configuration for Dapr messaging.
|
|
248
|
+
|
|
249
|
+
Attributes:
|
|
250
|
+
enabled: Whether bulk subscribe is enabled
|
|
251
|
+
max_messages_count: Maximum number of messages to receive in a batch
|
|
252
|
+
max_await_duration_ms: Maximum time to wait for messages in milliseconds
|
|
253
|
+
"""
|
|
254
|
+
|
|
255
|
+
enabled: bool = False
|
|
256
|
+
max_messages_count: int = Field(
|
|
257
|
+
default=100, serialization_alias="maxMessagesCount"
|
|
258
|
+
)
|
|
259
|
+
max_await_duration_ms: int = Field(
|
|
260
|
+
default=40, serialization_alias="maxAwaitDurationMs"
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
class MessageStatus(str, Enum):
|
|
264
|
+
"""Status codes for Dapr pub/sub subscription message handler responses.
|
|
265
|
+
|
|
266
|
+
Used in subscription handler responses to indicate how Dapr should handle the message.
|
|
267
|
+
Based on Dapr docs: https://docs.dapr.io/reference/api/pubsub_api/#expected-http-response
|
|
268
|
+
|
|
269
|
+
Attributes:
|
|
270
|
+
SUCCESS: Message was processed successfully.
|
|
271
|
+
RETRY: Message processing failed, should be retried.
|
|
272
|
+
DROP: Message should be dropped (sent to dead letter topic if configured).
|
|
273
|
+
"""
|
|
274
|
+
|
|
275
|
+
SUCCESS = "SUCCESS"
|
|
276
|
+
RETRY = "RETRY"
|
|
277
|
+
DROP = "DROP"
|
|
278
|
+
|
|
279
|
+
model_config = {"arbitrary_types_allowed": True}
|
|
280
|
+
|
|
281
|
+
component_name: str
|
|
282
|
+
topic: str
|
|
283
|
+
route: str
|
|
284
|
+
handler: Union[
|
|
285
|
+
Callable[[Any], Any], Callable[[Any], Coroutine[Any, Any, Any]]
|
|
286
|
+
] # Required callback function (sync or async)
|
|
287
|
+
bulk_config: Optional[BulkConfig] = None
|
|
288
|
+
dead_letter_topic: Optional[str] = None
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
class FileUploadResponse(BaseModel):
|
|
292
|
+
"""Response model for file upload endpoint matching heracles format.
|
|
293
|
+
|
|
294
|
+
Field names use camelCase to stay consistent with the upstream
|
|
295
|
+
Atlan ``/files`` endpoint contract.
|
|
296
|
+
"""
|
|
297
|
+
|
|
298
|
+
model_config = {
|
|
299
|
+
"json_schema_extra": {
|
|
300
|
+
"example": {
|
|
301
|
+
"id": "977f156b-9c78-4bfc-bd74-f603f18c078a",
|
|
302
|
+
"version": "weathered-firefly-9025",
|
|
303
|
+
"isActive": True,
|
|
304
|
+
"createdAt": 1764265919324,
|
|
305
|
+
"updatedAt": 1764265919324,
|
|
306
|
+
"fileName": "28bb016e-329f-46e1-b817-3fd315bdd7f0.csv",
|
|
307
|
+
"rawName": "ddls_export.csv",
|
|
308
|
+
"key": "28bb016e-329f-46e1-b817-3fd315bdd7f0.csv",
|
|
309
|
+
"extension": ".csv",
|
|
310
|
+
"contentType": "text/csv",
|
|
311
|
+
"fileSize": 39144,
|
|
312
|
+
"isEncrypted": False,
|
|
313
|
+
"redirectUrl": "",
|
|
314
|
+
"isUploaded": True,
|
|
315
|
+
"uploadedAt": "2024-01-01T00:00:00Z",
|
|
316
|
+
"isArchived": False,
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
id: str = Field(..., description="UUID of the file")
|
|
322
|
+
version: str = Field(..., description="Human-readable version string")
|
|
323
|
+
isActive: bool = Field(..., description="Whether the file is active")
|
|
324
|
+
createdAt: int = Field(..., description="Unix timestamp in milliseconds")
|
|
325
|
+
updatedAt: int = Field(..., description="Unix timestamp in milliseconds")
|
|
326
|
+
fileName: str = Field(..., description="UUID + extension")
|
|
327
|
+
rawName: str = Field(..., description="Original filename")
|
|
328
|
+
key: str = Field(..., description="Object store key (uuid+extension)")
|
|
329
|
+
extension: str = Field(..., description="File extension (e.g., '.csv')")
|
|
330
|
+
contentType: str = Field(..., description="Content type of the file")
|
|
331
|
+
fileSize: int = Field(..., description="File size in bytes")
|
|
332
|
+
isEncrypted: bool = Field(..., description="Whether the file is encrypted")
|
|
333
|
+
redirectUrl: str = Field(..., description="Redirect URL (empty for now)")
|
|
334
|
+
isUploaded: bool = Field(..., description="Whether the file is uploaded")
|
|
335
|
+
uploadedAt: str = Field(
|
|
336
|
+
..., description="ISO timestamp or '0001-01-01T00:00:00Z' default"
|
|
337
|
+
)
|
|
338
|
+
isArchived: bool = Field(..., description="Whether the file is archived")
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""Built-in App templates for common extraction patterns.
|
|
2
|
+
|
|
3
|
+
Provides v3-style App subclasses intended to be subclassed by connectors for SQL
|
|
4
|
+
metadata extraction and query extraction.
|
|
5
|
+
|
|
6
|
+
**Preferred (v3.1+):**
|
|
7
|
+
|
|
8
|
+
from application_sdk.templates import SqlApp
|
|
9
|
+
|
|
10
|
+
**Legacy (deprecated, use SqlApp instead):**
|
|
11
|
+
|
|
12
|
+
from application_sdk.templates import SqlMetadataExtractor, SqlQueryExtractor
|
|
13
|
+
from application_sdk.templates import IncrementalSqlMetadataExtractor
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from typing import TYPE_CHECKING
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from application_sdk.templates.base_metadata_extractor import BaseMetadataExtractor
|
|
22
|
+
from application_sdk.templates.incremental_sql_metadata_extractor import (
|
|
23
|
+
IncrementalSqlMetadataExtractor,
|
|
24
|
+
)
|
|
25
|
+
from application_sdk.templates.sql_app import SqlApp
|
|
26
|
+
from application_sdk.templates.sql_metadata_extractor import SqlMetadataExtractor
|
|
27
|
+
from application_sdk.templates.sql_query_extractor import SqlQueryExtractor
|
|
28
|
+
|
|
29
|
+
__all__ = [
|
|
30
|
+
"SqlApp",
|
|
31
|
+
"BaseMetadataExtractor",
|
|
32
|
+
"IncrementalSqlMetadataExtractor",
|
|
33
|
+
"SqlMetadataExtractor",
|
|
34
|
+
"SqlQueryExtractor",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
_module_map = {
|
|
38
|
+
"SqlApp": "application_sdk.templates.sql_app",
|
|
39
|
+
"BaseMetadataExtractor": "application_sdk.templates.base_metadata_extractor",
|
|
40
|
+
"IncrementalSqlMetadataExtractor": "application_sdk.templates.incremental_sql_metadata_extractor",
|
|
41
|
+
"SqlMetadataExtractor": "application_sdk.templates.sql_metadata_extractor",
|
|
42
|
+
"SqlQueryExtractor": "application_sdk.templates.sql_query_extractor",
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def __getattr__(name: str) -> object:
|
|
47
|
+
if name in _module_map:
|
|
48
|
+
import importlib # noqa: PLC0415 — defensive: keep inline
|
|
49
|
+
|
|
50
|
+
module = importlib.import_module(_module_map[name])
|
|
51
|
+
return getattr(module, name)
|
|
52
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"""Typed contracts for built-in App implementations."""
|
|
2
|
+
|
|
3
|
+
from application_sdk.templates.contracts.base_metadata_extraction import (
|
|
4
|
+
UploadInput,
|
|
5
|
+
UploadOutput,
|
|
6
|
+
)
|
|
7
|
+
from application_sdk.templates.contracts.incremental_sql import (
|
|
8
|
+
ExecuteColumnBatchInput,
|
|
9
|
+
ExecuteColumnBatchOutput,
|
|
10
|
+
FetchColumnsIncrementalInput,
|
|
11
|
+
FetchIncrementalMarkerInput,
|
|
12
|
+
FetchIncrementalMarkerOutput,
|
|
13
|
+
FetchTablesIncrementalInput,
|
|
14
|
+
IncrementalExtractionInput,
|
|
15
|
+
IncrementalExtractionOutput,
|
|
16
|
+
IncrementalRunContext,
|
|
17
|
+
IncrementalTaskInput,
|
|
18
|
+
PrepareColumnQueriesInput,
|
|
19
|
+
PrepareColumnQueriesOutput,
|
|
20
|
+
ReadCurrentStateInput,
|
|
21
|
+
ReadCurrentStateOutput,
|
|
22
|
+
UpdateMarkerInput,
|
|
23
|
+
UpdateMarkerOutput,
|
|
24
|
+
WriteCurrentStateInput,
|
|
25
|
+
WriteCurrentStateOutput,
|
|
26
|
+
)
|
|
27
|
+
from application_sdk.templates.contracts.sql_metadata import (
|
|
28
|
+
ExtractionInput,
|
|
29
|
+
ExtractionOutput,
|
|
30
|
+
ExtractionTaskInput,
|
|
31
|
+
ExtractionTaskOutput,
|
|
32
|
+
FetchColumnsInput,
|
|
33
|
+
FetchColumnsOutput,
|
|
34
|
+
FetchDatabasesInput,
|
|
35
|
+
FetchDatabasesOutput,
|
|
36
|
+
FetchProceduresInput,
|
|
37
|
+
FetchProceduresOutput,
|
|
38
|
+
FetchSchemasInput,
|
|
39
|
+
FetchSchemasOutput,
|
|
40
|
+
FetchTablesInput,
|
|
41
|
+
FetchTablesOutput,
|
|
42
|
+
FetchViewsInput,
|
|
43
|
+
FetchViewsOutput,
|
|
44
|
+
FilterMap,
|
|
45
|
+
PrimeAuthOutput,
|
|
46
|
+
TransformInput,
|
|
47
|
+
TransformOutput,
|
|
48
|
+
TreeSelectionExtractionInput,
|
|
49
|
+
)
|
|
50
|
+
from application_sdk.templates.contracts.sql_query import (
|
|
51
|
+
QueryBatchInput,
|
|
52
|
+
QueryBatchOutput,
|
|
53
|
+
QueryExtractionInput,
|
|
54
|
+
QueryExtractionOutput,
|
|
55
|
+
QueryFetchInput,
|
|
56
|
+
QueryFetchOutput,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
__all__ = [
|
|
60
|
+
# Base metadata extraction (deprecated upload_to_atlan task)
|
|
61
|
+
"UploadInput",
|
|
62
|
+
"UploadOutput",
|
|
63
|
+
# SQL metadata — base
|
|
64
|
+
"ExtractionInput",
|
|
65
|
+
"ExtractionOutput",
|
|
66
|
+
"ExtractionTaskInput",
|
|
67
|
+
"ExtractionTaskOutput",
|
|
68
|
+
"FetchColumnsInput",
|
|
69
|
+
"FetchColumnsOutput",
|
|
70
|
+
"FetchDatabasesInput",
|
|
71
|
+
"FetchDatabasesOutput",
|
|
72
|
+
"FetchProceduresInput",
|
|
73
|
+
"FetchProceduresOutput",
|
|
74
|
+
"FetchSchemasInput",
|
|
75
|
+
"FetchSchemasOutput",
|
|
76
|
+
"FetchTablesInput",
|
|
77
|
+
"FetchTablesOutput",
|
|
78
|
+
"FetchViewsInput",
|
|
79
|
+
"FetchViewsOutput",
|
|
80
|
+
"FilterMap",
|
|
81
|
+
"TreeSelectionExtractionInput",
|
|
82
|
+
"PrimeAuthOutput",
|
|
83
|
+
"TransformInput",
|
|
84
|
+
"TransformOutput",
|
|
85
|
+
# Incremental SQL
|
|
86
|
+
"ExecuteColumnBatchInput",
|
|
87
|
+
"ExecuteColumnBatchOutput",
|
|
88
|
+
"FetchColumnsIncrementalInput",
|
|
89
|
+
"FetchIncrementalMarkerInput",
|
|
90
|
+
"FetchIncrementalMarkerOutput",
|
|
91
|
+
"FetchTablesIncrementalInput",
|
|
92
|
+
"IncrementalExtractionInput",
|
|
93
|
+
"IncrementalExtractionOutput",
|
|
94
|
+
"IncrementalRunContext",
|
|
95
|
+
"IncrementalTaskInput",
|
|
96
|
+
"PrepareColumnQueriesInput",
|
|
97
|
+
"PrepareColumnQueriesOutput",
|
|
98
|
+
"ReadCurrentStateInput",
|
|
99
|
+
"ReadCurrentStateOutput",
|
|
100
|
+
"UpdateMarkerInput",
|
|
101
|
+
"UpdateMarkerOutput",
|
|
102
|
+
"WriteCurrentStateInput",
|
|
103
|
+
"WriteCurrentStateOutput",
|
|
104
|
+
# SQL query
|
|
105
|
+
"QueryBatchInput",
|
|
106
|
+
"QueryBatchOutput",
|
|
107
|
+
"QueryExtractionInput",
|
|
108
|
+
"QueryExtractionOutput",
|
|
109
|
+
"QueryFetchInput",
|
|
110
|
+
"QueryFetchOutput",
|
|
111
|
+
]
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Typed contracts for the deprecated upload_to_atlan task.
|
|
2
|
+
|
|
3
|
+
These contracts cover ``BaseMetadataExtractor.upload_to_atlan``, which is
|
|
4
|
+
now a thin ``@deprecated`` wrapper around :meth:`App.upload`. New code
|
|
5
|
+
should import :class:`UploadInput` / :class:`UploadOutput` directly from
|
|
6
|
+
``application_sdk.contracts.storage`` instead.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from application_sdk.contracts.base import Input, Output
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class UploadInput(Input):
|
|
15
|
+
"""Input for the deprecated ``upload_to_atlan`` task.
|
|
16
|
+
|
|
17
|
+
Carries a single ``output_path`` that the wrapper forwards as
|
|
18
|
+
``local_path`` on the storage ``UploadInput``.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
output_path: str = ""
|
|
22
|
+
"""Local path (file or directory) to push to the platform via App.upload."""
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class UploadOutput(Output):
|
|
26
|
+
"""Output from the deprecated ``upload_to_atlan`` task."""
|
|
27
|
+
|
|
28
|
+
migrated_files: int = 0
|
|
29
|
+
"""Number of files successfully uploaded."""
|
|
30
|
+
|
|
31
|
+
total_files: int = 0
|
|
32
|
+
"""Total number of files attempted (matches ``migrated_files`` on success)."""
|