smartbox 2.1.3__tar.gz → 2.2.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 (78) hide show
  1. smartbox-2.2.0/.github/ISSUE_TEMPLATE/new-reseller.md +18 -0
  2. {smartbox-2.1.3 → smartbox-2.2.0}/.github/workflows/publish-to-pypi.yml +1 -1
  3. {smartbox-2.1.3 → smartbox-2.2.0}/.github/workflows/python-package.yml +3 -3
  4. {smartbox-2.1.3 → smartbox-2.2.0}/PKG-INFO +7 -7
  5. {smartbox-2.1.3 → smartbox-2.2.0}/README.md +6 -6
  6. {smartbox-2.1.3 → smartbox-2.2.0}/pyproject.toml +1 -1
  7. {smartbox-2.1.3 → smartbox-2.2.0}/src/smartbox/__init__.py +5 -5
  8. {smartbox-2.1.3 → smartbox-2.2.0}/src/smartbox/cmd.py +5 -5
  9. {smartbox-2.1.3 → smartbox-2.2.0}/src/smartbox/error.py +2 -2
  10. smartbox-2.1.3/src/smartbox/resailer.py → smartbox-2.2.0/src/smartbox/reseller.py +41 -35
  11. {smartbox-2.1.3 → smartbox-2.2.0}/src/smartbox/session.py +13 -13
  12. {smartbox-2.1.3 → smartbox-2.2.0}/tests/conftest.py +8 -8
  13. {smartbox-2.1.3 → smartbox-2.2.0}/tests/test_cmd.py +8 -8
  14. smartbox-2.2.0/tests/test_reseller.py +58 -0
  15. {smartbox-2.1.3 → smartbox-2.2.0}/tests/test_session.py +11 -11
  16. {smartbox-2.1.3 → smartbox-2.2.0}/uv.lock +1 -1
  17. smartbox-2.1.3/.github/ISSUE_TEMPLATE/new-resailer.md +0 -18
  18. smartbox-2.1.3/tests/test_resailer.py +0 -58
  19. {smartbox-2.1.3 → smartbox-2.2.0}/.github/FUNDING.yml +0 -0
  20. {smartbox-2.1.3 → smartbox-2.2.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  21. {smartbox-2.1.3 → smartbox-2.2.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  22. {smartbox-2.1.3 → smartbox-2.2.0}/.github/dependabot.yml +0 -0
  23. {smartbox-2.1.3 → smartbox-2.2.0}/.gitignore +0 -0
  24. {smartbox-2.1.3 → smartbox-2.2.0}/.pre-commit-config.yaml +0 -0
  25. {smartbox-2.1.3 → smartbox-2.2.0}/.vscode/settings.json +0 -0
  26. {smartbox-2.1.3 → smartbox-2.2.0}/CHANGELOG.md +0 -0
  27. {smartbox-2.1.3 → smartbox-2.2.0}/CODEOWNERS +0 -0
  28. {smartbox-2.1.3 → smartbox-2.2.0}/LICENSE +0 -0
  29. {smartbox-2.1.3 → smartbox-2.2.0}/api-notes.md +0 -0
  30. {smartbox-2.1.3 → smartbox-2.2.0}/codecov.yml +0 -0
  31. {smartbox-2.1.3 → smartbox-2.2.0}/src/smartbox/models.py +0 -0
  32. {smartbox-2.1.3 → smartbox-2.2.0}/src/smartbox/py.typed +0 -0
  33. {smartbox-2.1.3 → smartbox-2.2.0}/src/smartbox/socket.py +0 -0
  34. {smartbox-2.1.3 → smartbox-2.2.0}/src/smartbox/update_manager.py +0 -0
  35. {smartbox-2.1.3 → smartbox-2.2.0}/tests/__init__.py +0 -0
  36. {smartbox-2.1.3 → smartbox-2.2.0}/tests/common.py +0 -0
  37. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device1/acm/1/samples.json +0 -0
  38. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device1/acm/1/setup.json +0 -0
  39. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device1/acm/1/status.json +0 -0
  40. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device1/connected.json +0 -0
  41. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device1/htr/0/samples.json +0 -0
  42. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device1/htr/0/setup.json +0 -0
  43. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device1/htr/0/status.json +0 -0
  44. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device1/htr_system/power_limit.json +0 -0
  45. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device1/mgr/away_status.json +0 -0
  46. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device1/mgr/nodes.json +0 -0
  47. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device1/pmo/3/samples.json +0 -0
  48. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device1/pmo/3/setup.json +0 -0
  49. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device1/pmo/3/status.json +0 -0
  50. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/connected.json +0 -0
  51. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/0/samples.json +0 -0
  52. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/0/setup.json +0 -0
  53. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/0/status.json +0 -0
  54. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/1/samples.json +0 -0
  55. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/1/setup.json +0 -0
  56. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/1/status.json +0 -0
  57. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/2/samples.json +0 -0
  58. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/2/setup.json +0 -0
  59. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/2/status.json +0 -0
  60. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/3/samples.json +0 -0
  61. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/3/setup.json +0 -0
  62. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/3/status.json +0 -0
  63. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/4/samples.json +0 -0
  64. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/4/setup.json +0 -0
  65. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/4/status.json +0 -0
  66. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/5/samples.json +0 -0
  67. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/5/setup.json +0 -0
  68. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_mod/5/status.json +0 -0
  69. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/htr_system/power_limit.json +0 -0
  70. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/mgr/away_status.json +0 -0
  71. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs/device2/mgr/nodes.json +0 -0
  72. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/devs.json +0 -0
  73. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/grouped_devs.json +0 -0
  74. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/groups/test_home/guest_users.json +0 -0
  75. {smartbox-2.1.3 → smartbox-2.2.0}/tests/fixtures/test_path.json +0 -0
  76. {smartbox-2.1.3 → smartbox-2.2.0}/tests/test_models.py +0 -0
  77. {smartbox-2.1.3 → smartbox-2.2.0}/tests/test_update_manager.py +0 -0
  78. {smartbox-2.1.3 → smartbox-2.2.0}/tox.ini +0 -0
@@ -0,0 +1,18 @@
1
+ ---
2
+ name: New reseller
3
+ about: Add a new available reseller.
4
+ title: "[RESELLER] New available reseller"
5
+ labels: reseller
6
+ assignees: Delmael
7
+
8
+ ---
9
+
10
+ > [!NOTE]
11
+ > If you do not see your current reseller in the available list, you can ask to add it. We cannot ensure your device go through this platform
12
+
13
+ * [ ] I have check with the `smartbox resellers` command that my reseller is not already present
14
+ * **Website url (mandatory)** :
15
+ * Name of the resellers:
16
+ * API url :
17
+ * Basic auth headers :
18
+ * Serial id:
@@ -22,7 +22,7 @@ jobs:
22
22
  with:
23
23
  python-version: ${{ env.PYTHON_VERSION }}
24
24
  - name: Set up Python ${{ env.PYTHON_VERSION }}
25
- uses: actions/setup-python@v5.4.0
25
+ uses: actions/setup-python@v5.5.0
26
26
  with:
27
27
  python-version: ${{ env.PYTHON_VERSION }}
28
28
  - name: Build a binary wheel and a source tarball
@@ -25,7 +25,7 @@ jobs:
25
25
  with:
26
26
  python-version: ${{ matrix.python-version }}
27
27
  - name: Set up Python ${{ matrix.python-version }}
28
- uses: actions/setup-python@v5.4.0
28
+ uses: actions/setup-python@v5.5.0
29
29
  with:
30
30
  python-version: ${{ matrix.python-version }}
31
31
  - name: Install the project
@@ -47,7 +47,7 @@ jobs:
47
47
  with:
48
48
  python-version: ${{ matrix.python-version }}
49
49
  - name: Set up Python ${{ matrix.python-version }}
50
- uses: actions/setup-python@v5.4.0
50
+ uses: actions/setup-python@v5.5.0
51
51
  with:
52
52
  python-version: ${{ matrix.python-version }}
53
53
  - name: Install the project
@@ -70,7 +70,7 @@ jobs:
70
70
  python-version: ${{ matrix.python-version }}
71
71
 
72
72
  - name: Set up Python ${{ matrix.python-version }}
73
- uses: actions/setup-python@v5.4.0
73
+ uses: actions/setup-python@v5.5.0
74
74
  with:
75
75
  python-version: ${{ matrix.python-version }}
76
76
  - name: Install the project
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: smartbox
3
- Version: 2.1.3
3
+ Version: 2.2.0
4
4
  Summary: Python API to control heating 'smart boxes'
5
5
  Project-URL: Homepage, https://github.com/ajtudela/smartbox
6
6
  Project-URL: Issues, https://github.com/ajtudela/smartbox/issues
@@ -53,7 +53,7 @@ A few common options are required for all commands:
53
53
  Verbose logging can be enabled with the `-v`/`--verbose` flag.
54
54
 
55
55
  ### Optional options
56
- These options are useful if your resailer is not configured.
56
+ These options are useful if your reseller is not configured.
57
57
 
58
58
  * `-b`/`--base-auth-creds`: An HTTP Basic Auth credential used to do initial
59
59
  authentication with the server. Use the base64 encoded string directly. See
@@ -61,7 +61,7 @@ These options are useful if your resailer is not configured.
61
61
  * `-a`/`--api-name`: The API name for your heater vendor. This is visible in
62
62
  the 'API Host' entry in the 'Version' menu item in the mobile app/web app. If
63
63
  the host name is of the form `api-foo.xxxx` or `api.xxxx` use the values
64
- `api-foo` or `api` respectively. The resailer has to be declared in the package.
64
+ `api-foo` or `api` respectively. The reseller has to be declared in the package.
65
65
  * `-r`/`--x-referer`: The referer of your request.
66
66
  * `-i`/`--x-serial-id`: The serial-id of your request.
67
67
 
@@ -132,11 +132,11 @@ The `health-check` command can be used to know if the API is alived
132
132
 
133
133
  smartbox <auth options...> health-check
134
134
 
135
- ### List available resailers
136
- The `resailers` command can be used to know which resailershas an automatic configuration.
137
- If your resailer is not present you can raise an issue in github, or use the optional options.
135
+ ### List available resellers
136
+ The `resellers` command can be used to know which resellers has an automatic configuration.
137
+ If your reseller is not present you can raise an issue in github, or use the optional options.
138
138
 
139
- smartbox <auth options...> resailers
139
+ smartbox <auth options...> resellers
140
140
 
141
141
 
142
142
  See [api-notes.md](./api-notes.md) for notes on REST and socket.io endpoints.
@@ -31,7 +31,7 @@ A few common options are required for all commands:
31
31
  Verbose logging can be enabled with the `-v`/`--verbose` flag.
32
32
 
33
33
  ### Optional options
34
- These options are useful if your resailer is not configured.
34
+ These options are useful if your reseller is not configured.
35
35
 
36
36
  * `-b`/`--base-auth-creds`: An HTTP Basic Auth credential used to do initial
37
37
  authentication with the server. Use the base64 encoded string directly. See
@@ -39,7 +39,7 @@ These options are useful if your resailer is not configured.
39
39
  * `-a`/`--api-name`: The API name for your heater vendor. This is visible in
40
40
  the 'API Host' entry in the 'Version' menu item in the mobile app/web app. If
41
41
  the host name is of the form `api-foo.xxxx` or `api.xxxx` use the values
42
- `api-foo` or `api` respectively. The resailer has to be declared in the package.
42
+ `api-foo` or `api` respectively. The reseller has to be declared in the package.
43
43
  * `-r`/`--x-referer`: The referer of your request.
44
44
  * `-i`/`--x-serial-id`: The serial-id of your request.
45
45
 
@@ -110,11 +110,11 @@ The `health-check` command can be used to know if the API is alived
110
110
 
111
111
  smartbox <auth options...> health-check
112
112
 
113
- ### List available resailers
114
- The `resailers` command can be used to know which resailershas an automatic configuration.
115
- If your resailer is not present you can raise an issue in github, or use the optional options.
113
+ ### List available resellers
114
+ The `resellers` command can be used to know which resellers has an automatic configuration.
115
+ If your reseller is not present you can raise an issue in github, or use the optional options.
116
116
 
117
- smartbox <auth options...> resailers
117
+ smartbox <auth options...> resellers
118
118
 
119
119
 
120
120
  See [api-notes.md](./api-notes.md) for notes on REST and socket.io endpoints.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "smartbox"
3
- version = "2.1.3"
3
+ version = "2.2.0"
4
4
  requires-python = ">=3.13"
5
5
  authors = [
6
6
  { name="Alberto Tudela", email="ajtudela@gmail.com" },
@@ -5,7 +5,7 @@ import importlib.metadata
5
5
  from .error import (
6
6
  APIUnavailableError,
7
7
  InvalidAuthError,
8
- ResailerNotExistError,
8
+ ResellerNotExistError,
9
9
  SmartboxError,
10
10
  )
11
11
  from .models import (
@@ -21,7 +21,7 @@ from .models import (
21
21
  NodeStatus,
22
22
  SmartboxNodeType,
23
23
  )
24
- from .resailer import AvailableResailers, SmartboxResailer
24
+ from .reseller import AvailableResellers, SmartboxReseller
25
25
  from .session import AsyncSmartboxSession, Session
26
26
  from .socket import SocketSession
27
27
  from .update_manager import UpdateManager
@@ -33,7 +33,7 @@ __all__ = [
33
33
  "APIUnavailableError",
34
34
  "AcmNodeStatus",
35
35
  "AsyncSmartboxSession",
36
- "AvailableResailers",
36
+ "AvailableResellers",
37
37
  "DefaultNodeStatus",
38
38
  "GuestUser",
39
39
  "Guests",
@@ -44,11 +44,11 @@ __all__ = [
44
44
  "NodeFactoryOptions",
45
45
  "NodeSetup",
46
46
  "NodeStatus",
47
- "ResailerNotExistError",
47
+ "ResellerNotExistError",
48
48
  "Session",
49
49
  "SmartboxError",
50
50
  "SmartboxNodeType",
51
- "SmartboxResailer",
51
+ "SmartboxReseller",
52
52
  "SocketSession",
53
53
  "UpdateManager",
54
54
  ]
@@ -7,7 +7,7 @@ from typing import Any
7
7
  from aiohttp import ClientSession
8
8
  import asyncclick as click
9
9
 
10
- from smartbox.resailer import AvailableResailers
10
+ from smartbox.reseller import AvailableResellers
11
11
  from smartbox.session import AsyncSmartboxSession
12
12
  from smartbox.socket import SocketSession
13
13
 
@@ -403,10 +403,10 @@ async def api_version(ctx) -> None:
403
403
  _pretty_print(version)
404
404
 
405
405
 
406
- @smartbox.command(help="Get the availables resailers.")
407
- def resailers() -> None:
408
- """Get the availables resailers."""
409
- for item in AvailableResailers.resailers.items():
406
+ @smartbox.command(help="Get the availables resellers.")
407
+ def resellers() -> None:
408
+ """Get the availables resellers."""
409
+ for item in AvailableResellers.resellers.items():
410
410
  print(item)
411
411
 
412
412
 
@@ -15,5 +15,5 @@ class APIUnavailableError(aiohttp.ClientConnectionError):
15
15
  """API is unavailable."""
16
16
 
17
17
 
18
- class ResailerNotExistError(Exception):
19
- """Resailer is not known."""
18
+ class ResellerNotExistError(Exception):
19
+ """Reseller is not known."""
@@ -1,18 +1,18 @@
1
- """Resailer of Smartbox."""
1
+ """Reseller of Smartbox."""
2
2
 
3
3
  import logging
4
4
  from typing import ClassVar
5
5
 
6
6
  from pydantic import BaseModel, ValidationError
7
7
 
8
- from smartbox.error import ResailerNotExistError
8
+ from smartbox.error import ResellerNotExistError
9
9
 
10
10
  SMARTBOX_GENERIC_BASIC_AUTH = "NTRiY2NiZmI0MWE5YTUxMTNmMDQ4OGQwOnZkaXZkaQ=="
11
11
  _LOGGER = logging.getLogger(__name__)
12
12
 
13
13
 
14
- class SmartboxResailer(BaseModel):
15
- """Model of Smartbox Resailer config."""
14
+ class SmartboxReseller(BaseModel):
15
+ """Model of Smartbox Reseller config."""
16
16
 
17
17
  name: str = "Smartbox"
18
18
  web_url: str = ""
@@ -21,49 +21,55 @@ class SmartboxResailer(BaseModel):
21
21
  serial_id: int = 0
22
22
 
23
23
 
24
- class AvailableResailers:
25
- """Resailers that have been verified."""
24
+ class AvailableResellers:
25
+ """Resellers that have been verified."""
26
26
 
27
- resailers: ClassVar[dict[str, SmartboxResailer]] = {
28
- "api": SmartboxResailer(
27
+ resellers: ClassVar[dict[str, SmartboxReseller]] = {
28
+ "api": SmartboxReseller(
29
29
  name="Helki",
30
30
  web_url="https://app.helki.com/",
31
31
  api_url="api",
32
32
  serial_id=1,
33
33
  ),
34
- "api-ehc": SmartboxResailer(
34
+ "api-ehc": SmartboxReseller(
35
35
  name="Electric Heating Company",
36
36
  web_url="https://control.electric-heatingcompany.co.uk/",
37
37
  api_url="api-ehc",
38
38
  serial_id=3,
39
39
  ),
40
- "api-climastar": SmartboxResailer(
40
+ "api-climastar": SmartboxReseller(
41
41
  name="Climastar",
42
42
  web_url="https://avantwifi.climastar.es/",
43
43
  api_url="api-climastar",
44
44
  serial_id=5,
45
45
  ),
46
- "api-elnur": SmartboxResailer(
46
+ "api-elnur": SmartboxReseller(
47
47
  name="Elnur",
48
48
  web_url="https://remotecontrol.elnur.es/",
49
49
  api_url="api-elnur",
50
50
  serial_id=7,
51
51
  ),
52
- "api-hjm": SmartboxResailer(
52
+ "api-hjm": SmartboxReseller(
53
53
  name="HJM",
54
54
  web_url="https://api.calorhjm.com/",
55
55
  api_url="api-hjm",
56
56
  serial_id=10,
57
57
  ),
58
- "api-haverland": SmartboxResailer(
58
+ "api-evconfort": SmartboxReseller(
59
+ name="Electrorad",
60
+ web_url="https://app.controls-electrorad.co.uk/",
61
+ api_url="api-evconfort",
62
+ serial_id=12,
63
+ ),
64
+ "api-haverland": SmartboxReseller(
59
65
  name="Haverland",
60
66
  web_url="https://i2control.haverland.com/",
61
67
  api_url="api-haverland",
62
68
  basic_auth="NTU2ZDc0MWI3OGUzYmU5YjU2NjA3NTQ4OnZkaXZkaQ==",
63
69
  serial_id=14,
64
70
  ),
65
- "api-lhz": SmartboxResailer(
66
- name="Technotherm",
71
+ "api-lhz": SmartboxReseller(
72
+ name="Technotherm / Lucht-LHZ",
67
73
  web_url="https://ttiapp.technotherm.com/",
68
74
  api_url="api-lhz",
69
75
  serial_id=16,
@@ -78,7 +84,7 @@ class AvailableResailers:
78
84
  serial_id: int | None = None,
79
85
  name: str = "Smartbox",
80
86
  ) -> None:
81
- """Check if resailer is already available or try to create one."""
87
+ """Check if reseller is already available or try to create one."""
82
88
  self._api_url = api_url
83
89
  self._basic_auth = basic_auth
84
90
  self._web_url = web_url
@@ -86,27 +92,27 @@ class AvailableResailers:
86
92
  self._name = name
87
93
 
88
94
  @property
89
- def resailer(self) -> SmartboxResailer:
90
- """Get the resailer."""
91
- resailer = self.resailers.get(self._api_url, None)
92
- if resailer is None:
95
+ def reseller(self) -> SmartboxReseller:
96
+ """Get the reseller."""
97
+ reseller = self.resellers.get(self._api_url, None)
98
+ if reseller is None:
93
99
  if (
94
100
  self._basic_auth is None
95
101
  or self._web_url is None
96
102
  or self._serial_id is None
97
103
  ):
98
- msg = "This Resailer is not yet available or some arguments are missing."
99
- raise ResailerNotExistError(msg)
104
+ msg = "This reseller is not yet available or some arguments are missing."
105
+ raise ResellerNotExistError(msg)
100
106
  try:
101
107
  _LOGGER.debug(
102
- "Creating a new resailer api_url (%s), name=%s, web_url %s, basic_auth=%s, serial_id=%s",
108
+ "Creating a new reseller api_url (%s), name=%s, web_url %s, basic_auth=%s, serial_id=%s",
103
109
  self._api_url,
104
110
  self._name,
105
111
  self._web_url,
106
112
  self._basic_auth,
107
113
  self._serial_id,
108
114
  )
109
- resailer = SmartboxResailer(
115
+ reseller = SmartboxReseller(
110
116
  api_url=self._api_url,
111
117
  basic_auth=self._basic_auth,
112
118
  web_url=self._web_url,
@@ -114,26 +120,26 @@ class AvailableResailers:
114
120
  name=self._name,
115
121
  )
116
122
  except ValidationError as e:
117
- raise ResailerNotExistError from e
123
+ raise ResellerNotExistError from e
118
124
  _LOGGER.debug(
119
- "Resailer api_url (%s), name=%s, web_url %s",
120
- resailer.api_url,
121
- resailer.name,
122
- resailer.web_url,
125
+ "Reseller api_url (%s), name=%s, web_url %s",
126
+ reseller.api_url,
127
+ reseller.name,
128
+ reseller.web_url,
123
129
  )
124
- return resailer
130
+ return reseller
125
131
 
126
132
  @property
127
133
  def api_url(self) -> str:
128
134
  """Get the api sub domain url."""
129
- return self.resailer.api_url
135
+ return self.reseller.api_url
130
136
 
131
137
  @property
132
138
  def name(self) -> str:
133
- """Get the name of resailer."""
134
- return self.resailer.name
139
+ """Get the name of reseller."""
140
+ return self.reseller.name
135
141
 
136
142
  @property
137
143
  def web_url(self) -> str:
138
- """Get the public websit of the resailer."""
139
- return self.resailer.web_url
144
+ """Get the public websit of the reseller."""
145
+ return self.reseller.web_url
@@ -31,7 +31,7 @@ from smartbox.models import (
31
31
  SmartboxNodeType,
32
32
  Token,
33
33
  )
34
- from smartbox.resailer import AvailableResailers, SmartboxResailer
34
+ from smartbox.reseller import AvailableResellers, SmartboxReseller
35
35
 
36
36
  _DEFAULT_RETRY_ATTEMPTS = 5
37
37
  _DEFAULT_BACKOFF_FACTOR = 0.1
@@ -59,13 +59,13 @@ class AsyncSession:
59
59
  x_referer: str | None = None,
60
60
  ) -> None:
61
61
  """Init the session."""
62
- self._resailer = AvailableResailers(
62
+ self._reseller = AvailableResellers(
63
63
  api_url=api_name,
64
64
  basic_auth=basic_auth_credentials,
65
65
  serial_id=x_serial_id,
66
66
  web_url=x_referer,
67
- ).resailer
68
- self._api_host: str = f"https://{self.resailer.api_url}.helki.com"
67
+ ).reseller
68
+ self._api_host: str = f"https://{self.reseller.api_url}.helki.com"
69
69
  self._basic_auth_credentials: str | None = basic_auth_credentials
70
70
  self._retry_attempts: int = retry_attempts
71
71
  self._backoff_factor: float = backoff_factor
@@ -78,20 +78,20 @@ class AsyncSession:
78
78
  "Authorization": f"Bearer {self._access_token}",
79
79
  "Content-Type": "application/json",
80
80
  }
81
- if self.resailer.serial_id:
82
- self._headers.update({"x-serialid": str(self.resailer.serial_id)})
83
- if self.resailer.web_url:
84
- self._headers.update({"x-referer": self.resailer.web_url})
81
+ if self.reseller.serial_id:
82
+ self._headers.update({"x-serialid": str(self.reseller.serial_id)})
83
+ if self.reseller.web_url:
84
+ self._headers.update({"x-referer": self.reseller.web_url})
85
85
 
86
86
  @property
87
- def resailer(self) -> SmartboxResailer:
88
- """Get the resailer."""
89
- return self._resailer
87
+ def reseller(self) -> SmartboxReseller:
88
+ """Get the reseller."""
89
+ return self._reseller
90
90
 
91
91
  @property
92
92
  def api_name(self) -> str:
93
93
  """Get the api sub domain url."""
94
- return self.resailer.api_url
94
+ return self.reseller.api_url
95
95
 
96
96
  @property
97
97
  def api_host(self) -> str:
@@ -150,7 +150,7 @@ class AsyncSession:
150
150
  del token_headers["Authorization"]
151
151
  token_headers.update(
152
152
  {
153
- "authorization": f"Basic {self.resailer.basic_auth}",
153
+ "authorization": f"Basic {self.reseller.basic_auth}",
154
154
  "Content-Type": "application/x-www-form-urlencoded",
155
155
  },
156
156
  )
@@ -3,7 +3,7 @@ from unittest.mock import patch
3
3
  from asyncclick.testing import CliRunner
4
4
  import pytest
5
5
 
6
- from smartbox.resailer import SmartboxResailer
6
+ from smartbox.reseller import SmartboxReseller
7
7
  from smartbox.session import AsyncSession, AsyncSmartboxSession, Session
8
8
  from smartbox.update_manager import UpdateManager
9
9
  from tests.common import fake_get_request
@@ -25,7 +25,7 @@ def update_manager(mock_session):
25
25
 
26
26
 
27
27
  @pytest.fixture
28
- def async_smartbox_session(mocker, resailer):
28
+ def async_smartbox_session(mocker, reseller):
29
29
  async_smartbox_session = AsyncSmartboxSession(
30
30
  api_name="test_api",
31
31
  username="test_user",
@@ -47,7 +47,7 @@ def async_smartbox_session(mocker, resailer):
47
47
 
48
48
 
49
49
  @pytest.fixture
50
- def session(resailer):
50
+ def session(reseller):
51
51
  return Session(
52
52
  api_name="test_api",
53
53
  username="test_user",
@@ -56,7 +56,7 @@ def session(resailer):
56
56
 
57
57
 
58
58
  @pytest.fixture
59
- def async_session(resailer):
59
+ def async_session(reseller):
60
60
  api_name = "test_api"
61
61
  username = "test_user"
62
62
  password = "test_password"
@@ -76,7 +76,7 @@ def async_session(resailer):
76
76
 
77
77
  @pytest.fixture
78
78
  def person():
79
- return SmartboxResailer(
79
+ return SmartboxReseller(
80
80
  name="test",
81
81
  api_url="test_api",
82
82
  basic_auth="test_credentials",
@@ -86,12 +86,12 @@ def person():
86
86
 
87
87
 
88
88
  @pytest.fixture
89
- def resailer(mocker):
89
+ def reseller(mocker):
90
90
  return mocker.patch(
91
- "smartbox.resailer.AvailableResailers.resailers",
91
+ "smartbox.reseller.AvailableResellers.resellers",
92
92
  new_callable=mocker.PropertyMock,
93
93
  return_value={
94
- "test_api": SmartboxResailer(
94
+ "test_api": SmartboxReseller(
95
95
  name="test",
96
96
  api_url="test_api",
97
97
  basic_auth="test_credentials",
@@ -263,21 +263,21 @@ async def test_node_samples(runner, mock_session):
263
263
 
264
264
 
265
265
  @pytest.mark.anyio
266
- async def test_resailers(runner, mocker):
267
- mock_resailers = mocker.patch("smartbox.cmd.AvailableResailers.resailers")
268
- mock_resailers.items.return_value = [
269
- ("resailer1", "details1"),
270
- ("resailer2", "details2"),
266
+ async def test_reseller(runner, mocker):
267
+ mock_resellers = mocker.patch("smartbox.cmd.AvailableResellers.resellers")
268
+ mock_resellers.items.return_value = [
269
+ ("reseller1", "details1"),
270
+ ("reseller2", "details2"),
271
271
  ]
272
272
 
273
273
  result = await runner.invoke(
274
274
  smartbox,
275
- [*DEFAULT_ARGS, "resailers"],
275
+ [*DEFAULT_ARGS, "resellers"],
276
276
  )
277
277
  assert result.exit_code == 0
278
- assert "resailer1" in result.output
278
+ assert "reseller1" in result.output
279
279
  assert "details1" in result.output
280
- assert "resailer2" in result.output
280
+ assert "reseller2" in result.output
281
281
  assert "details2" in result.output
282
282
 
283
283
 
@@ -0,0 +1,58 @@
1
+ import pytest
2
+
3
+ from smartbox import AsyncSmartboxSession, ResellerNotExistError
4
+ from smartbox.reseller import AvailableResellers
5
+
6
+
7
+ def test_available_resellers_existing_reseller():
8
+ reseller = AvailableResellers(api_url="api").reseller
9
+ assert reseller.name == "Helki"
10
+ assert reseller.api_url == "api"
11
+
12
+
13
+ def test_available_resellers_non_existing_reseller():
14
+ with pytest.raises(ResellerNotExistError):
15
+ AvailableResellers(api_url="non-existing-api").reseller
16
+
17
+
18
+ def test_available_resellers_custom_reseller():
19
+ serial_id = 99
20
+ _reseller = AvailableResellers(
21
+ api_url="custom-api",
22
+ basic_auth="custom-auth",
23
+ web_url="https://custom-url.com",
24
+ serial_id=serial_id,
25
+ name="Custom",
26
+ )
27
+ reseller = _reseller.reseller
28
+ assert reseller.name == "Custom"
29
+ assert reseller.api_url == "custom-api"
30
+ assert reseller.basic_auth == "custom-auth"
31
+ assert reseller.web_url == "https://custom-url.com"
32
+ assert reseller.serial_id == serial_id
33
+
34
+ assert _reseller.name == "Custom"
35
+ assert _reseller.api_url == "custom-api"
36
+ assert _reseller.web_url == "https://custom-url.com"
37
+
38
+
39
+ def test_reseller_invalid_data():
40
+ with pytest.raises(ResellerNotExistError):
41
+ AvailableResellers(
42
+ api_url="invalid-api",
43
+ basic_auth="invalid-auth",
44
+ web_url="invalid-url",
45
+ serial_id="invalid-serial-id",
46
+ ).reseller
47
+
48
+
49
+ @pytest.mark.asyncio
50
+ async def test_all_resellers():
51
+ for reseller in AvailableResellers.resellers.values():
52
+ _session = AsyncSmartboxSession(
53
+ username="", password="", api_name=reseller.api_url
54
+ )
55
+ check = await _session.health_check()
56
+ assert check is not None
57
+ version = await _session.api_version()
58
+ assert "major" in version
@@ -721,7 +721,7 @@ async def test_async_session_init():
721
721
 
722
722
 
723
723
  @pytest.mark.asyncio
724
- async def test_async_session_init_defaults(resailer):
724
+ async def test_async_session_init_defaults(reseller):
725
725
  api_name = "test_api"
726
726
  username = "test_user"
727
727
  password = "test_password"
@@ -777,7 +777,7 @@ async def test_authentication_success(async_session):
777
777
  mock_post.assert_called_once_with(
778
778
  url=f"{async_session._api_host}/client/token",
779
779
  headers={
780
- "authorization": f"Basic {async_session.resailer.basic_auth}",
780
+ "authorization": f"Basic {async_session.reseller.basic_auth}",
781
781
  "Content-Type": "application/x-www-form-urlencoded",
782
782
  "x-referer": "http",
783
783
  "x-serialid": "10",
@@ -812,10 +812,10 @@ async def test_authentication_invalid_response(async_session):
812
812
  mock_post.assert_called_once_with(
813
813
  url=f"{async_session._api_host}/client/token",
814
814
  headers={
815
- "authorization": f"Basic {async_session.resailer.basic_auth}",
815
+ "authorization": f"Basic {async_session.reseller.basic_auth}",
816
816
  "Content-Type": "application/x-www-form-urlencoded",
817
- "x-serialid": f"{async_session.resailer.serial_id}",
818
- "x-referer": f"{async_session.resailer.web_url}",
817
+ "x-serialid": f"{async_session.reseller.serial_id}",
818
+ "x-referer": f"{async_session.reseller.web_url}",
819
819
  },
820
820
  data=credentials,
821
821
  )
@@ -847,10 +847,10 @@ async def test_authentication_client_response_error(async_session):
847
847
  mock_post.assert_called_once_with(
848
848
  url=f"{async_session._api_host}/client/token",
849
849
  headers={
850
- "authorization": f"Basic {async_session.resailer.basic_auth}",
850
+ "authorization": f"Basic {async_session.reseller.basic_auth}",
851
851
  "Content-Type": "application/x-www-form-urlencoded",
852
- "x-serialid": f"{async_session.resailer.serial_id}",
853
- "x-referer": f"{async_session.resailer.web_url}",
852
+ "x-serialid": f"{async_session.reseller.serial_id}",
853
+ "x-referer": f"{async_session.reseller.web_url}",
854
854
  },
855
855
  data=credentials,
856
856
  )
@@ -877,10 +877,10 @@ async def test_authentication_client_response_unavailable(async_session):
877
877
  mock_post.assert_called_once_with(
878
878
  url=f"{async_session._api_host}/client/token",
879
879
  headers={
880
- "authorization": f"Basic {async_session.resailer.basic_auth}",
880
+ "authorization": f"Basic {async_session.reseller.basic_auth}",
881
881
  "Content-Type": "application/x-www-form-urlencoded",
882
- "x-serialid": f"{async_session.resailer.serial_id}",
883
- "x-referer": f"{async_session.resailer.web_url}",
882
+ "x-serialid": f"{async_session.reseller.serial_id}",
883
+ "x-referer": f"{async_session.reseller.web_url}",
884
884
  },
885
885
  data=credentials,
886
886
  )
@@ -685,7 +685,7 @@ wheels = [
685
685
 
686
686
  [[package]]
687
687
  name = "smartbox"
688
- version = "2.1.3"
688
+ version = "2.2.0"
689
689
  source = { editable = "." }
690
690
  dependencies = [
691
691
  { name = "aiohttp" },
@@ -1,18 +0,0 @@
1
- ---
2
- name: New resailer
3
- about: Add a new available resailer.
4
- title: "[RESAILER] New available resailer"
5
- labels: resailer
6
- assignees: Delmael
7
-
8
- ---
9
-
10
- > [!NOTE]
11
- > If you do not see your current resailer in the available list, you can ask to add it. We cannot ensure your device go through this platform
12
-
13
- * [ ] I have check with the `smartbox resailers` command that my resailer is not already present
14
- * **Website url (mandatory)** :
15
- * Name of the resailers:
16
- * API url :
17
- * Basic auth headers :
18
- * Serial id:
@@ -1,58 +0,0 @@
1
- import pytest
2
-
3
- from smartbox import AsyncSmartboxSession, ResailerNotExistError
4
- from smartbox.resailer import AvailableResailers
5
-
6
-
7
- def test_available_resailers_existing_resailer():
8
- resailer = AvailableResailers(api_url="api").resailer
9
- assert resailer.name == "Helki"
10
- assert resailer.api_url == "api"
11
-
12
-
13
- def test_available_resailers_non_existing_resailer():
14
- with pytest.raises(ResailerNotExistError):
15
- AvailableResailers(api_url="non-existing-api").resailer
16
-
17
-
18
- def test_available_resailers_custom_resailer():
19
- serial_id = 99
20
- _resailer = AvailableResailers(
21
- api_url="custom-api",
22
- basic_auth="custom-auth",
23
- web_url="https://custom-url.com",
24
- serial_id=serial_id,
25
- name="Custom",
26
- )
27
- resailer = _resailer.resailer
28
- assert resailer.name == "Custom"
29
- assert resailer.api_url == "custom-api"
30
- assert resailer.basic_auth == "custom-auth"
31
- assert resailer.web_url == "https://custom-url.com"
32
- assert resailer.serial_id == serial_id
33
-
34
- assert _resailer.name == "Custom"
35
- assert _resailer.api_url == "custom-api"
36
- assert _resailer.web_url == "https://custom-url.com"
37
-
38
-
39
- def test_resailer_invalid_data():
40
- with pytest.raises(ResailerNotExistError):
41
- AvailableResailers(
42
- api_url="invalid-api",
43
- basic_auth="invalid-auth",
44
- web_url="invalid-url",
45
- serial_id="invalid-serial-id",
46
- ).resailer
47
-
48
-
49
- @pytest.mark.asyncio
50
- async def test_all_resailers():
51
- for resailer in AvailableResailers.resailers.values():
52
- _session = AsyncSmartboxSession(
53
- username="", password="", api_name=resailer.api_url
54
- )
55
- check = await _session.health_check()
56
- assert check is not None
57
- version = await _session.api_version()
58
- assert "major" in version
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
File without changes
File without changes
File without changes