From 62f4176c5030a77b1a7172840faaa508dc81e79b Mon Sep 17 00:00:00 2001 From: onefloid <33193059+onefloid@users.noreply.github.com> Date: Thu, 11 Apr 2024 15:09:06 +0200 Subject: [PATCH 1/7] Refactor: Extract duplicated code to method --- Tests/ServerService_test.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Tests/ServerService_test.py b/Tests/ServerService_test.py index b5c2534d..55699a6b 100644 --- a/Tests/ServerService_test.py +++ b/Tests/ServerService_test.py @@ -426,17 +426,16 @@ def test_get_message_log_with_contains_filter_or_2(self): def test_session_context_default(self): threads = self.tm1.monitoring.get_threads() - for thread in threads: - if "GET /Threads" in thread["Function"] and thread["Name"] == self.config['tm1srv01']['user']: - self.assertTrue(thread["Context"] == "TM1py") - return - raise Exception("Did not find my own Thread") + self._test_session_context(threads, "TM1py") def test_session_context_custom(self): app_name = "Some Application" with TM1Service(**self.config['tm1srv01'], session_context=app_name) as tm1: threads = tm1.monitoring.get_threads() - for thread in threads: + self._test_session_context(threads, app_name) + + def _test_session_context(self, threads: list, app_name: str) -> None: + for thread in threads: if "GET /Threads" in thread["Function"] and thread["Name"] == self.config['tm1srv01']['user']: self.assertTrue(thread["Context"] == app_name) return From 3c10c313415a5e5481af92ac6297d6fa2835af2a Mon Sep 17 00:00:00 2001 From: onefloid <33193059+onefloid@users.noreply.github.com> Date: Thu, 11 Apr 2024 15:12:45 +0200 Subject: [PATCH 2/7] Fix: Ignore project specific vscode files --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 20b77cef..d63b772d 100644 --- a/.gitignore +++ b/.gitignore @@ -159,3 +159,6 @@ cython_debug/ # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. .idea/ + +# VSCode +.vscode/ From 607d61cef8f09f81404670cf2e970ca9f7f4fb31 Mon Sep 17 00:00:00 2001 From: onefloid <33193059+onefloid@users.noreply.github.com> Date: Thu, 11 Apr 2024 15:15:38 +0200 Subject: [PATCH 3/7] Fix: Ignore case and spaces for tm1 user name --- Tests/ServerService_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tests/ServerService_test.py b/Tests/ServerService_test.py index 55699a6b..eb684b87 100644 --- a/Tests/ServerService_test.py +++ b/Tests/ServerService_test.py @@ -13,6 +13,7 @@ from TM1py.Exceptions import TM1pyRestException from TM1py.Objects import Cube, Dimension, Hierarchy, Process from TM1py.Services import TM1Service +from TM1py.Utils.Utils import lower_and_drop_spaces @pytest.mark.skip(reason="Too slow for regular tests. Only run before releases") @@ -436,7 +437,7 @@ def test_session_context_custom(self): def _test_session_context(self, threads: list, app_name: str) -> None: for thread in threads: - if "GET /Threads" in thread["Function"] and thread["Name"] == self.config['tm1srv01']['user']: + if "GET /Threads" in thread["Function"] and lower_and_drop_spaces(thread["Name"]) == lower_and_drop_spaces(self.config['tm1srv01']['user']): self.assertTrue(thread["Context"] == app_name) return raise Exception("Did not find my own Thread") From 0d79ffd2f38e2c439aed8b99e721f595b6c6e14f Mon Sep 17 00:00:00 2001 From: onefloid <33193059+onefloid@users.noreply.github.com> Date: Thu, 11 Apr 2024 15:25:08 +0200 Subject: [PATCH 4/7] Fix: Get request api path --- Tests/ServerService_test.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Tests/ServerService_test.py b/Tests/ServerService_test.py index eb684b87..3fb5f833 100644 --- a/Tests/ServerService_test.py +++ b/Tests/ServerService_test.py @@ -434,12 +434,17 @@ def test_session_context_custom(self): with TM1Service(**self.config['tm1srv01'], session_context=app_name) as tm1: threads = tm1.monitoring.get_threads() self._test_session_context(threads, app_name) - + def _test_session_context(self, threads: list, app_name: str) -> None: for thread in threads: - if "GET /Threads" in thread["Function"] and lower_and_drop_spaces(thread["Name"]) == lower_and_drop_spaces(self.config['tm1srv01']['user']): - self.assertTrue(thread["Context"] == app_name) - return + if ( + "GET /Threads" in thread["Function"] + or "GET /api/v1/Threads" in thread["Function"] + ) and lower_and_drop_spaces(thread["Name"]) == lower_and_drop_spaces( + self.config["tm1srv01"]["user"] + ): + self.assertTrue(thread["Context"] == app_name) + return raise Exception("Did not find my own Thread") @classmethod From cbb88e4549fb3ee854c32baa828ddc555ed06e43 Mon Sep 17 00:00:00 2001 From: onefloid <33193059+onefloid@users.noreply.github.com> Date: Thu, 11 Apr 2024 16:27:28 +0200 Subject: [PATCH 5/7] Fix: Added /api/v1/Threads path --- TM1py/Services/ThreadService.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TM1py/Services/ThreadService.py b/TM1py/Services/ThreadService.py index 125421fb..c718c544 100644 --- a/TM1py/Services/ThreadService.py +++ b/TM1py/Services/ThreadService.py @@ -66,6 +66,8 @@ def cancel_all_running(self, **kwargs) -> list: continue if thread["Function"] == "GET /Threads": continue + if thread["Function"] == "GET /api/v1/Threads": + continue self.cancel(thread["ID"], **kwargs) canceled_threads.append(thread) return canceled_threads From 478f2cbd8ef4319b615acaa14ad4292f28194036 Mon Sep 17 00:00:00 2001 From: onefloid <33193059+onefloid@users.noreply.github.com> Date: Thu, 11 Apr 2024 16:55:46 +0200 Subject: [PATCH 6/7] Refactor: Extracted duplicated function to Utils module --- TM1py/Services/MessageLogService.py | 12 +++--------- TM1py/Services/TransactionLogService.py | 13 +++---------- TM1py/Utils/Utils.py | 5 +++++ 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/TM1py/Services/MessageLogService.py b/TM1py/Services/MessageLogService.py index 87e9262a..7aa98abf 100644 --- a/TM1py/Services/MessageLogService.py +++ b/TM1py/Services/MessageLogService.py @@ -1,4 +1,3 @@ -import pytz from warnings import warn from datetime import datetime @@ -8,7 +7,7 @@ from TM1py.Services.ObjectService import ObjectService from TM1py.Services.RestService import RestService from TM1py.Utils import verify_version, deprecated_in_version, odata_track_changes_header, require_ops_admin, require_data_admin, \ - format_url, CaseAndSpaceInsensitiveDict, CaseAndSpaceInsensitiveSet + format_url, CaseAndSpaceInsensitiveDict, CaseAndSpaceInsensitiveSet, utc_localize_time class MessageLogService(ObjectService): @@ -74,14 +73,14 @@ def get_entries(self, reverse: bool = True, since: datetime = None, if since: # If since doesn't have tz information, UTC is assumed if not since.tzinfo: - since = self.utc_localize_time(since) + since = utc_localize_time(since) log_filters.append(format_url( "TimeStamp ge {}", since.strftime("%Y-%m-%dT%H:%M:%SZ"))) if until: # If until doesn't have tz information, UTC is assumed if not until.tzinfo: - until = self.utc_localize_time(until) + until = utc_localize_time(until) log_filters.append(format_url( "TimeStamp le {}", until.strftime("%Y-%m-%dT%H:%M:%SZ"))) @@ -154,8 +153,3 @@ def get_last_process_message(self, process_name: str, **kwargs) -> Optional[str] message_log_entry = response_as_list[0] return message_log_entry['Message'] - @staticmethod - def utc_localize_time(timestamp): - timestamp = pytz.utc.localize(timestamp) - timestamp_utc = timestamp.astimezone(pytz.utc) - return timestamp_utc \ No newline at end of file diff --git a/TM1py/Services/TransactionLogService.py b/TM1py/Services/TransactionLogService.py index a578851b..add5aeab 100644 --- a/TM1py/Services/TransactionLogService.py +++ b/TM1py/Services/TransactionLogService.py @@ -1,4 +1,3 @@ -import pytz from warnings import warn from datetime import datetime @@ -6,7 +5,7 @@ from TM1py.Services.ObjectService import ObjectService from TM1py.Services.RestService import RestService -from TM1py.Utils import verify_version, deprecated_in_version, odata_track_changes_header, require_data_admin, format_url +from TM1py.Utils import verify_version, deprecated_in_version, odata_track_changes_header, require_data_admin, format_url, utc_localize_time class TransactionLogService(ObjectService): @@ -19,12 +18,6 @@ def __init__(self, rest: RestService): 2) self.last_delta_request = None - @staticmethod - def utc_localize_time(timestamp): - timestamp = pytz.utc.localize(timestamp) - timestamp_utc = timestamp.astimezone(pytz.utc) - return timestamp_utc - @deprecated_in_version(version="12.0.0") @odata_track_changes_header def initialize_delta_requests(self, filter=None, **kwargs): @@ -82,13 +75,13 @@ def get_entries(self, reverse: bool = True, user: str = None, cube: str = None, if since: # If since doesn't have tz information, UTC is assumed if not since.tzinfo: - since = self.utc_localize_time(since) + since = utc_localize_time(since) log_filters.append(format_url( "TimeStamp ge {}", since.strftime("%Y-%m-%dT%H:%M:%SZ"))) if until: # If until doesn't have tz information, UTC is assumed if not until.tzinfo: - until = self.utc_localize_time(until) + until = utc_localize_time(until) log_filters.append(format_url( "TimeStamp le {}", until.strftime("%Y-%m-%dT%H:%M:%SZ"))) url += "&$filter={}".format(" and ".join(log_filters)) diff --git a/TM1py/Utils/Utils.py b/TM1py/Utils/Utils.py index 1eb77d0a..a8a5a527 100644 --- a/TM1py/Utils/Utils.py +++ b/TM1py/Utils/Utils.py @@ -4,6 +4,7 @@ import http.client as http_client import json import math +import pytz import re import ssl import urllib.parse as urlparse @@ -1364,6 +1365,10 @@ def read_object_name_from_url(url: str, pattern: str) -> str: return unquote(match.group(1)) +def utc_localize_time(timestamp): + timestamp = pytz.utc.localize(timestamp) + timestamp_utc = timestamp.astimezone(pytz.utc) + return timestamp_utc class HTTPAdapterWithSocketOptions(HTTPAdapter): def __init__(self, *args, **kwargs): From 773a88f956ede633bb708bd907a8148fcd25991e Mon Sep 17 00:00:00 2001 From: onefloid <33193059+onefloid@users.noreply.github.com> Date: Thu, 11 Apr 2024 17:38:57 +0200 Subject: [PATCH 7/7] Fix: Replace missing method with function import --- TM1py/Services/AuditLogService.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/TM1py/Services/AuditLogService.py b/TM1py/Services/AuditLogService.py index 37c04799..eaa42044 100644 --- a/TM1py/Services/AuditLogService.py +++ b/TM1py/Services/AuditLogService.py @@ -8,7 +8,7 @@ from TM1py.Services.RestService import RestService from TM1py.Utils import verify_version, deprecated_in_version, odata_track_changes_header, require_data_admin, \ format_url, \ - require_version, require_ops_admin + require_version, require_ops_admin, utc_localize_time from TM1py.Services.ConfigurationService import ConfigurationService @@ -74,13 +74,13 @@ def get_entries(self, user: str = None, object_type: str = None, object_name: st if since: # If since doesn't have tz information, UTC is assumed if not since.tzinfo: - since = self.utc_localize_time(since) + since = utc_localize_time(since) log_filters.append(format_url( "TimeStamp ge {}", since.strftime("%Y-%m-%dT%H:%M:%SZ"))) if until: # If until doesn't have tz information, UTC is assumed if not until.tzinfo: - until = self.utc_localize_time(until) + until = utc_localize_time(until) log_filters.append(format_url( "TimeStamp le {}", until.strftime("%Y-%m-%dT%H:%M:%SZ"))) url += "&$filter={}".format(" and ".join(log_filters)) @@ -93,4 +93,4 @@ def get_entries(self, user: str = None, object_type: str = None, object_name: st @require_ops_admin def activate(self): config = {'Administration': {'AuditLog': {'Enable': True}}} - self.configuration.update_static(config) \ No newline at end of file + self.configuration.update_static(config)