aplos-nca-saas-sdk 0.0.2__py3-none-any.whl → 0.0.4__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.
@@ -4,9 +4,11 @@ All Rights Reserved. www.aplosanalytics.com LICENSED MATERIALS
4
4
  Property of Aplos Analytics, Utah, USA
5
5
  """
6
6
 
7
+ from typing import Optional
8
+
7
9
  import boto3
8
10
  import jwt as jwt_lib
9
- from typing import Optional
11
+ from mypy_boto3_cognito_idp.client import CognitoIdentityProviderClient
10
12
  from aplos_nca_saas_sdk.nca_resources.nca_app_configuration import (
11
13
  NCAAppConfiguration,
12
14
  )
@@ -31,7 +33,7 @@ class CognitoAuthenication:
31
33
  self.__access_token: Optional[str] = None
32
34
  self.__refresh_token: Optional[str] = None
33
35
  self.__region: str = region or "us-east-1"
34
- self.__client: Optional[boto3.client] = None
36
+ self.__client: Optional[CognitoIdentityProviderClient] = None
35
37
  self.__user_id: Optional[str] = None
36
38
  self.__tenant_id: Optional[str] = None
37
39
  self.__config: Optional[NCAAppConfiguration] = None
@@ -40,7 +42,7 @@ class CognitoAuthenication:
40
42
  self.__validate_parameters()
41
43
 
42
44
  @property
43
- def client(self) -> boto3.client:
45
+ def client(self) -> CognitoIdentityProviderClient:
44
46
  """
45
47
  Get the boto3 client
46
48
 
@@ -53,7 +55,7 @@ class CognitoAuthenication:
53
55
  return self.__client
54
56
 
55
57
  @property
56
- def client_id(self) -> str:
58
+ def client_id(self) -> str | None:
57
59
  """
58
60
  Client Id
59
61
  Returns:
@@ -62,7 +64,7 @@ class CognitoAuthenication:
62
64
  return self.__client_id
63
65
 
64
66
  @property
65
- def region(self) -> str:
67
+ def region(self) -> str | None:
66
68
  """
67
69
  Region
68
70
  Returns:
@@ -0,0 +1,13 @@
1
+ from typing import Dict
2
+ from typing import Any
3
+
4
+
5
+ class ConfigBase:
6
+ """Base Configuration Class"""
7
+
8
+ def __init__(self, enabled: bool = True):
9
+ self.enabled: bool = enabled
10
+
11
+ def load(self, test_config: Dict[str, Any]):
12
+ """Load the configuration from a dictionary"""
13
+ self.enabled = test_config.get("enabled", True)
@@ -0,0 +1,60 @@
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
+ from typing import List, Dict, Any
8
+ from aplos_nca_saas_sdk.integration_testing.configs._config_base import ConfigBase
9
+
10
+
11
+ class ApplicationDomain(ConfigBase):
12
+ """
13
+ Application Domain: Defines the domains that the application configuration tests will check against
14
+
15
+ """
16
+
17
+ def __init__(self):
18
+ super().__init__()
19
+ self.__domain: str | None = None
20
+
21
+ @property
22
+ def domain(self) -> str:
23
+ """The domain to validate"""
24
+ if self.__domain is None:
25
+ raise RuntimeError("Domain is not set")
26
+ return self.__domain
27
+
28
+ @domain.setter
29
+ def domains(self, value: str):
30
+ self.__domain = value
31
+
32
+
33
+ class ApplicationSettings:
34
+ """
35
+ Application Settings: Defines the domains that the application settings (configuration endpoint) tests will check against
36
+
37
+ """
38
+
39
+ def __init__(self):
40
+ self.__domains: List[ApplicationDomain] = []
41
+
42
+ @property
43
+ def domains(self) -> List[ApplicationDomain]:
44
+ return self.__domains
45
+
46
+ @domains.setter
47
+ def domains(self, value: List[ApplicationDomain]):
48
+ self.__domains = value
49
+
50
+ def load(self, test_config: Dict[str, Any]):
51
+ """Load the domains from the config"""
52
+ domains: List[Dict[str, Any]] = test_config.get("domains", [])
53
+
54
+ domain: Dict[str, Any]
55
+ for domain in domains:
56
+ app_domain = ApplicationDomain()
57
+ app_domain.domains = domain.get("domain", None)
58
+ app_domain.enabled = bool(domain.get("enabled", True))
59
+
60
+ self.__domains.append(app_domain)
@@ -0,0 +1,105 @@
1
+ {
2
+ "application_config_test": {
3
+ "purpose": "Tests the application configuration endpoints",
4
+ "domains": [
5
+ {
6
+ "domain": "api.example.com",
7
+ "expected_results" : {
8
+ "status_code": 200
9
+ },
10
+ "enabled": true
11
+ },
12
+ {
13
+ "domain": "XXXXXXXXXXXXXXXXXXXXX",
14
+ "expected_results" : {
15
+ "status_code": 403
16
+ },
17
+ "enabled": false
18
+ }
19
+ ]
20
+ },
21
+ "login_test": {
22
+ "purpose": "Tests the login endpoints",
23
+ "logins": [
24
+ {
25
+ "username": "foo",
26
+ "password": "barr",
27
+ "domain": "api.example.com",
28
+ "roles": []
29
+
30
+ },
31
+ {
32
+ "username": "XXXXXXXXXXXXXXXXXXXXX",
33
+ "password": "XXXXXXXXXXXXXXXXXXXXX",
34
+ "domain": "XXXXXXXXXXXXXXXXXXXXX",
35
+ "roles": [
36
+ "XXXXXXXXXXXXXXXXXXXXX"
37
+ ],
38
+ "enabled" : false,
39
+ "expected_results" : {
40
+ "exception": "InvalidCredentialsException"
41
+ }
42
+ }
43
+ ]
44
+ },
45
+ "file_upload_test": {
46
+ "purpose": "Tests the file upload endpoints.",
47
+ "notes": "a file can be on the local drive or pulled from a public https source.",
48
+ "login": {
49
+ "purpose": "optional: if present this login is used, unless a specific login is defined for the test",
50
+ "username": "foo",
51
+ "password": "bar",
52
+ "domain": "api.example.com"
53
+ },
54
+ "files": [
55
+ {
56
+ "file": "XXXXXXXXXXXXXXXXXXXXX",
57
+ "expected_results" : {
58
+ "status_code": 200
59
+ }
60
+ },
61
+ {
62
+ "file": "XXXXXXXXXXXXXXXXXXXXX",
63
+ "login" : {
64
+ "purpose": "optional: if present tests an upload for a specific user",
65
+ "username": "XXXXXXXXXXXXXXXXXXXXX",
66
+ "password": "XXXXXXXXXXXXXXXXXXXXX",
67
+ "domain": "XXXXXXXXXXXXXXXXXXXXX"
68
+ },
69
+ "expected_results" : {
70
+ "status_code": 403
71
+ }
72
+ }
73
+ ]
74
+ },
75
+ "analysis_execution_test": {
76
+ "purpose": "Tests the analysis execution endpoints.",
77
+ "login": {
78
+ "username": "XXXXXXXXXXXXXXXXXXXXX",
79
+ "password": "XXXXXXXXXXXXXXXXXXXXX",
80
+ "domain": "XXXXXXXXXXXXXXXXXXXXX"
81
+ },
82
+ "analyses": [
83
+ {
84
+ "file": "XXXXXXXXXXXXXXXXXXXXX",
85
+ "meta": {},
86
+ "config": {},
87
+ "expected_results" : {
88
+ "status_code": 200
89
+ }
90
+ }
91
+ ]
92
+ },
93
+ "validation_test": {
94
+ "purpose": "Tests the validation execution.",
95
+ "login": {
96
+ "username": "XXXXXXXXXXXXXXXXXXXXX",
97
+ "password": "XXXXXXXXXXXXXXXXXXXXX",
98
+ "domain": "XXXXXXXXXXXXXXXXXXXXX"
99
+ },
100
+ "expected_results": {
101
+ "status_code": 200
102
+ }
103
+ }
104
+
105
+ }
@@ -0,0 +1,105 @@
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
+ from typing import List, Optional, Dict, Any
8
+ from aplos_nca_saas_sdk.integration_testing.configs._config_base import ConfigBase
9
+
10
+
11
+ class Login(ConfigBase):
12
+ """
13
+ Application Login: Defines the login that the application configuration tests will check against
14
+
15
+ """
16
+
17
+ def __init__(
18
+ self,
19
+ username: Optional[str] = None,
20
+ passord: Optional[str] = None,
21
+ domain: Optional[str] = None,
22
+ roles: Optional[List[str]] = None,
23
+ ):
24
+ super().__init__()
25
+ self.__username: Optional[str] = username
26
+ self.__password: Optional[str] = passord
27
+ self.__domain: Optional[str] = domain
28
+ self.__roles: List[str] = roles if roles is not None else []
29
+
30
+ @property
31
+ def username(self) -> str:
32
+ if self.__username is None:
33
+ raise RuntimeError("Username is not set")
34
+ return self.__username
35
+
36
+ @username.setter
37
+ def username(self, value: str):
38
+ self.__username = value
39
+
40
+ @property
41
+ def password(self) -> str:
42
+ if self.__password is None:
43
+ raise RuntimeError("Password is not set")
44
+ return self.__password
45
+
46
+ @password.setter
47
+ def password(self, value: str):
48
+ self.__password = value
49
+
50
+ @property
51
+ def domain(self) -> str:
52
+ if self.__domain is None:
53
+ raise RuntimeError("Domain is not set")
54
+ return self.__domain
55
+
56
+ @domain.setter
57
+ def domain(self, value: str):
58
+ self.__domain = value
59
+
60
+ @property
61
+ def roles(self) -> List[str]:
62
+ """A list of roles to check for"""
63
+ return self.__roles
64
+
65
+ @roles.setter
66
+ def roles(self, value: List[str] | None):
67
+ if value is None:
68
+ value = []
69
+ self.__roles = value
70
+
71
+
72
+ class Logins(ConfigBase):
73
+ """
74
+ Application Logins: Defines the logins that the application configuration tests will check against
75
+
76
+ """
77
+
78
+ def __init__(self):
79
+ super().__init__()
80
+ self.__logins: List[Login] = []
81
+
82
+ @property
83
+ def list(self) -> List[Login]:
84
+ """List the logins"""
85
+ return self.__logins
86
+
87
+ def add(self, *, username: str, password: str, domain: str, enabled: bool = True):
88
+ """Add a loging"""
89
+ login = Login()
90
+ login.username = username
91
+ login.password = password
92
+ login.domain = domain
93
+ login.enabled = enabled
94
+ self.__logins.append(login)
95
+
96
+ def load(self, test_config: Dict[str, Any]):
97
+ """Load the logins from a list of dictionaries"""
98
+ self.enabled = bool(test_config.get("enabled", True))
99
+ logins: List[Dict[str, str]] = test_config.get("logins", [])
100
+ for login in logins:
101
+ self.add(
102
+ username=login["username"],
103
+ password=login["password"],
104
+ domain=login["domain"],
105
+ )
@@ -4,9 +4,14 @@ All Rights Reserved. www.aplosanalytics.com LICENSED MATERIALS
4
4
  Property of Aplos Analytics, Utah, USA
5
5
  """
6
6
 
7
- from typing import Dict, Any
8
- from aplos_nca_saas_sdk.utilities.environment_vars import EnvironmentVars
9
- from aplos_nca_saas_sdk.nca_resources.nca_endpoints import NCAEndpoints
7
+ from typing import Dict, Any, List
8
+
9
+ from aplos_nca_saas_sdk.integration_testing.integration_test_configurations import (
10
+ TestConfiguration,
11
+ )
12
+ from aplos_nca_saas_sdk.integration_testing.integration_test_response import (
13
+ IntegrationTestResponse,
14
+ )
10
15
 
11
16
 
12
17
  class IntegrationTestBase:
@@ -14,21 +19,52 @@ class IntegrationTestBase:
14
19
  Integration Test Base Class
15
20
  """
16
21
 
17
- def __init__(self, name: str, index: int = 0):
22
+ def __init__(self, name: str | None = None, index: int = 0):
18
23
  self.name = name
19
24
  self.index = index
20
- self.env_vars: EnvironmentVars = EnvironmentVars()
25
+ self.__config: TestConfiguration | None = None
26
+ self.__results: List[IntegrationTestResponse] = []
21
27
 
22
- if not self.env_vars.api_domain:
28
+ @property
29
+ def config(self) -> TestConfiguration:
30
+ """
31
+ Get the configuration for the test
32
+ """
33
+ if self.__config is None:
23
34
  raise RuntimeError(
24
- "APLOS_API_DOMAIN environment variable is not set. "
25
- "This is required to run the tests"
35
+ "Test configuration not set. "
36
+ "A configuration is required to run integration tests."
26
37
  )
38
+ return self.__config
39
+
40
+ @config.setter
41
+ def config(self, value: TestConfiguration):
42
+ """
43
+ Set the configuration for the test
44
+ """
45
+ self.__config = value
46
+
47
+ @property
48
+ def results(self) -> List[IntegrationTestResponse]:
49
+ """
50
+ Get the results of the test
51
+ """
52
+ return self.__results
27
53
 
28
- self.endpoints: NCAEndpoints = NCAEndpoints(
29
- aplos_saas_domain=self.env_vars.api_domain,
30
- )
54
+ def success(self) -> bool:
55
+ """
56
+ Returns True if all tests in the suite were successful
57
+ """
58
+ return all([result.success for result in self.results])
31
59
 
32
- def test(self) -> Dict[str, Any] | None:
33
- """Run the Test"""
60
+ def test(self) -> bool:
61
+ """
62
+ Run the Test
63
+ Args:
64
+ config: The Test Configuration
65
+ Returns:
66
+ True if the test was successful, False otherwise. If any
67
+ of the tests fail, it will be false. Execeptions are only
68
+ raised if the raise_on_failure flag is set to True.
69
+ """
34
70
  raise RuntimeError("This should be implemented by the subclass.")
@@ -0,0 +1,38 @@
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 json
8
+ from typing import Any, Dict
9
+ from aplos_nca_saas_sdk.integration_testing.configs.app_settings import (
10
+ ApplicationSettings,
11
+ )
12
+ from aplos_nca_saas_sdk.integration_testing.configs.login import Logins
13
+
14
+
15
+ class TestConfiguration:
16
+ """
17
+ Testing Suite Configuration: Provides a way to define the testing configuration for the Aplos Analytics SaaS SDK
18
+
19
+ """
20
+
21
+ def __init__(self):
22
+ self.app_config: ApplicationSettings = ApplicationSettings()
23
+ self.logins: Logins = Logins()
24
+
25
+ def load(self, file_path: str):
26
+ """
27
+ Loads the configuration from a file
28
+
29
+ :param file_path: The path to the configuration file
30
+ :return: None
31
+ """
32
+
33
+ config: Dict[str, Any] = {}
34
+ with open(file_path, "r", encoding="utf-8") as f:
35
+ config = json.load(f)
36
+
37
+ self.logins.load(config.get("login_test", {}))
38
+ self.app_config.load(config.get("application_config_test", {}))
@@ -0,0 +1,28 @@
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
+ from typing import Dict, Any, Optional
8
+
9
+
10
+ class IntegrationTestResponse:
11
+ """Integration Test Response"""
12
+
13
+ def __init__(self):
14
+ self.name: str = ""
15
+ self.meta: Dict[str, Any] = {}
16
+ self.response: Dict[str, Any] = {}
17
+ self.error: Optional[str] = None
18
+ self.success: bool = False
19
+
20
+ def to_dict(self) -> Dict[str, Any]:
21
+ """JSON Dictionary Object"""
22
+ return {
23
+ "name": self.name,
24
+ "meta": self.meta,
25
+ "response": self.response,
26
+ "error": self.error,
27
+ "success": self.success,
28
+ }
@@ -6,12 +6,18 @@ Property of Aplos Analytics, Utah, USA
6
6
 
7
7
  from typing import List, Dict, Any
8
8
  from datetime import datetime, UTC
9
+ from aws_lambda_powertools import Logger
9
10
  from aplos_nca_saas_sdk.integration_testing.integration_test_factory import (
10
11
  IntegrationTestFactory,
11
12
  )
12
13
  from aplos_nca_saas_sdk.integration_testing.integration_test_base import (
13
14
  IntegrationTestBase,
14
15
  )
16
+ from aplos_nca_saas_sdk.integration_testing.integration_test_configurations import (
17
+ TestConfiguration,
18
+ )
19
+
20
+ logger = Logger(service="IntegrationTestSuite")
15
21
 
16
22
 
17
23
  class IntegrationTestSuite:
@@ -21,64 +27,72 @@ class IntegrationTestSuite:
21
27
  self.test_results: List[Dict[str, Any]] = []
22
28
  self.verbose: bool = False
23
29
  self.raise_on_failure: bool = False
30
+ self.fail_fast: bool = False
24
31
 
25
- def test(self) -> bool:
32
+ def test(self, test_config: TestConfiguration) -> bool:
26
33
  """Run a full suite of integration tests"""
34
+
35
+ # reset the test results
36
+ self.test_results = []
37
+
27
38
  start_time: datetime = datetime.now(UTC)
28
39
  factory: IntegrationTestFactory = IntegrationTestFactory()
29
- test_class: IntegrationTestBase | None = None
30
- for test_class in factory.test_classes:
31
- test_instance: IntegrationTestBase = test_class
32
- test: Dict[str, Any] = {
33
- "test_name": test_instance.name,
40
+ test: IntegrationTestBase | None = None
41
+ for test in factory.test_classes:
42
+ test.config = test_config
43
+ test_result: Dict[str, Any] = {
44
+ "test_name": test.name,
34
45
  "success": True,
35
46
  "error": None,
36
47
  "start_time_utc": datetime.now(UTC),
37
48
  "end_time_utc": None,
38
49
  }
39
- if self.verbose:
40
- print(f"Running test class {test_instance.name}")
41
- try:
42
- results = test_instance.test()
43
- test["results"] = results
44
50
 
51
+ logger.info(f"Running test class {test.name}")
52
+ try:
53
+ success = test.test()
54
+ test_result["success"] = success
55
+ test_result["results"] = test.results
45
56
  except Exception as e: # pylint: disable=broad-except
46
- test["success"] = False
47
- test["error"] = str(e)
48
-
49
- test["end_time_utc"] = datetime.now(UTC)
50
- self.test_results.append(test)
51
-
52
- if self.verbose:
53
- if test["success"]:
54
- print(f"Test {test_instance.name} succeeded")
55
- else:
56
- print(
57
- f"Test {test_instance.name} failed with error {test['error']}"
58
- )
57
+ test_result["success"] = False
58
+ test_result["error"] = str(e)
59
+ if self.fail_fast:
60
+ # just break and let the failure routine handle it
61
+ break
62
+
63
+ test_result["end_time_utc"] = datetime.now(UTC)
64
+ self.test_results.append(test_result)
65
+
66
+ if test_result["success"]:
67
+ logger.info(f"Test {test.name} succeeded")
68
+ logger.debug(test_result)
69
+ else:
70
+ logger.error(test_result)
59
71
  # find the failures
60
72
  failures = [test for test in self.test_results if not test["success"]]
73
+ self.__print_results(start_time, failures)
61
74
 
62
75
  # print the results
63
76
 
77
+ if self.raise_on_failure and len(failures) > 0:
78
+ count = len(failures)
79
+ logger.error(f"{count} tests failed. Raising exception.")
80
+ raise RuntimeError(f"{count} tests failed")
81
+
82
+ return len(failures) == 0
83
+
84
+ def __print_results(self, start_time: datetime, failures: List[Dict[str, Any]]):
64
85
  print("Test Results:")
65
- for test in self.test_results:
66
- duration = test["end_time_utc"] - test["start_time_utc"]
86
+ for test_result in self.test_results:
87
+ duration = test_result["end_time_utc"] - test_result["start_time_utc"]
67
88
  print(
68
- f" {test['test_name']} {'succeeded' if test['success'] else 'failed'} duration: {duration}"
89
+ f" {test_result['test_name']} {'succeeded' if test_result['success'] else 'failed'} duration: {duration}"
69
90
  )
70
- if not test["success"]:
71
- print(f" Error: {test['error']}")
91
+ if not test_result["success"]:
92
+ print(f" Error: {test_result['error']}")
72
93
 
73
94
  print(f"Test Suite completed in {datetime.now(UTC) - start_time}")
74
95
 
75
96
  print(f"Total Tests: {len(self.test_results)}")
76
97
  print(f"Successful Tests: {len(self.test_results) - len(failures)}")
77
98
  print(f"Failed Tests: {len(failures)}")
78
-
79
- if self.raise_on_failure and len(failures) > 0:
80
- count = len(failures)
81
- print(f"{count} tests failed. Raising exception.")
82
- raise RuntimeError(f"{count} tests failed")
83
-
84
- return len(failures) == 0
@@ -5,10 +5,14 @@ Property of Aplos Analytics, Utah, USA
5
5
  """
6
6
 
7
7
  import os
8
+ from pathlib import Path
8
9
  from aplos_nca_saas_sdk.utilities.environment_services import EnvironmentServices
9
10
  from aplos_nca_saas_sdk.integration_testing.integration_test_suite import (
10
11
  IntegrationTestSuite,
11
12
  )
13
+ from aplos_nca_saas_sdk.integration_testing.integration_test_configurations import (
14
+ TestConfiguration,
15
+ )
12
16
 
13
17
 
14
18
  def main():
@@ -21,7 +25,36 @@ def main():
21
25
  evs.load_environment(starting_path=__file__, file_name=env_file)
22
26
 
23
27
  its: IntegrationTestSuite = IntegrationTestSuite()
24
- its.test()
28
+ config: TestConfiguration = TestConfiguration()
29
+
30
+ # normally we'd pull a test configuration file from Secrets Manager, Parameter Store, or some other secure location
31
+ # here we're going to pull the sample file and then override some it's values.
32
+ config_file = os.path.join(Path(__file__).parent, "configs", "config_sample.json")
33
+ # load it so we can see what it looks like
34
+ config.load(file_path=config_file)
35
+
36
+ # override the configuration
37
+ override_config(config)
38
+
39
+ its.test(test_config=config)
40
+
41
+
42
+ def override_config(config: TestConfiguration):
43
+ """Override the configuration for the tests"""
44
+ username = os.getenv("TEST_USERNAME")
45
+ password = os.getenv("TEST_PASSWORD")
46
+ domain = os.getenv("TEST_DOMAIN")
47
+
48
+ if not username or not password or not domain:
49
+ raise RuntimeError(
50
+ "TEST_USERNAME, TEST_PASSWORD, and TEST_DOMAIN must be set in the environment"
51
+ )
52
+
53
+ config.logins.list.clear()
54
+ config.logins.add(username=username, password=password, domain=domain)
55
+
56
+ config.app_config.domains.clear()
57
+ config.app_config.domains.append(domain)
25
58
 
26
59
 
27
60
  if __name__ == "__main__":
@@ -11,6 +11,10 @@ from aplos_nca_saas_sdk.integration_testing.integration_test_base import (
11
11
  IntegrationTestBase,
12
12
  )
13
13
 
14
+ from aplos_nca_saas_sdk.integration_testing.integration_test_response import (
15
+ IntegrationTestResponse,
16
+ )
17
+
14
18
 
15
19
  class TestAppConfiguration(IntegrationTestBase):
16
20
  """Application Configuration Tests"""
@@ -18,13 +22,22 @@ class TestAppConfiguration(IntegrationTestBase):
18
22
  def __init__(self):
19
23
  super().__init__(name="app_configuration")
20
24
 
21
- def test(self) -> dict:
25
+ def test(self) -> bool:
22
26
  """Test loading the application configuration"""
23
27
 
24
- config: NCAAppConfiguration = NCAAppConfiguration(self.env_vars.api_domain)
25
- response = config.get()
28
+ self.results.clear()
29
+ for domain in self.config.app_config.domains:
30
+ config: NCAAppConfiguration = NCAAppConfiguration(domain)
31
+
32
+ test_response: IntegrationTestResponse = IntegrationTestResponse()
33
+ test_response.meta = {"domain": domain}
34
+ try:
35
+ response = config.get()
36
+ test_response.response = response
37
+ test_response.success = True
38
+ except Exception as e: # pylint: disable=W0718
39
+ test_response.error = str(e)
26
40
 
27
- if response.status_code != 200:
28
- raise RuntimeError("App configuration url is not working.")
41
+ self.results.append(test_response)
29
42
 
30
- return response.json()
43
+ return self.success()
@@ -10,6 +10,9 @@ from aplos_nca_saas_sdk.nca_resources.nca_login import NCALogin
10
10
  from aplos_nca_saas_sdk.integration_testing.integration_test_base import (
11
11
  IntegrationTestBase,
12
12
  )
13
+ from aplos_nca_saas_sdk.integration_testing.integration_test_response import (
14
+ IntegrationTestResponse,
15
+ )
13
16
 
14
17
 
15
18
  class TestAppLogin(IntegrationTestBase):
@@ -18,15 +21,28 @@ class TestAppLogin(IntegrationTestBase):
18
21
  def __init__(self):
19
22
  super().__init__("app-login")
20
23
 
21
- def test(self) -> dict:
24
+ def test(self) -> bool:
22
25
  """Test a login"""
23
26
 
24
- user_name = self.env_vars.username
25
- password = self.env_vars.password
27
+ self.results.clear()
28
+
29
+ for login in self.config.logins.list:
30
+ test_response: IntegrationTestResponse = IntegrationTestResponse()
31
+ test_response.name = self.name
32
+ try:
33
+ nca_login = NCALogin(aplos_saas_domain=login.domain)
34
+ token = nca_login.authenticate(
35
+ username=login.username, password=login.password
36
+ )
37
+ test_response.response = token
38
+ if not token:
39
+ test_response.error = "Failed to authenticate"
40
+
41
+ else:
42
+ test_response.success = True
43
+ except Exception as e: # pylint: disable=w0718
44
+ test_response.error = str(e)
45
+
46
+ self.results.append(test_response)
26
47
 
27
- login = NCALogin(aplos_saas_domain=self.env_vars.api_domain)
28
- token = login.authenticate(username=user_name, password=password)
29
- if not token:
30
- raise RuntimeError("Failed to authenticate")
31
- else:
32
- return {"token": token}
48
+ return self.success()
@@ -48,6 +48,9 @@ class NCAEngine:
48
48
  @property
49
49
  def api_root(self) -> str:
50
50
  """Gets the base url"""
51
+ if self.__api_domain is None:
52
+ raise RuntimeError("Missing Aplos Api Domain")
53
+
51
54
  url = HttpUtilities.build_url(self.__api_domain)
52
55
  if isinstance(url, str):
53
56
  return (
@@ -59,7 +59,7 @@ class NCALogin:
59
59
  return self.__cognito
60
60
 
61
61
  @property
62
- def domain(self) -> str:
62
+ def domain(self) -> str | None:
63
63
  """
64
64
  Domain
65
65
  Returns:
@@ -6,7 +6,7 @@ class EnvironmentVars:
6
6
 
7
7
  def __init__(self) -> None:
8
8
  # load defaults
9
- self.api_domain = os.getenv("APLOS_API_DOMAIN")
9
+ self.api_domain = os.getenv("APLOS_API_DOMAIN", "")
10
10
 
11
11
  self.aws_region = os.getenv("COGNITO_REGION")
12
12
  self.client_id = os.getenv("COGNITO_CLIENT_ID")
@@ -17,7 +17,7 @@ class EnvironmentVars:
17
17
  self.metadata_file = os.getenv("METADATA_FILE")
18
18
  self.analysis_file = os.getenv("ANALYSIS_FILE")
19
19
 
20
- if "https://" in self.api_domain:
20
+ if self.api_domain is not None and "https://" in self.api_domain:
21
21
  self.api_domain = self.api_domain.replace("https://", "")
22
22
 
23
23
  self.aplos_api_url = f"https://{self.api_domain}"
@@ -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.2'
4
+ __version__ = '0.0.4'
@@ -0,0 +1,92 @@
1
+ Metadata-Version: 2.3
2
+ Name: aplos_nca_saas_sdk
3
+ Version: 0.0.4
4
+ Summary: Aplos NCA SaaS SDK
5
+ Project-URL: Homepage, https://aplosanalytics.com/
6
+ Project-URL: Documentation, https://docs.aplosanalytics.com/
7
+ Project-URL: Repository, https://github.com/AplosAnalytics/Aplos-NCA-SaaS-SDK
8
+ Project-URL: Issues, https://github.com/AplosAnalytics/Aplos-NCA-SaaS-SDK/issues
9
+ Author-email: Eric Wilson <eric.wilson@aplosanalytics.com>
10
+ License: MIT License
11
+ Keywords: Bioavailability Studies,Bioequivalence Studies,Clinical Pharmacology,Clinical Trials,Dose-Proportionality Studies,Drug Interaction Studies,NCA,Non-Compartmental Analysis,PK Analysis,PK modeling,Pharma Data Analysis,Pharmacokinetic Analysis,Pharmacokinetics,Pharmacokinetics Software,SaaS
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Topic :: Software Development :: Libraries
18
+ Requires-Python: >=3.10
19
+ Requires-Dist: aws-lambda-powertools>=3.3.0
20
+ Requires-Dist: boto3==1.34.110
21
+ Requires-Dist: mypy-boto3-cognito-idp>=1.35.68
22
+ Requires-Dist: pyjwt==2.9.0
23
+ Requires-Dist: python-dotenv==1.0.1
24
+ Requires-Dist: requests==2.31.0
25
+ Description-Content-Type: text/markdown
26
+
27
+ # Aplos NCA SaaS SDK for python
28
+
29
+ Welcome to the Aplos NCA SaaS SDK for automating your PK Analyis. A secure set of API's to connect to our Cloud System and automate your PK analysis.
30
+
31
+ This SDK works for our
32
+ - Trial Accounts (Multi Tenancy)
33
+ - Academic Accounts (Multi Tenancy)
34
+ - Professional Accounts (Multi Tenancy)
35
+ - Team Accounts (Single Tenancy)
36
+ - Enterprise Accounts (Single Tenancy)
37
+
38
+ ## Use 🐍 python to perform an NCA Analysis with the Aplos NCA SaaS Solution.
39
+ If you can make HTTPS 🔐 request 🛜 - you can automation your PK Analysis Workflow Systems.
40
+
41
+ ## 👉 We use this for our demos 🚀🚀 👈
42
+ > We'll keep this maintained as we use it for our customer demo as well as Integration Testings.
43
+ > So keep coming back for new features.
44
+ >
45
+ > If you're not sure how to get started, kick off the Integration Test Suite, set some break points
46
+ > and you'll see a wide range of example use cases.
47
+
48
+ ## API Settings 🛑 A valid Aplos NCA Account is required. 🛑
49
+
50
+
51
+ > In order to run the executions and connect to our system, you will need a valid account with an active subscription (reach out for a trial subscription if you are evaluating our solutions).
52
+ >
53
+ > You'll need your username (email address and a password), a Cognito Client Id
54
+ > which allows the USER_PASSWORD_AUTH flow, and your API URL.
55
+ >
56
+ > Technically if you have your API Domain (from your account), you can use this to query for your Cognito Client Id
57
+ >
58
+ > Otherwise, the Client Id (aka Cognito Client Key) and API URL can be found in your user account.
59
+ >
60
+ > Your username is your email address and your password would have been provided to you during your
61
+ > onboarding or with a "forgot password" request and reset.
62
+
63
+
64
+ ## API
65
+ You can use the API to integrate the Aplos NCA SaaS Cloud Solution into your workflow.
66
+ You can perform:
67
+ - Logins
68
+ - File Uploads
69
+ - PK Analysis Executions
70
+ - PK Analysis Results
71
+ - File Downloads
72
+ - PK Validations (run validations against our calculations engine)
73
+ - Tenant & User Management (for Team & Enterprise Accounts)
74
+ - and more...
75
+
76
+
77
+ ## API Integration Testing
78
+ You can use the integration testing to test your environment. You can also use the Integration Testing modules
79
+ to learn how to use the API.
80
+
81
+ ## Source
82
+ Full source code can also be found on [GitHub](https://github.com/AplosAnalytics/Aplos-NCA-SaaS-SDK)
83
+
84
+ ## Documentation
85
+ [The Docs](https://docs.aplosanalytics.com/)
86
+
87
+ ## Corporate Home Page
88
+ [Aplos Analytics](https://aplosanalytics.com/)
89
+
90
+
91
+
92
+
@@ -1,29 +1,35 @@
1
1
  aplos_nca_saas_sdk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- aplos_nca_saas_sdk/version.py,sha256=V3mRVcxh2tUI7Mn6MWg59BFD43T3MuX0gvMHJHOo4ok,171
3
- aplos_nca_saas_sdk/aws_resources/aws_cognito.py,sha256=jJQnHrIIKTry0Bk1vWem6WEKvxo-4BUI3O81WRWti_4,6306
2
+ aplos_nca_saas_sdk/version.py,sha256=gBIZC-1MsRi6HxaRfdvsl5EHu6glEpq7V2uKtlVdLyg,171
3
+ aplos_nca_saas_sdk/aws_resources/aws_cognito.py,sha256=pxyEdIoeeT7of_hjxYlplOnyLQpo3I-dnc5mHeGP47c,6427
4
4
  aplos_nca_saas_sdk/aws_resources/aws_s3_presigned_payload.py,sha256=rbTaeUgPpRsw1KV0YjnmkD5sQvlYet9XBj6Ie7nXz5Y,1987
5
5
  aplos_nca_saas_sdk/aws_resources/aws_s3_presigned_upload.py,sha256=WK7CKzuHcgU15k2BWiBqSZ8UdQSVSo39L8Las-7gvC0,3940
6
6
  aplos_nca_saas_sdk/files/analysis_files/single_ev/configuration_single_ev.json,sha256=lLnRV0jwzaSn32D8NlOekOF5oGFfUwugUlvlwoKz540,986
7
7
  aplos_nca_saas_sdk/files/analysis_files/single_ev/meta_data.json,sha256=p1KYOAe5Cl3rjtfF1t96oRG-QtFJJCo9otReRPNtvIk,447
8
8
  aplos_nca_saas_sdk/files/analysis_files/single_ev/single_ev.csv,sha256=qFSAlgLOmERsabMmp1X6PAZa-8yFthZlHacM_f7_AOY,6528
9
- aplos_nca_saas_sdk/integration_testing/integration_test_base.py,sha256=wp0uneVMnksj0hkSvks06CqyTB6YCDQs6qfVAWFIvnM,1037
9
+ aplos_nca_saas_sdk/integration_testing/integration_test_base.py,sha256=mdBTHUk-SjKGbvSy0T9aLXQKOULaruYAI9z4MB35FRk,2000
10
+ aplos_nca_saas_sdk/integration_testing/integration_test_configurations.py,sha256=ZE-Yqm8v7QPOPENmcVIksniFhikndHWVB21HkQspupE,1100
10
11
  aplos_nca_saas_sdk/integration_testing/integration_test_factory.py,sha256=9wQzdtBLMrBb4dfYkNE7-miyayPNhTHOWgqEMSL9-Yc,2081
11
- aplos_nca_saas_sdk/integration_testing/integration_test_suite.py,sha256=QHoJzAp9Qm4XTOeYE8waNqZmMh2S5XO2AYq0RfGwj4s,3020
12
- aplos_nca_saas_sdk/integration_testing/main.py,sha256=y2OqzPRccGb45d_MoAIRjxRblFHgHxZ8PH-e52R5blw,736
12
+ aplos_nca_saas_sdk/integration_testing/integration_test_response.py,sha256=HkHTb5-KbhVvYJJ-0PmcCuvQferejd1LyVU-QnGjDEU,742
13
+ aplos_nca_saas_sdk/integration_testing/integration_test_suite.py,sha256=sYm7EzhzVayL6BOSxJnOo0T97PWwdyx8LHuRxNy9yII,3598
14
+ aplos_nca_saas_sdk/integration_testing/main.py,sha256=M0Ee6QJXNzbeYzpyfDniNlZpySy9EZwYgtYzRZYXnnA,1976
13
15
  aplos_nca_saas_sdk/integration_testing/readme.md,sha256=sX-_gzx17UUF-ZqvCWq0R5zcqgOMC4JjQKnjgxQH9vM,629
14
- aplos_nca_saas_sdk/integration_testing/tests/app_configuration_test.py,sha256=Ezz3mZWE3Nv8CIfc-zXnpE0WgbI5QgQvVfHqP8lfb3Y,861
16
+ aplos_nca_saas_sdk/integration_testing/configs/_config_base.py,sha256=O48Y1r8JFe2KvSMTY5EttZAz1-hQsU6-Su6CzDUKDmE,347
17
+ aplos_nca_saas_sdk/integration_testing/configs/app_settings.py,sha256=vPWPIpk41I2BGeOZt6lvx6dob-_m5tI-al4KC_XBUsI,1700
18
+ aplos_nca_saas_sdk/integration_testing/configs/config_sample.json,sha256=50tqWe9OpD1b-EWe2_wQlwYtQ0n_OqfwobFkRraoxwc,3328
19
+ aplos_nca_saas_sdk/integration_testing/configs/login.py,sha256=ql2F8iqkbKLL7xeu7-D-Y1XJlR9NBcKEaAwOT53KBlo,2966
20
+ aplos_nca_saas_sdk/integration_testing/tests/app_configuration_test.py,sha256=_ZQqAPnXkruIpmV1hio4-xfWL_ggrGInGdxJw2nL5U0,1332
15
21
  aplos_nca_saas_sdk/integration_testing/tests/app_execution_test.py,sha256=bDyVvtOKSJdy0sdCVYVuCdUrQYhn8D3peCmM1OCkSVg,145
16
- aplos_nca_saas_sdk/integration_testing/tests/app_login_test.py,sha256=rE5hSDKgLLTkgL6pwtFax8SO1HknAXkLJvmFvb_BHtI,877
22
+ aplos_nca_saas_sdk/integration_testing/tests/app_login_test.py,sha256=gXMoDOnoxY9H5mjngRCd4GUYKtuCWv87g6l_X7Abnmc,1448
17
23
  aplos_nca_saas_sdk/integration_testing/tests/app_validation_test.py,sha256=bDyVvtOKSJdy0sdCVYVuCdUrQYhn8D3peCmM1OCkSVg,145
18
24
  aplos_nca_saas_sdk/nca_resources/nca_app_configuration.py,sha256=mRK_OK2k0q4o4pH11tpeR3yKve7sgw3XTtQ0HG9KKFU,1877
19
25
  aplos_nca_saas_sdk/nca_resources/nca_endpoints.py,sha256=8jQK8mniRFaQaGnpG1g_D0si8HCJciVvcLA6wFtOers,2026
20
- aplos_nca_saas_sdk/nca_resources/nca_executions.py,sha256=M-bwZOL9w4FNUfC8m2eMTw4H_P45J1psfffY6KeBwtM,12565
21
- aplos_nca_saas_sdk/nca_resources/nca_login.py,sha256=iw8JFITWm9vRyxzRlW4BJMVCQyL3Qeo_nwxKVB3bpUM,3024
26
+ aplos_nca_saas_sdk/nca_resources/nca_executions.py,sha256=LIar1Rs4_X0dRUlLmuYWARcEfa1BtKR4u4RGaSSdk1U,12663
27
+ aplos_nca_saas_sdk/nca_resources/nca_login.py,sha256=wTwuQhntyGKgm6C96ock3uyG8bFWCaMzG-0GJgQ3Ouo,3031
22
28
  aplos_nca_saas_sdk/utilities/commandline_args.py,sha256=WKIPNKMMMpEk580xXMQY7sGwxZP-uX6DVqD-8SX3NKM,11721
23
29
  aplos_nca_saas_sdk/utilities/environment_services.py,sha256=K6xnxDb9eNdmjJZKPW0JfmmV9rGGwm2urlxCBZwxMMs,2272
24
- aplos_nca_saas_sdk/utilities/environment_vars.py,sha256=abzjw2egdRJxrUP6sHDwCV4R56R4LzfsVI69QyHYvhU,776
30
+ aplos_nca_saas_sdk/utilities/environment_vars.py,sha256=pfcfX2eYmwYrmY-PZIHCONU9ds_-6GZmb-JibGROJGI,812
25
31
  aplos_nca_saas_sdk/utilities/http_utility.py,sha256=7VGWeSOuJbjnUQkzNA6cquKv0g2FJoHsBnDSgE2Buic,696
26
- aplos_nca_saas_sdk-0.0.2.dist-info/METADATA,sha256=wNz2934lydrL4HFRIaDjgMRh6jH9AOc-zDBhh3hCh18,2218
27
- aplos_nca_saas_sdk-0.0.2.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
28
- aplos_nca_saas_sdk-0.0.2.dist-info/licenses/LICENSE,sha256=pAZXnNE2dxxwXFIduGyn1gpvPefJtUYOYZOi3yeGG94,1068
29
- aplos_nca_saas_sdk-0.0.2.dist-info/RECORD,,
32
+ aplos_nca_saas_sdk-0.0.4.dist-info/METADATA,sha256=QQJysA2KZhm7Ju1nE6OL9ZIsDc3pRQmtz7PQM0IokhU,3769
33
+ aplos_nca_saas_sdk-0.0.4.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
34
+ aplos_nca_saas_sdk-0.0.4.dist-info/licenses/LICENSE,sha256=pAZXnNE2dxxwXFIduGyn1gpvPefJtUYOYZOi3yeGG94,1068
35
+ aplos_nca_saas_sdk-0.0.4.dist-info/RECORD,,
@@ -1,57 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: aplos_nca_saas_sdk
3
- Version: 0.0.2
4
- Summary: Aplos NCA SaaS SDK
5
- Project-URL: Homepage, https://aplosanalytics.com/
6
- Project-URL: Documentation, https://docs.aplosanalytics.com/
7
- Project-URL: Repository, https://github.com/AplosAnalytics/Aplos-NCA-SaaS-SDK
8
- Project-URL: Issues, https://github.com/AplosAnalytics/Aplos-NCA-SaaS-SDK/issues
9
- Author-email: Eric Wilson <eric.wilson@aplosanalytics.com>
10
- License: MIT License
11
- Classifier: Development Status :: 4 - Beta
12
- Classifier: Intended Audience :: Developers
13
- Classifier: License :: OSI Approved :: MIT License
14
- Classifier: Operating System :: OS Independent
15
- Classifier: Programming Language :: Python :: 3
16
- Classifier: Topic :: Software Development :: Libraries
17
- Requires-Python: >=3.10
18
- Requires-Dist: aws-lambda-powertools==2.38.1
19
- Requires-Dist: boto3==1.34.110
20
- Requires-Dist: pyjwt==2.9.0
21
- Requires-Dist: python-dotenv==1.0.1
22
- Requires-Dist: requests==2.31.0
23
- Description-Content-Type: text/markdown
24
-
25
- # Aplos NCA SaaS SDK for python
26
-
27
- You can use 🐍 python to perform analysis with Aplos NCA using API calls via secure HTTPS requests.
28
-
29
- > 👉 We use this for our demos 🚀🚀 👈
30
- > We'll keep this maintained as we use it for our customer demos. So keep coming back for new features.
31
-
32
-
33
- ## API Settings
34
-
35
- > 🛑 A valid Aplos NCA Account is required. 🛑
36
- > In order to run the executions and connect to our system, you will need a valid account with an active subscription.
37
- >
38
- > You'll need your username (email address and a password) a Cognito Client Id
39
- > which allows the USER_PASSWORD_AUTH flow, and your API URL.
40
- >
41
- > The Client Id (aka Cognito Client Key) and API URL can be found in your user account.
42
- > Your username is your email address and your password would have been provided to you during your
43
- > onboarding or with a "forgot password" request and reset.
44
-
45
-
46
- ## API
47
- You can use the API to integrate the Aplos NCA SaaS Cloud Solution into your workflow.
48
-
49
- ## API Integration Testing
50
- You can use the integration testing to test your environment. You can also use the Integration Testing modules
51
- to learn how to use the API.
52
-
53
- ## Source
54
- Full source code can also be found on [GitHub](https://github.com/AplosAnalytics/Aplos-NCA-SaaS-SDK)
55
-
56
-
57
-