atlan-application-sdk 0.1.1rc27__py3-none-any.whl → 0.1.1rc29__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.
@@ -0,0 +1,70 @@
1
+ from typing import Optional
2
+
3
+ from pyatlan.client.atlan import AtlanClient
4
+
5
+ from application_sdk.common.error_codes import ClientError
6
+ from application_sdk.constants import (
7
+ ATLAN_API_KEY,
8
+ ATLAN_API_TOKEN_GUID,
9
+ ATLAN_BASE_URL,
10
+ ATLAN_CLIENT_ID,
11
+ ATLAN_CLIENT_SECRET,
12
+ )
13
+ from application_sdk.observability.logger_adaptor import get_logger
14
+
15
+ logger = get_logger(__name__)
16
+
17
+
18
+ def get_client(
19
+ base_url: Optional[str] = None,
20
+ api_key: Optional[str] = None,
21
+ api_token_guid: Optional[str] = None,
22
+ ) -> AtlanClient:
23
+ """
24
+ Returns an authenticated AtlanClient instance using provided parameters or environment variables.
25
+
26
+ Selects authentication method based on the presence of parameters or environment variables and validates the required configuration.
27
+ In general, the use of environment variables is recommended. Any parameters specified will override the environment variables.
28
+
29
+ Args:
30
+ base_url: Atlan base URL (overrides ATLAN_BASE_URL)
31
+ api_key: Atlan API key (overrides ATLAN_API_KEY)
32
+ api_token_guid: API token GUID (overrides API_TOKEN_GUID)
33
+ """
34
+ # Resolve final values (parameters override env vars)
35
+ final_token_guid = api_token_guid or ATLAN_API_TOKEN_GUID
36
+ final_base_url = base_url or ATLAN_BASE_URL
37
+ final_api_key = api_key or ATLAN_API_KEY
38
+
39
+ # Priority 1: Token-based auth (recommended for production)
40
+ if final_token_guid:
41
+ if final_base_url or final_api_key: # Check original params, not env vars
42
+ logger.warning(
43
+ "Token auth takes precedence - ignoring base_url/api_key parameters as well as ATLAN_BASE_URL and ATLAN_API_KEY environment variables."
44
+ )
45
+ return _get_client_from_token(final_token_guid)
46
+
47
+ # Priority 2: API key + base URL auth
48
+ if not final_base_url:
49
+ raise ClientError(
50
+ "ATLAN_BASE_URL is required (via parameter or environment variable)"
51
+ )
52
+ if not final_api_key:
53
+ raise ClientError(
54
+ "ATLAN_API_KEY is required (via parameter or environment variable)"
55
+ )
56
+
57
+ logger.info("Using API key-based authentication")
58
+ return AtlanClient(base_url=final_base_url, api_key=final_api_key)
59
+
60
+
61
+ def _get_client_from_token(api_token_guid: str):
62
+ if not ATLAN_CLIENT_ID:
63
+ raise ClientError(
64
+ f"{ClientError.AUTH_CONFIG_ERROR}: Environment variable CLIENT_ID is required when API_TOKEN_GUID is set."
65
+ )
66
+ if not ATLAN_CLIENT_SECRET:
67
+ raise ClientError(
68
+ f"{ClientError.AUTH_CONFIG_ERROR}: Environment variable CLIENT_SECRET is required when API_TOKEN_GUID is set."
69
+ )
70
+ return AtlanClient.from_token_guid(guid=api_token_guid)
@@ -0,0 +1,32 @@
1
+ from dapr import clients
2
+
3
+ from application_sdk.observability.logger_adaptor import get_logger
4
+
5
+ logger = get_logger(__name__)
6
+
7
+
8
+ def is_component_registered(component_name: str) -> bool:
9
+ """Check if a DAPR component with the given name is registered.
10
+
11
+ Args:
12
+ component_name: Name of the component to check.
13
+
14
+ Returns:
15
+ True if the component is present, False otherwise or on metadata errors.
16
+ """
17
+ try:
18
+ with clients.DaprClient() as client:
19
+ metadata = client.get_metadata()
20
+ # Each registered component has fields: name, type (e.g., "eventstore")
21
+ for component in getattr(metadata, "registered_components", []):
22
+ if component.name == component_name:
23
+ return True
24
+ return False
25
+ except Exception:
26
+ # If we cannot read metadata, behave conservatively and report unavailable
27
+ logger.warning(
28
+ "Failed to read Dapr metadata for component availability check; treating as unavailable",
29
+ exc_info=True,
30
+ extra={"component_name": component_name},
31
+ )
32
+ return False
@@ -131,9 +131,9 @@ EVENT_STORE_NAME = os.getenv("EVENT_STORE_NAME", "eventstore")
131
131
  #: Whether to enable Atlan storage upload
132
132
  ENABLE_ATLAN_UPLOAD = os.getenv("ENABLE_ATLAN_UPLOAD", "false").lower() == "true"
133
133
  # Dapr Client Configuration
134
- #: Maximum gRPC message length in bytes for Dapr client (default: 16MB)
134
+ #: Maximum gRPC message length in bytes for Dapr client (default: 100MB)
135
135
  DAPR_MAX_GRPC_MESSAGE_LENGTH = int(
136
- os.getenv("DAPR_MAX_GRPC_MESSAGE_LENGTH", "16777216")
136
+ os.getenv("DAPR_MAX_GRPC_MESSAGE_LENGTH", "104857600")
137
137
  )
138
138
  #: Name of the deployment secret store component in DAPR
139
139
  DEPLOYMENT_SECRET_STORE_NAME = os.getenv(
@@ -217,3 +217,10 @@ TRACES_FILE_NAME = "traces.parquet"
217
217
  ENABLE_OBSERVABILITY_DAPR_SINK = (
218
218
  os.getenv("ATLAN_ENABLE_OBSERVABILITY_DAPR_SINK", "false").lower() == "true"
219
219
  )
220
+
221
+ # atlan_client configuration (non ATLAN_ prefix are rooted in pyatlan SDK, to be revisited)
222
+ ATLAN_API_TOKEN_GUID = os.getenv("API_TOKEN_GUID")
223
+ ATLAN_BASE_URL = os.getenv("ATLAN_BASE_URL")
224
+ ATLAN_API_KEY = os.getenv("ATLAN_API_KEY")
225
+ ATLAN_CLIENT_ID = os.getenv("CLIENT_ID")
226
+ ATLAN_CLIENT_SECRET = os.getenv("CLIENT_SECRET")
@@ -116,7 +116,7 @@ class BaseSQLHandler(HandlerInterface):
116
116
  async def fetch_metadata(
117
117
  self,
118
118
  metadata_type: Optional[str] = None,
119
- database: Optional[str] = None,
119
+ database: str = "",
120
120
  ) -> List[Dict[str, str]]:
121
121
  """
122
122
  Fetch metadata based on the requested type.
@@ -76,6 +76,7 @@ class StateStoreInput:
76
76
  state = {}
77
77
 
78
78
  try:
79
+ logger.info(f"Trying to download state object for {id} with type {type}")
79
80
  local_state_file_path = os.path.join(TEMPORARY_PATH, state_file_path)
80
81
  ObjectStoreInput.download_file_from_object_store(
81
82
  download_file_prefix=TEMPORARY_PATH,
@@ -86,10 +87,11 @@ class StateStoreInput:
86
87
  with open(local_state_file_path, "r") as file:
87
88
  state = json.load(file)
88
89
 
90
+ logger.info(f"State object downloaded for {id} with type {type}")
89
91
  except Exception as e:
90
92
  # local error message is "file not found", while in object store it is "object not found"
91
93
  if "not found" in str(e).lower():
92
- logger.debug(
94
+ logger.info(
93
95
  f"No state found for {type.value} with id '{id}', returning empty dict"
94
96
  )
95
97
  else:
@@ -14,6 +14,7 @@ from dapr import clients
14
14
  from pydantic import BaseModel, Field
15
15
  from temporalio import activity, workflow
16
16
 
17
+ from application_sdk.common.dapr_utils import is_component_registered
17
18
  from application_sdk.constants import APPLICATION_NAME, EVENT_STORE_NAME
18
19
  from application_sdk.observability.logger_adaptor import get_logger
19
20
 
@@ -155,6 +156,11 @@ class EventStore:
155
156
  Example:
156
157
  >>> EventStore.create_generic_event(Event(event_type="test", data={"test": "test"}))
157
158
  """
159
+ if not is_component_registered(EVENT_STORE_NAME):
160
+ logger.warning(
161
+ "Skipping event publish because event store component is not registered",
162
+ )
163
+ return
158
164
  try:
159
165
  if enrich_metadata:
160
166
  event = cls.enrich_event_metadata(event)
@@ -84,8 +84,8 @@ class StateStoreOutput:
84
84
  >>> from application_sdk.outputs.statestore import StateStoreOutput
85
85
  >>> await StateStoreOutput.save_state_object("wf-123", {"test": "test"}, "workflow")
86
86
  """
87
-
88
87
  try:
88
+ logger.info(f"Saving state object for {id} with type {type}")
89
89
  # get the current state from object store
90
90
  current_state = StateStoreInput.get_state(id, type)
91
91
  state_file_path = build_state_store_path(id, type)
@@ -106,7 +106,7 @@ class StateStoreOutput:
106
106
  file_path=local_state_file_path,
107
107
  object_store_name=UPSTREAM_OBJECT_STORE_NAME,
108
108
  )
109
-
109
+ logger.info(f"State object saved for {id} with type {type}")
110
110
  return current_state
111
111
  except Exception as e:
112
112
  logger.error(f"Failed to store state: {str(e)}")
@@ -493,7 +493,7 @@ class APIServer(ServerInterface):
493
493
  metrics = get_metrics()
494
494
 
495
495
  metadata_type = body.root.get("type", "all")
496
- database = body.root.get("database", None)
496
+ database = body.root.get("database", "")
497
497
 
498
498
  try:
499
499
  if not self.handler:
@@ -2,4 +2,4 @@
2
2
  Version information for the application_sdk package.
3
3
  """
4
4
 
5
- __version__ = "0.1.1rc27"
5
+ __version__ = "0.1.1rc29"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: atlan-application-sdk
3
- Version: 0.1.1rc27
3
+ Version: 0.1.1rc29
4
4
  Summary: Atlan Application SDK is a Python library for developing applications on the Atlan Platform
5
5
  Project-URL: Repository, https://github.com/atlanhq/application-sdk
6
6
  Project-URL: Documentation, https://github.com/atlanhq/application-sdk/README.md
@@ -26,7 +26,7 @@ Requires-Dist: fastapi[standard]>=0.115.0
26
26
  Requires-Dist: loguru>=0.7.3
27
27
  Requires-Dist: opentelemetry-exporter-otlp>=1.27.0
28
28
  Requires-Dist: psutil>=7.0.0
29
- Requires-Dist: pyatlan>=7.1.1
29
+ Requires-Dist: pyatlan>=7.1.6
30
30
  Requires-Dist: pydantic>=2.10.6
31
31
  Requires-Dist: python-dotenv>=1.1.0
32
32
  Requires-Dist: uvloop>=0.21.0; sys_platform != 'win32'
@@ -1,6 +1,6 @@
1
1
  application_sdk/__init__.py,sha256=2e2mvmLJ5dxmJGPELtb33xwP-j6JMdoIuqKycEn7hjg,151
2
- application_sdk/constants.py,sha256=n7pIycAD8olbB-nzXTvKPahUiuT8tIAR4quj9VPLNg0,8980
3
- application_sdk/version.py,sha256=are5jaXFs9oL9m2TQqMgiBrJuVelURMxLka4krzJ5YQ,88
2
+ application_sdk/constants.py,sha256=JMJdTVjIJZX1XrvxISAcPh3YQ3aYKBTSQ2thqiF8BR4,9304
3
+ application_sdk/version.py,sha256=nz1bVN0dhTMXPXvzYhNi0nvqWuV89WrvMhZPFwwenkc,88
4
4
  application_sdk/worker.py,sha256=2fLjuKNJafhaQXrHzmxXYO22F4ZSc0igMjoxXVNBFfk,6167
5
5
  application_sdk/activities/__init__.py,sha256=EH5VTHcfGykIX7V1HsG0J1Z-1FbJEXTQOET0HdzFDjU,9519
6
6
  application_sdk/activities/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -15,6 +15,7 @@ application_sdk/application/__init__.py,sha256=wCaAsoQ-wIYtfeG6hNwwLi8PcufjwMBjm
15
15
  application_sdk/application/metadata_extraction/sql.py,sha256=ohpV4qZ92uKRlH7I_8G67ocnWkZJAZCU_7XdvqYPiN4,7966
16
16
  application_sdk/clients/__init__.py,sha256=C9T84J7V6ZumcoWJPAxdd3tqSmbyciaGBJn-CaCCny0,1341
17
17
  application_sdk/clients/atlan_auth.py,sha256=MQznmvVKrlOT_Tp232W4UrOupRrx9Dx9zQm3n1R7kD8,8938
18
+ application_sdk/clients/atlan_client.py,sha256=f2-Uk5KiPIDJEhGkfYctA_f3CwoVB_mWNBMVvxeLuY4,2684
18
19
  application_sdk/clients/sql.py,sha256=tW89SHuuWdU5jv8lDUP5AUCEpR2CF_5TyUvYDCBHses,17880
19
20
  application_sdk/clients/temporal.py,sha256=kiB9W2e3x6gGtFC9e7vqTIBNGbt7nyS6p7j2hLKdsgI,22364
20
21
  application_sdk/clients/utils.py,sha256=zLFOJbTr_6TOqnjfVFGY85OtIXZ4FQy_rquzjaydkbY,779
@@ -22,6 +23,7 @@ application_sdk/clients/workflow.py,sha256=6bSqmA3sNCk9oY68dOjBUDZ9DhNKQxPD75qqE
22
23
  application_sdk/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
24
  application_sdk/common/aws_utils.py,sha256=aeL3BTMzv1UWJ4KxfwY5EsfYnxtS1FKNJ4xKdHeoTjc,3438
24
25
  application_sdk/common/credential_utils.py,sha256=M9oraG2uPeOSbxUAOJlP2IeClsDD79EhNkdow42dFsI,3025
26
+ application_sdk/common/dapr_utils.py,sha256=0yHqDP6qNb1OT-bX2XRYQPZ5xkGkV13nyRw6GkPlHs8,1136
25
27
  application_sdk/common/dataframe_utils.py,sha256=PId9vT6AUoq3tesiTd4sSUvW7RUhPWdAAEBLuOprks4,1262
26
28
  application_sdk/common/error_codes.py,sha256=uROVfOOMrGPO8JroWB3vs5rIEhr0GfcPqXAK9wdhcVQ,13742
27
29
  application_sdk/common/utils.py,sha256=ktCZLp-AEiyd-IPOgbD83Dg9qa8Z0Sj_mJmmdSzpOak,14759
@@ -41,7 +43,7 @@ application_sdk/docgen/parsers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5
41
43
  application_sdk/docgen/parsers/directory.py,sha256=8Kk2sjb-0l2wLO_njdlcuHjv5akoNgmf-FmaDSaE4WM,7751
42
44
  application_sdk/docgen/parsers/manifest.py,sha256=3NP-dBTpHAUQa477usMIDaKSb_9xfLE8G3RX0T1Bq2s,3318
43
45
  application_sdk/handlers/__init__.py,sha256=U7kKwVWK0FZz1uIJ2ANN0C5tD83k_9Nyz0ns6ttr92g,1152
44
- application_sdk/handlers/sql.py,sha256=qyLbTG9HZYX5_PAsvoSKANVcK53JS3sLUrqXMgXr1T8,16112
46
+ application_sdk/handlers/sql.py,sha256=oeB-sgWwPYo31xaD87TyMc0h51Sary1F-CmhExt9_Pk,16100
45
47
  application_sdk/inputs/__init__.py,sha256=_d-cUhcDyoJTJR3PdQkC831go6VDw9AM6Bg7-qm3NHI,1900
46
48
  application_sdk/inputs/iceberg.py,sha256=xiv1kNtVx1k0h3ZJbJeXjZwdfBGSy9j9orYP_AyCYlI,2756
47
49
  application_sdk/inputs/json.py,sha256=J1CVz0YGQHDyq840TyoBHE7Baua2yIFHzsrybiZbeWk,6079
@@ -49,7 +51,7 @@ application_sdk/inputs/objectstore.py,sha256=mOC5Bv10tZg9y4oikff_QViHSWZ_FHiotI9
49
51
  application_sdk/inputs/parquet.py,sha256=Hsi6Nz_KwxFMB6DcHSQov5y_hRkoeN7e4xfpYwogveo,6346
50
52
  application_sdk/inputs/secretstore.py,sha256=WPGvsPMLUaARvXA6JSa4uHp7tQcCW4NMIIUDQyM3F-I,3946
51
53
  application_sdk/inputs/sql_query.py,sha256=1EREgea6kKNaMIyX2HLJgbJ07rtAgLasd9NyvDcdZok,10636
52
- application_sdk/inputs/statestore.py,sha256=Ib87toiYzSEg7_7C0o6CeS-c0vsjaJqiIEIKwiwXAcE,2954
54
+ application_sdk/inputs/statestore.py,sha256=ORWnv8ZCqC1wT4vlW4v5EemJT4oQ3t_DlpjKDAgTRTs,3117
53
55
  application_sdk/observability/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
56
  application_sdk/observability/logger_adaptor.py,sha256=WTqnNg78W2SRGOQVhELVLn6KMRsurkG1kc7essL08Lk,29529
55
57
  application_sdk/observability/metrics_adaptor.py,sha256=4TYPNn38zLeqxwf7cUbe8wh_zwQlr-nyiXjJsiEhTEM,16445
@@ -59,15 +61,15 @@ application_sdk/observability/utils.py,sha256=MKEpT0WYtpATUgLgJDkGQaAP_t-jpDYMUK
59
61
  application_sdk/observability/decorators/observability_decorator.py,sha256=JNrWNXT5W4klmlAc5b8C3_VBjDu0PI64W2ptr7LMzk4,8110
60
62
  application_sdk/outputs/__init__.py,sha256=HX8VcN22xyrkoRWdjQj8TrC5dEUG7cPzOcvJhlprqAs,8415
61
63
  application_sdk/outputs/atlan_storage.py,sha256=HQLbuyOZQC-GxYAiCVJakIJizTWy926tdMGOHvaBlD8,6029
62
- application_sdk/outputs/eventstore.py,sha256=fEW1oo9ncKylF5uLXTgjyRQZCrj72Gta3CaeduSX8nw,5548
64
+ application_sdk/outputs/eventstore.py,sha256=MY9x_2A8Gempa1B3GQJ-C-B4dVrqO5u4Sfpla-2u91Q,5827
63
65
  application_sdk/outputs/iceberg.py,sha256=IGtj5WDgqLu6vzDEvw5DLsKsjm29Krto3AHvWpemr0A,5311
64
66
  application_sdk/outputs/json.py,sha256=xF-8mY3BZRRejip4s9npIUuFaAxgFmBQVaLMkrI_iCI,14117
65
67
  application_sdk/outputs/objectstore.py,sha256=TJvgfkJpGRK129ttxY7qRYJ7ASKZA4R6-0BUA3Lk7mc,4450
66
68
  application_sdk/outputs/parquet.py,sha256=A2EnEx1zWjaXk10u3eJusmWxGxt8WR7CHXDaJgsKpq0,11040
67
69
  application_sdk/outputs/secretstore.py,sha256=JS9vUzb11leDpcMQSCnLJuE9Ww-9G3wMvCdUKBPaw9I,1342
68
- application_sdk/outputs/statestore.py,sha256=erviUTNyK-iLPe03i4r-G-5D3uAWdRnkW83Hnu7wI7o,3854
70
+ application_sdk/outputs/statestore.py,sha256=XiEag2e9WW3_D3xbWQGoNrHiFJz9916qcIvhrROX8_8,3999
69
71
  application_sdk/server/__init__.py,sha256=KTqE1YPw_3WDVMWatJUuf9OOiobLM2K5SMaBrI62sCo,1568
70
- application_sdk/server/fastapi/__init__.py,sha256=QiIaR43QhgJaLeKs5lTghfxCAGxVxFnYAudy47akbP4,27783
72
+ application_sdk/server/fastapi/__init__.py,sha256=MnyLA75XP0_k3_yGp9nw9CTxw4Qa1DIZIs__BgzqJWI,27781
71
73
  application_sdk/server/fastapi/models.py,sha256=mFFxteDS3ZYXaq7Apor_Meo5WNxTCxqdrMkmTKQjvP0,6687
72
74
  application_sdk/server/fastapi/utils.py,sha256=2XI4DylhRQsukhX67lpAzRNCHeFCSpbuNd7TlE2IBJA,1164
73
75
  application_sdk/server/fastapi/middleware/logmiddleware.py,sha256=CxcPtDmCbSfSZ8RyI09nIshVIbCokyyA9bByQJ2G_ns,2545
@@ -129,8 +131,8 @@ application_sdk/workflows/metadata_extraction/__init__.py,sha256=jHUe_ZBQ66jx8bg
129
131
  application_sdk/workflows/metadata_extraction/sql.py,sha256=_NhszxIgmcQI6lVpjJoyJRFLwPYvJw1Dyqox_m9K2RA,11947
130
132
  application_sdk/workflows/query_extraction/__init__.py,sha256=n066_CX5RpJz6DIxGMkKS3eGSRg03ilaCtsqfJWQb7Q,117
131
133
  application_sdk/workflows/query_extraction/sql.py,sha256=kT_JQkLCRZ44ZpaC4QvPL6DxnRIIVh8gYHLqRbMI-hA,4826
132
- atlan_application_sdk-0.1.1rc27.dist-info/METADATA,sha256=pCLOauLHmtbMy_oEfXKXH_3GTXy9A577cgk8oLvWD_I,5473
133
- atlan_application_sdk-0.1.1rc27.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
134
- atlan_application_sdk-0.1.1rc27.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
135
- atlan_application_sdk-0.1.1rc27.dist-info/licenses/NOTICE,sha256=A-XVVGt3KOYuuMmvSMIFkg534F1vHiCggEBp4Ez3wGk,1041
136
- atlan_application_sdk-0.1.1rc27.dist-info/RECORD,,
134
+ atlan_application_sdk-0.1.1rc29.dist-info/METADATA,sha256=7b1L-yRwcdWGPeLEMGohOjAP9hmWpu-v024DqAF3Nzc,5473
135
+ atlan_application_sdk-0.1.1rc29.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
136
+ atlan_application_sdk-0.1.1rc29.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
137
+ atlan_application_sdk-0.1.1rc29.dist-info/licenses/NOTICE,sha256=A-XVVGt3KOYuuMmvSMIFkg534F1vHiCggEBp4Ez3wGk,1041
138
+ atlan_application_sdk-0.1.1rc29.dist-info/RECORD,,