From aa8364269b979c697970b4e143a543e2fd55be49 Mon Sep 17 00:00:00 2001 From: Marco Julian Moser Date: Sat, 4 Nov 2023 10:05:46 +0000 Subject: [PATCH 1/4] moved IntegrationAPIV2 client to separate folder --- src/sxapi/base.py | 16 ------------ src/sxapi/cli/cli_user.py | 2 +- src/sxapi/integrationV2/__init__.py | 28 +++++++++++++++++++++ tests/test_base.py | 2 +- tests/test_publicV2/test_get_sensor_data.py | 2 +- 5 files changed, 31 insertions(+), 19 deletions(-) create mode 100644 src/sxapi/integrationV2/__init__.py diff --git a/src/sxapi/base.py b/src/sxapi/base.py index ea3ce77..29a6053 100644 --- a/src/sxapi/base.py +++ b/src/sxapi/base.py @@ -5,8 +5,6 @@ import requests -INTEGRATION_API_V2_BASE_URL = "https://api.smaxtec.com/integration/v2" - class ApiTypes(Enum): PUBLIC = 1 @@ -90,17 +88,3 @@ def delete(self, path, *args, **kwargs): url = self.to_url(path) r = self.session.delete(url, *args, **kwargs) return r.json() - - -class IntegrationAPIV2(BaseAPI): - def __init__(self, base_url=None, email=None, password=None, api_token=None): - """Initialize a new integration api client instance.""" - base_url = base_url or INTEGRATION_API_V2_BASE_URL - api_type = ApiTypes.INTEGRATION - super().__init__( - base_url, - email=email, - password=password, - api_token=api_token, - api_type=api_type, - ) diff --git a/src/sxapi/cli/cli_user.py b/src/sxapi/cli/cli_user.py index f7d2d3f..28adee6 100644 --- a/src/sxapi/cli/cli_user.py +++ b/src/sxapi/cli/cli_user.py @@ -2,7 +2,7 @@ import keyring -from sxapi.base import IntegrationAPIV2 +from sxapi.integrationV2 import IntegrationAPIV2 from sxapi.publicV2 import PublicAPIV2 diff --git a/src/sxapi/integrationV2/__init__.py b/src/sxapi/integrationV2/__init__.py new file mode 100644 index 0000000..0625169 --- /dev/null +++ b/src/sxapi/integrationV2/__init__.py @@ -0,0 +1,28 @@ +from sxapi.base import ( + ApiTypes, + BaseAPI, +) +from sxapi.integrationV2.accounts import Accounts +from sxapi.integrationV2.tranlations import Translations +from sxapi.integrationV2.users import Users + +INTEGRATION_API_V2_BASE_URL = "https://api.smaxtec.com/integration/v2" + + +class IntegrationAPIV2(BaseAPI): + def __init__(self, base_url=None, email=None, password=None, api_token=None): + """Initialize a new integration api client instance.""" + base_url = base_url or INTEGRATION_API_V2_BASE_URL + api_type = ApiTypes.INTEGRATION + + self.users = Users(api=self) + self.translations = Translations(api=self) + self.accounts = Accounts(api=self) + + super().__init__( + base_url, + email=email, + password=password, + api_token=api_token, + api_type=api_type, + ) diff --git a/tests/test_base.py b/tests/test_base.py index e29831a..30b0e0d 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -1,6 +1,6 @@ import mock -from sxapi.base import IntegrationAPIV2 +from sxapi.integrationV2 import IntegrationAPIV2 from sxapi.publicV2 import PublicAPIV2 diff --git a/tests/test_publicV2/test_get_sensor_data.py b/tests/test_publicV2/test_get_sensor_data.py index 781f62f..fd7bab0 100644 --- a/tests/test_publicV2/test_get_sensor_data.py +++ b/tests/test_publicV2/test_get_sensor_data.py @@ -2,7 +2,7 @@ import mock -from sxapi.base import IntegrationAPIV2 +from sxapi.integrationV2 import IntegrationAPIV2 from sxapi.publicV2 import PublicAPIV2 from sxapi.publicV2.sensordata import get_sensor_data_from_animal From 261ba485eb2d5c94722c7b8456364535d2f95b4c Mon Sep 17 00:00:00 2001 From: Marco Julian Moser Date: Sat, 4 Nov 2023 10:06:44 +0000 Subject: [PATCH 2/4] added accounts endpoint --- src/sxapi/integrationV2/accounts.py | 95 +++++++++++++++++++ .../test_integrationV2/test_intgr_accounts.py | 65 +++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 src/sxapi/integrationV2/accounts.py create mode 100644 tests/test_integrationV2/test_intgr_accounts.py diff --git a/src/sxapi/integrationV2/accounts.py b/src/sxapi/integrationV2/accounts.py new file mode 100644 index 0000000..ea98f62 --- /dev/null +++ b/src/sxapi/integrationV2/accounts.py @@ -0,0 +1,95 @@ +class Accounts: + """ + This Class represents the /accounts endpoint fo the IntegrationAPIV2 + https://api.smaxtec.com/integration/v2/ + """ + + def __init__(self, api=None): + self.api = api + self.path_suffix = "/accounts" + + def get_usages(self, **kwargs): + """Get usages of provided account numbers. + + Args: + **kwargs: Optional parameters of the API call. + Find supported parameters under + https://api.smaxtec.com/integration/v2/ + + Returns: + dict: Response of API call. List of usages on success, + error message else. + + """ + params = {} + + for k, v in kwargs.items(): + params[k] = v + + url_suffix = self.path_suffix + "/usages" + return self.api.get(url_suffix, json=params) + + def put( + self, + account_nr, + account_name, + partner_id, + address_name, + street, + county_code, + **kwargs, + ): + """Update an account. + + Args: + account_nr (str): Account number of the account + account_name (str): Name of the account + partner_id (str): Partner ID of the account + address_name (str): Name of the address of the account + street (str): Street of the address of the account + county_code (str): Country code of the address of the account + **kwargs: Optional parameters of the API call. + Find supported parameters under + https://api.smaxtec.com/integration/v2/ + + Returns: + dict: Response of API call. Updated account on success, + error message else. + + """ + params = { + "account_name": account_name, + "partner_id": partner_id, + "address_name": address_name, + "street": street, + "county_code": county_code, + } + + for k, v in kwargs.items(): + params[k] = v + + url_suffix = self.path_suffix + f"/{account_nr}" + return self.api.put(url_suffix, json=params) + + def put_organisation(self, account_nr, organisation_id, **kwargs): + """Add an account to an organisation. + + Args: + account_nr (str): Account number of the account + organisation_id (str): Organisation ID of the organisation + **kwargs: Optional parameters of the API call. + Find supported parameters under + https://api.smaxtec.com/integration/v2/ + + Returns: + dict: Response of API call. Result on success, + error message else. + + """ + params = {} + + for k, v in kwargs.items(): + params[k] = v + + url_suffix = self.path_suffix + f"/{account_nr}/organisation/{organisation_id}" + return self.api.put(url_suffix, json=params) diff --git a/tests/test_integrationV2/test_intgr_accounts.py b/tests/test_integrationV2/test_intgr_accounts.py new file mode 100644 index 0000000..efcee88 --- /dev/null +++ b/tests/test_integrationV2/test_intgr_accounts.py @@ -0,0 +1,65 @@ +import mock + +from sxapi.integrationV2 import IntegrationAPIV2 + + +@mock.patch("sxapi.integrationV2.IntegrationAPIV2.get") +def test_get_usages(get_mock): + test_api = IntegrationAPIV2() + test_api.accounts.get_usages(kwarg1="kwarg1") + + call_args = get_mock.call_args_list[0] + + assert get_mock.call_count == 1 + assert call_args.args[0] == "/accounts/usages" + assert call_args.kwargs["json"] == { + "kwarg1": "kwarg1", + } + + +@mock.patch("sxapi.integrationV2.IntegrationAPIV2.put") +def test_put(put_mock): + test_api = IntegrationAPIV2() + test_api.accounts.put( + "test_account_nr", + "test_account_name", + "test_partner_id", + "test_address_name", + "test_street", + "test_county_code", + kwarg1="kwarg1", + ) + + call_args = put_mock.call_args_list[0] + + assert put_mock.call_count == 1 + assert call_args.args[0] == "/accounts/test_account_nr" + assert call_args.kwargs["json"] == { + "account_name": "test_account_name", + "partner_id": "test_partner_id", + "address_name": "test_address_name", + "street": "test_street", + "county_code": "test_county_code", + "kwarg1": "kwarg1", + } + + +@mock.patch("sxapi.integrationV2.IntegrationAPIV2.put") +def test_put_organisation(put_mock): + test_api = IntegrationAPIV2() + test_api.accounts.put_organisation( + "test_account_nr", + "test_organisation_id", + kwarg1="kwarg1", + ) + + call_args = put_mock.call_args_list[0] + + assert put_mock.call_count == 1 + assert ( + call_args.args[0] + == "/accounts/test_account_nr/organisation/test_organisation_id" + ) + assert call_args.kwargs["json"] == { + "kwarg1": "kwarg1", + } From 171211a8e947f211ef1cd92ccaf084bc60bf67c9 Mon Sep 17 00:00:00 2001 From: Marco Julian Moser Date: Sat, 4 Nov 2023 10:07:16 +0000 Subject: [PATCH 3/4] added users endpoint --- src/sxapi/integrationV2/users.py | 51 ++++++++++++++++++++ tests/test_integrationV2/test_intgr_users.py | 33 +++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 src/sxapi/integrationV2/users.py create mode 100644 tests/test_integrationV2/test_intgr_users.py diff --git a/src/sxapi/integrationV2/users.py b/src/sxapi/integrationV2/users.py new file mode 100644 index 0000000..139f176 --- /dev/null +++ b/src/sxapi/integrationV2/users.py @@ -0,0 +1,51 @@ +class Users: + """ + This Class represents the /users endpoint fo the IntegrationAPIV2 + https://api.smaxtec.com/integration/v2/ + """ + + def __init__(self, api=None): + self.api = api + self.path_suffix = "/users" + + def get(self, **kwargs): + """Grant access to demo farm + + Args: + **kwargs: Optional parameters of the API call. + Find supported parameters under + https://api.smaxtec.com/integration/v2/ + + Returns: + dict: Response of API call. Demo farm User on success, + error message else. + + """ + params = {} + + for k, v in kwargs.items(): + params[k] = v + + return self.api.get(self.path_suffix, json=params) + + def post_session_token(self, user, password, **kwargs): + """Creates a new session token. + + Args: + user (str): Email of the user to be logged in + password (str): Password of the user to be logged in + **kwargs: Optional parameters of the API call. + Find supported parameters under + https://api.smaxtec.com/integration/v2/ + + Returns: + dict: Response of API call. Created session token on success, + error message else. + + """ + params = {"user": user, "password": password} + + for k, v in kwargs.items(): + params[k] = v + + return self.api.post(self.path_suffix + "/session_token", json=params) diff --git a/tests/test_integrationV2/test_intgr_users.py b/tests/test_integrationV2/test_intgr_users.py new file mode 100644 index 0000000..2e00d45 --- /dev/null +++ b/tests/test_integrationV2/test_intgr_users.py @@ -0,0 +1,33 @@ +import mock + +from sxapi.integrationV2 import IntegrationAPIV2 + + +@mock.patch("sxapi.integrationV2.IntegrationAPIV2.get") +def test_get(get_mock): + test_api = IntegrationAPIV2() + test_api.users.get(kwarg1="kwarg1") + + call_args = get_mock.call_args_list[0] + + assert get_mock.call_count == 1 + assert call_args.args[0] == "/users" + assert call_args.kwargs["json"] == { + "kwarg1": "kwarg1", + } + + +@mock.patch("sxapi.integrationV2.IntegrationAPIV2.post") +def test_post_session_token(post_mock): + test_api = IntegrationAPIV2() + test_api.users.post_session_token("test_user", "test_password", kwarg1="kwarg1") + + call_args = post_mock.call_args_list[0] + + assert post_mock.call_count == 1 + assert call_args.args[0] == "/users/session_token" + assert call_args.kwargs["json"] == { + "user": "test_user", + "password": "test_password", + "kwarg1": "kwarg1", + } From 86b5e405459d3198927fe2b3f3b7bcac77216196 Mon Sep 17 00:00:00 2001 From: Marco Julian Moser Date: Sat, 4 Nov 2023 10:07:34 +0000 Subject: [PATCH 4/4] added translations endpoint --- src/sxapi/integrationV2/tranlations.py | 54 +++++++++++++++++++ .../test_intgr_translations.py | 31 +++++++++++ 2 files changed, 85 insertions(+) create mode 100644 src/sxapi/integrationV2/tranlations.py create mode 100644 tests/test_integrationV2/test_intgr_translations.py diff --git a/src/sxapi/integrationV2/tranlations.py b/src/sxapi/integrationV2/tranlations.py new file mode 100644 index 0000000..70f79ab --- /dev/null +++ b/src/sxapi/integrationV2/tranlations.py @@ -0,0 +1,54 @@ +class Translations: + """ + This Class represents the /translations endpoint fo the IntegrationAPIV2 + https://api.smaxtec.com/integration/v2/ + """ + + def __init__(self, api=None): + self.api = api + self.path_suffix = "/translations" + + def get_events(self, language, **kwargs): + """Get translations for events. + + Args: + language (str): Language of the events to be returned + **kwargs: Optional parameters of the API call. + Find supported parameters under + https://api.smaxtec.com/integration/v2/ + + Returns: + dict: Response of API call. List of events on success, + error message else. + + """ + params = {} + + for k, v in kwargs.items(): + params[k] = v + + url_suffix = self.path_suffix + f"/{language}/events" + return self.api.get(url_suffix, json=params) + + def get_event_types(self, language, event_type, **kwargs): + """Get translations for event types. + + Args: + language (str): Language of the event types to be returned + event_type (str): Type of the event types to be returned + **kwargs: Optional parameters of the API call. + Find supported parameters under + https://api.smaxtec.com/integration/v2/ + + Returns: + dict: Response of API call. List of event types on success, + error message else. + + """ + params = {} + + for k, v in kwargs.items(): + params[k] = v + + url_suffix = self.path_suffix + f"/{language}/events/{event_type}" + return self.api.get(url_suffix, json=params) diff --git a/tests/test_integrationV2/test_intgr_translations.py b/tests/test_integrationV2/test_intgr_translations.py new file mode 100644 index 0000000..2aad3c5 --- /dev/null +++ b/tests/test_integrationV2/test_intgr_translations.py @@ -0,0 +1,31 @@ +import mock + +from sxapi.integrationV2 import IntegrationAPIV2 + + +@mock.patch("sxapi.integrationV2.IntegrationAPIV2.get") +def test_get_events(get_mock): + test_api = IntegrationAPIV2() + test_api.translations.get_events("en", kwarg1="kwarg1") + + call_args = get_mock.call_args_list[0] + + assert get_mock.call_count == 1 + assert call_args.args[0] == "/translations/en/events" + assert call_args.kwargs["json"] == { + "kwarg1": "kwarg1", + } + + +@mock.patch("sxapi.integrationV2.IntegrationAPIV2.get") +def test_get_event_types(get_mock): + test_api = IntegrationAPIV2() + test_api.translations.get_event_types("en", "test_event_type", kwarg1="kwarg1") + + call_args = get_mock.call_args_list[0] + + assert get_mock.call_count == 1 + assert call_args.args[0] == "/translations/en/events/test_event_type" + assert call_args.kwargs["json"] == { + "kwarg1": "kwarg1", + }