aplos-nca-saas-sdk 0.0.11__tar.gz → 0.0.12__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 (66) hide show
  1. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/.gitignore +2 -1
  2. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/PKG-INFO +1 -1
  3. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/pyproject.toml +1 -1
  4. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/aws_resources/aws_cognito.py +11 -5
  5. aplos_nca_saas_sdk-0.0.11/src/aplos_nca_saas_sdk/integration_testing/configs/app_settings.py → aplos_nca_saas_sdk-0.0.12/src/aplos_nca_saas_sdk/integration_testing/configs/app_settings_config.py +8 -8
  6. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/integration_testing/configs/config_sample.json +27 -14
  7. aplos_nca_saas_sdk-0.0.12/src/aplos_nca_saas_sdk/integration_testing/configs/file_upload_config.py +94 -0
  8. aplos_nca_saas_sdk-0.0.11/src/aplos_nca_saas_sdk/integration_testing/configs/login.py → aplos_nca_saas_sdk-0.0.12/src/aplos_nca_saas_sdk/integration_testing/configs/login_config.py +23 -11
  9. aplos_nca_saas_sdk-0.0.12/src/aplos_nca_saas_sdk/integration_testing/configs/nca_execution_config.py +186 -0
  10. aplos_nca_saas_sdk-0.0.12/src/aplos_nca_saas_sdk/integration_testing/files/executions/config1.json +46 -0
  11. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/integration_testing/integration_test_base.py +8 -1
  12. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/integration_testing/integration_test_configurations.py +10 -6
  13. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/integration_testing/main.py +1 -2
  14. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/integration_testing/tests/app_login_test.py +1 -1
  15. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/integration_testing/tests/file_upload_test.py +13 -10
  16. aplos_nca_saas_sdk-0.0.12/src/aplos_nca_saas_sdk/integration_testing/tests/nca_analysis_test.py +89 -0
  17. aplos_nca_saas_sdk-0.0.11/src/aplos_nca_saas_sdk/nca_resources/nca_executions.py → aplos_nca_saas_sdk-0.0.12/src/aplos_nca_saas_sdk/nca_resources/nca_analysis.py +148 -87
  18. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/nca_resources/nca_file_upload.py +5 -5
  19. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/nca_resources/nca_login.py +4 -4
  20. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/utilities/commandline_args.py +6 -28
  21. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/utilities/environment_vars.py +7 -0
  22. aplos_nca_saas_sdk-0.0.12/src/aplos_nca_saas_sdk/utilities/file_utility.py +33 -0
  23. aplos_nca_saas_sdk-0.0.12/src/aplos_nca_saas_sdk/utilities/http_utility.py +46 -0
  24. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/version.py +1 -1
  25. aplos_nca_saas_sdk-0.0.11/src/aplos_nca_saas_sdk/integration_testing/configs/file_upload.py +0 -104
  26. aplos_nca_saas_sdk-0.0.11/src/aplos_nca_saas_sdk/integration_testing/tests/app_validation_test.py +0 -5
  27. aplos_nca_saas_sdk-0.0.11/src/aplos_nca_saas_sdk/utilities/http_utility.py +0 -30
  28. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/.pypirc +0 -0
  29. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/.vscode/launch.json +0 -0
  30. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/.vscode/settings.json +0 -0
  31. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/LICENSE +0 -0
  32. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/README.md +0 -0
  33. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/devops/pypi/build.py +0 -0
  34. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/devops/pypi/readme.md +0 -0
  35. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/devops/requirements.txt +0 -0
  36. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/docs/images/API_Configuration_blur.png +0 -0
  37. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/docs/images/aplos-nca-commandline-cropped.png +0 -0
  38. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/docs/images/aplos-nca-commandline.png +0 -0
  39. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/mypy.ini +0 -0
  40. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/mypy_checks.py +0 -0
  41. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/readme.md +0 -0
  42. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/requirements.txt +0 -0
  43. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/run-checks.sh +0 -0
  44. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/__init__.py +0 -0
  45. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/aws_resources/aws_s3_presigned_payload.py +0 -0
  46. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/aws_resources/aws_s3_presigned_upload.py +0 -0
  47. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/files/analysis_files/single_ev/configuration_single_ev.json +0 -0
  48. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/files/analysis_files/single_ev/meta_data.json +0 -0
  49. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/files/analysis_files/single_ev/single_ev.csv +0 -0
  50. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/integration_testing/configs/_config_base.py +0 -0
  51. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/integration_testing/files/uploads/input1.csv +0 -0
  52. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/integration_testing/files/uploads/input1.dat +0 -0
  53. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/integration_testing/files/uploads/input1.sas7bdat +0 -0
  54. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/integration_testing/files/uploads/input1.xls +0 -0
  55. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/integration_testing/files/uploads/input1.xlsx +0 -0
  56. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/integration_testing/files/uploads/input1.xpt +0 -0
  57. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/integration_testing/integration_test_factory.py +0 -0
  58. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/integration_testing/integration_test_response.py +0 -0
  59. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/integration_testing/integration_test_suite.py +0 -0
  60. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/integration_testing/readme.md +0 -0
  61. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/integration_testing/tests/app_configuration_test.py +0 -0
  62. /aplos_nca_saas_sdk-0.0.11/src/aplos_nca_saas_sdk/integration_testing/tests/app_execution_test.py → /aplos_nca_saas_sdk-0.0.12/src/aplos_nca_saas_sdk/integration_testing/tests/validation_test.py +0 -0
  63. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/nca_resources/nca_app_configuration.py +0 -0
  64. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/nca_resources/nca_endpoints.py +0 -0
  65. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/src/aplos_nca_saas_sdk/utilities/environment_services.py +0 -0
  66. {aplos_nca_saas_sdk-0.0.11 → aplos_nca_saas_sdk-0.0.12}/tests/__init__.py +0 -0
@@ -11,4 +11,5 @@ dist/
11
11
  # don't track environment files
12
12
  .env
13
13
  .env.*
14
- .config.*
14
+ .config.*
15
+ .aplos-nca-output
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aplos_nca_saas_sdk
3
- Version: 0.0.11
3
+ Version: 0.0.12
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.11"
29
+ version = "0.0.12"
30
30
  authors = [
31
31
  { name="Eric Wilson", email="eric.wilson@aplosanalytics.com" }
32
32
  ]
@@ -14,10 +14,9 @@ from aplos_nca_saas_sdk.nca_resources.nca_app_configuration import (
14
14
  )
15
15
 
16
16
 
17
- class CognitoAuthenication:
17
+ class CognitoAuthentication:
18
18
  """
19
19
  Cognito Authentication
20
-
21
20
  """
22
21
 
23
22
  def __init__(
@@ -73,6 +72,12 @@ class CognitoAuthenication:
73
72
  return self.__region
74
73
 
75
74
  def __validate_parameters(self) -> None:
75
+ """
76
+ Validate the required parameters.
77
+ We need either:
78
+ - the Cognito ClientId and Cognito Region
79
+ - or the Aplos Domain (which can get the clientId and region)
80
+ """
76
81
  if self.__client_id is None and self.__aplos_domain is not None:
77
82
  self.__config = NCAAppConfiguration(aplos_saas_domain=self.__aplos_domain)
78
83
  self.__client_id = self.__config.cognito_client_id
@@ -81,14 +86,12 @@ class CognitoAuthenication:
81
86
  if self.__client_id is None:
82
87
  raise RuntimeError(
83
88
  "Missing Cognito Client Id. "
84
- "Pass in a client_id as a command arg or set the COGNITO_CLIENT_ID enviornment var. "
85
89
  "Alternatively, set the aplos_domain to automatically get the client_id and region."
86
90
  )
87
91
 
88
92
  if self.__region is None:
89
93
  raise RuntimeError(
90
94
  "Missing Cognito Region"
91
- "Pass in a region as a command arg or set the COGNITO_REGION enviornment var. "
92
95
  "Alternatively, set the aplos_domain to automatically get the client_id and region."
93
96
  )
94
97
 
@@ -139,13 +142,16 @@ class CognitoAuthenication:
139
142
  self.__parse_jwt(self.__jwt)
140
143
  return self.__jwt
141
144
 
142
- raise RuntimeError("Failed to get a JWT token")
145
+ raise RuntimeError(
146
+ "Failed to get a JWT token. Check the error logs for more information."
147
+ )
143
148
 
144
149
  def __parse_jwt(self, encoded_jwt: str) -> None:
145
150
  # Decode the payload (second part) from Base64
146
151
  decoded_jwt: dict = jwt_lib.decode(
147
152
  encoded_jwt, options={"verify_signature": False}
148
153
  )
154
+ # custom fields contain information we'll need for later requests
149
155
  self.__user_id = decoded_jwt.get("custom:aplos_user_id")
150
156
  self.__tenant_id = decoded_jwt.get("custom:aplos_user_tenant_id")
151
157
 
@@ -8,7 +8,7 @@ from typing import List, Dict, Any
8
8
  from aplos_nca_saas_sdk.integration_testing.configs._config_base import ConfigBase
9
9
 
10
10
 
11
- class ApplicationDomain(ConfigBase):
11
+ class ApplicationDomainConfig(ConfigBase):
12
12
  """
13
13
  Application Domain: Defines the domains that the application configuration tests will check against
14
14
 
@@ -30,7 +30,7 @@ class ApplicationDomain(ConfigBase):
30
30
  self.__domain = value
31
31
 
32
32
 
33
- class ApplicationDomains(ConfigBase):
33
+ class ApplicationDomainConfigs(ConfigBase):
34
34
  """
35
35
  Application ApplicationDomain: Defines the Domains that the application configuration tests will check against
36
36
 
@@ -38,16 +38,16 @@ class ApplicationDomains(ConfigBase):
38
38
 
39
39
  def __init__(self):
40
40
  super().__init__()
41
- self.__domains: List[ApplicationDomain] = []
41
+ self.__domains: List[ApplicationDomainConfig] = []
42
42
 
43
43
  @property
44
- def list(self) -> List[ApplicationDomain]:
44
+ def list(self) -> List[ApplicationDomainConfig]:
45
45
  """List the logins"""
46
46
  return self.__domains
47
47
 
48
48
  def add(self, *, domain: str, enabled: bool = True):
49
49
  """Add a loging"""
50
- app_domain = ApplicationDomain()
50
+ app_domain = ApplicationDomainConfig()
51
51
  app_domain.domain = domain
52
52
  app_domain.enabled = enabled
53
53
  self.__domains.append(app_domain)
@@ -60,7 +60,7 @@ class ApplicationDomains(ConfigBase):
60
60
 
61
61
  domain: Dict[str, Any]
62
62
  for domain in domains:
63
- app_domain = ApplicationDomain()
63
+ app_domain = ApplicationDomainConfig()
64
64
  app_domain.domain = domain.get("domain", None)
65
65
  app_domain.enabled = bool(domain.get("enabled", True))
66
66
 
@@ -75,10 +75,10 @@ class ApplicationSettings(ConfigBase):
75
75
 
76
76
  def __init__(self):
77
77
  super().__init__()
78
- self.__domains: ApplicationDomains = ApplicationDomains()
78
+ self.__domains: ApplicationDomainConfigs = ApplicationDomainConfigs()
79
79
 
80
80
  @property
81
- def domains(self) -> ApplicationDomains:
81
+ def domains(self) -> ApplicationDomainConfigs:
82
82
  """List of the domain"""
83
83
  return self.__domains
84
84
 
@@ -4,14 +4,14 @@
4
4
  "domains": [
5
5
  {
6
6
  "domain": "api.example.com",
7
- "expected_results" : {
7
+ "expected_results": {
8
8
  "status_code": 200
9
9
  },
10
10
  "enabled": true
11
11
  },
12
12
  {
13
13
  "domain": "XXXXXXXXXXXXXXXXXXXXX",
14
- "expected_results" : {
14
+ "expected_results": {
15
15
  "status_code": 403
16
16
  },
17
17
  "enabled": false
@@ -26,7 +26,6 @@
26
26
  "password": "barr",
27
27
  "domain": "api.example.com",
28
28
  "roles": []
29
-
30
29
  },
31
30
  {
32
31
  "username": "XXXXXXXXXXXXXXXXXXXXX",
@@ -35,12 +34,12 @@
35
34
  "roles": [
36
35
  "XXXXXXXXXXXXXXXXXXXXX"
37
36
  ],
38
- "enabled" : false,
39
- "expected_results" : {
37
+ "enabled": false,
38
+ "expected_results": {
40
39
  "exception": "InvalidCredentialsException"
41
40
  }
42
41
  }
43
- ]
42
+ ]
44
43
  },
45
44
  "file_upload_test": {
46
45
  "purpose": "Tests the file upload endpoints.",
@@ -49,7 +48,7 @@
49
48
  "purpose": "optional: if present this login is used, unless a specific login is defined for the test",
50
49
  "username": "foo",
51
50
  "password": "bar",
52
- "domain": "api.example.com"
51
+ "domain": "api.example.com"
53
52
  },
54
53
  "files": [
55
54
  {
@@ -57,11 +56,11 @@
57
56
  },
58
57
  {
59
58
  "file": "XXXXXXXXXXXXXXXXXXXXX",
60
- "login" : {
59
+ "login": {
61
60
  "purpose": "optional: if present tests an upload for a specific user",
62
61
  "username": "XXXXXXXXXXXXXXXXXXXXX",
63
62
  "password": "XXXXXXXXXXXXXXXXXXXXX",
64
- "domain": "XXXXXXXXXXXXXXXXXXXXX"
63
+ "domain": "XXXXXXXXXXXXXXXXXXXXX"
65
64
  }
66
65
  }
67
66
  ]
@@ -71,14 +70,29 @@
71
70
  "login": {
72
71
  "username": "XXXXXXXXXXXXXXXXXXXXX",
73
72
  "password": "XXXXXXXXXXXXXXXXXXXXX",
74
- "domain": "XXXXXXXXXXXXXXXXXXXXX"
73
+ "domain": "XXXXXXXXXXXXXXXXXXXXX"
75
74
  },
75
+ "output_dir": "XXXXXXXXXXXXXXXXXXXXX",
76
76
  "analyses": [
77
- {
77
+ {
78
+ "file": "XXXXXXXXXXXXXXXXXXXXX",
79
+ "meta": {},
80
+ "config": {},
81
+ "expected_results": {
82
+ "status_code": 200
83
+ },
84
+ "output_dir": "XXXXXXXXXXXXXXXXXXXXX"
85
+ },
86
+ {
78
87
  "file": "XXXXXXXXXXXXXXXXXXXXX",
79
88
  "meta": {},
80
89
  "config": {},
81
- "expected_results" : {
90
+ "login": {
91
+ "username": "XXXXXXXXXXXXXXXXXXXXX",
92
+ "password": "XXXXXXXXXXXXXXXXXXXXX",
93
+ "domain": "XXXXXXXXXXXXXXXXXXXXX"
94
+ },
95
+ "expected_results": {
82
96
  "status_code": 200
83
97
  }
84
98
  }
@@ -89,11 +103,10 @@
89
103
  "login": {
90
104
  "username": "XXXXXXXXXXXXXXXXXXXXX",
91
105
  "password": "XXXXXXXXXXXXXXXXXXXXX",
92
- "domain": "XXXXXXXXXXXXXXXXXXXXX"
106
+ "domain": "XXXXXXXXXXXXXXXXXXXXX"
93
107
  },
94
108
  "expected_results": {
95
109
  "status_code": 200
96
110
  }
97
111
  }
98
-
99
112
  }
@@ -0,0 +1,94 @@
1
+ """
2
+ Copyright 2024 Aplos Analytics
3
+ All Rights Reserved. www.aplosanalytics.com LICENSED MATERIALS
4
+ Property of Aplos Analytics, Utah, USA
5
+ """
6
+
7
+ import os
8
+ from typing import List, Dict, Any
9
+ from aplos_nca_saas_sdk.integration_testing.configs._config_base import ConfigBase
10
+ from aplos_nca_saas_sdk.integration_testing.configs.login_config import (
11
+ LoginConfig,
12
+ LoginConfigs,
13
+ )
14
+ from aplos_nca_saas_sdk.utilities.environment_services import EnvironmentServices
15
+ from aplos_nca_saas_sdk.utilities.file_utility import FileUtility
16
+
17
+
18
+ class FileUploadConfig(ConfigBase):
19
+ """
20
+ File Upload: Defines the login that the application configuration tests will check against
21
+
22
+ """
23
+
24
+ def __init__(self, login: LoginConfig, file_path: str):
25
+ super().__init__()
26
+ if login is None:
27
+ raise RuntimeError("Login is required")
28
+ self.__login = login
29
+ if file_path is None:
30
+ raise RuntimeError("file_path is required")
31
+ self.__filepath = file_path
32
+
33
+ @property
34
+ def login(self) -> LoginConfig:
35
+ """The users login"""
36
+ return self.__login
37
+
38
+ @property
39
+ def file_path(self) -> str:
40
+ """The file path to file being uploaded"""
41
+ path = FileUtility.load_filepath(self.__filepath)
42
+
43
+ if not os.path.exists(path):
44
+ raise RuntimeError(f"The Upload File was not found: {path}")
45
+
46
+ return path
47
+
48
+
49
+ class FileUploadConfigs(ConfigBase):
50
+ """
51
+ File Uploads: Defines the files that the application file upload tests will check against
52
+
53
+ """
54
+
55
+ def __init__(self):
56
+ super().__init__()
57
+ self.__fileuploads: List[FileUploadConfig] = []
58
+
59
+ @property
60
+ def list(self) -> List[FileUploadConfig]:
61
+ """List the file uploads"""
62
+ return list(filter(lambda x: x.enabled, self.__fileuploads))
63
+
64
+ def add(self, *, file_path: str, login: LoginConfig, enabled: bool = True):
65
+ """Add a file upload"""
66
+ file_upload = FileUploadConfig(login, file_path)
67
+ file_upload.enabled = enabled
68
+ self.__fileuploads.append(file_upload)
69
+
70
+ def load(self, test_config: Dict[str, Any]):
71
+ """Load the file uploads from a list of dictionaries"""
72
+
73
+ super().load(test_config)
74
+ test_config_login: LoginConfig | None = LoginConfigs.try_load_login(
75
+ test_config.get("login", None)
76
+ )
77
+ file_uploads: List[Dict[str, Any]] = test_config.get("files", [])
78
+ login: LoginConfig | None = None
79
+ for file_upload in file_uploads:
80
+ enabled = bool(file_upload.get("enabled", True))
81
+ if "login" in file_upload:
82
+ login = LoginConfigs.try_load_login(file_upload["login"])
83
+ else:
84
+ login = test_config_login
85
+
86
+ file_path = file_upload.get("file", None)
87
+
88
+ if not file_path:
89
+ raise RuntimeError("file_path is required")
90
+
91
+ if not login:
92
+ raise RuntimeError("login configuration is required")
93
+
94
+ self.add(file_path=file_path, login=login, enabled=enabled)
@@ -8,7 +8,7 @@ from typing import List, Optional, Dict, Any
8
8
  from aplos_nca_saas_sdk.integration_testing.configs._config_base import ConfigBase
9
9
 
10
10
 
11
- class Login(ConfigBase):
11
+ class LoginConfig(ConfigBase):
12
12
  """
13
13
  Application Login: Defines the login that the application configuration tests will check against
14
14
 
@@ -69,7 +69,7 @@ class Login(ConfigBase):
69
69
  self.__roles = value
70
70
 
71
71
 
72
- class Logins(ConfigBase):
72
+ class LoginConfigs(ConfigBase):
73
73
  """
74
74
  Application Logins: Defines the logins that the application configuration tests will check against
75
75
 
@@ -77,16 +77,16 @@ class Logins(ConfigBase):
77
77
 
78
78
  def __init__(self):
79
79
  super().__init__()
80
- self.__logins: List[Login] = []
80
+ self.__logins: List[LoginConfig] = []
81
81
 
82
82
  @property
83
- def list(self) -> List[Login]:
83
+ def list(self) -> List[LoginConfig]:
84
84
  """List the logins"""
85
85
  return self.__logins
86
86
 
87
87
  def add(self, *, username: str, password: str, domain: str, enabled: bool = True):
88
88
  """Add a loging"""
89
- login = Login()
89
+ login = LoginConfig()
90
90
  login.username = username
91
91
  login.password = password
92
92
  login.domain = domain
@@ -95,12 +95,24 @@ class Logins(ConfigBase):
95
95
 
96
96
  def load(self, test_config: Dict[str, Any]):
97
97
  """Load the logins from a list of dictionaries"""
98
- # self.enabled = bool(test_config.get("enabled", True))
98
+
99
99
  super().load(test_config)
100
100
  logins: List[Dict[str, str]] = test_config.get("logins", [])
101
101
  for login in logins:
102
- self.add(
103
- username=login["username"],
104
- password=login["password"],
105
- domain=login["domain"],
106
- )
102
+ login_config = LoginConfigs.try_load_login(login)
103
+ if login_config is None:
104
+ continue
105
+ self.__logins.append(login_config)
106
+
107
+ @staticmethod
108
+ def try_load_login(login_config: Dict[str, Any]) -> LoginConfig | None:
109
+ """Attempts to intialize a Login from a configuration object"""
110
+ login: LoginConfig | None = None
111
+ if login_config is not None:
112
+ username = login_config.get("username", None)
113
+ password = login_config.get("password", None)
114
+ domain = login_config.get("domain", None)
115
+ enabled = login_config.get("enabled", True)
116
+ login = LoginConfig(username, password, domain)
117
+ login.enabled = enabled
118
+ return login
@@ -0,0 +1,186 @@
1
+ """
2
+ Copyright 2024 Aplos Analytics
3
+ All Rights Reserved. www.aplosanalytics.com LICENSED MATERIALS
4
+ Property of Aplos Analytics, Utah, USA
5
+ """
6
+
7
+ import os
8
+ import json
9
+ from typing import Any, Dict, List
10
+ from aplos_nca_saas_sdk.integration_testing.configs._config_base import ConfigBase
11
+ from aplos_nca_saas_sdk.integration_testing.configs.login_config import (
12
+ LoginConfig,
13
+ LoginConfigs,
14
+ )
15
+ from aplos_nca_saas_sdk.utilities.file_utility import FileUtility
16
+ from aws_lambda_powertools import Logger
17
+
18
+ logger = Logger(service="NCAExecutionConfig")
19
+
20
+
21
+ class NCAExecutionConfig(ConfigBase):
22
+ """
23
+ NCA Execution Config: Defines an NCA Execution configuration that the application execution tests will check against
24
+
25
+ """
26
+
27
+ def __init__(
28
+ self,
29
+ login: LoginConfig,
30
+ input_file_path: str,
31
+ config_data: dict,
32
+ meta_data: str | dict | None = None,
33
+ output_dir: str | None = None,
34
+ unzip_after_download: bool = False,
35
+ ):
36
+ super().__init__()
37
+
38
+ if login is None:
39
+ raise RuntimeError("login is required")
40
+ self.__login = login
41
+
42
+ if input_file_path is None:
43
+ raise RuntimeError("input_file_path is required")
44
+ self.__input_file_path = input_file_path
45
+
46
+ if config_data is None:
47
+ raise RuntimeError("config_data is required")
48
+ self.__config_data = config_data
49
+
50
+ self.__meta_data = meta_data
51
+ self.__output_dir = output_dir
52
+ self.__unzip_after_download = unzip_after_download
53
+
54
+ @property
55
+ def login(self) -> LoginConfig:
56
+ """Login Configuration"""
57
+ return self.__login
58
+
59
+ @property
60
+ def input_file_path(self) -> str:
61
+ """Input File Path"""
62
+ return self.__input_file_path
63
+
64
+ @property
65
+ def config_data(self) -> Dict[str, Any]:
66
+ """Config Data"""
67
+ return self.__config_data
68
+
69
+ @property
70
+ def meta_data(self) -> str | Dict[str, Any] | None:
71
+ """Optional Meta Data"""
72
+ return self.__meta_data
73
+
74
+ @property
75
+ def output_dir(self) -> str | None:
76
+ """Local Output Directory"""
77
+ return self.__output_dir
78
+
79
+ @property
80
+ def unzip_after_download(self) -> bool:
81
+ """Indicates if the download should be unzipped"""
82
+ return self.__unzip_after_download
83
+
84
+
85
+ class NCAExecutionConfigs(ConfigBase):
86
+ """
87
+ NCA Execution Configs: Defines the configurations that the application NCA Engine tests will check against
88
+
89
+ """
90
+
91
+ def __init__(self):
92
+ super().__init__()
93
+ self.__nca_executions: List[NCAExecutionConfig] = []
94
+
95
+ @property
96
+ def list(self) -> List[NCAExecutionConfig]:
97
+ """List the nca execution configurations"""
98
+ return list(filter(lambda x: x.enabled, self.__nca_executions))
99
+
100
+ def add(
101
+ self,
102
+ *,
103
+ login: LoginConfig,
104
+ input_file_path: str,
105
+ config_data: dict,
106
+ meta_data: str | dict | None = None,
107
+ output_dir: str | None = None,
108
+ unzip_after_download: bool = False,
109
+ enabled: bool = True,
110
+ ):
111
+ """Add an NCA Execution Config"""
112
+ nca_excution_config = NCAExecutionConfig(
113
+ login,
114
+ input_file_path,
115
+ config_data,
116
+ meta_data,
117
+ output_dir,
118
+ unzip_after_download,
119
+ )
120
+ nca_excution_config.enabled = enabled
121
+ self.__nca_executions.append(nca_excution_config)
122
+
123
+ def load(self, test_config: Dict[str, Any]):
124
+ """Loads the NCA Execution configs from a list of dictionaries"""
125
+
126
+ super().load(test_config)
127
+
128
+ base_login: LoginConfig | None = LoginConfigs.try_load_login(
129
+ test_config.get("login", None)
130
+ )
131
+ base_output_dir: str = test_config.get("output_dir", None)
132
+ analyses: List[Dict[str, Any]] = test_config.get("analyses", [])
133
+ for analysis in analyses:
134
+ enabled = bool(analysis.get("enabled", True))
135
+ login: LoginConfig | None = None
136
+ if "login" in analysis:
137
+ login = LoginConfigs.try_load_login(analysis["login"])
138
+ else:
139
+ login = base_login
140
+
141
+ if "output_dir" in analysis:
142
+ output_dir = analysis["output_dir"]
143
+ else:
144
+ output_dir = base_output_dir
145
+
146
+ if not login:
147
+ raise RuntimeError("Failed to load the login configuration")
148
+
149
+ self.add(
150
+ login=login,
151
+ input_file_path=analysis["file"],
152
+ config_data=self.__load_config_data(analysis=analysis),
153
+ meta_data=self.__load_meta_data(analysis=analysis),
154
+ output_dir=output_dir,
155
+ unzip_after_download=True,
156
+ enabled=enabled,
157
+ )
158
+
159
+ def __load_meta_data(self, analysis: Dict[str, Any]) -> Dict[str, Any]:
160
+ data: Dict[str, Any] = {}
161
+ data = analysis.get("meta", {}).get("data", {})
162
+
163
+ return data
164
+
165
+ def __load_config_data(self, analysis: Dict[str, Any]) -> Dict[str, Any]:
166
+ config_data: Dict[str, Any] = {}
167
+ config_data = analysis.get("config", {}).get("data")
168
+
169
+ if config_data:
170
+ return config_data
171
+
172
+ config_file_path: str = analysis.get("config", {}).get("file")
173
+
174
+ logger.info(
175
+ {
176
+ "message": "Initializing config_data from file",
177
+ "config_data": config_file_path,
178
+ }
179
+ )
180
+ config_path = FileUtility.load_filepath(config_file_path)
181
+ if os.path.exists(config_path) is False:
182
+ raise RuntimeError(f"Config file not found: {config_path}")
183
+ with open(config_path, "r", encoding="utf-8") as f:
184
+ config_data = json.load(f)
185
+
186
+ return config_data
@@ -0,0 +1,46 @@
1
+ {
2
+ "version": "2024-02-22",
3
+ "designations": {
4
+ "blq": "BLQ",
5
+ "missing": "NS",
6
+ "concentration_unit": "ng/mL"
7
+ },
8
+ "columns": {
9
+ "time": "time",
10
+ "unique_id": "subject",
11
+ "concentration": {
12
+ "observed": "conc_obs",
13
+ "analyzed": "conc"
14
+ },
15
+ "sorting": [
16
+ "subject",
17
+ "time"
18
+ ],
19
+ "grouping": [
20
+ "subject"
21
+ ]
22
+ },
23
+ "dosing": {
24
+ "amount": 10000,
25
+ "unit": "mg",
26
+ "frequency": "single",
27
+ "type": "ev"
28
+ },
29
+ "time": {
30
+ "unit": "hr",
31
+ "time_of_administration": 0
32
+ },
33
+ "kel_rules": {
34
+ "regression_statistic": "adj_r2",
35
+ "minimum_statistic": 0,
36
+ "maximum_extrapolation_linear": 0,
37
+ "maximum_extrapolation_logarithmic": 0,
38
+ "maximum_time_points": 0,
39
+ "minimum_span": 0,
40
+ "earliest_time_point": 0,
41
+ "tie": [
42
+ "kel_n",
43
+ "kel_lower"
44
+ ]
45
+ }
46
+ }
@@ -21,11 +21,18 @@ class IntegrationTestBase(ABC):
21
21
  """
22
22
 
23
23
  def __init__(self, name: str | None = None, index: int = 0):
24
- self.name = name
24
+ self.__name = name
25
25
  self.index = index
26
26
  self.__config: TestConfiguration = TestConfiguration()
27
27
  self.__results: List[IntegrationTestResponse] = []
28
28
 
29
+ @property
30
+ def name(self) -> str:
31
+ """
32
+ Get the name of the test
33
+ """
34
+ return self.__name if self.__name is not None else self.__class__.__name__
35
+
29
36
  @property
30
37
  def config(self) -> TestConfiguration:
31
38
  """