python-terminusgps 49.3.0__tar.gz → 50.1.0__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.
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/PKG-INFO +1 -1
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/docs/source/conf.py +1 -1
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/pyproject.toml +1 -1
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/terminusgps/authorizenet/service.py +2 -3
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/terminusgps/wialon/session.py +1 -2
- python_terminusgps-50.1.0/terminusgps/wialon/utils.py +209 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/uv.lock +37 -25
- python_terminusgps-49.3.0/terminusgps/tests/authorizenet/__init__.py +0 -0
- python_terminusgps-49.3.0/terminusgps/tests/wialon/__init__.py +0 -0
- python_terminusgps-49.3.0/terminusgps/wialon/__init__.py +0 -0
- python_terminusgps-49.3.0/terminusgps/wialon/items/__init__.py +0 -1
- python_terminusgps-49.3.0/terminusgps/wialon/items/account.py +0 -217
- python_terminusgps-49.3.0/terminusgps/wialon/items/base.py +0 -272
- python_terminusgps-49.3.0/terminusgps/wialon/items/factory.py +0 -126
- python_terminusgps-49.3.0/terminusgps/wialon/items/resource.py +0 -126
- python_terminusgps-49.3.0/terminusgps/wialon/items/retranslator.py +0 -39
- python_terminusgps-49.3.0/terminusgps/wialon/items/route.py +0 -35
- python_terminusgps-49.3.0/terminusgps/wialon/items/unit.py +0 -152
- python_terminusgps-49.3.0/terminusgps/wialon/items/unit_group.py +0 -55
- python_terminusgps-49.3.0/terminusgps/wialon/items/user.py +0 -135
- python_terminusgps-49.3.0/terminusgps/wialon/utils.py +0 -417
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/.github/workflows/sphinx.yml +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/.gitignore +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/.python-version +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/COPYING +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/README.md +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/docs/Makefile +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/docs/make.bat +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/docs/requirements.txt +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/docs/source/authorizenet/api.rst +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/docs/source/authorizenet/constants.rst +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/docs/source/authorizenet/index.rst +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/docs/source/authorizenet/service.rst +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/docs/source/index.rst +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/docs/source/mixins.rst +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/docs/source/validators.rst +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/docs/source/wialon/constants.rst +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/docs/source/wialon/exceptions.rst +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/docs/source/wialon/index.rst +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/docs/source/wialon/items.rst +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/docs/source/wialon/session.rst +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/docs/source/wialon/usage.rst +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/docs/source/wialon/utils.rst +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/terminusgps/__init__.py +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/terminusgps/authorizenet/__init__.py +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/terminusgps/authorizenet/api/__init__.py +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/terminusgps/authorizenet/api/address_profiles.py +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/terminusgps/authorizenet/api/customer_profiles.py +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/terminusgps/authorizenet/api/payment_profiles.py +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/terminusgps/authorizenet/api/subscriptions.py +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/terminusgps/authorizenet/api/transactions.py +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/terminusgps/authorizenet/constants.py +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/terminusgps/default_settings.py +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/terminusgps/mixins.py +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/terminusgps/validators.py +0 -0
- {python_terminusgps-49.3.0/terminusgps/tests → python_terminusgps-50.1.0/terminusgps/wialon}/__init__.py +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/terminusgps/wialon/constants.py +0 -0
- {python_terminusgps-49.3.0 → python_terminusgps-50.1.0}/terminusgps/wialon/flags.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-terminusgps
|
|
3
|
-
Version:
|
|
3
|
+
Version: 50.1.0
|
|
4
4
|
Summary: Provides abstractions/utilities for working with Wialon API, Authorize.NET API, AWS API, and more.
|
|
5
5
|
Project-URL: Documentation, https://terminusgps.github.io/python-terminusgps
|
|
6
6
|
Project-URL: Repository, https://github.com/terminusgps/python-terminusgps
|
|
@@ -12,7 +12,7 @@ sys.path.insert(0, os.path.abspath("../../"))
|
|
|
12
12
|
project = "python-terminusgps"
|
|
13
13
|
copyright = "2025, Terminus GPS, LLC"
|
|
14
14
|
author = "Terminus GPS, LLC"
|
|
15
|
-
release = "
|
|
15
|
+
release = "50.1.0"
|
|
16
16
|
|
|
17
17
|
# -- General configuration ---------------------------------------------------
|
|
18
18
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "python-terminusgps"
|
|
3
|
-
version = "
|
|
3
|
+
version = "50.1.0"
|
|
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" } ]
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from abc import ABC
|
|
2
1
|
from functools import cached_property
|
|
3
2
|
|
|
4
3
|
from authorizenet.apicontractsv1 import merchantAuthenticationType
|
|
@@ -35,8 +34,8 @@ class AuthorizenetControllerExecutionError(Exception):
|
|
|
35
34
|
return self._code
|
|
36
35
|
|
|
37
36
|
|
|
38
|
-
class AuthorizenetService
|
|
39
|
-
"""
|
|
37
|
+
class AuthorizenetService:
|
|
38
|
+
"""Service for safely interacting with the Authorizenet API."""
|
|
40
39
|
|
|
41
40
|
REQUIRED_SETTINGS = (
|
|
42
41
|
"MERCHANT_AUTH_ENVIRONMENT",
|
|
@@ -15,8 +15,7 @@ class WialonAPIError(Exception):
|
|
|
15
15
|
try:
|
|
16
16
|
self._code = int(message._code)
|
|
17
17
|
except ValueError:
|
|
18
|
-
|
|
19
|
-
self._code = 6
|
|
18
|
+
self._code = 6 # 'Unknown Error' according to Wialon
|
|
20
19
|
return super().__init__(message, *args, **kwargs)
|
|
21
20
|
|
|
22
21
|
@property
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import secrets
|
|
2
|
+
import string
|
|
3
|
+
import typing
|
|
4
|
+
|
|
5
|
+
from terminusgps.wialon.session import WialonSession
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"generate_wialon_password",
|
|
9
|
+
"get_unit_from_iccid",
|
|
10
|
+
"get_unit_from_imei",
|
|
11
|
+
"get_units_from_carrier",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def generate_wialon_password(length: int = 32) -> str:
|
|
16
|
+
"""
|
|
17
|
+
Generates a Wialon compliant password between ``8`` and ``64`` characters.
|
|
18
|
+
|
|
19
|
+
The generated password will contain:
|
|
20
|
+
|
|
21
|
+
- At least one uppercase letter.
|
|
22
|
+
- At least one lowercase letter.
|
|
23
|
+
- At least one special symbol.
|
|
24
|
+
- At least three digits.
|
|
25
|
+
|
|
26
|
+
:param length: Length of the generated password. Default is ``32``.
|
|
27
|
+
:type length: int
|
|
28
|
+
:raises ValueError: If ``length`` was less than ``8`` or greater than ``64``.
|
|
29
|
+
:returns: A Wialon compliant password.
|
|
30
|
+
:rtype: str
|
|
31
|
+
|
|
32
|
+
"""
|
|
33
|
+
if length > 64:
|
|
34
|
+
raise ValueError(
|
|
35
|
+
f"Password cannot be greater than 64 characters in length, got {length}."
|
|
36
|
+
)
|
|
37
|
+
elif length < 8:
|
|
38
|
+
raise ValueError(
|
|
39
|
+
f"Password cannot be less than 8 characters in length, got {length}."
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
s0 = list(string.ascii_uppercase)
|
|
43
|
+
s1 = list(string.ascii_lowercase)
|
|
44
|
+
s2 = list(string.digits)
|
|
45
|
+
s3 = list("!@#$%^*()[]-_+")
|
|
46
|
+
|
|
47
|
+
while True:
|
|
48
|
+
password = "".join(
|
|
49
|
+
[secrets.choice(s0 + s1 + s2 + s3) for _ in range(length)]
|
|
50
|
+
)
|
|
51
|
+
if (
|
|
52
|
+
any(c.islower() for c in password)
|
|
53
|
+
and any(c.isupper() for c in password)
|
|
54
|
+
and sum(c.isdigit() for c in password) >= 3
|
|
55
|
+
and any(c in s3 for c in password)
|
|
56
|
+
):
|
|
57
|
+
break
|
|
58
|
+
return password
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def get_unit_from_iccid(
|
|
62
|
+
iccid: str,
|
|
63
|
+
session: WialonSession,
|
|
64
|
+
*,
|
|
65
|
+
flags: int = 1,
|
|
66
|
+
use_cache: bool = True,
|
|
67
|
+
afield_key: str = "iccid",
|
|
68
|
+
) -> dict[str, typing.Any]:
|
|
69
|
+
"""
|
|
70
|
+
Returns a Wialon unit from a telecom iccid.
|
|
71
|
+
|
|
72
|
+
:param iccid: A telecom iccid number.
|
|
73
|
+
:type iccid: str
|
|
74
|
+
:param session: A valid Wialon API session.
|
|
75
|
+
:type session: ~terminusgps.wialon.session.WialonSession
|
|
76
|
+
:param flags: Wialon API response format flags. Default is ``1``.
|
|
77
|
+
:type flags: int
|
|
78
|
+
:param use_cache: Whether to use a cached Wialon API response or force a Wialon API call. Default is :py:obj:`True`.
|
|
79
|
+
:type use_cache: bool
|
|
80
|
+
:param afield_key: Admin field key to search against. Default is ``"iccid"``.
|
|
81
|
+
:type afield_key: str
|
|
82
|
+
:raises ValueError: If multiple units were found with the provided iccid.
|
|
83
|
+
:raises ValueError: If zero units were found with the provided iccid.
|
|
84
|
+
:raises WialonAPIError: If something went wrong calling the Wialon API.
|
|
85
|
+
:returns: A Wialon unit dictionary.
|
|
86
|
+
:rtype: dict[str, ~typing.Any]
|
|
87
|
+
|
|
88
|
+
"""
|
|
89
|
+
response = session.wialon_api.core_search_items(
|
|
90
|
+
**{
|
|
91
|
+
"spec": {
|
|
92
|
+
"itemsType": "avl_unit",
|
|
93
|
+
"propName": "rel_adminfield_name,rel_adminfield_value",
|
|
94
|
+
"propValueMask": f"{afield_key},{iccid}",
|
|
95
|
+
"sortType": "sys_name",
|
|
96
|
+
"propType": "admin_fields,admin_fields",
|
|
97
|
+
},
|
|
98
|
+
"force": int(not use_cache),
|
|
99
|
+
"flags": flags,
|
|
100
|
+
"from": 0,
|
|
101
|
+
"to": 0,
|
|
102
|
+
}
|
|
103
|
+
)
|
|
104
|
+
if int(response["totalItemsCount"]) > 1:
|
|
105
|
+
raise ValueError(f"Multiple units found for iccid #{iccid}.")
|
|
106
|
+
elif int(response["totalItemsCount"]) == 0:
|
|
107
|
+
raise ValueError(f"No units found for iccid #{iccid}.")
|
|
108
|
+
return response["items"][0]
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def get_unit_from_imei(
|
|
112
|
+
imei: str,
|
|
113
|
+
session: WialonSession,
|
|
114
|
+
*,
|
|
115
|
+
flags: int = 1,
|
|
116
|
+
use_cache: bool = True,
|
|
117
|
+
) -> dict[str, typing.Any]:
|
|
118
|
+
"""
|
|
119
|
+
Returns a Wialon unit ID from an IMEI (sys_unique_id) number.
|
|
120
|
+
|
|
121
|
+
:param imei: An IMEI number.
|
|
122
|
+
:type imei: str
|
|
123
|
+
:param session: A valid Wialon API session.
|
|
124
|
+
:type session: ~terminusgps.wialon.session.WialonSession
|
|
125
|
+
:param flags: Wialon API response format flags. Default is ``1``.
|
|
126
|
+
:type flags: int
|
|
127
|
+
:param use_cache: Whether to use a cached Wialon API response or force a Wialon API call. Default is :py:obj:`True`.
|
|
128
|
+
:type use_cache: bool
|
|
129
|
+
:raises ValueError: If multiple units were found with the provided IMEI number.
|
|
130
|
+
:raises ValueError: If zero units were found with the provided IMEI number.
|
|
131
|
+
:raises WialonAPIError: If something went wrong calling the Wialon API.
|
|
132
|
+
:returns: A Wialon unit dictionary.
|
|
133
|
+
:rtype: dict[str, ~typing.Any]
|
|
134
|
+
|
|
135
|
+
"""
|
|
136
|
+
response = session.wialon_api.core_search_items(
|
|
137
|
+
**{
|
|
138
|
+
"spec": {
|
|
139
|
+
"itemsType": "avl_unit",
|
|
140
|
+
"propName": "sys_unique_id",
|
|
141
|
+
"propValueMask": imei,
|
|
142
|
+
"sortType": "sys_name",
|
|
143
|
+
"propType": "property",
|
|
144
|
+
},
|
|
145
|
+
"force": int(not use_cache),
|
|
146
|
+
"flags": flags,
|
|
147
|
+
"from": 0,
|
|
148
|
+
"to": 0,
|
|
149
|
+
}
|
|
150
|
+
)
|
|
151
|
+
if int(response["totalItemsCount"]) > 1:
|
|
152
|
+
raise ValueError(f"Multiple units found for IMEI #{imei}.")
|
|
153
|
+
elif int(response["totalItemsCount"]) == 0:
|
|
154
|
+
raise ValueError(f"No units found for IMEI #{imei}.")
|
|
155
|
+
return response["items"][0]
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def get_units_from_carrier(
|
|
159
|
+
carrier: str,
|
|
160
|
+
session: WialonSession,
|
|
161
|
+
*,
|
|
162
|
+
use_cache: bool = True,
|
|
163
|
+
afield_key: str = "carrier",
|
|
164
|
+
flags: int = 1,
|
|
165
|
+
start: int = 0,
|
|
166
|
+
end: int = 0,
|
|
167
|
+
) -> list[dict[str, typing.Any]]:
|
|
168
|
+
"""
|
|
169
|
+
Returns a list of Wialon unit IDs by telecom carrier name.
|
|
170
|
+
|
|
171
|
+
The list may be empty if no units were found.
|
|
172
|
+
|
|
173
|
+
:param carrier: A telecom carrier name.
|
|
174
|
+
:type carrier: str
|
|
175
|
+
:param session: A valid Wialon API session.
|
|
176
|
+
:type session: ~terminusgps.wialon.session.WialonSession
|
|
177
|
+
:param use_cache: Whether to use a cached Wialon API response or force a Wialon API call. Default is :py:obj:`True`.
|
|
178
|
+
:type use_cache: bool
|
|
179
|
+
:param afield_key: Admin field key to search against. Default is ``"carrier"``.
|
|
180
|
+
:type afield_key: str
|
|
181
|
+
:param flags: Wialon API response flags. Default is ``1``.
|
|
182
|
+
:type flags: int
|
|
183
|
+
:param start: Start index. Default is ``0``.
|
|
184
|
+
:type start: int
|
|
185
|
+
:param end: End index. Default is ``0``.
|
|
186
|
+
:type end: int
|
|
187
|
+
:raises WialonAPIError: If something went wrong calling the Wialon API.
|
|
188
|
+
:returns: A list of Wialon unit dictionaries.
|
|
189
|
+
:rtype: list[dict[str, ~typing.Any]]
|
|
190
|
+
|
|
191
|
+
"""
|
|
192
|
+
response = session.wialon_api.core_search_items(
|
|
193
|
+
**{
|
|
194
|
+
"spec": {
|
|
195
|
+
"itemsType": "avl_unit",
|
|
196
|
+
"propName": "rel_adminfield_name,rel_adminfield_value",
|
|
197
|
+
"propValueMask": f"{afield_key},{carrier}",
|
|
198
|
+
"sortType": "sys_name",
|
|
199
|
+
"propType": "admin_fields,admin_fields",
|
|
200
|
+
},
|
|
201
|
+
"force": int(not use_cache),
|
|
202
|
+
"flags": flags,
|
|
203
|
+
"from": start,
|
|
204
|
+
"to": end,
|
|
205
|
+
}
|
|
206
|
+
)
|
|
207
|
+
if int(response["totalItemsCount"]) == 0:
|
|
208
|
+
return []
|
|
209
|
+
return response["items"]
|
|
@@ -180,15 +180,15 @@ wheels = [
|
|
|
180
180
|
|
|
181
181
|
[[package]]
|
|
182
182
|
name = "beautifulsoup4"
|
|
183
|
-
version = "4.14.
|
|
183
|
+
version = "4.14.3"
|
|
184
184
|
source = { registry = "https://pypi.org/simple" }
|
|
185
185
|
dependencies = [
|
|
186
186
|
{ name = "soupsieve" },
|
|
187
187
|
{ name = "typing-extensions" },
|
|
188
188
|
]
|
|
189
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
189
|
+
sdist = { url = "https://files.pythonhosted.org/packages/c3/b0/1c6a16426d389813b48d95e26898aff79abbde42ad353958ad95cc8c9b21/beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86", size = 627737 }
|
|
190
190
|
wheels = [
|
|
191
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
191
|
+
{ url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721 },
|
|
192
192
|
]
|
|
193
193
|
|
|
194
194
|
[[package]]
|
|
@@ -268,21 +268,21 @@ wheels = [
|
|
|
268
268
|
|
|
269
269
|
[[package]]
|
|
270
270
|
name = "django"
|
|
271
|
-
version = "
|
|
271
|
+
version = "6.0"
|
|
272
272
|
source = { registry = "https://pypi.org/simple" }
|
|
273
273
|
dependencies = [
|
|
274
274
|
{ name = "asgiref" },
|
|
275
275
|
{ name = "sqlparse" },
|
|
276
276
|
{ name = "tzdata", marker = "sys_platform == 'win32'" },
|
|
277
277
|
]
|
|
278
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
278
|
+
sdist = { url = "https://files.pythonhosted.org/packages/15/75/19762bfc4ea556c303d9af8e36f0cd910ab17dff6c8774644314427a2120/django-6.0.tar.gz", hash = "sha256:7b0c1f50c0759bbe6331c6a39c89ae022a84672674aeda908784617ef47d8e26", size = 10932418 }
|
|
279
279
|
wheels = [
|
|
280
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
280
|
+
{ url = "https://files.pythonhosted.org/packages/d7/ae/f19e24789a5ad852670d6885f5480f5e5895576945fcc01817dfd9bc002a/django-6.0-py3-none-any.whl", hash = "sha256:1cc2c7344303bbfb7ba5070487c17f7fc0b7174bbb0a38cebf03c675f5f19b6d", size = 8339181 },
|
|
281
281
|
]
|
|
282
282
|
|
|
283
283
|
[[package]]
|
|
284
284
|
name = "django-stubs"
|
|
285
|
-
version = "5.2.
|
|
285
|
+
version = "5.2.8"
|
|
286
286
|
source = { registry = "https://pypi.org/simple" }
|
|
287
287
|
dependencies = [
|
|
288
288
|
{ name = "django" },
|
|
@@ -290,22 +290,22 @@ dependencies = [
|
|
|
290
290
|
{ name = "types-pyyaml" },
|
|
291
291
|
{ name = "typing-extensions" },
|
|
292
292
|
]
|
|
293
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
293
|
+
sdist = { url = "https://files.pythonhosted.org/packages/6c/75/97626224fd8f1787bb6f7f06944efcfddd5da7764bf741cf7f59d102f4a0/django_stubs-5.2.8.tar.gz", hash = "sha256:9bba597c9a8ed8c025cae4696803d5c8be1cf55bfc7648a084cbf864187e2f8b", size = 257709 }
|
|
294
294
|
wheels = [
|
|
295
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
295
|
+
{ url = "https://files.pythonhosted.org/packages/7d/3f/7c9543ad5ade5ce1d33d187a3abd82164570314ebee72c6206ab5c044ebf/django_stubs-5.2.8-py3-none-any.whl", hash = "sha256:a3c63119fd7062ac63d58869698d07c9e5ec0561295c4e700317c54e8d26716c", size = 508136 },
|
|
296
296
|
]
|
|
297
297
|
|
|
298
298
|
[[package]]
|
|
299
299
|
name = "django-stubs-ext"
|
|
300
|
-
version = "5.2.
|
|
300
|
+
version = "5.2.8"
|
|
301
301
|
source = { registry = "https://pypi.org/simple" }
|
|
302
302
|
dependencies = [
|
|
303
303
|
{ name = "django" },
|
|
304
304
|
{ name = "typing-extensions" },
|
|
305
305
|
]
|
|
306
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
306
|
+
sdist = { url = "https://files.pythonhosted.org/packages/14/a2/d67f4a5200ff7626b104eddceaf529761cba4ed318a73ffdb0677551be73/django_stubs_ext-5.2.8.tar.gz", hash = "sha256:b39938c46d7a547cd84e4a6378dbe51a3dd64d70300459087229e5fee27e5c6b", size = 6487 }
|
|
307
307
|
wheels = [
|
|
308
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
308
|
+
{ url = "https://files.pythonhosted.org/packages/da/2d/cb0151b780c3730cf0f2c0fcb1b065a5e88f877cf7a9217483c375353af1/django_stubs_ext-5.2.8-py3-none-any.whl", hash = "sha256:1dd5470c9675591362c78a157a3cf8aec45d0e7a7f0cf32f227a1363e54e0652", size = 9949 },
|
|
309
309
|
]
|
|
310
310
|
|
|
311
311
|
[[package]]
|
|
@@ -748,7 +748,7 @@ wheels = [
|
|
|
748
748
|
|
|
749
749
|
[[package]]
|
|
750
750
|
name = "python-terminusgps"
|
|
751
|
-
version = "
|
|
751
|
+
version = "50.1.0"
|
|
752
752
|
source = { editable = "." }
|
|
753
753
|
dependencies = [
|
|
754
754
|
{ name = "authorizenet" },
|
|
@@ -820,13 +820,25 @@ wheels = [
|
|
|
820
820
|
{ url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738 },
|
|
821
821
|
]
|
|
822
822
|
|
|
823
|
+
[[package]]
|
|
824
|
+
name = "roman-numerals"
|
|
825
|
+
version = "4.0.0"
|
|
826
|
+
source = { registry = "https://pypi.org/simple" }
|
|
827
|
+
sdist = { url = "https://files.pythonhosted.org/packages/6b/20/a6b20239f54814de5c34bf3f504e553b11780c2aad3677ad2daf989f1fb3/roman_numerals-4.0.0.tar.gz", hash = "sha256:231287018a8788bf8c0718482a08c15b90458523ea1d840a18a791a86d4583b3", size = 9027 }
|
|
828
|
+
wheels = [
|
|
829
|
+
{ url = "https://files.pythonhosted.org/packages/ad/9d/ad950fd3b65cf0974c633862320829f3d461aef125b981504277c8409a93/roman_numerals-4.0.0-py3-none-any.whl", hash = "sha256:4131feb23ba1a542494873e4cee7844ec8d226a750134efc65ceb20939ed33c9", size = 7668 },
|
|
830
|
+
]
|
|
831
|
+
|
|
823
832
|
[[package]]
|
|
824
833
|
name = "roman-numerals-py"
|
|
825
|
-
version = "
|
|
834
|
+
version = "4.0.0"
|
|
826
835
|
source = { registry = "https://pypi.org/simple" }
|
|
827
|
-
|
|
836
|
+
dependencies = [
|
|
837
|
+
{ name = "roman-numerals" },
|
|
838
|
+
]
|
|
839
|
+
sdist = { url = "https://files.pythonhosted.org/packages/7e/02/6cb667fc1872c5fe814971be2973317f0747d86f1c0aac37d0e1a1df1ecc/roman_numerals_py-4.0.0.tar.gz", hash = "sha256:f7fa8dff5b7b7251d3a7586b97c57a0698e2e28898fa42c23bcc0cf51b02aee9", size = 1119 }
|
|
828
840
|
wheels = [
|
|
829
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
841
|
+
{ url = "https://files.pythonhosted.org/packages/d2/b7/c0aa3b0154e022faa8e8b4eadda0c49f53b09b6b8d55ed3b7cd311abfd92/roman_numerals_py-4.0.0-py3-none-any.whl", hash = "sha256:dfcecf6e0cddbf2ee1112e7e2ebf58ba771984f075cb57a30e1811cee4f06332", size = 1244 },
|
|
830
842
|
]
|
|
831
843
|
|
|
832
844
|
[[package]]
|
|
@@ -979,11 +991,11 @@ wheels = [
|
|
|
979
991
|
|
|
980
992
|
[[package]]
|
|
981
993
|
name = "sqlparse"
|
|
982
|
-
version = "0.5.
|
|
994
|
+
version = "0.5.4"
|
|
983
995
|
source = { registry = "https://pypi.org/simple" }
|
|
984
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
996
|
+
sdist = { url = "https://files.pythonhosted.org/packages/18/67/701f86b28d63b2086de47c942eccf8ca2208b3be69715a1119a4e384415a/sqlparse-0.5.4.tar.gz", hash = "sha256:4396a7d3cf1cd679c1be976cf3dc6e0a51d0111e87787e7a8d780e7d5a998f9e", size = 120112 }
|
|
985
997
|
wheels = [
|
|
986
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
998
|
+
{ url = "https://files.pythonhosted.org/packages/25/70/001ee337f7aa888fb2e3f5fd7592a6afc5283adb1ed44ce8df5764070f22/sqlparse-0.5.4-py3-none-any.whl", hash = "sha256:99a9f0314977b76d776a0fcb8554de91b9bb8a18560631d6bc48721d07023dcb", size = 45933 },
|
|
987
999
|
]
|
|
988
1000
|
|
|
989
1001
|
[[package]]
|
|
@@ -1006,20 +1018,20 @@ wheels = [
|
|
|
1006
1018
|
|
|
1007
1019
|
[[package]]
|
|
1008
1020
|
name = "tzdata"
|
|
1009
|
-
version = "2025.
|
|
1021
|
+
version = "2025.3"
|
|
1010
1022
|
source = { registry = "https://pypi.org/simple" }
|
|
1011
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
1023
|
+
sdist = { url = "https://files.pythonhosted.org/packages/5e/a7/c202b344c5ca7daf398f3b8a477eeb205cf3b6f32e7ec3a6bac0629ca975/tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7", size = 196772 }
|
|
1012
1024
|
wheels = [
|
|
1013
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1025
|
+
{ url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521 },
|
|
1014
1026
|
]
|
|
1015
1027
|
|
|
1016
1028
|
[[package]]
|
|
1017
1029
|
name = "urllib3"
|
|
1018
|
-
version = "2.
|
|
1030
|
+
version = "2.6.2"
|
|
1019
1031
|
source = { registry = "https://pypi.org/simple" }
|
|
1020
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
1032
|
+
sdist = { url = "https://files.pythonhosted.org/packages/1e/24/a2a2ed9addd907787d7aa0355ba36a6cadf1768b934c652ea78acbd59dcd/urllib3-2.6.2.tar.gz", hash = "sha256:016f9c98bb7e98085cb2b4b17b87d2c702975664e4f060c6532e64d1c1a5e797", size = 432930 }
|
|
1021
1033
|
wheels = [
|
|
1022
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1034
|
+
{ url = "https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl", hash = "sha256:ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd", size = 131182 },
|
|
1023
1035
|
]
|
|
1024
1036
|
|
|
1025
1037
|
[[package]]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from .factory import WialonObjectFactory
|
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
import collections.abc
|
|
2
|
-
import decimal
|
|
3
|
-
import typing
|
|
4
|
-
|
|
5
|
-
from terminusgps.wialon.items.base import WialonObject, requires_id
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class WialonAccount(WialonObject):
|
|
9
|
-
"""A Wialon `account <https://help.wialon.com/en/wialon-hosting/user-guide/management-system/accounts-and-resources>`_."""
|
|
10
|
-
|
|
11
|
-
def create(
|
|
12
|
-
self, resource_id: int | str, billing_plan: str
|
|
13
|
-
) -> dict[str, str]:
|
|
14
|
-
"""
|
|
15
|
-
Creates the account in Wialon and sets its id.
|
|
16
|
-
|
|
17
|
-
:param resource_id: A Wialon resource id.
|
|
18
|
-
:type creator_id: int | str
|
|
19
|
-
:param billing_plan: A Wialon account billing plan.
|
|
20
|
-
:type billing_plan: str
|
|
21
|
-
:raises ValueError: If ``resource_id`` wasn't a digit.
|
|
22
|
-
:raises ~terminusgps.wialon.session.WialonAPIError: If something went wrong calling the Wialon API.
|
|
23
|
-
:returns: A Wialon object dictionary.
|
|
24
|
-
:rtype: dict[str, str]
|
|
25
|
-
|
|
26
|
-
"""
|
|
27
|
-
if isinstance(resource_id, str) and not resource_id.isdigit():
|
|
28
|
-
raise ValueError(
|
|
29
|
-
f"'resource_id' must be a digit, got '{resource_id}'."
|
|
30
|
-
)
|
|
31
|
-
response = self.session.wialon_api.account_create_account(
|
|
32
|
-
**{"itemId": resource_id, "plan": billing_plan}
|
|
33
|
-
)
|
|
34
|
-
self.id = resource_id
|
|
35
|
-
return response
|
|
36
|
-
|
|
37
|
-
@typing.override
|
|
38
|
-
@requires_id
|
|
39
|
-
def delete(
|
|
40
|
-
self, reasons: collections.abc.Collection[str] | None = None
|
|
41
|
-
) -> dict[str, str]:
|
|
42
|
-
"""
|
|
43
|
-
Deletes the account in Wialon.
|
|
44
|
-
|
|
45
|
-
:param reasons: An optional collection of reason strings. Default is :py:obj:`None`.
|
|
46
|
-
:type reasons: ~collections.abc.Collection[str] | None
|
|
47
|
-
:raises AssertionError: If the Wialon account id wasn't set.
|
|
48
|
-
:raises ~terminusgps.wialon.session.WialonAPIError: If something went wrong calling the Wialon API.
|
|
49
|
-
:returns: An empty dictionary.
|
|
50
|
-
:rtype: dict[str, str]
|
|
51
|
-
|
|
52
|
-
"""
|
|
53
|
-
return self.session.wialon_api.account_delete_account(
|
|
54
|
-
**{"itemId": self.id, "reasons": reasons}
|
|
55
|
-
if reasons is not None
|
|
56
|
-
else {"itemId": self.id}
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
@requires_id
|
|
60
|
-
def activate(self) -> dict[str, str]:
|
|
61
|
-
"""
|
|
62
|
-
Enables the account in Wialon.
|
|
63
|
-
|
|
64
|
-
:raises AssertionError: If the Wialon account id wasn't set.
|
|
65
|
-
:raises ~terminusgps.wialon.session.WialonAPIError: If something went wrong calling the Wialon API.
|
|
66
|
-
:returns: An empty dictionary.
|
|
67
|
-
:rtype: dict[str, str]
|
|
68
|
-
|
|
69
|
-
"""
|
|
70
|
-
return self.session.wialon_api.account_enable_account(
|
|
71
|
-
**{"itemId": self.id, "enable": 1}
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
@requires_id
|
|
75
|
-
def deactivate(self) -> dict[str, str]:
|
|
76
|
-
"""
|
|
77
|
-
Disables the account in Wialon.
|
|
78
|
-
|
|
79
|
-
:raises AssertionError: If the Wialon account id wasn't set.
|
|
80
|
-
:raises ~terminusgps.wialon.session.WialonAPIError: If something went wrong calling the Wialon API.
|
|
81
|
-
:returns: An empty dictionary.
|
|
82
|
-
:rtype: dict[str, str]
|
|
83
|
-
|
|
84
|
-
"""
|
|
85
|
-
return self.session.wialon_api.account_enable_account(
|
|
86
|
-
**{"itemId": self.id, "enable": 0}
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
@requires_id
|
|
90
|
-
def do_payment(
|
|
91
|
-
self,
|
|
92
|
-
balance_update: decimal.Decimal,
|
|
93
|
-
days_update: int,
|
|
94
|
-
description: str,
|
|
95
|
-
) -> dict[str, str]:
|
|
96
|
-
"""
|
|
97
|
-
Makes an account payment in Wialon.
|
|
98
|
-
|
|
99
|
-
:param balance_update: Amount to update the account balance by. Can be negative.
|
|
100
|
-
:type balance_update: ~decimal.Decimal
|
|
101
|
-
:param days_update: Amount of days to add to the account.
|
|
102
|
-
:type days_update: str
|
|
103
|
-
:param description: A description for the payment.
|
|
104
|
-
:type description: str
|
|
105
|
-
:raises AssertionError: If the Wialon account id wasn't set.
|
|
106
|
-
:raises ~terminusgps.wialon.session.WialonAPIError: If something went wrong calling the Wialon API.
|
|
107
|
-
:returns: An empty dictionary.
|
|
108
|
-
:rtype: dict[str, str]
|
|
109
|
-
|
|
110
|
-
"""
|
|
111
|
-
return self.session.wialon_api.account_do_payment(
|
|
112
|
-
**{
|
|
113
|
-
"itemId": self.id,
|
|
114
|
-
"balanceUpdate": str(balance_update),
|
|
115
|
-
"daysUpdate": days_update,
|
|
116
|
-
"description": description,
|
|
117
|
-
}
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
@requires_id
|
|
121
|
-
def set_dealer_rights(self, enabled: bool) -> dict[str, str]:
|
|
122
|
-
"""
|
|
123
|
-
Enables or disables the account's dealer rights in Wialon.
|
|
124
|
-
|
|
125
|
-
:param enabled: Whether to set the account as a dealer or not.
|
|
126
|
-
:type enabled: bool
|
|
127
|
-
:raises AssertionError: If the Wialon account id wasn't set.
|
|
128
|
-
:raises ~terminusgps.wialon.session.WialonAPIError: If something went wrong calling the Wialon API.
|
|
129
|
-
:returns: An empty dictionary.
|
|
130
|
-
:rtype: dict[str, str]
|
|
131
|
-
|
|
132
|
-
"""
|
|
133
|
-
return self.session.wialon_api.account_update_dealer_rights(
|
|
134
|
-
**{"itemId": self.id, "enable": int(enabled)}
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
@requires_id
|
|
138
|
-
def set_flags(
|
|
139
|
-
self,
|
|
140
|
-
flags: int,
|
|
141
|
-
block_balance: decimal.Decimal = decimal.Decimal("0.00"),
|
|
142
|
-
deny_balance: decimal.Decimal = decimal.Decimal("0.00"),
|
|
143
|
-
) -> dict[str, str]:
|
|
144
|
-
"""
|
|
145
|
-
Sets settings flags for the account in Wialon.
|
|
146
|
-
|
|
147
|
-
:param flags: A Wialon account settings flag integer.
|
|
148
|
-
:type flags: int
|
|
149
|
-
:param block_balance: Balance required for account blocking. Default is ``0.00``.
|
|
150
|
-
:type block_balance: ~decimal.Decimal
|
|
151
|
-
:param deny_balance: Balance required for service denial. Default is ``0.00``.
|
|
152
|
-
:type deny_balance: ~decimal.Decimal
|
|
153
|
-
:raises AssertionError: If the Wialon account id wasn't set.
|
|
154
|
-
:raises ~terminusgps.wialon.session.WialonAPIError: If something went wrong calling the Wialon API.
|
|
155
|
-
:returns: An empty dictionary.
|
|
156
|
-
:rtype: dict[str, str]
|
|
157
|
-
|
|
158
|
-
"""
|
|
159
|
-
return self.session.wialon_api.account_update_flags(
|
|
160
|
-
**{
|
|
161
|
-
"itemId": self.id,
|
|
162
|
-
"flags": flags,
|
|
163
|
-
"blockBalance": block_balance,
|
|
164
|
-
"denyBalance": deny_balance,
|
|
165
|
-
}
|
|
166
|
-
)
|
|
167
|
-
|
|
168
|
-
@requires_id
|
|
169
|
-
def set_plan(self, name: str) -> dict[str, str]:
|
|
170
|
-
"""
|
|
171
|
-
Sets the account's billing plan to ``name``.
|
|
172
|
-
|
|
173
|
-
:param name: A Wialon billing plan name.
|
|
174
|
-
:type name: str
|
|
175
|
-
:raises AssertionError: If the Wialon account id wasn't set.
|
|
176
|
-
:raises ~terminusgps.wialon.session.WialonAPIError: If something went wrong calling the Wialon API.
|
|
177
|
-
:returns: An empty dictionary.
|
|
178
|
-
:rtype: dict[str, str]
|
|
179
|
-
|
|
180
|
-
"""
|
|
181
|
-
return self.session.wialon_api.account_update_plan(
|
|
182
|
-
**{"itemId": self.id, "plan": name}
|
|
183
|
-
)
|
|
184
|
-
|
|
185
|
-
@requires_id
|
|
186
|
-
def set_minimum_days(self, days: int) -> dict[str, str]:
|
|
187
|
-
"""
|
|
188
|
-
Sets the account's minimum days to ``days`` in Wialon.
|
|
189
|
-
|
|
190
|
-
:param days: Minimum number of days as an integer.
|
|
191
|
-
:type days: int
|
|
192
|
-
:raises AssertionError: If the Wialon account id wasn't set.
|
|
193
|
-
:raises ~terminusgps.wialon.session.WialonAPIError: If something went wrong calling the Wialon API.
|
|
194
|
-
:returns: An empty dictionary.
|
|
195
|
-
:rtype: dict[str, str]
|
|
196
|
-
|
|
197
|
-
"""
|
|
198
|
-
return self.session.wialon_api.account_update_min_days(
|
|
199
|
-
**{"itemId": self.id, "minDays": days}
|
|
200
|
-
)
|
|
201
|
-
|
|
202
|
-
@requires_id
|
|
203
|
-
def get_data(self, response_type: int = 1) -> dict[str, str]:
|
|
204
|
-
"""
|
|
205
|
-
Returns account data from Wialon.
|
|
206
|
-
|
|
207
|
-
:param response_type: A response flag integer. Default is ``1``.
|
|
208
|
-
:type response_type: int
|
|
209
|
-
:raises AssertionError: If the Wialon account id wasn't set.
|
|
210
|
-
:raises ~terminusgps.wialon.session.WialonAPIError: If something went wrong calling the Wialon API.
|
|
211
|
-
:returns: A dictionary containing the account's data from Wialon.
|
|
212
|
-
:rtype: dict[str, str]
|
|
213
|
-
|
|
214
|
-
"""
|
|
215
|
-
return self.session.wialon_api.account_get_account_data(
|
|
216
|
-
**{"itemId": self.id, "type": response_type}
|
|
217
|
-
)
|