python-terminusgps 1.14.0__tar.gz → 1.15.1__tar.gz
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.
Potentially problematic release.
This version of python-terminusgps might be problematic. Click here for more details.
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/PKG-INFO +1 -1
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/pyproject.toml +1 -1
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/wialon/constants.py +1 -1
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/wialon/items/unit.py +6 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/wialon/items/user.py +28 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/wialon/session.py +48 -13
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/uv.lock +1 -1
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/.gitignore +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/COPYING +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/README.md +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/__init__.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/authorizenet/__init__.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/authorizenet/auth.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/authorizenet/profiles/__init__.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/authorizenet/profiles/addresses.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/authorizenet/profiles/base.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/authorizenet/profiles/customers.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/authorizenet/profiles/payments.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/authorizenet/subscriptions.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/aws/__init__.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/aws/secrets.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/aws/ses.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/settings.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/twilio/__init__.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/twilio/caller.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/wialon/__init__.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/wialon/errors.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/wialon/flags.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/wialon/items/__init__.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/wialon/items/base.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/wialon/items/notification.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/wialon/items/resource.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/wialon/items/retranslator.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/wialon/items/route.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/wialon/items/unit_group.py +0 -0
- {python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/wialon/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-terminusgps
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.15.1
|
|
4
4
|
Summary: Provides abstractions/utilities for working with Wialon API, Authorize.NET API, AWS API, and more.
|
|
5
5
|
Project-URL: Documentation, https://app.terminusgps.com/docs/apps/python-terminusgps/index.html
|
|
6
6
|
Project-URL: Repository, https://github.com/terminusgps/python-terminusgps
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "python-terminusgps"
|
|
3
|
-
version = "1.
|
|
3
|
+
version = "1.15.1"
|
|
4
4
|
description = "Provides abstractions/utilities for working with Wialon API, Authorize.NET API, AWS API, and more."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [ {name = "Blake Nall", email = "blake@terminusgps.com" } ]
|
|
@@ -36,6 +36,12 @@ class WialonUnit(WialonBase):
|
|
|
36
36
|
)
|
|
37
37
|
return response.get("item", {}).get("id")
|
|
38
38
|
|
|
39
|
+
@property
|
|
40
|
+
def available_commands(self) -> dict:
|
|
41
|
+
return self.session.wialon_api.core_get_hw_cmds(
|
|
42
|
+
**{"deviceTypeId": 0, "unitId": self.id}
|
|
43
|
+
)
|
|
44
|
+
|
|
39
45
|
def execute_command(
|
|
40
46
|
self,
|
|
41
47
|
name: str,
|
|
@@ -180,3 +180,31 @@ class WialonUser(WialonBase):
|
|
|
180
180
|
"newPassword": new_password,
|
|
181
181
|
}
|
|
182
182
|
)
|
|
183
|
+
|
|
184
|
+
def verify_auth(self, destination: str, method: str = "email") -> str:
|
|
185
|
+
"""
|
|
186
|
+
Sends an authentication code to ``destination`` via ``method``.
|
|
187
|
+
|
|
188
|
+
``Method`` can be ``"email"`` or ``"sms"``.
|
|
189
|
+
|
|
190
|
+
:param destination: The email or phone number to send an auth code to.
|
|
191
|
+
:type destination: :py:obj:`str`
|
|
192
|
+
:param method: Email or sms. Default is ``"email"``.
|
|
193
|
+
:type method: :py:obj:`str`
|
|
194
|
+
:raises ValueError: If the method isn't ``"email"`` or ``"sms"``.
|
|
195
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
196
|
+
:returns: An auth code.
|
|
197
|
+
:rtype: :py:obj:`str`
|
|
198
|
+
|
|
199
|
+
"""
|
|
200
|
+
if method != "email" or "sms":
|
|
201
|
+
raise ValueError(f"Invalid method '{method}'.")
|
|
202
|
+
|
|
203
|
+
response = self.session.wialon_api.user_verify_auth(
|
|
204
|
+
**{
|
|
205
|
+
"userId": self.id,
|
|
206
|
+
"type": 1 if method == "email" else 0,
|
|
207
|
+
"destination": destination,
|
|
208
|
+
}
|
|
209
|
+
)
|
|
210
|
+
return response.get("code")
|
|
@@ -1,34 +1,67 @@
|
|
|
1
1
|
import threading
|
|
2
2
|
import logging
|
|
3
|
+
|
|
3
4
|
from typing import Any
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from datetime import datetime
|
|
4
7
|
|
|
5
8
|
from wialon.api import WialonError
|
|
6
9
|
from wialon.api import Wialon as WialonAPI
|
|
7
10
|
from django.conf import settings
|
|
11
|
+
from django.utils import timezone
|
|
8
12
|
|
|
9
13
|
from .errors import WialonLogoutError, WialonLoginError
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class WialonAPICall:
|
|
18
|
+
action: str
|
|
19
|
+
timestamp: datetime
|
|
20
|
+
args: tuple
|
|
21
|
+
kwargs: dict
|
|
22
|
+
result: Any = None
|
|
23
|
+
error: Exception | None = None
|
|
12
24
|
|
|
13
25
|
|
|
14
26
|
class Wialon(WialonAPI):
|
|
15
27
|
def __init__(self, log_level: int = logging.INFO, *args, **kwargs) -> None:
|
|
16
28
|
super().__init__(*args, **kwargs)
|
|
29
|
+
self.call_history: list[WialonAPICall] = []
|
|
17
30
|
self.logger = self.create_logger(log_level)
|
|
18
|
-
self.callstack = []
|
|
19
31
|
|
|
20
32
|
@property
|
|
21
|
-
def
|
|
22
|
-
return len(self.
|
|
33
|
+
def total_calls(self) -> int:
|
|
34
|
+
return len(self.call_history)
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def successful_calls(self) -> list[WialonAPICall | None]:
|
|
38
|
+
return [call for call in self.call_history if not call.error]
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def failed_calls(self) -> list[WialonAPICall | None]:
|
|
42
|
+
return [call for call in self.call_history if call.error]
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def failure_rate(self) -> float:
|
|
46
|
+
return len(self.failed_calls) / self.total_calls
|
|
23
47
|
|
|
24
48
|
def call(self, action_name: str, *argc, **kwargs) -> Any:
|
|
25
|
-
self.logger.
|
|
26
|
-
self.
|
|
49
|
+
self.logger.info(f"Executing '{action_name}'...")
|
|
50
|
+
self.logger.debug(f"Executing '{action_name}' using: '{kwargs}'")
|
|
51
|
+
call_record = WialonAPICall(
|
|
52
|
+
action=action_name, timestamp=timezone.now(), args=argc, kwargs=kwargs
|
|
53
|
+
)
|
|
54
|
+
|
|
27
55
|
try:
|
|
28
|
-
|
|
56
|
+
result = super().call(action_name, *argc, **kwargs)
|
|
57
|
+
call_record.result = result
|
|
58
|
+
return result
|
|
29
59
|
except WialonError as e:
|
|
30
|
-
self.logger.
|
|
60
|
+
self.logger.warning(f"Failed to execute '{action_name}': '{e}'")
|
|
61
|
+
call_record.error = e
|
|
31
62
|
raise
|
|
63
|
+
finally:
|
|
64
|
+
self.call_history.append(call_record)
|
|
32
65
|
|
|
33
66
|
def create_logger(self, log_level: int) -> logging.Logger:
|
|
34
67
|
logger = logging.getLogger(self.__class__.__name__)
|
|
@@ -262,13 +295,13 @@ class WialonSession:
|
|
|
262
295
|
:rtype: :py:obj:`str`
|
|
263
296
|
|
|
264
297
|
"""
|
|
265
|
-
self.logger.debug("Logging into Wialon API session...")
|
|
266
298
|
try:
|
|
267
299
|
response = self.wialon_api.token_login(**{"token": token, "fl": flags})
|
|
268
300
|
self._set_login_response(response)
|
|
301
|
+
self.logger.info(f"Logged into Wialon API session '{response.get('eid')}'")
|
|
269
302
|
return response.get("eid")
|
|
270
303
|
except (WialonError, AssertionError) as e:
|
|
271
|
-
self.logger.critical(e)
|
|
304
|
+
self.logger.critical(f"Failed to login to Wialon API: '{e}'")
|
|
272
305
|
raise WialonLoginError(token, e)
|
|
273
306
|
|
|
274
307
|
def logout(self) -> None:
|
|
@@ -280,13 +313,15 @@ class WialonSession:
|
|
|
280
313
|
:rtype: :py:obj:`None`
|
|
281
314
|
|
|
282
315
|
"""
|
|
283
|
-
self.logger.debug(f"Logging out of Wialon API session '{self.id}'...")
|
|
284
316
|
response: dict = self.wialon_api.core_logout({})
|
|
285
317
|
self.logger.info(
|
|
286
|
-
f"
|
|
318
|
+
f"Logged out of session '{self.id}' after {self.wialon_api.total_calls} Wialon API calls."
|
|
287
319
|
)
|
|
320
|
+
self.logger.debug(f"Failure rate: {self.wialon_api.failure_rate}%")
|
|
288
321
|
if response.get("error") != 0:
|
|
289
|
-
self.logger.
|
|
322
|
+
self.logger.warning(
|
|
323
|
+
f"Failed to logout of session: '{response.get('message')}'"
|
|
324
|
+
)
|
|
290
325
|
raise WialonLogoutError(str(self.id))
|
|
291
326
|
|
|
292
327
|
def _set_login_response(self, login_response: dict) -> None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/authorizenet/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/authorizenet/profiles/base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/authorizenet/subscriptions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/wialon/items/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/wialon/items/notification.py
RENAMED
|
File without changes
|
{python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/wialon/items/resource.py
RENAMED
|
File without changes
|
{python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/wialon/items/retranslator.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_terminusgps-1.14.0 → python_terminusgps-1.15.1}/terminusgps/wialon/items/unit_group.py
RENAMED
|
File without changes
|
|
File without changes
|