aplos-nca-saas-sdk 0.0.12__py3-none-any.whl → 0.0.14__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.
- aplos_nca_saas_sdk/integration_testing/configs/_config_base.py +7 -2
- aplos_nca_saas_sdk/integration_testing/configs/app_settings_config.py +36 -36
- aplos_nca_saas_sdk/integration_testing/configs/config_sample.json +10 -10
- aplos_nca_saas_sdk/integration_testing/configs/file_upload_config.py +1 -1
- aplos_nca_saas_sdk/integration_testing/configs/login_config.py +15 -14
- aplos_nca_saas_sdk/integration_testing/configs/nca_execution_config.py +1 -1
- aplos_nca_saas_sdk/integration_testing/integration_test_base.py +2 -2
- aplos_nca_saas_sdk/integration_testing/integration_test_configurations.py +9 -5
- aplos_nca_saas_sdk/integration_testing/integration_test_factory.py +1 -1
- aplos_nca_saas_sdk/integration_testing/integration_test_response.py +1 -1
- aplos_nca_saas_sdk/integration_testing/integration_test_suite.py +10 -3
- aplos_nca_saas_sdk/integration_testing/main.py +9 -8
- aplos_nca_saas_sdk/integration_testing/readme.md +1 -1
- aplos_nca_saas_sdk/integration_testing/tests/app_configuration_test.py +4 -4
- aplos_nca_saas_sdk/integration_testing/tests/app_login_test.py +3 -3
- aplos_nca_saas_sdk/integration_testing/tests/file_upload_test.py +40 -91
- aplos_nca_saas_sdk/integration_testing/tests/nca_analysis_test.py +2 -2
- aplos_nca_saas_sdk/integration_testing/tests/validation_test.py +1 -1
- aplos_nca_saas_sdk/nca_resources/_api_base.py +44 -0
- aplos_nca_saas_sdk/{aws_resources → nca_resources}/aws_cognito.py +2 -2
- aplos_nca_saas_sdk/{aws_resources → nca_resources}/aws_s3_presigned_payload.py +3 -3
- aplos_nca_saas_sdk/{aws_resources → nca_resources}/aws_s3_presigned_upload.py +28 -22
- aplos_nca_saas_sdk/nca_resources/nca_analysis.py +23 -167
- aplos_nca_saas_sdk/nca_resources/nca_app_configuration.py +4 -4
- aplos_nca_saas_sdk/nca_resources/{nca_login.py → nca_authenticator.py} +23 -20
- aplos_nca_saas_sdk/nca_resources/nca_endpoints.py +56 -30
- aplos_nca_saas_sdk/nca_resources/nca_file_download.py +130 -0
- aplos_nca_saas_sdk/nca_resources/nca_file_upload.py +27 -29
- aplos_nca_saas_sdk/nca_resources/nca_validations.py +34 -0
- aplos_nca_saas_sdk/run_analysis_execution.py +148 -0
- aplos_nca_saas_sdk/utilities/commandline_args.py +29 -13
- aplos_nca_saas_sdk/utilities/environment_services.py +3 -2
- aplos_nca_saas_sdk/utilities/environment_vars.py +10 -4
- aplos_nca_saas_sdk/utilities/file_utility.py +1 -1
- aplos_nca_saas_sdk/utilities/http_utility.py +1 -26
- aplos_nca_saas_sdk/version.py +1 -1
- {aplos_nca_saas_sdk-0.0.12.dist-info → aplos_nca_saas_sdk-0.0.14.dist-info}/METADATA +1 -1
- aplos_nca_saas_sdk-0.0.14.dist-info/RECORD +51 -0
- {aplos_nca_saas_sdk-0.0.12.dist-info → aplos_nca_saas_sdk-0.0.14.dist-info}/licenses/LICENSE +1 -1
- aplos_nca_saas_sdk-0.0.12.dist-info/RECORD +0 -47
- /aplos_nca_saas_sdk/{files/analysis_files/single_ev/configuration_single_ev.json → sample_files/analysis_files/single_ev/config.json} +0 -0
- /aplos_nca_saas_sdk/{files/analysis_files/single_ev/single_ev.csv → sample_files/analysis_files/single_ev/input.csv} +0 -0
- /aplos_nca_saas_sdk/{files → sample_files}/analysis_files/single_ev/meta_data.json +0 -0
- {aplos_nca_saas_sdk-0.0.12.dist-info → aplos_nca_saas_sdk-0.0.14.dist-info}/WHEEL +0 -0
@@ -1,25 +1,25 @@
|
|
1
1
|
"""
|
2
|
-
Copyright 2024 Aplos Analytics
|
2
|
+
Copyright 2024-2025 Aplos Analytics
|
3
3
|
All Rights Reserved. www.aplosanalytics.com LICENSED MATERIALS
|
4
4
|
Property of Aplos Analytics, Utah, USA
|
5
5
|
"""
|
6
6
|
|
7
7
|
from typing import Optional
|
8
|
-
from aplos_nca_saas_sdk.
|
8
|
+
from aplos_nca_saas_sdk.nca_resources.aws_cognito import CognitoAuthentication
|
9
9
|
from aplos_nca_saas_sdk.nca_resources.nca_app_configuration import (
|
10
10
|
NCAAppConfiguration,
|
11
11
|
)
|
12
12
|
|
13
13
|
|
14
|
-
class
|
15
|
-
"""NCA
|
14
|
+
class NCAAuthenticator:
|
15
|
+
"""NCA Authenticator"""
|
16
16
|
|
17
17
|
def __init__(
|
18
18
|
self,
|
19
19
|
*,
|
20
20
|
cognito_client_id: Optional[str] = None,
|
21
21
|
cognito_region: Optional[str] = None,
|
22
|
-
|
22
|
+
host: Optional[str] = None,
|
23
23
|
) -> None:
|
24
24
|
"""
|
25
25
|
NCA SaaS Login
|
@@ -27,18 +27,16 @@ class NCALogin:
|
|
27
27
|
Args:
|
28
28
|
cognito_client_id (Optional[str], optional): Cognito Client Id. Defaults to None.
|
29
29
|
cognito_region (Optional[str], optional): Cognito Region. Defaults to None.
|
30
|
-
|
30
|
+
host (Optional[str], optional): Aplos NCA SaaS host. Defaults to None.
|
31
31
|
|
32
32
|
Requirements:
|
33
33
|
Either pass in the cognito_client_id and cognito_region.
|
34
|
-
or set the
|
34
|
+
or set the host to automatically get the client_id and region.
|
35
35
|
"""
|
36
|
-
|
37
|
-
self.access_token: Optional[str] = None
|
38
|
-
self.refresh_token: Optional[str] = None
|
36
|
+
|
39
37
|
self.__cognito_client_id = cognito_client_id
|
40
38
|
self.__region = cognito_region
|
41
|
-
self.
|
39
|
+
self.__host: Optional[str] = host
|
42
40
|
self.__cognito: Optional[CognitoAuthentication] = None
|
43
41
|
self.__config: Optional[NCAAppConfiguration] = None
|
44
42
|
|
@@ -53,19 +51,19 @@ class NCALogin:
|
|
53
51
|
self.__cognito = CognitoAuthentication(
|
54
52
|
client_id=self.__cognito_client_id,
|
55
53
|
region=self.__region,
|
56
|
-
aplos_domain=self.
|
54
|
+
aplos_domain=self.__host,
|
57
55
|
)
|
58
56
|
|
59
57
|
return self.__cognito
|
60
58
|
|
61
59
|
@property
|
62
|
-
def
|
60
|
+
def host(self) -> str | None:
|
63
61
|
"""
|
64
62
|
Domain
|
65
63
|
Returns:
|
66
|
-
str: the
|
64
|
+
str: the host
|
67
65
|
"""
|
68
|
-
return self.
|
66
|
+
return self.__host
|
69
67
|
|
70
68
|
@property
|
71
69
|
def config(self) -> NCAAppConfiguration:
|
@@ -75,13 +73,13 @@ class NCALogin:
|
|
75
73
|
NCAAppConfiguration: object to handle the NCA App Configuration
|
76
74
|
"""
|
77
75
|
if self.__config is None:
|
78
|
-
if self.
|
76
|
+
if self.__host is None:
|
79
77
|
raise RuntimeError(
|
80
78
|
"Failed to get Aplos Configuration. The Domain is not set."
|
81
79
|
)
|
82
80
|
|
83
81
|
self.__config = NCAAppConfiguration(
|
84
|
-
|
82
|
+
host=self.__host,
|
85
83
|
)
|
86
84
|
|
87
85
|
return self.__config
|
@@ -96,9 +94,14 @@ class NCALogin:
|
|
96
94
|
Args:
|
97
95
|
username (str): the username
|
98
96
|
password (str): the users password
|
99
|
-
|
97
|
+
Returns:
|
98
|
+
str: JWT (JSON Web Token)
|
100
99
|
"""
|
100
|
+
if not username:
|
101
|
+
raise ValueError("Missing username. Please provide a valid username.")
|
102
|
+
if not password:
|
103
|
+
raise ValueError("Missing password. Please provide a valid password.")
|
101
104
|
|
102
|
-
self.
|
105
|
+
self.cognito.login(username=username, password=password)
|
103
106
|
|
104
|
-
return self.jwt
|
107
|
+
return self.cognito.jwt
|
@@ -1,5 +1,5 @@
|
|
1
1
|
"""
|
2
|
-
Copyright 2024 Aplos Analytics
|
2
|
+
Copyright 2024-2025 Aplos Analytics
|
3
3
|
All Rights Reserved. www.aplosanalytics.com LICENSED MATERIALS
|
4
4
|
Property of Aplos Analytics, Utah, USA
|
5
5
|
"""
|
@@ -8,51 +8,77 @@ Property of Aplos Analytics, Utah, USA
|
|
8
8
|
class NCAEndpoints:
|
9
9
|
"""Aplos NCA SaaS Endpoints"""
|
10
10
|
|
11
|
-
def __init__(
|
12
|
-
self
|
11
|
+
def __init__(
|
12
|
+
self, *, host: str, tenant_id: str | None = None, user_id: str | None = None
|
13
|
+
):
|
14
|
+
self.__host: str = host
|
13
15
|
self.__protocal: str = "https://"
|
16
|
+
self.tenant_id: str | None = tenant_id
|
17
|
+
self.user_id: str | None = user_id
|
14
18
|
|
15
|
-
|
16
|
-
|
17
|
-
|
19
|
+
@property
|
20
|
+
def origin(self) -> str:
|
21
|
+
"""The origin path e.g. https://api.aplos-nca.com"""
|
22
|
+
base = f"{self.__protocal}{self.__host}"
|
23
|
+
return base
|
18
24
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
if not tenant_id:
|
23
|
-
raise ValueError("Tenant ID is required on the users path")
|
24
|
-
route = f"{route}/users/{user_id}"
|
25
|
+
@property
|
26
|
+
def tenant_path(self) -> str:
|
27
|
+
"""Returns the tenant path"""
|
25
28
|
|
26
|
-
|
29
|
+
if not self.tenant_id:
|
30
|
+
raise ValueError("Missing Tenant Id")
|
27
31
|
|
28
|
-
|
32
|
+
return f"{self.origin}/tenants/{self.tenant_id}"
|
33
|
+
|
34
|
+
@property
|
35
|
+
def user_path(self) -> str:
|
36
|
+
"""Returns the user path"""
|
37
|
+
|
38
|
+
if not self.user_id:
|
39
|
+
raise ValueError("Missing User Id")
|
40
|
+
return f"{self.tenant_path}/users/{self.user_id}"
|
41
|
+
|
42
|
+
@property
|
43
|
+
def tenant(self) -> str:
|
29
44
|
"""Returns the tenant endpoint"""
|
30
|
-
return f"{self.
|
45
|
+
return f"{self.tenant_path}"
|
31
46
|
|
47
|
+
@property
|
32
48
|
def app_configuration(self) -> str:
|
33
|
-
"""
|
34
|
-
|
49
|
+
"""
|
50
|
+
Returns the configuration endpoint. This is a public endpoint.
|
51
|
+
"""
|
52
|
+
return f"{self.origin}/app/configuration"
|
35
53
|
|
36
|
-
|
54
|
+
@property
|
55
|
+
def user(self) -> str:
|
37
56
|
"""Returns the user endpoint"""
|
38
|
-
return f"{self.
|
57
|
+
return f"{self.user_path}"
|
39
58
|
|
40
|
-
|
59
|
+
@property
|
60
|
+
def executions(self) -> str:
|
41
61
|
"""Returns the executions endpoint"""
|
42
|
-
return f"{self.
|
62
|
+
return f"{self.user_path}/nca/executions"
|
43
63
|
|
44
|
-
def execution(self,
|
64
|
+
def execution(self, execution_id: str) -> str:
|
45
65
|
"""Returns the executions endpoint"""
|
46
|
-
return f"{self.executions
|
66
|
+
return f"{self.executions}/{execution_id}"
|
47
67
|
|
48
|
-
|
68
|
+
@property
|
69
|
+
def validations(self) -> str:
|
70
|
+
"""Returns the validations endpoint"""
|
71
|
+
return f"{self.user_path}/nca/validations"
|
72
|
+
|
73
|
+
@property
|
74
|
+
def files(self) -> str:
|
49
75
|
"""Returns the files endpoint"""
|
50
|
-
return f"{self.
|
76
|
+
return f"{self.user_path}/nca/files"
|
51
77
|
|
52
|
-
def file(self,
|
78
|
+
def file(self, file_id: str) -> str:
|
53
79
|
"""Returns the file endpoint"""
|
54
|
-
return f"{self.files
|
55
|
-
|
56
|
-
def file_data(self,
|
80
|
+
return f"{self.files}/{file_id}"
|
81
|
+
|
82
|
+
def file_data(self, file_id: str) -> str:
|
57
83
|
"""Returns get file data endpoint"""
|
58
|
-
return f"{self.
|
84
|
+
return f"{self.files}/{file_id}/data"
|
@@ -0,0 +1,130 @@
|
|
1
|
+
"""
|
2
|
+
Copyright 2024-2025 Aplos Analytics
|
3
|
+
All Rights Reserved. www.aplosanalytics.com LICENSED MATERIALS
|
4
|
+
Property of Aplos Analytics, Utah, USA
|
5
|
+
"""
|
6
|
+
|
7
|
+
import time
|
8
|
+
from typing import Any, Dict, List
|
9
|
+
from datetime import datetime, timedelta
|
10
|
+
from aws_lambda_powertools import Logger
|
11
|
+
from aplos_nca_saas_sdk.nca_resources._api_base import NCAApiBaseClass
|
12
|
+
from aplos_nca_saas_sdk.nca_resources.aws_s3_presigned_upload import (
|
13
|
+
S3PresignedUrlUpload,
|
14
|
+
)
|
15
|
+
|
16
|
+
from aplos_nca_saas_sdk.utilities.http_utility import HttpUtilities
|
17
|
+
import requests
|
18
|
+
|
19
|
+
logger = Logger(service="nca-file-download")
|
20
|
+
|
21
|
+
|
22
|
+
class NCAFileDownload(NCAApiBaseClass):
|
23
|
+
"""NCA File Download"""
|
24
|
+
|
25
|
+
def __init__(self, host: str) -> None:
|
26
|
+
super().__init__(host)
|
27
|
+
|
28
|
+
def upload(
|
29
|
+
self,
|
30
|
+
input_file_path: str,
|
31
|
+
user_name: str | None = None,
|
32
|
+
password: str | None = None,
|
33
|
+
) -> Dict[str, Any]:
|
34
|
+
"""
|
35
|
+
Uploads a file to the Aplos NCA Cloud
|
36
|
+
|
37
|
+
Args:
|
38
|
+
input_file_path (str): local path to the file
|
39
|
+
|
40
|
+
Raises:
|
41
|
+
ValueError: _description_
|
42
|
+
|
43
|
+
Returns:
|
44
|
+
Dict: {"file_id": id, "statu_code": 204}
|
45
|
+
"""
|
46
|
+
if input_file_path is None or not input_file_path:
|
47
|
+
raise ValueError("Valid input_file_path is required.")
|
48
|
+
|
49
|
+
if not self.authenticator.cognito.jwt:
|
50
|
+
if not user_name or not password:
|
51
|
+
raise ValueError(
|
52
|
+
"Valid user_name and password are required or you can set the authenticator object."
|
53
|
+
)
|
54
|
+
self.authenticator.authenticate(username=user_name, password=password)
|
55
|
+
|
56
|
+
uploader: S3PresignedUrlUpload = S3PresignedUrlUpload(self.host)
|
57
|
+
uploader.authenticator = self.authenticator
|
58
|
+
|
59
|
+
upload_response: Dict[str, Any] = uploader.upload_file(
|
60
|
+
input_file=input_file_path
|
61
|
+
)
|
62
|
+
|
63
|
+
return upload_response
|
64
|
+
|
65
|
+
def download(
|
66
|
+
self,
|
67
|
+
file_id: str,
|
68
|
+
user_name: str | None = None,
|
69
|
+
password: str | None = None,
|
70
|
+
) -> Dict[str, Any]:
|
71
|
+
"""
|
72
|
+
Downloads a file from the Aplos NCA Cloud
|
73
|
+
|
74
|
+
Args:
|
75
|
+
file_id (str): the id of the file to download
|
76
|
+
|
77
|
+
Raises:
|
78
|
+
ValueError: _description_
|
79
|
+
|
80
|
+
Returns:
|
81
|
+
Dict: {"file_id": id, "statu_code": 204}
|
82
|
+
"""
|
83
|
+
|
84
|
+
logger.info({"message": "Downloading file", "file_id": file_id})
|
85
|
+
|
86
|
+
file_info_endpoint = self.endpoints.file(
|
87
|
+
file_id,
|
88
|
+
)
|
89
|
+
|
90
|
+
if not self.authenticator.cognito.jwt:
|
91
|
+
if not user_name or not password:
|
92
|
+
raise ValueError(
|
93
|
+
"Valid user_name and password are required or you can set the authenticator object."
|
94
|
+
)
|
95
|
+
self.authenticator.authenticate(username=user_name, password=password)
|
96
|
+
|
97
|
+
max_wait_in_minutes: int = 3
|
98
|
+
headers = HttpUtilities.get_headers(self.authenticator.cognito.jwt)
|
99
|
+
current_time = datetime.now()
|
100
|
+
|
101
|
+
# Create a timedelta object representing 3 minutes
|
102
|
+
time_delta = timedelta(minutes=max_wait_in_minutes)
|
103
|
+
# Add the timedelta to the current time
|
104
|
+
max_time = current_time + time_delta
|
105
|
+
|
106
|
+
complete = False
|
107
|
+
json_response: Dict[str, Any] = {}
|
108
|
+
while not complete:
|
109
|
+
response = requests.get(file_info_endpoint, headers=headers, timeout=60)
|
110
|
+
json_response: dict = response.json()
|
111
|
+
errors: List[Dict[str, Any]] = []
|
112
|
+
errors.extend(json_response.get("errors") or [])
|
113
|
+
status = json_response.get("workable_state")
|
114
|
+
complete = status == "ready"
|
115
|
+
|
116
|
+
if status == "invalid" or len(errors) > 0:
|
117
|
+
break
|
118
|
+
if complete:
|
119
|
+
break
|
120
|
+
if not complete:
|
121
|
+
time.sleep(5)
|
122
|
+
if datetime.now() > max_time:
|
123
|
+
error = (
|
124
|
+
"Timeout attempting to get conversion file status. "
|
125
|
+
f"The current timeout limit is {max_wait_in_minutes} minutes. "
|
126
|
+
"You may need to up the timeout period, or check for errors. "
|
127
|
+
)
|
128
|
+
raise RuntimeError(error)
|
129
|
+
|
130
|
+
return json_response
|
@@ -1,41 +1,28 @@
|
|
1
1
|
"""
|
2
|
-
Copyright 2024 Aplos Analytics
|
2
|
+
Copyright 2024-2025 Aplos Analytics
|
3
3
|
All Rights Reserved. www.aplosanalytics.com LICENSED MATERIALS
|
4
4
|
Property of Aplos Analytics, Utah, USA
|
5
5
|
"""
|
6
6
|
|
7
7
|
from typing import Any, Dict
|
8
|
-
from aplos_nca_saas_sdk.
|
9
|
-
from aplos_nca_saas_sdk.nca_resources.
|
10
|
-
|
8
|
+
from aplos_nca_saas_sdk.nca_resources._api_base import NCAApiBaseClass
|
9
|
+
from aplos_nca_saas_sdk.nca_resources.aws_s3_presigned_upload import (
|
10
|
+
S3PresignedUrlUpload,
|
11
|
+
)
|
11
12
|
|
12
13
|
|
13
|
-
class NCAFileUpload:
|
14
|
+
class NCAFileUpload(NCAApiBaseClass):
|
14
15
|
"""NCA File Upload"""
|
15
16
|
|
16
|
-
def __init__(self,
|
17
|
-
|
18
|
-
raise ValueError("Authenticated nca_login is required.")
|
17
|
+
def __init__(self, host: str) -> None:
|
18
|
+
super().__init__(host)
|
19
19
|
|
20
|
-
|
21
|
-
self
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
def api_root(self) -> str:
|
27
|
-
"""Gets the base url"""
|
28
|
-
|
29
|
-
if self.__api_domain is None:
|
30
|
-
raise RuntimeError("Missing Aplos Api Domain")
|
31
|
-
|
32
|
-
url = HttpUtilities.build_url(
|
33
|
-
self.__api_domain, self.__tenant_id, self.__user_id
|
34
|
-
)
|
35
|
-
|
36
|
-
return url
|
37
|
-
|
38
|
-
def upload(self, input_file_path: str) -> Dict[str, Any]:
|
20
|
+
def upload(
|
21
|
+
self,
|
22
|
+
input_file_path: str,
|
23
|
+
user_name: str | None = None,
|
24
|
+
password: str | None = None,
|
25
|
+
) -> Dict[str, Any]:
|
39
26
|
"""
|
40
27
|
Uploads a file to the Aplos NCA Cloud
|
41
28
|
|
@@ -51,7 +38,18 @@ class NCAFileUpload:
|
|
51
38
|
if input_file_path is None or not input_file_path:
|
52
39
|
raise ValueError("Valid input_file_path is required.")
|
53
40
|
|
54
|
-
|
55
|
-
|
41
|
+
if not self.authenticator.cognito.jwt:
|
42
|
+
if not user_name or not password:
|
43
|
+
raise ValueError(
|
44
|
+
"Valid user_name and password are required or you can set the authenticator object."
|
45
|
+
)
|
46
|
+
self.authenticator.authenticate(username=user_name, password=password)
|
47
|
+
|
48
|
+
uploader: S3PresignedUrlUpload = S3PresignedUrlUpload(self.host)
|
49
|
+
uploader.authenticator = self.authenticator
|
50
|
+
|
51
|
+
upload_response: Dict[str, Any] = uploader.upload_file(
|
52
|
+
input_file=input_file_path
|
53
|
+
)
|
56
54
|
|
57
55
|
return upload_response
|
@@ -0,0 +1,34 @@
|
|
1
|
+
"""
|
2
|
+
Copyright 2024-2025 Aplos Analytics
|
3
|
+
All Rights Reserved. www.aplosanalytics.com LICENSED MATERIALS
|
4
|
+
Property of Aplos Analytics, Utah, USA
|
5
|
+
"""
|
6
|
+
|
7
|
+
import requests
|
8
|
+
|
9
|
+
from aplos_nca_saas_sdk.nca_resources._api_base import NCAApiBaseClass
|
10
|
+
|
11
|
+
|
12
|
+
class NCAValidation(NCAApiBaseClass):
|
13
|
+
"""NCA Analysis Validation API"""
|
14
|
+
|
15
|
+
def __init__(self, host: str) -> None:
|
16
|
+
super().__init__(host)
|
17
|
+
|
18
|
+
def validate(self, jwt: str) -> bool:
|
19
|
+
"""
|
20
|
+
Validates the JWT
|
21
|
+
|
22
|
+
Args:
|
23
|
+
jwt (str): JWT
|
24
|
+
|
25
|
+
Returns:
|
26
|
+
bool: True if the JWT is valid
|
27
|
+
"""
|
28
|
+
url = self.endpoints.validations
|
29
|
+
response = requests.post(url, json={"jwt": jwt}, timeout=30)
|
30
|
+
|
31
|
+
if response.status_code != 200:
|
32
|
+
return False
|
33
|
+
|
34
|
+
return True
|
@@ -0,0 +1,148 @@
|
|
1
|
+
"""
|
2
|
+
Copyright 2024-2025 Aplos Analytics
|
3
|
+
All Rights Reserved. www.aplosanalytics.com LICENSED MATERIALS
|
4
|
+
Property of Aplos Analytics, Utah, USA
|
5
|
+
"""
|
6
|
+
|
7
|
+
import json
|
8
|
+
import os
|
9
|
+
from pathlib import Path
|
10
|
+
|
11
|
+
from aws_lambda_powertools import Logger
|
12
|
+
|
13
|
+
from aplos_nca_saas_sdk.nca_resources.nca_analysis import NCAAnalysis
|
14
|
+
from aplos_nca_saas_sdk.utilities.commandline_args import CommandlineArgs
|
15
|
+
|
16
|
+
logger = Logger()
|
17
|
+
|
18
|
+
|
19
|
+
def main():
|
20
|
+
"""Run Main when then file is run directly"""
|
21
|
+
try:
|
22
|
+
print("Welcome to the NCA Engine Upload & Execution Demo")
|
23
|
+
args = CommandlineArgs()
|
24
|
+
files_path = os.path.join(
|
25
|
+
Path(__file__).parent, "sample_files", "analysis_files", "single_ev"
|
26
|
+
)
|
27
|
+
|
28
|
+
# set up some defaults to make the demos quicker
|
29
|
+
args.analysis_file_default = os.path.join(files_path, "input.csv")
|
30
|
+
args.config_file_default = os.path.join(files_path, "config.json")
|
31
|
+
args.metadata_file_default = os.path.join(files_path, "meta_data.json")
|
32
|
+
args.output_directory_default = os.path.join(files_path, ".output")
|
33
|
+
if not args.is_valid():
|
34
|
+
print("\n\n")
|
35
|
+
print("Missing some arguments.")
|
36
|
+
exit()
|
37
|
+
|
38
|
+
analysis_api = NCAAnalysis(host=str(args.host))
|
39
|
+
analysis_api.verbose = True
|
40
|
+
|
41
|
+
print("\tLoading analysis configurations")
|
42
|
+
print(f"\t\t...{os.path.basename(args.config_file)}")
|
43
|
+
config_data: dict = read_json_file(str(args.config_file))
|
44
|
+
|
45
|
+
print("\tLoading analysis meta data")
|
46
|
+
print(f"\t\t...{os.path.basename(args.metadata_file)}")
|
47
|
+
meta_data = optional_json_loads(read_text_file(str(args.metadata_file)))
|
48
|
+
|
49
|
+
wait_for_results = True
|
50
|
+
max_wait_in_seconds = 900 # 15 minutes
|
51
|
+
resutls = analysis_api.execute(
|
52
|
+
username=str(args.username),
|
53
|
+
password=str(args.password),
|
54
|
+
input_file_path=str(args.analysis_file),
|
55
|
+
config_data=config_data,
|
56
|
+
meta_data=meta_data,
|
57
|
+
output_directory=str(args.output_directory),
|
58
|
+
wait_for_results=wait_for_results,
|
59
|
+
max_wait_in_seconds=max_wait_in_seconds,
|
60
|
+
)
|
61
|
+
|
62
|
+
if not wait_for_results:
|
63
|
+
exec_id = resutls.get("execution", {}).get("execution_id", "")
|
64
|
+
print(
|
65
|
+
"Analysis execution has been queued. We're not waiting for the results."
|
66
|
+
)
|
67
|
+
print(f"Please check your results with execution id {exec_id}.")
|
68
|
+
|
69
|
+
print("🙌 Thank you for using the NCA API for an Analysis Execution Demo. 🙌")
|
70
|
+
except Exception as e: # pylint: disable=w0718
|
71
|
+
print(
|
72
|
+
"🚨 An error occured ... exiting with an error. Please check your settings and try again."
|
73
|
+
)
|
74
|
+
print(
|
75
|
+
"If you believe this is bug please create a support ticket and include the execution id (if available)."
|
76
|
+
)
|
77
|
+
print(
|
78
|
+
"If it's not reported in the error below check your account for the failed execution."
|
79
|
+
)
|
80
|
+
|
81
|
+
print(str(e))
|
82
|
+
|
83
|
+
|
84
|
+
def optional_json_loads(data: str | dict) -> str | dict:
|
85
|
+
"""
|
86
|
+
Attempts to load the data as json, fails gracefull and retuns the data is if it fails
|
87
|
+
Args:
|
88
|
+
data (str): data as string
|
89
|
+
|
90
|
+
Returns:
|
91
|
+
str | dict: either the data as is or a converted dictionary/json object
|
92
|
+
"""
|
93
|
+
if isinstance(data, dict):
|
94
|
+
return data
|
95
|
+
|
96
|
+
try:
|
97
|
+
data = json.loads(str(data))
|
98
|
+
finally:
|
99
|
+
pass
|
100
|
+
return data
|
101
|
+
|
102
|
+
|
103
|
+
def read_json_file(file_path: str) -> dict:
|
104
|
+
"""
|
105
|
+
Reads a file and returns the json
|
106
|
+
Args:
|
107
|
+
file_path (str): _description_
|
108
|
+
|
109
|
+
Raises:
|
110
|
+
FileNotFoundError: _description_
|
111
|
+
|
112
|
+
Returns:
|
113
|
+
dict: _description_
|
114
|
+
"""
|
115
|
+
if not os.path.exists(file_path):
|
116
|
+
raise FileNotFoundError(f"File Not Found: {file_path}")
|
117
|
+
|
118
|
+
data = None
|
119
|
+
with open(file_path, mode="r", encoding="utf8") as file:
|
120
|
+
data = json.load(file)
|
121
|
+
|
122
|
+
return data
|
123
|
+
|
124
|
+
|
125
|
+
def read_text_file(file_path: str) -> str:
|
126
|
+
"""
|
127
|
+
Read files contents
|
128
|
+
Args:
|
129
|
+
file_path (str): path to the file
|
130
|
+
|
131
|
+
Raises:
|
132
|
+
FileNotFoundError: if the file is not found
|
133
|
+
|
134
|
+
Returns:
|
135
|
+
str: the files data
|
136
|
+
"""
|
137
|
+
if not os.path.exists(file_path):
|
138
|
+
raise FileNotFoundError(f"File Not Found: {file_path}")
|
139
|
+
|
140
|
+
data = None
|
141
|
+
with open(file_path, mode="r", encoding="utf8") as file:
|
142
|
+
data = file.read()
|
143
|
+
|
144
|
+
return data
|
145
|
+
|
146
|
+
|
147
|
+
if __name__ == "__main__":
|
148
|
+
main()
|