aplos-nca-saas-sdk 0.0.16__tar.gz → 0.0.18__tar.gz

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 (69) hide show
  1. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/PKG-INFO +1 -1
  2. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/pyproject.toml +1 -1
  3. aplos_nca_saas_sdk-0.0.18/requirements.dev.txt +1 -0
  4. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/configs/login_config.py +3 -3
  5. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/configs/nca_execution_config.py +79 -24
  6. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/example_main.py +2 -2
  7. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/readme.md +4 -4
  8. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/tests/file_upload_test.py +8 -12
  9. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/tests/nca_analysis_test.py +5 -1
  10. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/nca_resources/nca_analysis.py +26 -13
  11. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/nca_resources/nca_file_download.py +26 -10
  12. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/run_analysis_execution.py +4 -4
  13. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/utilities/commandline_args.py +7 -7
  14. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/utilities/environment_services.py +5 -4
  15. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/version.py +1 -1
  16. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/.gitignore +0 -0
  17. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/.pypirc +0 -0
  18. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/.vscode/launch.json +0 -0
  19. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/.vscode/settings.json +0 -0
  20. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/LICENSE +0 -0
  21. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/README.md +0 -0
  22. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/devops/pypi/build.py +0 -0
  23. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/devops/pypi/readme.md +0 -0
  24. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/devops/requirements.txt +0 -0
  25. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/docs/images/API_Configuration_blur.png +0 -0
  26. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/docs/images/aplos-nca-commandline-cropped.png +0 -0
  27. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/docs/images/aplos-nca-commandline.png +0 -0
  28. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/mypy.ini +0 -0
  29. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/mypy_checks.py +0 -0
  30. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/readme.md +0 -0
  31. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/requirements.txt +0 -0
  32. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/run-checks.sh +0 -0
  33. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/__init__.py +0 -0
  34. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/configs/_config_base.py +0 -0
  35. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/configs/app_settings_config.py +0 -0
  36. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/configs/config_sample.json +0 -0
  37. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/configs/file_upload_config.py +0 -0
  38. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/configs/nca_validation_config.py +0 -0
  39. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/files/executions/config1.json +0 -0
  40. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/files/uploads/input1.csv +0 -0
  41. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/files/uploads/input1.dat +0 -0
  42. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/files/uploads/input1.sas7bdat +0 -0
  43. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/files/uploads/input1.xls +0 -0
  44. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/files/uploads/input1.xlsx +0 -0
  45. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/files/uploads/input1.xpt +0 -0
  46. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/integration_test_base.py +0 -0
  47. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/integration_test_configurations.py +0 -0
  48. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/integration_test_factory.py +0 -0
  49. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/integration_test_response.py +0 -0
  50. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/integration_test_suite.py +0 -0
  51. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/tests/app_configuration_test.py +0 -0
  52. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/tests/app_login_test.py +0 -0
  53. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/integration_testing/tests/nca_analysis_validation_test.py +0 -0
  54. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/nca_resources/_api_base.py +0 -0
  55. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/nca_resources/aws_cognito.py +0 -0
  56. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/nca_resources/aws_s3_presigned_payload.py +0 -0
  57. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/nca_resources/aws_s3_presigned_upload.py +0 -0
  58. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/nca_resources/nca_app_configuration.py +0 -0
  59. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/nca_resources/nca_authenticator.py +0 -0
  60. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/nca_resources/nca_endpoints.py +0 -0
  61. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/nca_resources/nca_file_upload.py +0 -0
  62. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/nca_resources/nca_validations.py +0 -0
  63. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/sample_files/analysis_files/single_ev/config.json +0 -0
  64. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/sample_files/analysis_files/single_ev/input.csv +0 -0
  65. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/sample_files/analysis_files/single_ev/meta_data.json +0 -0
  66. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/utilities/environment_vars.py +0 -0
  67. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/utilities/file_utility.py +0 -0
  68. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/src/aplos_nca_saas_sdk/utilities/http_utility.py +0 -0
  69. {aplos_nca_saas_sdk-0.0.16 → aplos_nca_saas_sdk-0.0.18}/tests/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aplos_nca_saas_sdk
3
- Version: 0.0.16
3
+ Version: 0.0.18
4
4
  Summary: Aplos NCA SaaS SDK
5
5
  Project-URL: Homepage, https://aplosanalytics.com/
6
6
  Project-URL: Documentation, https://docs.aplosanalytics.com/
@@ -26,7 +26,7 @@ keywords = [
26
26
  "Clinical Trials"
27
27
  ]
28
28
 
29
- version = "0.0.16"
29
+ version = "0.0.18"
30
30
  authors = [
31
31
  { name="Eric Wilson", email="eric.wilson@aplosanalytics.com" }
32
32
  ]
@@ -0,0 +1 @@
1
+ mypy
@@ -17,13 +17,13 @@ class LoginConfig(ConfigBase):
17
17
  def __init__(
18
18
  self,
19
19
  username: Optional[str] = None,
20
- passord: Optional[str] = None,
20
+ password: Optional[str] = None,
21
21
  host: Optional[str] = None,
22
22
  roles: Optional[List[str]] = None,
23
23
  ):
24
24
  super().__init__()
25
25
  self.__username: Optional[str] = username
26
- self.__password: Optional[str] = passord
26
+ self.__password: Optional[str] = password
27
27
  self.__host: Optional[str] = host
28
28
  self.__roles: List[str] = roles if roles is not None else []
29
29
 
@@ -110,7 +110,7 @@ class LoginConfigs(ConfigBase):
110
110
 
111
111
  @staticmethod
112
112
  def try_load_login(login_config: Dict[str, Any]) -> LoginConfig | None:
113
- """Attempts to intialize a Login from a configuration object"""
113
+ """Attempts to initialize a Login from a configuration object"""
114
114
  login: LoginConfig | None = None
115
115
  if login_config is not None:
116
116
  username = login_config.get("username", None)
@@ -34,6 +34,12 @@ class NCAExecutionConfig(ConfigBase):
34
34
  meta_data: str | dict | None = None,
35
35
  output_dir: str | None = None,
36
36
  unzip_after_download: bool = False,
37
+ data_processing: str | dict | None = None,
38
+ post_processing: str | dict | None = None,
39
+ full_payload: str | dict | None = None,
40
+ wait_for_results: bool = True,
41
+ max_wait_in_seconds: int = 600,
42
+ enabled: bool = True
37
43
  ):
38
44
  super().__init__()
39
45
 
@@ -52,6 +58,12 @@ class NCAExecutionConfig(ConfigBase):
52
58
  self.__meta_data = meta_data
53
59
  self.__output_dir = output_dir
54
60
  self.__unzip_after_download = unzip_after_download
61
+ self.__data_processing = data_processing
62
+ self.__post_processing = post_processing
63
+ self.__full_payload = full_payload
64
+ self.wait_for_results = wait_for_results
65
+ self.max_wait_in_seconds = max_wait_in_seconds
66
+ self.enabled = enabled
55
67
 
56
68
  @property
57
69
  def login(self) -> LoginConfig:
@@ -83,6 +95,20 @@ class NCAExecutionConfig(ConfigBase):
83
95
  """Indicates if the download should be unzipped"""
84
96
  return self.__unzip_after_download
85
97
 
98
+ @property
99
+ def data_processing(self) -> str | Dict[str, Any] | None:
100
+ """Pre Processing"""
101
+ return self.__data_processing
102
+
103
+ @property
104
+ def post_processing(self) -> str | Dict[str, Any] | None:
105
+ """Post Processing"""
106
+ return self.__post_processing
107
+
108
+ @property
109
+ def full_payload(self) -> str | Dict[str, Any] | None:
110
+ """Full Payload"""
111
+ return self.__full_payload
86
112
 
87
113
  class NCAExecutionConfigs(ConfigBase):
88
114
  """
@@ -106,21 +132,27 @@ class NCAExecutionConfigs(ConfigBase):
106
132
  input_file_path: str,
107
133
  config_data: dict,
108
134
  meta_data: str | dict | None = None,
135
+ data_processing: str | dict | None = None,
136
+ post_processing: str | dict | None = None,
109
137
  output_dir: str | None = None,
110
138
  unzip_after_download: bool = False,
111
139
  enabled: bool = True,
140
+ full_payload: str | dict | None = None,
112
141
  ):
113
142
  """Add an NCA Execution Config"""
114
- nca_excution_config = NCAExecutionConfig(
143
+ nca_execution_config = NCAExecutionConfig(
115
144
  login,
116
145
  input_file_path,
117
146
  config_data,
118
147
  meta_data,
119
148
  output_dir,
120
149
  unzip_after_download,
150
+ data_processing,
151
+ post_processing,
152
+ full_payload,
121
153
  )
122
- nca_excution_config.enabled = enabled
123
- self.__nca_executions.append(nca_excution_config)
154
+ nca_execution_config.enabled = enabled
155
+ self.__nca_executions.append(nca_execution_config)
124
156
 
125
157
  def load(self, test_config: Dict[str, Any]):
126
158
  """Loads the NCA Execution configs from a list of dictionaries"""
@@ -150,41 +182,64 @@ class NCAExecutionConfigs(ConfigBase):
150
182
  if not login:
151
183
  raise RuntimeError("Failed to load the login configuration")
152
184
 
185
+
186
+ full_payload = self.__load_dictionary_data_or_file(key="payload", analysis=analysis, optional=True)
187
+ config_data = self.__load_dictionary_data_or_file(key="config", analysis=analysis, optional=True)
188
+
189
+ if not config_data and not full_payload:
190
+ raise RuntimeError("Failed to load the config data")
191
+
192
+ meta_data = self.__load_dictionary_data_or_file(key="meta", analysis=analysis, optional=True)
193
+ data_cleaning = self.__load_dictionary_data_or_file(key="data_cleaning", analysis=analysis, optional=True)
194
+ post_processing = self.__load_dictionary_data_or_file(key="post_processing", analysis=analysis, optional=True)
195
+ wait_for_results =str(analysis.get("wait_for_results", True)).lower() == "true"
196
+ max_wait_in_seconds = int(analysis.get("max_wait_in_seconds", 600))
197
+
153
198
  self.add(
154
199
  login=login,
155
200
  input_file_path=analysis["file"],
156
- config_data=self.__load_config_data(analysis=analysis),
157
- meta_data=self.__load_meta_data(analysis=analysis),
201
+ config_data=config_data,
202
+ meta_data=meta_data,
158
203
  output_dir=output_dir,
159
204
  unzip_after_download=True,
160
205
  enabled=enabled,
206
+ full_payload=full_payload,
207
+ data_processing=data_cleaning,
208
+ post_processing=post_processing,
209
+ wait_for_results=wait_for_results,
210
+ max_wait_in_seconds=max_wait_in_seconds
161
211
  )
162
212
 
163
- def __load_meta_data(self, analysis: Dict[str, Any]) -> Dict[str, Any]:
164
- data: Dict[str, Any] = {}
165
- data = analysis.get("meta", {}).get("data", {})
166
-
167
- return data
168
213
 
169
- def __load_config_data(self, analysis: Dict[str, Any]) -> Dict[str, Any]:
170
- config_data: Dict[str, Any] = {}
171
- config_data = analysis.get("config", {}).get("data")
214
+ def __load_dictionary_data_or_file(self, key: str, analysis: Dict[str, Any], optional: bool = False ) -> Dict[str, Any] | None:
215
+ data: Dict[str, Any] = {}
216
+ data = analysis.get(key, {}).get("data", {})
172
217
 
173
- if config_data:
174
- return config_data
218
+ if data:
219
+ return data
175
220
 
176
- config_file_path: str = analysis.get("config", {}).get("file")
221
+ file_path: str = analysis.get(key, {}).get("file")
177
222
 
178
223
  logger.info(
179
224
  {
180
- "message": "Initializing config_data from file",
181
- "config_data": config_file_path,
225
+ "message": f"Initializing {key} from file",
226
+ "key": key,
227
+ "file_path": file_path,
182
228
  }
183
229
  )
184
- config_path = FileUtility.load_filepath(config_file_path)
185
- if os.path.exists(config_path) is False:
186
- raise RuntimeError(f"Config file not found: {config_path}")
187
- with open(config_path, "r", encoding="utf-8") as f:
188
- config_data = json.load(f)
230
+ if not file_path:
231
+ if optional:
232
+ return None
233
+ raise RuntimeError(f"Data for {key} not found: {file_path}")
234
+
235
+ path = FileUtility.load_filepath(file_path)
236
+ if os.path.exists(path) is False:
237
+ if optional:
238
+ return None
239
+ raise RuntimeError(f"Data for {key} not found: {path}")
240
+ with open(path, "r", encoding="utf-8") as f:
241
+ data = json.load(f)
242
+
243
+ return data
189
244
 
190
- return config_data
245
+
@@ -18,8 +18,8 @@ from aplos_nca_saas_sdk.integration_testing.integration_test_configurations impo
18
18
  def main():
19
19
  """This is an example on how you can run the unit tests"""
20
20
 
21
- # Optionally use our convient Environment Services loader
22
- # which can help during intial testings.
21
+ # Optionally use our convenient Environment Services loader
22
+ # which can help during initial testings.
23
23
  evs: EnvironmentServices = EnvironmentServices()
24
24
  # see if we have a local .env, .env.uat, etc configured to look up
25
25
  env_file = os.getenv("ENV_FILE")
@@ -12,7 +12,7 @@ The integration tests will require the following:
12
12
  ### Users
13
13
  You will need valid user accounts with the appropriate permissions for the endpoints they are executing.
14
14
 
15
- If you are testing permission bounderies then you should set up multiple users with different permissions.
15
+ If you are testing permission boundaries then you should set up multiple users with different permissions.
16
16
 
17
17
 
18
18
  ### Subscriptions
@@ -44,8 +44,8 @@ from aplos_nca_saas_sdk.integration_testing.integration_test_configurations impo
44
44
  def main():
45
45
  """This is an example on how you can run the unit tests"""
46
46
 
47
- # Optionally use our convient Environment Services loader
48
- # which can help during intial testings.
47
+ # Optionally use our convenient Environment Services loader
48
+ # which can help during initial testings.
49
49
  evs: EnvironmentServices = EnvironmentServices()
50
50
  # See if we have a local .env, .env.uat, etc configured to look up
51
51
  # for local configuration settings
@@ -83,7 +83,7 @@ def main():
83
83
  ### Configs
84
84
  Tests are run based on configurations. The following is an example of supported configurations:
85
85
 
86
- - Appliction Configuration Settings
86
+ - Application Configuration Settings
87
87
  - Logins & Access
88
88
  - Executing an Analysis
89
89
  - Running a Validation
@@ -5,11 +5,13 @@ Property of Aplos Analytics, Utah, USA
5
5
  """
6
6
 
7
7
  import time
8
- from datetime import datetime, timedelta
9
- from typing import Any, Dict, List
8
+ from typing import Any, Dict
10
9
 
11
- import requests
12
10
  from aws_lambda_powertools import Logger
11
+
12
+ from aplos_nca_saas_sdk.integration_testing.configs.file_upload_config import (
13
+ FileUploadConfig,
14
+ )
13
15
  from aplos_nca_saas_sdk.integration_testing.configs.login_config import LoginConfig
14
16
  from aplos_nca_saas_sdk.integration_testing.integration_test_base import (
15
17
  IntegrationTestBase,
@@ -17,13 +19,9 @@ from aplos_nca_saas_sdk.integration_testing.integration_test_base import (
17
19
  from aplos_nca_saas_sdk.integration_testing.integration_test_response import (
18
20
  IntegrationTestResponse,
19
21
  )
20
- from aplos_nca_saas_sdk.nca_resources.nca_file_upload import NCAFileUpload
21
- from aplos_nca_saas_sdk.nca_resources.nca_file_download import NCAFileDownload
22
22
  from aplos_nca_saas_sdk.nca_resources.nca_authenticator import NCAAuthenticator
23
- from aplos_nca_saas_sdk.utilities.http_utility import HttpUtilities
24
- from aplos_nca_saas_sdk.integration_testing.configs.file_upload_config import (
25
- FileUploadConfig,
26
- )
23
+ from aplos_nca_saas_sdk.nca_resources.nca_file_download import NCAFileDownload
24
+ from aplos_nca_saas_sdk.nca_resources.nca_file_upload import NCAFileUpload
27
25
 
28
26
  logger = Logger()
29
27
 
@@ -46,9 +44,7 @@ class FileUploadTest(IntegrationTestBase):
46
44
  try:
47
45
  # Confirm Login
48
46
  nca_login = self.__login(file_upload.login)
49
- # if not nca_login.cognito.jwt:
50
- # test_response.error = "Failed to authenticate"
51
- # else:
47
+
52
48
  # Confirm Upload
53
49
  upload_response: Dict[str, Any] = self.__upload(
54
50
  nca_login, file_upload.file_path
@@ -63,9 +63,13 @@ class NCAAnalysisTest(IntegrationTestBase):
63
63
  ),
64
64
  config_data=nca_execution_config.config_data,
65
65
  meta_data=nca_execution_config.meta_data,
66
- wait_for_results=True,
66
+ wait_for_results=nca_execution_config.wait_for_results,
67
+ wait_for_results_timeout=nca_execution_config.max_wait_in_seconds,
67
68
  output_directory=nca_execution_config.output_dir,
68
69
  unzip_after_download=False,
70
+ data_processing=nca_execution_config.data_processing,
71
+ post_processing=nca_execution_config.post_processing,
72
+ full_payload=nca_execution_config.full_payload,
69
73
  )
70
74
 
71
75
  # Verify Download
@@ -41,13 +41,16 @@ class NCAAnalysis(NCAApiBaseClass):
41
41
  config_data: dict,
42
42
  *,
43
43
  meta_data: str | dict | None = None,
44
+ post_processing: str | dict | None = None,
45
+ data_processing: str | dict | None = None,
44
46
  wait_for_results: bool = True,
45
47
  max_wait_in_seconds: int = 900,
46
48
  output_directory: str | None = None,
47
49
  unzip_after_download: bool = False,
50
+ full_payload: str | dict | None = None
48
51
  ) -> Dict[str, Any]:
49
52
  """
50
- Executes an analsysis.
53
+ Executes an analysis.
51
54
  - Uploads an analysis file.
52
55
  - Adds the execution to the queue.
53
56
 
@@ -81,11 +84,14 @@ class NCAAnalysis(NCAApiBaseClass):
81
84
  "Unexpected empty file_id when attempting to upload file."
82
85
  )
83
86
 
84
- self.log("\tAdding analyis to the queue.")
87
+ self.log("\tAdding analysis to the queue.")
85
88
  execution_response: Dict[str, Any] = self.__add_to_queue(
86
89
  file_id=file_id,
87
90
  config_data=config_data,
88
91
  meta_data=meta_data,
92
+ post_processing=post_processing,
93
+ data_processing=data_processing,
94
+ full_payload=full_payload
89
95
  )
90
96
 
91
97
  execution_id: str = execution_response.get("execution_id", "")
@@ -130,6 +136,9 @@ class NCAAnalysis(NCAApiBaseClass):
130
136
  file_id: str,
131
137
  config_data: dict,
132
138
  meta_data: str | dict | None = None,
139
+ post_processing: str | dict | None = None,
140
+ data_processing: str | dict | None = None,
141
+ full_payload: str | dict | None = None
133
142
  ) -> Dict[str, Any]:
134
143
  """
135
144
  Adds the analysis to the execution queue.
@@ -151,15 +160,19 @@ class NCAAnalysis(NCAApiBaseClass):
151
160
  "Missing config_data. Please provide a valid config_data."
152
161
  )
153
162
  headers = self.authenticator.get_jwt_http_headers()
154
- # to start a new execution we need the location of the file (s3 bucket and object key)
155
- # you basic configuration
156
- # optional meta data
157
-
158
- submission = {
159
- "file": {"id": file_id},
160
- "configuration": config_data,
161
- "meta_data": meta_data,
162
- }
163
+
164
+ submission: Dict[str, Any] = {}
165
+
166
+ if full_payload:
167
+ submission = full_payload
168
+ else:
169
+ submission = {
170
+ "file": {"id": file_id},
171
+ "configuration": config_data,
172
+ "meta_data": meta_data,
173
+ "post_processing": post_processing,
174
+ "data_processing": data_processing
175
+ }
163
176
 
164
177
  response: requests.Response = requests.post(
165
178
  self.endpoints.executions,
@@ -171,13 +184,13 @@ class NCAAnalysis(NCAApiBaseClass):
171
184
 
172
185
  if response.status_code == 403:
173
186
  raise PermissionError(
174
- "Failed to execute. A 403 response occured. "
187
+ "Failed to execute. A 403 response occurred. "
175
188
  "This could a token issue or a url path issue "
176
189
  "By default unknown gateway calls return 403 errors. "
177
190
  )
178
191
  elif response.status_code != 200:
179
192
  raise RuntimeError(
180
- f"Unknown Error occured during executions: {response.status_code}. "
193
+ f"Unknown Error occurred during executions: {response.status_code}. "
181
194
  f"Reason: {response.reason}"
182
195
  )
183
196
 
@@ -5,16 +5,17 @@ Property of Aplos Analytics, Utah, USA
5
5
  """
6
6
 
7
7
  import time
8
- from typing import Any, Dict, List
9
8
  from datetime import datetime, timedelta
9
+ from typing import Any, Dict, List
10
+
11
+ import requests
10
12
  from aws_lambda_powertools import Logger
13
+
11
14
  from aplos_nca_saas_sdk.nca_resources._api_base import NCAApiBaseClass
12
15
  from aplos_nca_saas_sdk.nca_resources.aws_s3_presigned_upload import (
13
16
  S3PresignedUrlUpload,
14
17
  )
15
-
16
18
  from aplos_nca_saas_sdk.utilities.http_utility import HttpUtilities
17
- import requests
18
19
 
19
20
  logger = Logger(service="nca-file-download")
20
21
 
@@ -41,7 +42,8 @@ class NCAFileDownload(NCAApiBaseClass):
41
42
  ValueError: _description_
42
43
 
43
44
  Returns:
44
- Dict: {"file_id": id, "statu_code": 204}
45
+ Dict: {"file_id": id, "status_code": 204, ...}
46
+ 204 Response staus_code is a success
45
47
  """
46
48
  if input_file_path is None or not input_file_path:
47
49
  raise ValueError("Valid input_file_path is required.")
@@ -67,12 +69,19 @@ class NCAFileDownload(NCAApiBaseClass):
67
69
  file_id: str,
68
70
  user_name: str | None = None,
69
71
  password: str | None = None,
72
+ wait_time_in_seconds: float = 5,
73
+ max_tries: float = 12,
74
+ required_workable_state: str = "ready",
70
75
  ) -> Dict[str, Any]:
71
76
  """
72
77
  Downloads a file from the Aplos NCA Cloud
73
78
 
74
79
  Args:
75
80
  file_id (str): the id of the file to download
81
+ user_name Optional(str): the username used to connect. If not specified
82
+ the authenticator is required.
83
+ password Optional(str): the password used to connect. If not specified
84
+ the authenticator is required.
76
85
 
77
86
  Raises:
78
87
  ValueError: _description_
@@ -94,12 +103,17 @@ class NCAFileDownload(NCAApiBaseClass):
94
103
  )
95
104
  self.authenticator.authenticate(username=user_name, password=password)
96
105
 
97
- max_wait_in_minutes: int = 3
98
106
  headers = HttpUtilities.get_headers(self.authenticator.cognito.jwt)
99
107
  current_time = datetime.now()
100
108
 
101
- # Create a timedelta object representing 3 minutes
102
- time_delta = timedelta(minutes=max_wait_in_minutes)
109
+ if max_tries < 0:
110
+ max_tries = 1
111
+ if wait_time_in_seconds < 0:
112
+ wait_time_in_seconds = 1
113
+
114
+ max_wait_time_in_seconds = wait_time_in_seconds * max_tries
115
+ # Create a timedelta object representing x seconds
116
+ time_delta = timedelta(seconds=max_wait_time_in_seconds)
103
117
  # Add the timedelta to the current time
104
118
  max_time = current_time + time_delta
105
119
 
@@ -113,16 +127,18 @@ class NCAFileDownload(NCAApiBaseClass):
113
127
  status = json_response.get("workable_state")
114
128
  complete = status == "ready"
115
129
 
130
+ if not required_workable_state or required_workable_state == "any":
131
+ break
116
132
  if status == "invalid" or len(errors) > 0:
117
133
  break
118
134
  if complete:
119
135
  break
120
136
  if not complete:
121
- time.sleep(5)
137
+ time.sleep(wait_time_in_seconds)
122
138
  if datetime.now() > max_time:
123
139
  error = (
124
- "Timeout attempting to get conversion file status. "
125
- f"The current timeout limit is {max_wait_in_minutes} minutes. "
140
+ "Timeout attempting to get an analysis file. "
141
+ f"The current timeout limit is {max_wait_time_in_seconds} seconds. "
126
142
  "You may need to up the timeout period, or check for errors. "
127
143
  )
128
144
  raise RuntimeError(error)
@@ -48,7 +48,7 @@ def main():
48
48
 
49
49
  wait_for_results = True
50
50
  max_wait_in_seconds = 900 # 15 minutes
51
- resutls = analysis_api.execute(
51
+ results = analysis_api.execute(
52
52
  username=str(args.username),
53
53
  password=str(args.password),
54
54
  input_file_path=str(args.analysis_file),
@@ -60,7 +60,7 @@ def main():
60
60
  )
61
61
 
62
62
  if not wait_for_results:
63
- exec_id = resutls.get("execution", {}).get("execution_id", "")
63
+ exec_id = results.get("execution", {}).get("execution_id", "")
64
64
  print(
65
65
  "Analysis execution has been queued. We're not waiting for the results."
66
66
  )
@@ -69,7 +69,7 @@ def main():
69
69
  print("🙌 Thank you for using the NCA API for an Analysis Execution Demo. 🙌")
70
70
  except Exception as e: # pylint: disable=w0718
71
71
  print(
72
- "🚨 An error occured ... exiting with an error. Please check your settings and try again."
72
+ "🚨 An error occurred ... exiting with an error. Please check your settings and try again."
73
73
  )
74
74
  print(
75
75
  "If you believe this is bug please create a support ticket and include the execution id (if available)."
@@ -83,7 +83,7 @@ def main():
83
83
 
84
84
  def optional_json_loads(data: str | dict) -> str | dict:
85
85
  """
86
- Attempts to load the data as json, fails gracefull and retuns the data is if it fails
86
+ Attempts to load the data as json, fails graceful and returns the data is if it fails
87
87
  Args:
88
88
  data (str): data as string
89
89
 
@@ -39,7 +39,7 @@ class CommandlineArgs:
39
39
  "-c", "--config-file", required=False, help="Path to the configuration file"
40
40
  )
41
41
  self.parser.add_argument(
42
- "-f", "--analyis-file", required=False, help="Path to the analysis file"
42
+ "-f", "--analysis-file", required=False, help="Path to the analysis file"
43
43
  )
44
44
  self.parser.add_argument(
45
45
  "-m", "--metadata-file", required=False, help="Path to the metadata file"
@@ -82,7 +82,7 @@ class CommandlineArgs:
82
82
  self.password: str | None = None
83
83
  self.host: str | None = None
84
84
 
85
- # excuction setup
85
+ # execution setup
86
86
  self.config_file: str | None = None
87
87
  self.config_file_default: str | None = None
88
88
  self.analysis_file: str | None = None
@@ -102,21 +102,21 @@ class CommandlineArgs:
102
102
  Returns:
103
103
  bool: True if they are all valid
104
104
  """
105
- # see if we have any aruments
105
+ # see if we have any arguments
106
106
  args = self.parser.parse_args()
107
107
 
108
108
  self.username = args.username
109
109
  self.password = args.password
110
110
  self.config_file = args.config_file
111
111
  # anything with a dash (in the args) is accessed with an underscore
112
- self.analysis_file = args.analyis_file
112
+ self.analysis_file = args.analysis_file
113
113
  self.host = args.host
114
114
 
115
115
  self.metadata_file = args.metadata_file
116
116
  self.skip = args.skip
117
117
  self.output_directory = args.output_directory
118
118
  self.environment_file = args.environment_file
119
- # no args check to see if they have them in the environmet
119
+ # no args check to see if they have them in the environment
120
120
 
121
121
  # if we have an environment file we'll want to load it before checking any defaults
122
122
  self.check_for_environment_config()
@@ -258,9 +258,9 @@ class CommandlineArgs:
258
258
  self, starting_path: str, file_name: str, raise_error_if_not_found: bool = True
259
259
  ) -> str | None:
260
260
  """Searches the project directory structor for a file"""
261
- parents = 10
261
+
262
262
  starting_path = starting_path or __file__
263
-
263
+ parents = len(starting_path.split(os.sep)) -1
264
264
  paths: List[str] = []
265
265
  for parent in range(parents):
266
266
  path = Path(starting_path).parents[parent].absolute()
@@ -61,9 +61,9 @@ class EnvironmentServices:
61
61
  self, starting_path: str, file_name: str, raise_error_if_not_found: bool = True
62
62
  ) -> str | None:
63
63
  """Searches the project directory structure for a file"""
64
- parents = 10
64
+
65
65
  starting_path = starting_path or __file__
66
-
66
+ parents = len(starting_path.split(os.sep)) -1
67
67
  paths: List[str] = []
68
68
  for parent in range(parents):
69
69
  path = Path(starting_path).parents[parent].absolute()
@@ -87,8 +87,9 @@ class EnvironmentServices:
87
87
  raise_error_if_not_found: bool = True,
88
88
  ) -> str | None:
89
89
  """From a given starting point, move up the directory chain until you find the modules root"""
90
- parents = 10
90
+
91
91
  starting_path = starting_path or __file__
92
+ parents = len(starting_path.split(os.sep)) -1
92
93
  MODULE_ROOT = "aplos_nca_saas_sdk" # pylint: disable=c0103
93
94
  paths: List[str] = []
94
95
  for parent in range(parents):
@@ -103,7 +104,7 @@ class EnvironmentServices:
103
104
  if raise_error_if_not_found:
104
105
  searched_paths = "\n".join(paths)
105
106
  raise RuntimeError(
106
- f"Failed to locate the moduel root: {MODULE_ROOT} in: \n {searched_paths}"
107
+ f"Failed to locate the module root: {MODULE_ROOT} in: \n {searched_paths}"
107
108
  )
108
109
 
109
110
  return None
@@ -1,4 +1,4 @@
1
1
  # Aplos NCA SaaS SDK Version File
2
2
  # This is automatically generated during the build process.
3
3
  # DO NOT UPDATE IT DIRECTLY. IT WILL BE OVERWRITTEN.
4
- __version__ = '0.0.16'
4
+ __version__ = '0.0.18'