From 3e3e385adb1c346bd6fc5fe330c83ef3f58bc1ca Mon Sep 17 00:00:00 2001 From: Aleksandar Gargenta Date: Sun, 7 Nov 2021 16:12:57 -0800 Subject: [PATCH] Added support for RemoteLRS.timeout Making it possible to override the default platform socket timeout with an explicit 'timeout' property. This is useful when making requests against an unresponsive LRS in a time-sensitive environment. --- examples/example_script.py | 1 + test/remote_lrs_test.py | 7 ++++++ test/resources/lrs_properties.py.template | 1 + tincan/remote_lrs.py | 28 +++++++++++++++++++++-- 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/examples/example_script.py b/examples/example_script.py index 28cd65f..026f3cb 100644 --- a/examples/example_script.py +++ b/examples/example_script.py @@ -21,6 +21,7 @@ lrs = RemoteLRS( version=lrs_properties.version, endpoint=lrs_properties.endpoint, + timeout=lrs_properties.timeout, username=lrs_properties.username, password=lrs_properties.password, ) diff --git a/test/remote_lrs_test.py b/test/remote_lrs_test.py index 73a7713..927affb 100644 --- a/test/remote_lrs_test.py +++ b/test/remote_lrs_test.py @@ -54,12 +54,14 @@ class RemoteLRSTest(unittest.TestCase): def setUp(self): self.endpoint = lrs_properties.endpoint + self.timeout = lrs_properties.timeout self.version = lrs_properties.version self.username = lrs_properties.username self.password = lrs_properties.password self.lrs = RemoteLRS( version=self.version, endpoint=self.endpoint, + timeout=self.timeout, username=self.username, password=self.password, ) @@ -126,6 +128,7 @@ def test_instantiation(self): lrs = RemoteLRS() self.assertIsInstance(lrs, RemoteLRS) self.assertIsNone(lrs.endpoint) + self.assertIsNone(lrs.timeout) self.assertIsNone(lrs.auth) self.assertEqual(Version.latest, lrs.version) @@ -142,6 +145,10 @@ def test_about_failure(self): self.assertFalse(response.success) + def test_operation_without_timeout(self): + self.lrs.timeout = None + self.test_about() + def test_save_statement(self): statement = Statement( actor=self.agent, diff --git a/test/resources/lrs_properties.py.template b/test/resources/lrs_properties.py.template index a457ad5..77d0391 100644 --- a/test/resources/lrs_properties.py.template +++ b/test/resources/lrs_properties.py.template @@ -4,6 +4,7 @@ Contains user-specific information for testing. endpoint = "" +timeout = # an optional timeout in seconds version = "" # 1.0.1 | 1.0.0 | 0.95 | 0.9 username = "" password = "" diff --git a/tincan/remote_lrs.py b/tincan/remote_lrs.py index 69a5c87..3f750d5 100644 --- a/tincan/remote_lrs.py +++ b/tincan/remote_lrs.py @@ -15,6 +15,7 @@ import http.client import json import base64 +import socket from urllib.parse import urlparse, urlencode @@ -45,6 +46,7 @@ class RemoteLRS(Base): _props_req = [ 'version', 'endpoint', + 'timeout', 'auth', ] @@ -57,6 +59,8 @@ def __init__(self, *args, **kwargs): :param endpoint: lrs endpoint :type endpoint: str | unicode + :param timeout: Timeout (in seconds) used for lrs communication + :type timeout: float :param version: Version used for lrs communication :type version: str | unicode :param username: Username for lrs. Used to build the authentication string. @@ -69,6 +73,7 @@ def __init__(self, *args, **kwargs): self._version = Version.latest self._endpoint = None + self._timeout = None self._auth = None if "username" in kwargs \ @@ -115,10 +120,11 @@ def _send_request(self, request): parsed = urlparse(url) + timeout = self.timeout or socket._GLOBAL_DEFAULT_TIMEOUT if parsed.scheme == "https": - web_req = http.client.HTTPSConnection(parsed.hostname, parsed.port) + web_req = http.client.HTTPSConnection(parsed.hostname, parsed.port, timeout=timeout) else: - web_req = http.client.HTTPConnection(parsed.hostname, parsed.port) + web_req = http.client.HTTPConnection(parsed.hostname, parsed.port, timeout=timeout) path = parsed.path if parsed.query or parsed.path: @@ -854,6 +860,24 @@ def endpoint(self, value): self._endpoint = value + @property + def timeout(self): + """The timeout to use when connecting to the Remote LRS + + :setter type: float + :rtype: float + """ + return self._timeout + + @timeout.setter + def timeout(self, value): + if value: + if not isinstance(value, float): + value = float(value) + if value < 0: + raise ValueError("Timeout must be positive number", value) + self._timeout = value + @property def version(self): """Version being used for remote LRS communication