atlan-application-sdk 0.1.1rc26__py3-none-any.whl → 0.1.1rc27__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.
@@ -27,11 +27,14 @@ from dotenv import load_dotenv
27
27
 
28
28
  load_dotenv(dotenv_path=".env")
29
29
 
30
+ # Static Constants
31
+ LOCAL_ENVIRONMENT = "local"
32
+
30
33
  # Application Constants
31
34
  #: Name of the application, used for identification
32
35
  APPLICATION_NAME = os.getenv("ATLAN_APPLICATION_NAME", "default")
33
36
  #: Name of the deployment, used to distinguish between different deployments of the same application
34
- DEPLOYMENT_NAME = os.getenv("ATLAN_DEPLOYMENT_NAME", "local")
37
+ DEPLOYMENT_NAME = os.getenv("ATLAN_DEPLOYMENT_NAME", LOCAL_ENVIRONMENT)
35
38
  #: Host address for the application's HTTP server
36
39
  APP_HOST = str(os.getenv("ATLAN_APP_HTTP_HOST", "localhost"))
37
40
  #: Port number for the application's HTTP server
@@ -46,8 +49,6 @@ APP_DASHBOARD_PORT = int(os.getenv("ATLAN_APP_DASHBOARD_PORT", "8000"))
46
49
  SQL_SERVER_MIN_VERSION = os.getenv("ATLAN_SQL_SERVER_MIN_VERSION")
47
50
  #: Path to the SQL queries directory
48
51
  SQL_QUERIES_PATH = os.getenv("ATLAN_SQL_QUERIES_PATH", "app/sql")
49
- #: Whether to use local development mode (used for instance to fetch secrets from the local state store)
50
- LOCAL_DEVELOPMENT = os.getenv("ATLAN_LOCAL_DEVELOPMENT", "false").lower() == "true"
51
52
 
52
53
  # Output Path Constants
53
54
  #: Output path format for workflows (example: objectstore://bucket/artifacts/apps/{application_name}/workflows/{workflow_id}/{workflow_run_id})
@@ -2,7 +2,7 @@
2
2
 
3
3
  import json
4
4
  import os
5
- from typing import Dict, List, Optional
5
+ from typing import Dict, List, Union
6
6
 
7
7
  import orjson
8
8
  from dapr.clients import DaprClient
@@ -27,7 +27,7 @@ class ObjectStoreInput:
27
27
  cls,
28
28
  operation: str,
29
29
  metadata: Dict[str, str],
30
- data: Optional[bytes] = None,
30
+ data: Union[bytes, str] = "",
31
31
  object_store_name: str = DEPLOYMENT_OBJECT_STORE_NAME,
32
32
  ) -> bytes:
33
33
  """
@@ -172,7 +172,7 @@ class ObjectStoreInput:
172
172
  try:
173
173
  # this takes care of listing from all type of storage - local as well as object stores
174
174
  metadata = {"prefix": prefix, "fileName": prefix} if prefix else {}
175
- data = json.dumps({"prefix": prefix}).encode("utf-8") if prefix else None
175
+ data = json.dumps({"prefix": prefix}).encode("utf-8") if prefix else ""
176
176
 
177
177
  response_data = cls._invoke_dapr_binding(
178
178
  operation=cls.OBJECT_LIST_OPERATION,
@@ -233,7 +233,7 @@ class ObjectStoreInput:
233
233
  """
234
234
  try:
235
235
  metadata = {"key": file_path, "fileName": file_path}
236
- data = json.dumps({"key": file_path}).encode("utf-8") if file_path else None
236
+ data = json.dumps({"key": file_path}).encode("utf-8") if file_path else ""
237
237
 
238
238
  response_data = cls._invoke_dapr_binding(
239
239
  operation=cls.OBJECT_GET_OPERATION,
@@ -1,4 +1,5 @@
1
1
  import glob
2
+ import os
2
3
  from typing import TYPE_CHECKING, AsyncIterator, Iterator, List, Optional, Union
3
4
 
4
5
  from application_sdk.inputs import Input
@@ -41,27 +42,32 @@ class ParquetInput(Input):
41
42
  self.input_prefix = input_prefix
42
43
  self.file_names = file_names
43
44
 
44
- async def download_files(self, remote_file_path: str) -> Optional[str]:
45
+ async def download_files(self, local_file_path: str) -> Optional[str]:
45
46
  """Read a file from the object store.
46
47
 
47
48
  Args:
48
- remote_file_path (str): Path to the remote file in object store.
49
+ local_file_path (str): Path to the local file in the temp directory.
49
50
 
50
51
  Returns:
51
52
  Optional[str]: Path to the downloaded local file.
52
53
  """
53
- parquet_files = glob.glob(remote_file_path)
54
+ parquet_files = glob.glob(local_file_path)
54
55
  if not parquet_files:
55
56
  if self.input_prefix:
56
57
  logger.info(
57
- f"Reading file from object store: {remote_file_path} from {self.input_prefix}"
58
- )
59
- ObjectStoreInput.download_files_from_object_store(
60
- self.input_prefix, remote_file_path
58
+ f"Reading file from object store: {local_file_path} from {self.input_prefix}"
61
59
  )
60
+ if os.path.isdir(local_file_path):
61
+ ObjectStoreInput.download_files_from_object_store(
62
+ self.input_prefix, local_file_path
63
+ )
64
+ else:
65
+ ObjectStoreInput.download_file_from_object_store(
66
+ self.input_prefix, local_file_path
67
+ )
62
68
  else:
63
69
  raise ValueError(
64
- f"No parquet files found in {remote_file_path} and no input prefix provided"
70
+ f"No parquet files found in {local_file_path} and no input prefix provided"
65
71
  )
66
72
 
67
73
  async def get_dataframe(self) -> "pd.DataFrame":
@@ -8,9 +8,10 @@ from typing import Any, Dict
8
8
  from dapr.clients import DaprClient
9
9
 
10
10
  from application_sdk.constants import (
11
+ DEPLOYMENT_NAME,
11
12
  DEPLOYMENT_SECRET_PATH,
12
13
  DEPLOYMENT_SECRET_STORE_NAME,
13
- LOCAL_DEVELOPMENT,
14
+ LOCAL_ENVIRONMENT,
14
15
  SECRET_STORE_NAME,
15
16
  )
16
17
  from application_sdk.observability.logger_adaptor import get_logger
@@ -41,7 +42,7 @@ class SecretStoreInput:
41
42
  Returns:
42
43
  Dict with processed secret data
43
44
  """
44
- if LOCAL_DEVELOPMENT:
45
+ if DEPLOYMENT_NAME == LOCAL_ENVIRONMENT:
45
46
  return {}
46
47
 
47
48
  try:
@@ -82,7 +82,6 @@ class AtlanStorageOutput:
82
82
 
83
83
  logger.debug(f"Successfully migrated: {file_path}")
84
84
  return file_path, True, ""
85
-
86
85
  except Exception as e:
87
86
  error_msg = str(e)
88
87
  logger.error(f"Failed to migrate file {file_path}: {error_msg}")
@@ -1,6 +1,7 @@
1
1
  """Object store interface for the application."""
2
2
 
3
3
  import os
4
+ import shutil
4
5
 
5
6
  from dapr.clients import DaprClient
6
7
  from temporalio import activity
@@ -15,6 +16,22 @@ activity.logger = logger
15
16
  class ObjectStoreOutput:
16
17
  OBJECT_CREATE_OPERATION = "create"
17
18
 
19
+ @staticmethod
20
+ def _cleanup_local_path(path: str) -> None:
21
+ """Remove a file or directory (recursively). Ignores if doesn't exist.
22
+ Args:
23
+ path (str): The path to the file or directory to remove.
24
+ """
25
+ try:
26
+ if os.path.isfile(path) or os.path.islink(path):
27
+ os.remove(path)
28
+ elif os.path.isdir(path):
29
+ shutil.rmtree(path)
30
+ except FileNotFoundError:
31
+ pass # ignore if the file or directory doesn't exist
32
+ except Exception as e:
33
+ logger.warning(f"Error cleaning up {path}: {str(e)}")
34
+
18
35
  @classmethod
19
36
  async def push_file_to_object_store(
20
37
  cls,
@@ -62,6 +79,7 @@ class ObjectStoreOutput:
62
79
  f"Error pushing file {relative_path} to object store: {str(e)}"
63
80
  )
64
81
  raise e
82
+ cls._cleanup_local_path(file_path)
65
83
 
66
84
  @classmethod
67
85
  async def push_files_to_object_store(
@@ -3,7 +3,7 @@
3
3
  import uuid
4
4
  from typing import Any, Dict
5
5
 
6
- from application_sdk.constants import LOCAL_DEVELOPMENT
6
+ from application_sdk.constants import DEPLOYMENT_NAME, LOCAL_ENVIRONMENT
7
7
  from application_sdk.inputs.statestore import StateType
8
8
  from application_sdk.outputs.statestore import StateStoreOutput
9
9
 
@@ -26,7 +26,7 @@ class SecretStoreOutput:
26
26
  >>> SecretStoreOutput.save_secret({"username": "admin", "password": "password"})
27
27
  "1234567890"
28
28
  """
29
- if LOCAL_DEVELOPMENT:
29
+ if DEPLOYMENT_NAME == LOCAL_ENVIRONMENT:
30
30
  # NOTE: (development) temporary solution to store the credentials in the state store.
31
31
  # In production, dapr doesn't support creating secrets.
32
32
  credential_guid = str(uuid.uuid4())
@@ -2,4 +2,4 @@
2
2
  Version information for the application_sdk package.
3
3
  """
4
4
 
5
- __version__ = "0.1.1rc26"
5
+ __version__ = "0.1.1rc27"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: atlan-application-sdk
3
- Version: 0.1.1rc26
3
+ Version: 0.1.1rc27
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
@@ -31,7 +31,7 @@ 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'
33
33
  Provides-Extra: daft
34
- Requires-Dist: getdaft[sql]>=0.4.12; extra == 'daft'
34
+ Requires-Dist: daft[sql]>=0.4.12; extra == 'daft'
35
35
  Provides-Extra: iam-auth
36
36
  Requires-Dist: boto3>=1.38.6; extra == 'iam-auth'
37
37
  Provides-Extra: iceberg
@@ -1,6 +1,6 @@
1
1
  application_sdk/__init__.py,sha256=2e2mvmLJ5dxmJGPELtb33xwP-j6JMdoIuqKycEn7hjg,151
2
- application_sdk/constants.py,sha256=txVsXgN9aBsDXw0Dw9XqYbdTsLTVP5qTS26I1IKpVCA,9111
3
- application_sdk/version.py,sha256=fqQ1fw6udcOHy2GZF5O3JVl7ADaHX-iU2cezF5M4P04,88
2
+ application_sdk/constants.py,sha256=n7pIycAD8olbB-nzXTvKPahUiuT8tIAR4quj9VPLNg0,8980
3
+ application_sdk/version.py,sha256=are5jaXFs9oL9m2TQqMgiBrJuVelURMxLka4krzJ5YQ,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
@@ -45,9 +45,9 @@ application_sdk/handlers/sql.py,sha256=qyLbTG9HZYX5_PAsvoSKANVcK53JS3sLUrqXMgXr1
45
45
  application_sdk/inputs/__init__.py,sha256=_d-cUhcDyoJTJR3PdQkC831go6VDw9AM6Bg7-qm3NHI,1900
46
46
  application_sdk/inputs/iceberg.py,sha256=xiv1kNtVx1k0h3ZJbJeXjZwdfBGSy9j9orYP_AyCYlI,2756
47
47
  application_sdk/inputs/json.py,sha256=J1CVz0YGQHDyq840TyoBHE7Baua2yIFHzsrybiZbeWk,6079
48
- application_sdk/inputs/objectstore.py,sha256=z7BaEpVzoiscZ2Tdq9vPBWj4MZb3LjygE2dd1jn1ZRo,8788
49
- application_sdk/inputs/parquet.py,sha256=rrDI_OAktZIpWMIJIvyNoqrDg-lH2t_4NnB_x6JmX30,6101
50
- application_sdk/inputs/secretstore.py,sha256=3JieHdRXEOATWwJW4jkuRvcd7EDUHR0akSXhqtSM0Q0,3906
48
+ application_sdk/inputs/objectstore.py,sha256=mOC5Bv10tZg9y4oikff_QViHSWZ_FHiotI9xdrlAIok,8781
49
+ application_sdk/inputs/parquet.py,sha256=Hsi6Nz_KwxFMB6DcHSQov5y_hRkoeN7e4xfpYwogveo,6346
50
+ application_sdk/inputs/secretstore.py,sha256=WPGvsPMLUaARvXA6JSa4uHp7tQcCW4NMIIUDQyM3F-I,3946
51
51
  application_sdk/inputs/sql_query.py,sha256=1EREgea6kKNaMIyX2HLJgbJ07rtAgLasd9NyvDcdZok,10636
52
52
  application_sdk/inputs/statestore.py,sha256=Ib87toiYzSEg7_7C0o6CeS-c0vsjaJqiIEIKwiwXAcE,2954
53
53
  application_sdk/observability/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -58,13 +58,13 @@ application_sdk/observability/traces_adaptor.py,sha256=0eQJPN-tYA_dV8D3uEa5ZiX9g
58
58
  application_sdk/observability/utils.py,sha256=MKEpT0WYtpATUgLgJDkGQaAP_t-jpDYMUKDfEvr8Phg,2448
59
59
  application_sdk/observability/decorators/observability_decorator.py,sha256=JNrWNXT5W4klmlAc5b8C3_VBjDu0PI64W2ptr7LMzk4,8110
60
60
  application_sdk/outputs/__init__.py,sha256=HX8VcN22xyrkoRWdjQj8TrC5dEUG7cPzOcvJhlprqAs,8415
61
- application_sdk/outputs/atlan_storage.py,sha256=V4fXslizhpsOg7_on_a_RM8IEAl6wa3fqd8BcceXjsg,6030
61
+ application_sdk/outputs/atlan_storage.py,sha256=HQLbuyOZQC-GxYAiCVJakIJizTWy926tdMGOHvaBlD8,6029
62
62
  application_sdk/outputs/eventstore.py,sha256=fEW1oo9ncKylF5uLXTgjyRQZCrj72Gta3CaeduSX8nw,5548
63
63
  application_sdk/outputs/iceberg.py,sha256=IGtj5WDgqLu6vzDEvw5DLsKsjm29Krto3AHvWpemr0A,5311
64
64
  application_sdk/outputs/json.py,sha256=xF-8mY3BZRRejip4s9npIUuFaAxgFmBQVaLMkrI_iCI,14117
65
- application_sdk/outputs/objectstore.py,sha256=CfEI13tgp-WyQAEDyBelUZULUzAxHMxrdZifn66mIKo,3771
65
+ application_sdk/outputs/objectstore.py,sha256=TJvgfkJpGRK129ttxY7qRYJ7ASKZA4R6-0BUA3Lk7mc,4450
66
66
  application_sdk/outputs/parquet.py,sha256=A2EnEx1zWjaXk10u3eJusmWxGxt8WR7CHXDaJgsKpq0,11040
67
- application_sdk/outputs/secretstore.py,sha256=AuLcM-wmzr7ZTXePLk3dunj3vhIhWkigQ-XYJo6SOZA,1306
67
+ application_sdk/outputs/secretstore.py,sha256=JS9vUzb11leDpcMQSCnLJuE9Ww-9G3wMvCdUKBPaw9I,1342
68
68
  application_sdk/outputs/statestore.py,sha256=erviUTNyK-iLPe03i4r-G-5D3uAWdRnkW83Hnu7wI7o,3854
69
69
  application_sdk/server/__init__.py,sha256=KTqE1YPw_3WDVMWatJUuf9OOiobLM2K5SMaBrI62sCo,1568
70
70
  application_sdk/server/fastapi/__init__.py,sha256=QiIaR43QhgJaLeKs5lTghfxCAGxVxFnYAudy47akbP4,27783
@@ -129,8 +129,8 @@ application_sdk/workflows/metadata_extraction/__init__.py,sha256=jHUe_ZBQ66jx8bg
129
129
  application_sdk/workflows/metadata_extraction/sql.py,sha256=_NhszxIgmcQI6lVpjJoyJRFLwPYvJw1Dyqox_m9K2RA,11947
130
130
  application_sdk/workflows/query_extraction/__init__.py,sha256=n066_CX5RpJz6DIxGMkKS3eGSRg03ilaCtsqfJWQb7Q,117
131
131
  application_sdk/workflows/query_extraction/sql.py,sha256=kT_JQkLCRZ44ZpaC4QvPL6DxnRIIVh8gYHLqRbMI-hA,4826
132
- atlan_application_sdk-0.1.1rc26.dist-info/METADATA,sha256=wnjrsH3xghiBQv3BLczFc9_PpnmVhohjtlC80qHzUuo,5476
133
- atlan_application_sdk-0.1.1rc26.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
134
- atlan_application_sdk-0.1.1rc26.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
135
- atlan_application_sdk-0.1.1rc26.dist-info/licenses/NOTICE,sha256=zlRshGtgfjXFcCKn_hwuILOFV9-NoKe0e2Tjy98_lrw,1044
136
- atlan_application_sdk-0.1.1rc26.dist-info/RECORD,,
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,,
@@ -19,7 +19,7 @@ Apache License 2.0 Dependencies:
19
19
  - Apache Atlas (https://github.com/apache/atlas) under Apache-2.0 license
20
20
  - Elasticsearch DSL (https://github.com/elastic/elasticsearch-dsl-py) under Apache-2.0 license
21
21
  - orjson (https://github.com/ijl/orjson)
22
- - getdaft (https://github.com/Eventual-Inc/Daft)
22
+ - daft (https://github.com/Eventual-Inc/Daft)
23
23
  - pyiceberg (https://github.com/apache/iceberg-python)
24
24
  - pyarrow (https://github.com/apache/arrow/tree/main/python)
25
25
  - dapr (https://github.com/dapr/python-sdk/)