python-terminusgps 31.7.0__py3-none-any.whl → 31.7.2__py3-none-any.whl
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-31.7.0.dist-info → python_terminusgps-31.7.2.dist-info}/METADATA +2 -2
- {python_terminusgps-31.7.0.dist-info → python_terminusgps-31.7.2.dist-info}/RECORD +8 -9
- terminusgps/wialon/constants.py +27 -7
- terminusgps/wialon/session.py +45 -24
- terminusgps/wialon/tests/test_session.py +9 -7
- terminusgps/wialon/tests/test_utils.py +2 -2
- terminusgps/wialon/logger.py +0 -29
- {python_terminusgps-31.7.0.dist-info → python_terminusgps-31.7.2.dist-info}/WHEEL +0 -0
- {python_terminusgps-31.7.0.dist-info → python_terminusgps-31.7.2.dist-info}/licenses/COPYING +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-terminusgps
|
|
3
|
-
Version: 31.7.
|
|
3
|
+
Version: 31.7.2
|
|
4
4
|
Summary: Provides abstractions/utilities for working with Wialon API, Authorize.NET API, AWS API, and more.
|
|
5
5
|
Project-URL: Documentation, https://docs.terminusgps.com
|
|
6
6
|
Project-URL: Repository, https://github.com/terminusgps/python-terminusgps
|
|
@@ -16,8 +16,8 @@ Requires-Dist: argparse>=1.4.0
|
|
|
16
16
|
Requires-Dist: authorizenet>=1.1.5
|
|
17
17
|
Requires-Dist: boto3>=1.34.144
|
|
18
18
|
Requires-Dist: django>=5.1.5
|
|
19
|
+
Requires-Dist: loguru>=0.7.3
|
|
19
20
|
Requires-Dist: matplotlib>=3.10.1
|
|
20
|
-
Requires-Dist: opencv-contrib-python-headless>=4.11.0.86
|
|
21
21
|
Requires-Dist: pandas>=2.2.3
|
|
22
22
|
Requires-Dist: python-wialon>=1.2.4
|
|
23
23
|
Requires-Dist: pyzbar>=0.1.9
|
|
@@ -28,10 +28,9 @@ terminusgps/twilio/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
28
28
|
terminusgps/twilio/tests/test_caller.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
29
|
terminusgps/twilio/tests/test_validators.py,sha256=CETv7Mcr19UMMfh1UaWSV26FiOeh2WCK_VutfKXnf7g,1428
|
|
30
30
|
terminusgps/wialon/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
31
|
-
terminusgps/wialon/constants.py,sha256=
|
|
31
|
+
terminusgps/wialon/constants.py,sha256=Ju2XL2A4DPFD-w8NjYqEfnnqregl1luPT0XGhGSUnO8,6316
|
|
32
32
|
terminusgps/wialon/flags.py,sha256=M50EdhxQ8IMnJnU0mrHK7-h8Asc6tvNiTOOfd1dBW6A,12815
|
|
33
|
-
terminusgps/wialon/
|
|
34
|
-
terminusgps/wialon/session.py,sha256=SGiHH58h8d3n4dQqKrLjWKlZvNHjBqpWqK6GKofMCBo,10079
|
|
33
|
+
terminusgps/wialon/session.py,sha256=09WYWvON_H844IFfdt7_x1we6tHhQSkt9K_BEedBjv0,10396
|
|
35
34
|
terminusgps/wialon/utils.py,sha256=JWHZ7VEeo8VNBH67gjOAQk5ITKuPllWDlJ4dVSQ5blA,11002
|
|
36
35
|
terminusgps/wialon/validators.py,sha256=CVEpFsxqplEcpv4U2ipA6v9y5cSrMKFUXLvze-3vs4U,4223
|
|
37
36
|
terminusgps/wialon/items/__init__.py,sha256=3BVthghekMvhMQSzQgBMlD_phxmKSmp3Zvmo-z0O8Bs,211
|
|
@@ -44,9 +43,9 @@ terminusgps/wialon/items/unit_group.py,sha256=QV2ZZgICaN3n6W1pFIyMLyNKB6KYBsLyKG
|
|
|
44
43
|
terminusgps/wialon/items/user.py,sha256=5LgwalGO8KS_7psmAVmAlnC0S6SPBDZMOuT5ZqPKRmo,7758
|
|
45
44
|
terminusgps/wialon/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
46
45
|
terminusgps/wialon/tests/test_items.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
47
|
-
terminusgps/wialon/tests/test_session.py,sha256=
|
|
48
|
-
terminusgps/wialon/tests/test_utils.py,sha256=
|
|
49
|
-
python_terminusgps-31.7.
|
|
50
|
-
python_terminusgps-31.7.
|
|
51
|
-
python_terminusgps-31.7.
|
|
52
|
-
python_terminusgps-31.7.
|
|
46
|
+
terminusgps/wialon/tests/test_session.py,sha256=9mBlYchMo9NeqRIZsmxYzrM1zBHorqu4ooxqSNppLpI,1336
|
|
47
|
+
terminusgps/wialon/tests/test_utils.py,sha256=SK4PxJQGECFnzx_EQeRAQfsQ5_3FLaVcis2W9u_ibuI,1730
|
|
48
|
+
python_terminusgps-31.7.2.dist-info/METADATA,sha256=t9yLXs5VwoG9MV9BpmEvx5HCt-MpX2cjXumX4lT0M10,1581
|
|
49
|
+
python_terminusgps-31.7.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
50
|
+
python_terminusgps-31.7.2.dist-info/licenses/COPYING,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
51
|
+
python_terminusgps-31.7.2.dist-info/RECORD,,
|
terminusgps/wialon/constants.py
CHANGED
|
@@ -5,15 +5,35 @@ from . import flags
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class WialonGeofenceType(enum.IntEnum):
|
|
8
|
+
"""
|
|
9
|
+
A type of Wialon geofence.
|
|
10
|
+
|
|
11
|
+
`Wialon geofence type reference <https://sdk.wialon.com/wiki/en/kit/remoteapi/apiref/resource/update_zone>`_
|
|
12
|
+
|
|
13
|
+
"""
|
|
14
|
+
|
|
8
15
|
LINE = 1
|
|
16
|
+
"""Line geofence."""
|
|
9
17
|
POLYGON = 2
|
|
18
|
+
"""Polygon geofence."""
|
|
10
19
|
CIRCLE = 3
|
|
20
|
+
"""Circular geofence."""
|
|
11
21
|
|
|
12
22
|
|
|
13
23
|
class WialonMeasurementUnit(enum.IntEnum):
|
|
24
|
+
"""
|
|
25
|
+
A Wialon measurement unit.
|
|
26
|
+
|
|
27
|
+
`Wialon measurement unit reference <https://sdk.wialon.com/wiki/en/local/remoteapi1904/apiref/item/update_measure_units>`_
|
|
28
|
+
|
|
29
|
+
"""
|
|
30
|
+
|
|
14
31
|
METRIC = 0
|
|
32
|
+
"""Metric system."""
|
|
15
33
|
US = 1
|
|
34
|
+
"""US measurement system."""
|
|
16
35
|
IMPERIAL = 2
|
|
36
|
+
"""Imperial measurement system."""
|
|
17
37
|
|
|
18
38
|
|
|
19
39
|
class WialonItemsType(enum.StrEnum):
|
|
@@ -25,19 +45,19 @@ class WialonItemsType(enum.StrEnum):
|
|
|
25
45
|
"""
|
|
26
46
|
|
|
27
47
|
HARDWARE = "avl_hw"
|
|
28
|
-
"""
|
|
48
|
+
"""A hardware type."""
|
|
29
49
|
RESOURCE = "avl_resource"
|
|
30
|
-
"""
|
|
50
|
+
"""A resource."""
|
|
31
51
|
RETRANSLATOR = "avl_retranslator"
|
|
32
|
-
"""
|
|
52
|
+
"""A retranslator."""
|
|
33
53
|
ROUTE = "avl_route"
|
|
34
|
-
"""
|
|
54
|
+
"""A route."""
|
|
35
55
|
UNIT = "avl_unit"
|
|
36
|
-
"""
|
|
56
|
+
"""A unit."""
|
|
37
57
|
UNIT_GROUP = "avl_unit_group"
|
|
38
|
-
"""
|
|
58
|
+
"""A unit group."""
|
|
39
59
|
USER = "user"
|
|
40
|
-
"""
|
|
60
|
+
"""A user."""
|
|
41
61
|
|
|
42
62
|
|
|
43
63
|
class WialonItemProperty(enum.StrEnum):
|
terminusgps/wialon/session.py
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import dataclasses
|
|
2
2
|
import datetime
|
|
3
|
-
import logging
|
|
4
3
|
import typing
|
|
5
4
|
|
|
6
5
|
import wialon.api
|
|
7
6
|
from django.conf import settings
|
|
8
7
|
from django.utils import timezone
|
|
9
|
-
|
|
10
|
-
from terminusgps.wialon.logger import WialonLogger
|
|
8
|
+
from loguru import logger
|
|
11
9
|
|
|
12
10
|
|
|
13
11
|
@dataclasses.dataclass
|
|
@@ -21,12 +19,17 @@ class WialonAPICall:
|
|
|
21
19
|
|
|
22
20
|
|
|
23
21
|
class Wialon(wialon.api.Wialon):
|
|
24
|
-
def __init__(
|
|
22
|
+
def __init__(
|
|
23
|
+
self, log_level: int = 10, log_days: int = 10, *args, **kwargs
|
|
24
|
+
) -> None:
|
|
25
25
|
super().__init__(*args, **kwargs)
|
|
26
26
|
self.call_history: list[WialonAPICall] = []
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
logger.add(
|
|
28
|
+
f"logs/{self.__class__.__name__}.log",
|
|
29
|
+
level=log_level,
|
|
30
|
+
retention=f"{log_days} days",
|
|
31
|
+
diagnose=settings.DEBUG,
|
|
32
|
+
)
|
|
30
33
|
|
|
31
34
|
@property
|
|
32
35
|
def total_calls(self) -> int:
|
|
@@ -37,7 +40,7 @@ class Wialon(wialon.api.Wialon):
|
|
|
37
40
|
return self.call("token_login", *args, **kwargs)
|
|
38
41
|
|
|
39
42
|
def call(self, action_name: str, *argc, **kwargs) -> typing.Any:
|
|
40
|
-
|
|
43
|
+
logger.debug(f"Executing '{action_name}'...")
|
|
41
44
|
call_record = WialonAPICall(
|
|
42
45
|
action=action_name, timestamp=timezone.now(), args=argc, kwargs=kwargs
|
|
43
46
|
)
|
|
@@ -45,11 +48,11 @@ class Wialon(wialon.api.Wialon):
|
|
|
45
48
|
try:
|
|
46
49
|
result = super().call(action_name, *argc, **kwargs)
|
|
47
50
|
call_record.result = result
|
|
48
|
-
|
|
51
|
+
logger.debug(f"Executed '{action_name}' successfully.")
|
|
49
52
|
return result
|
|
50
53
|
except wialon.api.WialonError as e:
|
|
51
54
|
call_record.error = e
|
|
52
|
-
|
|
55
|
+
logger.warning(f"Failed to execute '{action_name}': '{e}'")
|
|
53
56
|
return
|
|
54
57
|
finally:
|
|
55
58
|
self.call_history.append(call_record)
|
|
@@ -63,7 +66,8 @@ class WialonSession:
|
|
|
63
66
|
scheme: str = "https",
|
|
64
67
|
host: str = "hst-api.wialon.com",
|
|
65
68
|
port: int = 443,
|
|
66
|
-
log_level: int =
|
|
69
|
+
log_level: int = 10,
|
|
70
|
+
log_days: int = 10,
|
|
67
71
|
) -> None:
|
|
68
72
|
"""
|
|
69
73
|
Starts or continues a Wialon API session.
|
|
@@ -78,13 +82,19 @@ class WialonSession:
|
|
|
78
82
|
:type host: :py:obj:`str`
|
|
79
83
|
:param port: Wialon API host port. Default is ``443``.
|
|
80
84
|
:type port: :py:obj:`int`
|
|
81
|
-
:param log_level:
|
|
85
|
+
:param log_level: Level of emitted logs. Default is ``10``.
|
|
82
86
|
:type log_level: :py:obj:`int`
|
|
83
87
|
:returns: Nothing.
|
|
84
88
|
:rtype: :py:obj:`None`
|
|
85
89
|
|
|
86
90
|
"""
|
|
87
91
|
|
|
92
|
+
logger.add(
|
|
93
|
+
f"logs/{self.__class__.__name__}.log",
|
|
94
|
+
level=log_level,
|
|
95
|
+
retention=f"{log_days} days",
|
|
96
|
+
diagnose=settings.DEBUG,
|
|
97
|
+
)
|
|
88
98
|
self._token = token or settings.WIALON_TOKEN
|
|
89
99
|
self._username = None
|
|
90
100
|
self._gis_sid = None
|
|
@@ -92,11 +102,13 @@ class WialonSession:
|
|
|
92
102
|
self._wsdk_version = None
|
|
93
103
|
self._uid = None
|
|
94
104
|
self.wialon_api = Wialon(
|
|
95
|
-
scheme=scheme,
|
|
105
|
+
scheme=scheme,
|
|
106
|
+
host=host,
|
|
107
|
+
port=port,
|
|
108
|
+
sid=sid,
|
|
109
|
+
log_level=log_level,
|
|
110
|
+
log_days=log_days,
|
|
96
111
|
)
|
|
97
|
-
self.logger = WialonLogger(
|
|
98
|
-
logging.getLogger(self.__class__.__name__), level=log_level
|
|
99
|
-
).get_logger()
|
|
100
112
|
|
|
101
113
|
def __str__(self) -> str:
|
|
102
114
|
return str(self.id)
|
|
@@ -127,6 +139,17 @@ class WialonSession:
|
|
|
127
139
|
"""
|
|
128
140
|
self.logout()
|
|
129
141
|
|
|
142
|
+
@property
|
|
143
|
+
def active(self) -> bool:
|
|
144
|
+
"""
|
|
145
|
+
Whether or not the session is logged in.
|
|
146
|
+
|
|
147
|
+
:type: :py:obj:`bool`
|
|
148
|
+
:value: :py:obj:`False`
|
|
149
|
+
|
|
150
|
+
"""
|
|
151
|
+
return bool(self.id)
|
|
152
|
+
|
|
130
153
|
@property
|
|
131
154
|
def gis_geocode(self) -> str | None:
|
|
132
155
|
"""
|
|
@@ -288,13 +311,13 @@ class WialonSession:
|
|
|
288
311
|
|
|
289
312
|
"""
|
|
290
313
|
try:
|
|
291
|
-
|
|
314
|
+
logger.debug("Logging into Wialon API session...")
|
|
292
315
|
response = self.wialon_api.token_login(**{"token": token, "fl": flags})
|
|
293
316
|
self._set_login_response(response)
|
|
294
|
-
|
|
317
|
+
logger.debug(f"Logged into Wialon API session '{response.get('eid')}'")
|
|
295
318
|
return response.get("eid")
|
|
296
319
|
except (wialon.api.WialonError, AssertionError) as e:
|
|
297
|
-
|
|
320
|
+
logger.critical(f"Failed to login to Wialon API: '{e}'")
|
|
298
321
|
raise
|
|
299
322
|
|
|
300
323
|
def logout(self) -> None:
|
|
@@ -305,16 +328,14 @@ class WialonSession:
|
|
|
305
328
|
:rtype: :py:obj:`None`
|
|
306
329
|
|
|
307
330
|
"""
|
|
308
|
-
|
|
331
|
+
logger.debug("Logging out of Wialon API session...")
|
|
309
332
|
response: dict = self.wialon_api.core_logout({})
|
|
310
333
|
self.wialon_api.sid = None
|
|
311
334
|
|
|
312
335
|
if response.get("error") != 0:
|
|
313
|
-
|
|
314
|
-
f"Failed to logout of session: '{response.get('message')}'"
|
|
315
|
-
)
|
|
336
|
+
logger.warning(f"Failed to logout of session: '{response.get('message')}'")
|
|
316
337
|
else:
|
|
317
|
-
|
|
338
|
+
logger.debug(
|
|
318
339
|
f"Logged out after {self.wialon_api.total_calls} Wialon API calls."
|
|
319
340
|
)
|
|
320
341
|
|
|
@@ -1,18 +1,22 @@
|
|
|
1
|
+
import os
|
|
1
2
|
import unittest
|
|
2
3
|
|
|
3
4
|
from django.conf import settings
|
|
4
5
|
|
|
5
|
-
from
|
|
6
|
+
from terminusgps.wialon.session import WialonSession
|
|
7
|
+
|
|
8
|
+
TEST_WIALON_TOKEN = os.getenv("WIALON_TOKEN") or settings.WIALON_TOKEN
|
|
6
9
|
|
|
7
10
|
|
|
8
11
|
class WialonSessionTestCase(unittest.TestCase):
|
|
9
12
|
def setUp(self) -> None:
|
|
10
|
-
|
|
11
|
-
self.fail("'WIALON_TOKEN' setting is required.")
|
|
12
|
-
|
|
13
|
-
self.token = settings.WIALON_TOKEN
|
|
13
|
+
self.token = TEST_WIALON_TOKEN
|
|
14
14
|
self.session = WialonSession()
|
|
15
15
|
|
|
16
|
+
def tearDown(self) -> None:
|
|
17
|
+
if self.session.active:
|
|
18
|
+
self.session.logout()
|
|
19
|
+
|
|
16
20
|
def test_session_init(self) -> None:
|
|
17
21
|
self.assertIsNone(self.session.id)
|
|
18
22
|
self.assertIsNone(self.session.username)
|
|
@@ -31,10 +35,8 @@ class WialonSessionTestCase(unittest.TestCase):
|
|
|
31
35
|
self.session.login(self.token)
|
|
32
36
|
response = self.session.wialon_api.core_bad_call({})
|
|
33
37
|
self.assertIsNone(response)
|
|
34
|
-
self.session.logout()
|
|
35
38
|
|
|
36
39
|
def test_session_valid_call_count(self) -> None:
|
|
37
40
|
self.session.login(self.token) # Login/logout does not count
|
|
38
41
|
self.session.wialon_api.avl_evts()
|
|
39
42
|
self.assertEqual(self.session.wialon_api.total_calls, 1)
|
|
40
|
-
self.session.logout()
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import string
|
|
2
2
|
import unittest
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
from .. import utils
|
|
4
|
+
from terminusgps.wialon import utils
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
class WialonUtilsTestCase(unittest.TestCase):
|
|
@@ -35,6 +34,7 @@ class WialonUtilsTestCase(unittest.TestCase):
|
|
|
35
34
|
self.fail("Generated password did not contain an uppercase letter.")
|
|
36
35
|
if not any([c for c in password if c in s1]):
|
|
37
36
|
self.fail("Generated password did not contain a lowercase letter.")
|
|
37
|
+
# TODO: Make this check for 3 digits
|
|
38
38
|
if not any([c for c in password if c in s2]):
|
|
39
39
|
self.fail("Generated password did not contain a digit.")
|
|
40
40
|
if not any([c for c in password if c in s3]):
|
terminusgps/wialon/logger.py
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class WialonLogger:
|
|
5
|
-
def __init__(
|
|
6
|
-
self,
|
|
7
|
-
logger: logging.Logger,
|
|
8
|
-
level: int = logging.DEBUG,
|
|
9
|
-
format: str = "%(name)s - %(levelname)s - %(asctime)s - %(message)s",
|
|
10
|
-
use_stream_handler: bool = True,
|
|
11
|
-
use_file_handler: bool = False,
|
|
12
|
-
filename: str = "wialon_debug.log",
|
|
13
|
-
) -> None:
|
|
14
|
-
self.logger = logger
|
|
15
|
-
self.logger.setLevel(level)
|
|
16
|
-
formatter = logging.Formatter(format)
|
|
17
|
-
|
|
18
|
-
if use_stream_handler and not self.logger.handlers:
|
|
19
|
-
stream_handler = logging.StreamHandler()
|
|
20
|
-
stream_handler.setFormatter(formatter)
|
|
21
|
-
self.logger.addHandler(stream_handler)
|
|
22
|
-
|
|
23
|
-
if use_file_handler and not self.logger.handlers:
|
|
24
|
-
file_handler = logging.FileHandler(filename)
|
|
25
|
-
file_handler.setFormatter(formatter)
|
|
26
|
-
self.logger.addHandler(file_handler)
|
|
27
|
-
|
|
28
|
-
def get_logger(self) -> logging.Logger:
|
|
29
|
-
return self.logger
|
|
File without changes
|
{python_terminusgps-31.7.0.dist-info → python_terminusgps-31.7.2.dist-info}/licenses/COPYING
RENAMED
|
File without changes
|