python-terminusgps 49.2.0__tar.gz → 50.0.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.
Files changed (58) hide show
  1. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/PKG-INFO +1 -1
  2. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/docs/source/conf.py +1 -1
  3. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/pyproject.toml +1 -1
  4. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/terminusgps/authorizenet/constants.py +18 -0
  5. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/terminusgps/wialon/session.py +1 -2
  6. python_terminusgps-50.0.0/terminusgps/wialon/utils.py +180 -0
  7. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/uv.lock +25 -25
  8. python_terminusgps-49.2.0/terminusgps/tests/authorizenet/__init__.py +0 -0
  9. python_terminusgps-49.2.0/terminusgps/tests/wialon/__init__.py +0 -0
  10. python_terminusgps-49.2.0/terminusgps/wialon/__init__.py +0 -0
  11. python_terminusgps-49.2.0/terminusgps/wialon/items/__init__.py +0 -1
  12. python_terminusgps-49.2.0/terminusgps/wialon/items/account.py +0 -217
  13. python_terminusgps-49.2.0/terminusgps/wialon/items/base.py +0 -272
  14. python_terminusgps-49.2.0/terminusgps/wialon/items/factory.py +0 -126
  15. python_terminusgps-49.2.0/terminusgps/wialon/items/resource.py +0 -126
  16. python_terminusgps-49.2.0/terminusgps/wialon/items/retranslator.py +0 -39
  17. python_terminusgps-49.2.0/terminusgps/wialon/items/route.py +0 -35
  18. python_terminusgps-49.2.0/terminusgps/wialon/items/unit.py +0 -152
  19. python_terminusgps-49.2.0/terminusgps/wialon/items/unit_group.py +0 -55
  20. python_terminusgps-49.2.0/terminusgps/wialon/items/user.py +0 -135
  21. python_terminusgps-49.2.0/terminusgps/wialon/utils.py +0 -417
  22. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/.github/workflows/sphinx.yml +0 -0
  23. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/.gitignore +0 -0
  24. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/.python-version +0 -0
  25. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/COPYING +0 -0
  26. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/README.md +0 -0
  27. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/docs/Makefile +0 -0
  28. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/docs/make.bat +0 -0
  29. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/docs/requirements.txt +0 -0
  30. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/docs/source/authorizenet/api.rst +0 -0
  31. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/docs/source/authorizenet/constants.rst +0 -0
  32. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/docs/source/authorizenet/index.rst +0 -0
  33. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/docs/source/authorizenet/service.rst +0 -0
  34. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/docs/source/index.rst +0 -0
  35. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/docs/source/mixins.rst +0 -0
  36. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/docs/source/validators.rst +0 -0
  37. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/docs/source/wialon/constants.rst +0 -0
  38. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/docs/source/wialon/exceptions.rst +0 -0
  39. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/docs/source/wialon/index.rst +0 -0
  40. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/docs/source/wialon/items.rst +0 -0
  41. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/docs/source/wialon/session.rst +0 -0
  42. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/docs/source/wialon/usage.rst +0 -0
  43. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/docs/source/wialon/utils.rst +0 -0
  44. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/terminusgps/__init__.py +0 -0
  45. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/terminusgps/authorizenet/__init__.py +0 -0
  46. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/terminusgps/authorizenet/api/__init__.py +0 -0
  47. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/terminusgps/authorizenet/api/address_profiles.py +0 -0
  48. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/terminusgps/authorizenet/api/customer_profiles.py +0 -0
  49. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/terminusgps/authorizenet/api/payment_profiles.py +0 -0
  50. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/terminusgps/authorizenet/api/subscriptions.py +0 -0
  51. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/terminusgps/authorizenet/api/transactions.py +0 -0
  52. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/terminusgps/authorizenet/service.py +0 -0
  53. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/terminusgps/default_settings.py +0 -0
  54. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/terminusgps/mixins.py +0 -0
  55. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/terminusgps/validators.py +0 -0
  56. {python_terminusgps-49.2.0/terminusgps/tests → python_terminusgps-50.0.0/terminusgps/wialon}/__init__.py +0 -0
  57. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/terminusgps/wialon/constants.py +0 -0
  58. {python_terminusgps-49.2.0 → python_terminusgps-50.0.0}/terminusgps/wialon/flags.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-terminusgps
3
- Version: 49.2.0
3
+ Version: 50.0.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 = "49.2.0"
15
+ release = "50.0.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 = "49.2.0"
3
+ version = "50.0.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" } ]
@@ -4,6 +4,24 @@ from django.db import models
4
4
  from django.utils.translation import gettext_lazy as _
5
5
 
6
6
 
7
+ class BankAccountType(models.TextChoices):
8
+ CHECKING = "checking", _("Checking account")
9
+ """Checking account."""
10
+ SAVINGS = "savings", _("Savings account")
11
+ """Savings account."""
12
+ BUSINESS_CHECKING = "businessChecking", _("Business checking account")
13
+ """Business checking account."""
14
+
15
+
16
+ class ECheckType(models.TextChoices):
17
+ PPD = "PPD", _("Prearranged Payment and Deposit Entry")
18
+ """Prearranged Payment and Deposit Entry."""
19
+ TEL = "TEL", _("Telephone-Initiated Entry")
20
+ """Telephone-Initiated Entry."""
21
+ WEB = "WEB", _("Web-Initiated Entry")
22
+ """Web-Initiated Entry."""
23
+
24
+
7
25
  class CreditCardType(models.TextChoices):
8
26
  AMEX = apicontractsv1.cardTypeEnum.AmericanExpress, _("American Express")
9
27
  """American express card."""
@@ -15,8 +15,7 @@ class WialonAPIError(Exception):
15
15
  try:
16
16
  self._code = int(message._code)
17
17
  except ValueError:
18
- # 6 = 'Unknown Error' according to Wialon
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,180 @@
1
+ import secrets
2
+ import string
3
+
4
+ from terminusgps.wialon.session import WialonSession
5
+
6
+
7
+ def get_id_from_iccid(
8
+ iccid: str,
9
+ session: WialonSession,
10
+ *,
11
+ use_cache: bool = True,
12
+ afield_key: str = "iccid",
13
+ ) -> int | None:
14
+ """
15
+ Returns a Wialon unit ID from a telecom iccid.
16
+
17
+ :param iccid: A telecom iccid number.
18
+ :type iccid: str
19
+ :param session: A valid Wialon API session.
20
+ :type session: ~terminusgps.wialon.session.WialonSession
21
+ :param use_cache: Whether to use a cached Wialon API response or force a Wialon API call. Default is :py:obj:`True`.
22
+ :type use_cache: bool
23
+ :param afield_key: Admin field key to search against. Default is ``"iccid"``.
24
+ :type afield_key: str
25
+ :raises ValueError: If multiple units were found with the provided iccid.
26
+ :raises ValueError: If zero units were found with the provided iccid.
27
+ :returns: A Wialon unit ID, if found.
28
+ :rtype: int | None
29
+
30
+ """
31
+ response = session.wialon_api.core_search_items(
32
+ **{
33
+ "spec": {
34
+ "itemsType": "avl_unit",
35
+ "propName": "rel_adminfield_name,rel_adminfield_value",
36
+ "propValueMask": f"{afield_key},{iccid}",
37
+ "sortType": "sys_name",
38
+ "propType": "admin_fields,admin_fields",
39
+ },
40
+ "force": int(not use_cache),
41
+ "flags": 1,
42
+ "from": 0,
43
+ "to": 0,
44
+ }
45
+ )
46
+ if int(response["totalItemsCount"]) > 1:
47
+ raise ValueError(f"Multiple units found for iccid #{iccid}.")
48
+ elif int(response["totalItemsCount"]) == 0:
49
+ raise ValueError(f"No units found for iccid #{iccid}.")
50
+ return int(response["items"][0]["id"])
51
+
52
+
53
+ def get_id_from_imei(
54
+ imei: str, session: WialonSession, *, use_cache: bool = True
55
+ ) -> int | None:
56
+ """
57
+ Returns a Wialon unit ID from an IMEI (sys_unique_id) number.
58
+
59
+ :param imei: An IMEI number.
60
+ :type imei: str
61
+ :param session: A valid Wialon API session.
62
+ :type session: ~terminusgps.wialon.session.WialonSession
63
+ :param use_cache: Whether to use a cached Wialon API response or force a Wialon API call. Default is :py:obj:`True`.
64
+ :type use_cache: bool
65
+ :raises ValueError: If multiple units were found with the provided IMEI number.
66
+ :raises ValueError: If zero units were found with the provided IMEI number.
67
+ :returns: A Wialon unit ID, if found.
68
+ :rtype: int | None
69
+
70
+ """
71
+ response = session.wialon_api.core_search_items(
72
+ **{
73
+ "spec": {
74
+ "itemsType": "avl_unit",
75
+ "propName": "sys_unique_id",
76
+ "propValueMask": imei,
77
+ "sortType": "sys_name",
78
+ "propType": "property",
79
+ },
80
+ "force": int(not use_cache),
81
+ "flags": 1,
82
+ "from": 0,
83
+ "to": 0,
84
+ }
85
+ )
86
+ if int(response["totalItemsCount"]) > 1:
87
+ raise ValueError(f"Multiple units found for IMEI #{imei}.")
88
+ elif int(response["totalItemsCount"]) == 0:
89
+ raise ValueError(f"No units found for IMEI #{imei}.")
90
+ return int(response["items"][0]["id"])
91
+
92
+
93
+ def get_ids_from_carrier(
94
+ carrier: str,
95
+ session: WialonSession,
96
+ *,
97
+ use_cache: bool = True,
98
+ afield_key: str = "carrier",
99
+ ) -> list[int]:
100
+ """
101
+ Returns a list of Wialon unit IDs by telecom carrier name.
102
+
103
+ The list may be empty if no units were found.
104
+
105
+ :param carrier: A telecom carrier name.
106
+ :type carrier: str
107
+ :param session: A valid Wialon API session.
108
+ :type session: ~terminusgps.wialon.session.WialonSession
109
+ :param use_cache: Whether to use a cached Wialon API response or force a Wialon API call. Default is :py:obj:`True`.
110
+ :type use_cache: bool
111
+ :param afield_key: Admin field key to search against. Default is ``"carrier"``.
112
+ :type afield_key: str
113
+ :returns: A list of Wialon unit IDs, if any were found.
114
+ :rtype: list[int]
115
+
116
+ """
117
+ response = session.wialon_api.core_search_items(
118
+ **{
119
+ "spec": {
120
+ "itemsType": "avl_unit",
121
+ "propName": "rel_adminfield_name,rel_adminfield_value",
122
+ "propValueMask": f"{afield_key},{carrier}",
123
+ "sortType": "sys_name",
124
+ "propType": "admin_fields,admin_fields",
125
+ },
126
+ "force": int(not use_cache),
127
+ "flags": 1,
128
+ "from": 0,
129
+ "to": 0,
130
+ }
131
+ )
132
+ if int(response["totalItemsCount"]) == 0:
133
+ return []
134
+ return [int(unit["id"]) for unit in response["items"]]
135
+
136
+
137
+ def generate_wialon_password(length: int = 32) -> str:
138
+ """
139
+ Generates a Wialon compliant password between ``8`` and ``64`` characters.
140
+
141
+ The generated password will contain:
142
+
143
+ - At least one uppercase letter.
144
+ - At least one lowercase letter.
145
+ - At least one special symbol.
146
+ - At least three digits.
147
+
148
+ :param length: Length of the generated password. Default is ``32``.
149
+ :type length: int
150
+ :raises ValueError: If ``length`` was less than ``8`` or greater than ``64``.
151
+ :returns: A Wialon compliant password.
152
+ :rtype: str
153
+
154
+ """
155
+ if length > 64:
156
+ raise ValueError(
157
+ f"Password cannot be greater than 64 characters in length, got {length}."
158
+ )
159
+ elif length < 8:
160
+ raise ValueError(
161
+ f"Password cannot be less than 8 characters in length, got {length}."
162
+ )
163
+
164
+ s0 = list(string.ascii_uppercase)
165
+ s1 = list(string.ascii_lowercase)
166
+ s2 = list(string.digits)
167
+ s3 = list("!@#$%^*()[]-_+")
168
+
169
+ while True:
170
+ password = "".join(
171
+ [secrets.choice(s0 + s1 + s2 + s3) for _ in range(length)]
172
+ )
173
+ if (
174
+ any(c.islower() for c in password)
175
+ and any(c.isupper() for c in password)
176
+ and sum(c.isdigit() for c in password) >= 3
177
+ and any(c in s3 for c in password)
178
+ ):
179
+ break
180
+ return password
@@ -128,11 +128,11 @@ wheels = [
128
128
 
129
129
  [[package]]
130
130
  name = "asgiref"
131
- version = "3.10.0"
131
+ version = "3.11.0"
132
132
  source = { registry = "https://pypi.org/simple" }
133
- sdist = { url = "https://files.pythonhosted.org/packages/46/08/4dfec9b90758a59acc6be32ac82e98d1fbfc321cb5cfa410436dbacf821c/asgiref-3.10.0.tar.gz", hash = "sha256:d89f2d8cd8b56dada7d52fa7dc8075baa08fb836560710d38c292a7a3f78c04e", size = 37483 }
133
+ sdist = { url = "https://files.pythonhosted.org/packages/76/b9/4db2509eabd14b4a8c71d1b24c8d5734c52b8560a7b1e1a8b56c8d25568b/asgiref-3.11.0.tar.gz", hash = "sha256:13acff32519542a1736223fb79a715acdebe24286d98e8b164a73085f40da2c4", size = 37969 }
134
134
  wheels = [
135
- { url = "https://files.pythonhosted.org/packages/17/9c/fc2331f538fbf7eedba64b2052e99ccf9ba9d6888e2f41441ee28847004b/asgiref-3.10.0-py3-none-any.whl", hash = "sha256:aef8a81283a34d0ab31630c9b7dfe70c812c95eba78171367ca8745e88124734", size = 24050 },
135
+ { url = "https://files.pythonhosted.org/packages/91/be/317c2c55b8bbec407257d45f5c8d1b6867abc76d12043f2d3d58c538a4ea/asgiref-3.11.0-py3-none-any.whl", hash = "sha256:1db9021efadb0d9512ce8ffaf72fcef601c7b73a8807a1bb2ef143dc6b14846d", size = 24096 },
136
136
  ]
137
137
 
138
138
  [[package]]
@@ -180,15 +180,15 @@ wheels = [
180
180
 
181
181
  [[package]]
182
182
  name = "beautifulsoup4"
183
- version = "4.14.2"
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/77/e9/df2358efd7659577435e2177bfa69cba6c33216681af51a707193dec162a/beautifulsoup4-4.14.2.tar.gz", hash = "sha256:2a98ab9f944a11acee9cc848508ec28d9228abfd522ef0fad6a02a72e0ded69e", size = 625822 }
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/94/fe/3aed5d0be4d404d12d36ab97e2f1791424d9ca39c2f754a6285d59a3b01d/beautifulsoup4-4.14.2-py3-none-any.whl", hash = "sha256:5ef6fa3a8cbece8488d66985560f97ed091e22bbc4e9c2338508a9d5de6d4515", size = 106392 },
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 = "5.2.8"
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/05/a2/933dbbb3dd9990494960f6e64aca2af4c0745b63b7113f59a822df92329e/django-5.2.8.tar.gz", hash = "sha256:23254866a5bb9a2cfa6004e8b809ec6246eba4b58a7589bc2772f1bcc8456c7f", size = 10849032 }
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/5e/3d/a035a4ee9b1d4d4beee2ae6e8e12fe6dee5514b21f62504e22efcbd9fb46/django-5.2.8-py3-none-any.whl", hash = "sha256:37e687f7bd73ddf043e2b6b97cfe02fcbb11f2dbb3adccc6a2b18c6daa054d7f", size = 8289692 },
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.7"
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/5d/a8/bc8c55212978f1e666486b60a4bfb0bc3a066de8212fa7389ff0f3dca639/django_stubs-5.2.7.tar.gz", hash = "sha256:2a07e47a8a867836a763c6bba8bf3775847b4fd9555bfa940360e32d0ee384a1", size = 257339 }
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/ad/66/1c8063eee88a943f01d073dbbbda34ed093bf6e19738178506a66abbd5ad/django_stubs-5.2.7-py3-none-any.whl", hash = "sha256:2864e74b56ead866ff1365a051f24d852f6ed02238959664f558a6c9601c95bf", size = 507733 },
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.7"
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/9b/6f/a0bab0e6a7676ab3ca02d51b459444e9bd6dd747e3a43b9c24cae6d0a1c6/django_stubs_ext-5.2.7.tar.gz", hash = "sha256:b690655bd4cb8a44ae57abb314e0995dc90414280db8f26fff0cb9fb367d1cac", size = 6524 }
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/f8/c9/60445606e26706d3fccadf3b80ee1a9f32c1012683ff2ada7580937b2da9/django_stubs_ext-5.2.7-py3-none-any.whl", hash = "sha256:0466a7132587d49c5bbe12082ac9824d117a0dedcad5d0ada75a6e0d3aca6f60", size = 9979 },
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 = "49.2.0"
751
+ version = "50.0.0"
752
752
  source = { editable = "." }
753
753
  dependencies = [
754
754
  { name = "authorizenet" },
@@ -979,11 +979,11 @@ wheels = [
979
979
 
980
980
  [[package]]
981
981
  name = "sqlparse"
982
- version = "0.5.3"
982
+ version = "0.5.4"
983
983
  source = { registry = "https://pypi.org/simple" }
984
- sdist = { url = "https://files.pythonhosted.org/packages/e5/40/edede8dd6977b0d3da179a342c198ed100dd2aba4be081861ee5911e4da4/sqlparse-0.5.3.tar.gz", hash = "sha256:09f67787f56a0b16ecdbde1bfc7f5d9c3371ca683cfeaa8e6ff60b4807ec9272", size = 84999 }
984
+ sdist = { url = "https://files.pythonhosted.org/packages/18/67/701f86b28d63b2086de47c942eccf8ca2208b3be69715a1119a4e384415a/sqlparse-0.5.4.tar.gz", hash = "sha256:4396a7d3cf1cd679c1be976cf3dc6e0a51d0111e87787e7a8d780e7d5a998f9e", size = 120112 }
985
985
  wheels = [
986
- { url = "https://files.pythonhosted.org/packages/a9/5c/bfd6bd0bf979426d405cc6e71eceb8701b148b16c21d2dc3c261efc61c7b/sqlparse-0.5.3-py3-none-any.whl", hash = "sha256:cf2196ed3418f3ba5de6af7e82c694a9fbdbfecccdfc72e281548517081f16ca", size = 44415 },
986
+ { url = "https://files.pythonhosted.org/packages/25/70/001ee337f7aa888fb2e3f5fd7592a6afc5283adb1ed44ce8df5764070f22/sqlparse-0.5.4-py3-none-any.whl", hash = "sha256:99a9f0314977b76d776a0fcb8554de91b9bb8a18560631d6bc48721d07023dcb", size = 45933 },
987
987
  ]
988
988
 
989
989
  [[package]]
@@ -1006,20 +1006,20 @@ wheels = [
1006
1006
 
1007
1007
  [[package]]
1008
1008
  name = "tzdata"
1009
- version = "2025.2"
1009
+ version = "2025.3"
1010
1010
  source = { registry = "https://pypi.org/simple" }
1011
- sdist = { url = "https://files.pythonhosted.org/packages/95/32/1a225d6164441be760d75c2c42e2780dc0873fe382da3e98a2e1e48361e5/tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9", size = 196380 }
1011
+ sdist = { url = "https://files.pythonhosted.org/packages/5e/a7/c202b344c5ca7daf398f3b8a477eeb205cf3b6f32e7ec3a6bac0629ca975/tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7", size = 196772 }
1012
1012
  wheels = [
1013
- { url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839 },
1013
+ { url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521 },
1014
1014
  ]
1015
1015
 
1016
1016
  [[package]]
1017
1017
  name = "urllib3"
1018
- version = "2.5.0"
1018
+ version = "2.6.2"
1019
1019
  source = { registry = "https://pypi.org/simple" }
1020
- sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185 }
1020
+ sdist = { url = "https://files.pythonhosted.org/packages/1e/24/a2a2ed9addd907787d7aa0355ba36a6cadf1768b934c652ea78acbd59dcd/urllib3-2.6.2.tar.gz", hash = "sha256:016f9c98bb7e98085cb2b4b17b87d2c702975664e4f060c6532e64d1c1a5e797", size = 432930 }
1021
1021
  wheels = [
1022
- { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795 },
1022
+ { url = "https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl", hash = "sha256:ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd", size = 131182 },
1023
1023
  ]
1024
1024
 
1025
1025
  [[package]]
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
- )