def setUpClass(cls): # create a configured API client cls.secrets = CredentialsSource.secrets_path() cls.os_environ_dict_str = 'os.environ' cls.source_config_details, cls.config_keys = CredentialsSource.fetch_credentials( ), CredentialsSource.fetch_config_keys() cls.pat_token = CredentialsSource.fetch_pat()
def test_get_api_with_configuration(self): factory = ApiClientFactory( api_secrets_filename=CredentialsSource.secrets_path() ) api = factory.build(InstrumentsApi) self.assertIsInstance(api, InstrumentsApi) self.validate_api(api)
def test_get_api_without_tcp_keep_alive(self): api_factory = ApiClientFactory( api_secrets_filename=CredentialsSource.secrets_path()) # Make sure tcp_keep_alive was passed through all of the layers self.assertFalse(api_factory.api_client.configuration.tcp_keep_alive) self.assertIsInstance(api_factory.api_client.rest_client.pool_manager, (PoolManager, ProxyManager))
def api_client(cls): if not cls._api_client: with cls._lock: if not cls._api_client: cls._api_client = ApiClientBuilder().build( CredentialsSource.secrets_path()) return cls._api_client
def test_get_unknown_api_throws_exception(self, _, api_to_build, error_message): factory = ApiClientFactory( api_secrets_filename=CredentialsSource.secrets_path() ) with self.assertRaises(TypeError) as error: factory.build(api_to_build) self.assertEqual(error.exception.args[0], error_message)
def test_get_api_with_token_url_as_env_var(self): token, refresh_token = tu.get_okta_tokens(CredentialsSource.secrets_path()) with patch.dict('os.environ', {"FBN_LUSID_API_URL": source_config_details["api_url"]}, clear=True): factory = ApiClientFactory( token=token, app_name=source_config_details["app_name"]) api = factory.build(InstrumentsApi) self.assertIsInstance(api, InstrumentsApi) self.validate_api(api)
def test_get_api_with_info(self): factory = ApiClientFactory( api_secrets_filename=CredentialsSource.secrets_path()) api = factory.build(ScopesApi) self.assertIsInstance(api, ScopesApi) result = api.list_scopes(call_info=lambda r: print(r)) self.assertIsNotNone(result)
def test_get_api_with_token(self): token, refresh_token = tu.get_okta_tokens( CredentialsSource.secrets_path()) factory = ApiClientFactory(token=token, api_url=source_config_details["api_url"], app_name=source_config_details["app_name"]) api = factory.build(InstrumentsApi) self.assertIsInstance(api, InstrumentsApi) self.validate_api(api)
def test_wrapped_method(self): factory = ApiClientFactory( api_secrets_filename=CredentialsSource.secrets_path()) wrapped_scopes_api = factory.build(InstrumentsApi) portfolio = InstrumentsApi(wrapped_scopes_api.api_client) self.assertEqual(portfolio.__doc__, wrapped_scopes_api.__doc__) self.assertEqual(portfolio.__module__, wrapped_scopes_api.__module__) self.assertDictEqual(portfolio.__dict__, wrapped_scopes_api.__dict__)
def test_get_api_with_str_none_token(self): factory = ApiClientFactory( token=RefreshingToken(), api_url=source_config_details["api_url"], app_name=source_config_details["app_name"], api_secrets_filename=CredentialsSource.secrets_path(), ) api = factory.build(InstrumentsApi) self.assertIsInstance(api, InstrumentsApi) self.validate_api(api)
def test_get_info_with_invalid_param_throws_error(self): factory = ApiClientFactory( api_secrets_filename=CredentialsSource.secrets_path() ) api = factory.build(InstrumentsApi) self.assertIsInstance(api, InstrumentsApi) with self.assertRaises(ValueError) as error: api.get_instrument_identifier_types(call_info="invalid param") self.assertEqual(error.exception.args[0], "call_info value must be a lambda")
def test_get_token(self): original_token, refresh_token = tu.get_okta_tokens(CredentialsSource.secrets_path()) refreshed_token = RefreshingToken(token_url=self.config.token_url, client_id=self.config.client_id, client_secret=self.config.client_secret, initial_access_token=original_token, initial_token_expiry=3600, refresh_token=refresh_token) self.assertIsNotNone(refreshed_token) self.assertEqual(original_token, refreshed_token)
def test_use_apifactory_multiple_threads(self): with patch.dict('os.environ', self.get_env_vars_without_pat(), clear=True): access_token = str(ApiClientFactory( api_secrets_filename=CredentialsSource.secrets_path() ).api_client.configuration.access_token) api_factory = ApiClientFactory( api_secrets_filename=CredentialsSource.secrets_path() ) def get_identifier_types(factory): return factory.build(InstrumentsApi).get_instrument_identifier_types() thread1 = Thread(target=get_identifier_types, args=[api_factory]) thread2 = Thread(target=get_identifier_types, args=[api_factory]) thread3 = Thread(target=get_identifier_types, args=[api_factory]) with patch("requests.post") as identity_mock: identity_mock.side_effect = lambda *args, **kwargs: MockApiResponse( json_data={ "access_token": f"{access_token}", "refresh_token": "mock_refresh_token", "expires_in": 3600 }, status_code=200 ) thread1.start() thread2.start() thread3.start() thread1.join() thread2.join() thread3.join() # Ensure that we only got an access token once self.assertEqual(1, identity_mock.call_count)
def test_can_make_header(self): original_token, refresh_token = tu.get_okta_tokens(CredentialsSource.secrets_path()) refreshed_token = RefreshingToken(token_url=self.config.token_url, client_id=self.config.client_id, client_secret=self.config.client_secret, initial_access_token=original_token, initial_token_expiry=3600, refresh_token=refresh_token) header = "Bearer " + refreshed_token self.assertIsNotNone(header)
def test_get_api_with_correlation_id_from_param(self): env_vars = {config_keys[key]["env"]: value for key, value in source_config_details.items() if value is not None} with patch.dict('os.environ', env_vars, clear=True): factory = ApiClientFactory( api_secrets_filename=CredentialsSource.secrets_path(), correlation_id="param-correlation-id" ) api = factory.build(InstrumentsApi) self.assertIsInstance(api, InstrumentsApi) self.validate_api(api) self.assertTrue("CorrelationId" in api.api_client.default_headers, msg="CorrelationId not found in headers") self.assertEquals(api.api_client.default_headers["CorrelationId"], "param-correlation-id")
def get_okta_tokens(): original_token = "" refresh_token = "" def extract_refresh_token(okta_response): nonlocal refresh_token nonlocal original_token okta_json = okta_response.json() refresh_token = okta_json["refresh_token"] original_token = okta_json["access_token"] ApiClientBuilder().build( CredentialsSource.secrets_path(), extract_refresh_token ) return original_token, refresh_token
def test_token_when_not_expired_does_not_refresh(self): original_token, refresh_token = tu.get_okta_tokens(CredentialsSource.secrets_path()) refreshed_token = RefreshingToken(token_url=self.config.token_url, client_id=self.config.client_id, client_secret=self.config.client_secret, initial_access_token=original_token, initial_token_expiry=3600, refresh_token=refresh_token) self.assertIsNotNone(refreshed_token) # force de-referencing the token value first_value = f"{refreshed_token}" sleep(1) self.assertEqual(first_value, refreshed_token)
def test_use_apifactory_with_id_provider_response_handler(self): """ Ensures that an id_provider_response handler that is passed to the ApiClientFactory can be used during communication with the id provider (if appropriate). """ responses = [] def record_response(id_provider_response): nonlocal responses responses.append(id_provider_response.status_code) api_factory = ApiClientFactory( api_secrets_filename=CredentialsSource.secrets_path(), id_provider_response_handler=record_response) api = api_factory.build(InstrumentsApi) self.validate_api(api) self.assertGreater(len(responses), 0)
import unittest from unittest.mock import patch import inspect from lusid import ApiConfigurationLoader from lusid.utilities.api_configuration import ApiConfiguration from lusid.utilities.proxy_config import ProxyConfig from utilities import CredentialsSource from utilities.temp_file_manager import TempFileManager source_config_details, config_keys = CredentialsSource.fetch_credentials( ), CredentialsSource.fetch_config_keys() class ApiConfigurationLoaderTests(unittest.TestCase): """ These test ensure that the ApiConfigurationLoader works as expected """ OS_ENVIRON = "os_environ" def assert_config_values(self, config, secrets): """ Not a test. This is used to test the values of the ApiConfiguration. :param lusid.utilities.ApiConfiguration config: The ApiConfiguration to test the values of :param dict secrets: A dictionary with the secrets using a common addressing scheme for both environment variables and secret file variables
def setUpClass(cls): cls.config = ApiConfigurationLoader.load(CredentialsSource.secrets_path())
def setUpClass(cls): # add mock to the module lusid.api.MockApi = MockApi cls.factory = ApiClientFactory(api_secrets_filename=CredentialsSource.secrets_path())
from lusid.utilities import ApiClientFactory from utilities import TokenUtilities as tu, CredentialsSource from utilities.temp_file_manager import TempFileManager from utilities import MockApiResponse class UnknownApi: pass class UnknownImpl: pass source_config_details, config_keys = CredentialsSource.fetch_credentials(), CredentialsSource.fetch_config_keys() pat_token = CredentialsSource.fetch_pat() class RefreshingToken(UserString): def __init__(self): token_data = {"expires": datetime.now(), "current_access_token": ""} def get_token(): token_data["current_access_token"] = None return token_data["current_access_token"] self.access_token = get_token def __getattribute__(self, name): token = object.__getattribute__(self, "access_token")()