python-tado 0.18.0__tar.gz → 0.18.2__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_tado-0.18.0/python_tado.egg-info → python_tado-0.18.2}/PKG-INFO +4 -1
- {python_tado-0.18.0 → python_tado-0.18.2}/PyTado/const.py +6 -0
- {python_tado-0.18.0 → python_tado-0.18.2}/PyTado/exceptions.py +0 -4
- {python_tado-0.18.0 → python_tado-0.18.2}/PyTado/http.py +20 -10
- {python_tado-0.18.0 → python_tado-0.18.2}/PyTado/interface/api/hops_tado.py +1 -1
- {python_tado-0.18.0 → python_tado-0.18.2}/PyTado/interface/api/my_tado.py +1 -1
- {python_tado-0.18.0 → python_tado-0.18.2}/PyTado/interface/interface.py +1 -1
- {python_tado-0.18.0 → python_tado-0.18.2}/pyproject.toml +2 -2
- {python_tado-0.18.0 → python_tado-0.18.2/python_tado.egg-info}/PKG-INFO +4 -1
- {python_tado-0.18.0 → python_tado-0.18.2}/python_tado.egg-info/SOURCES.txt +4 -2
- {python_tado-0.18.0 → python_tado-0.18.2}/python_tado.egg-info/requires.txt +3 -0
- python_tado-0.18.2/tests/test_http.py +180 -0
- {python_tado-0.18.0 → python_tado-0.18.2}/tests/test_my_tado.py +1 -1
- {python_tado-0.18.0 → python_tado-0.18.2}/tests/test_my_zone.py +2 -2
- python_tado-0.18.2/tests/test_tado_interface.py +84 -0
- {python_tado-0.18.0 → python_tado-0.18.2}/AUTHORS +0 -0
- {python_tado-0.18.0 → python_tado-0.18.2}/LICENSE +0 -0
- {python_tado-0.18.0 → python_tado-0.18.2}/PyTado/__init__.py +0 -0
- {python_tado-0.18.0 → python_tado-0.18.2}/PyTado/__main__.py +0 -0
- {python_tado-0.18.0 → python_tado-0.18.2}/PyTado/interface/__init__.py +0 -0
- {python_tado-0.18.0 → python_tado-0.18.2}/PyTado/interface/api/__init__.py +0 -0
- /python_tado-0.18.0/PyTado/logging.py → /python_tado-0.18.2/PyTado/logger.py +0 -0
- {python_tado-0.18.0 → python_tado-0.18.2}/PyTado/zone/__init__.py +0 -0
- {python_tado-0.18.0 → python_tado-0.18.2}/PyTado/zone/hops_zone.py +0 -0
- {python_tado-0.18.0 → python_tado-0.18.2}/PyTado/zone/my_zone.py +0 -0
- {python_tado-0.18.0 → python_tado-0.18.2}/README.md +0 -0
- {python_tado-0.18.0 → python_tado-0.18.2}/python_tado.egg-info/dependency_links.txt +0 -0
- {python_tado-0.18.0 → python_tado-0.18.2}/python_tado.egg-info/entry_points.txt +0 -0
- {python_tado-0.18.0 → python_tado-0.18.2}/python_tado.egg-info/not-zip-safe +0 -0
- {python_tado-0.18.0 → python_tado-0.18.2}/python_tado.egg-info/top_level.txt +0 -0
- {python_tado-0.18.0 → python_tado-0.18.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: python-tado
|
|
3
|
-
Version: 0.18.
|
|
3
|
+
Version: 0.18.2
|
|
4
4
|
Summary: PyTado from chrism0dwk, modfied by w.malgadey, diplix, michaelarnauts, LenhartStephan, splifter, syssi, andersonshatch, Yippy, p0thi, Coffee2CodeNL, chiefdragon, FilBr, nikilase, albertomontesg, Moritz-Schmidt, palazzem
|
|
5
5
|
Author-email: Chris Jewell <chrism0dwk@gmail.com>, "w.malgadey" <w.malgadey@gmail.com>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -699,7 +699,10 @@ Requires-Dist: black>=24.3; extra == "dev"
|
|
|
699
699
|
Requires-Dist: pytype; extra == "dev"
|
|
700
700
|
Requires-Dist: pylint; extra == "dev"
|
|
701
701
|
Requires-Dist: types-requests; extra == "dev"
|
|
702
|
+
Requires-Dist: responses; extra == "dev"
|
|
703
|
+
Requires-Dist: coverage; extra == "dev"
|
|
702
704
|
Requires-Dist: pytest; extra == "dev"
|
|
705
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
703
706
|
|
|
704
707
|
PyTado -- Pythonize your central heating
|
|
705
708
|
========================================
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
"""Constant values for the Tado component."""
|
|
2
2
|
|
|
3
|
+
# Api credentials
|
|
4
|
+
CLIENT_ID = "tado-web-app"
|
|
5
|
+
CLIENT_SECRET = (
|
|
6
|
+
"wZaRN7rpjn3FoNyF5IFuxg9uMzYJcvOoQ8QWiIqS3hfk6gLhVlG57j5YNoZL2Rtc"
|
|
7
|
+
)
|
|
8
|
+
|
|
3
9
|
# Types
|
|
4
10
|
TYPE_AIR_CONDITIONING = "AIR_CONDITIONING"
|
|
5
11
|
TYPE_HEATING = "HEATING"
|
|
@@ -9,10 +9,6 @@ class TadoNotSupportedException(TadoException):
|
|
|
9
9
|
"""Exception to indicate a requested action is not supported by Tado."""
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class TadoXNotSupportedException(TadoException):
|
|
13
|
-
"""Exception to indicate a requested action is not supported by the Tado X API."""
|
|
14
|
-
|
|
15
|
-
|
|
16
12
|
class TadoCredentialsException(TadoException):
|
|
17
13
|
"""Exception to indicate something with credentials"""
|
|
18
14
|
|
|
@@ -11,8 +11,9 @@ from typing import Any
|
|
|
11
11
|
|
|
12
12
|
import requests
|
|
13
13
|
|
|
14
|
-
from PyTado.
|
|
15
|
-
from PyTado.
|
|
14
|
+
from PyTado.const import CLIENT_ID, CLIENT_SECRET
|
|
15
|
+
from PyTado.exceptions import TadoException, TadoWrongCredentialsException
|
|
16
|
+
from PyTado.logger import Logger
|
|
16
17
|
|
|
17
18
|
_LOGGER = Logger(__name__)
|
|
18
19
|
|
|
@@ -141,7 +142,8 @@ class Http:
|
|
|
141
142
|
self._headers = {"Referer": "https://app.tado.com/"}
|
|
142
143
|
self._username = username
|
|
143
144
|
self._password = password
|
|
144
|
-
self._id, self.
|
|
145
|
+
self._id, self._token_refresh = self._login()
|
|
146
|
+
self._x_api = self._check_x_line_generation()
|
|
145
147
|
|
|
146
148
|
def _log_response(self, response: requests.Response, *args, **kwargs):
|
|
147
149
|
og_request_method = response.request.method
|
|
@@ -199,6 +201,7 @@ class Http:
|
|
|
199
201
|
|
|
200
202
|
return response.json()
|
|
201
203
|
|
|
204
|
+
@property
|
|
202
205
|
def is_x_line(self):
|
|
203
206
|
return self._x_api
|
|
204
207
|
|
|
@@ -249,10 +252,8 @@ class Http:
|
|
|
249
252
|
|
|
250
253
|
url = "https://auth.tado.com/oauth/token"
|
|
251
254
|
data = {
|
|
252
|
-
"client_id":
|
|
253
|
-
"client_secret":
|
|
254
|
-
"wZaRN7rpjn3FoNyF5IFuxg9uMzYJcvOoQ8QWiIqS3hfk6gLhVlG57j5YNoZL2Rtc"
|
|
255
|
-
),
|
|
255
|
+
"client_id": CLIENT_ID,
|
|
256
|
+
"client_secret": CLIENT_SECRET,
|
|
256
257
|
"grant_type": "refresh_token",
|
|
257
258
|
"scope": "home.user",
|
|
258
259
|
"refresh_token": self._token_refresh,
|
|
@@ -273,7 +274,13 @@ class Http:
|
|
|
273
274
|
},
|
|
274
275
|
)
|
|
275
276
|
|
|
276
|
-
|
|
277
|
+
if response.status_code == 200:
|
|
278
|
+
self._set_oauth_header(response.json())
|
|
279
|
+
return
|
|
280
|
+
|
|
281
|
+
raise TadoException(
|
|
282
|
+
f"Unknown error while refreshing token with status code {response.status_code}"
|
|
283
|
+
)
|
|
277
284
|
|
|
278
285
|
def _login(self) -> tuple[int, bool, str] | None:
|
|
279
286
|
|
|
@@ -310,9 +317,12 @@ class Http:
|
|
|
310
317
|
if response.status_code == 200:
|
|
311
318
|
refresh_token = self._set_oauth_header(response.json())
|
|
312
319
|
id_ = self._get_id()
|
|
313
|
-
x_api_ = self._check_x_line_generation()
|
|
314
320
|
|
|
315
|
-
return id_,
|
|
321
|
+
return id_, refresh_token
|
|
322
|
+
|
|
323
|
+
raise TadoException(
|
|
324
|
+
f"Login failed for unknown reason with status code {response.status_code}"
|
|
325
|
+
)
|
|
316
326
|
|
|
317
327
|
def _get_id(self) -> int:
|
|
318
328
|
request = TadoRequest()
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "python-tado"
|
|
7
|
-
version = "0.18.
|
|
7
|
+
version = "0.18.2"
|
|
8
8
|
description = "PyTado from chrism0dwk, modfied by w.malgadey, diplix, michaelarnauts, LenhartStephan, splifter, syssi, andersonshatch, Yippy, p0thi, Coffee2CodeNL, chiefdragon, FilBr, nikilase, albertomontesg, Moritz-Schmidt, palazzem"
|
|
9
9
|
authors = [
|
|
10
10
|
{ name = "Chris Jewell", email = "chrism0dwk@gmail.com" },
|
|
@@ -30,7 +30,7 @@ classifiers = [
|
|
|
30
30
|
GitHub = "https://github.com/wmalgadey/PyTado"
|
|
31
31
|
|
|
32
32
|
[project.optional-dependencies]
|
|
33
|
-
dev = ["black>=24.3", "pytype", "pylint", "types-requests", "pytest"]
|
|
33
|
+
dev = ["black>=24.3", "pytype", "pylint", "types-requests", "responses", "coverage", "pytest", "pytest-cov"]
|
|
34
34
|
|
|
35
35
|
[project.scripts]
|
|
36
36
|
pytado = "pytado.__main__:main"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: python-tado
|
|
3
|
-
Version: 0.18.
|
|
3
|
+
Version: 0.18.2
|
|
4
4
|
Summary: PyTado from chrism0dwk, modfied by w.malgadey, diplix, michaelarnauts, LenhartStephan, splifter, syssi, andersonshatch, Yippy, p0thi, Coffee2CodeNL, chiefdragon, FilBr, nikilase, albertomontesg, Moritz-Schmidt, palazzem
|
|
5
5
|
Author-email: Chris Jewell <chrism0dwk@gmail.com>, "w.malgadey" <w.malgadey@gmail.com>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -699,7 +699,10 @@ Requires-Dist: black>=24.3; extra == "dev"
|
|
|
699
699
|
Requires-Dist: pytype; extra == "dev"
|
|
700
700
|
Requires-Dist: pylint; extra == "dev"
|
|
701
701
|
Requires-Dist: types-requests; extra == "dev"
|
|
702
|
+
Requires-Dist: responses; extra == "dev"
|
|
703
|
+
Requires-Dist: coverage; extra == "dev"
|
|
702
704
|
Requires-Dist: pytest; extra == "dev"
|
|
705
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
703
706
|
|
|
704
707
|
PyTado -- Pythonize your central heating
|
|
705
708
|
========================================
|
|
@@ -7,7 +7,7 @@ PyTado/__main__.py
|
|
|
7
7
|
PyTado/const.py
|
|
8
8
|
PyTado/exceptions.py
|
|
9
9
|
PyTado/http.py
|
|
10
|
-
PyTado/
|
|
10
|
+
PyTado/logger.py
|
|
11
11
|
PyTado/interface/__init__.py
|
|
12
12
|
PyTado/interface/interface.py
|
|
13
13
|
PyTado/interface/api/__init__.py
|
|
@@ -23,5 +23,7 @@ python_tado.egg-info/entry_points.txt
|
|
|
23
23
|
python_tado.egg-info/not-zip-safe
|
|
24
24
|
python_tado.egg-info/requires.txt
|
|
25
25
|
python_tado.egg-info/top_level.txt
|
|
26
|
+
tests/test_http.py
|
|
26
27
|
tests/test_my_tado.py
|
|
27
|
-
tests/test_my_zone.py
|
|
28
|
+
tests/test_my_zone.py
|
|
29
|
+
tests/test_tado_interface.py
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"""Test the Http class."""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime, timedelta
|
|
4
|
+
import json
|
|
5
|
+
import responses
|
|
6
|
+
import unittest
|
|
7
|
+
|
|
8
|
+
from PyTado.const import CLIENT_ID, CLIENT_SECRET
|
|
9
|
+
from PyTado.exceptions import TadoException, TadoWrongCredentialsException
|
|
10
|
+
|
|
11
|
+
from . import common
|
|
12
|
+
|
|
13
|
+
from PyTado.http import Http
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class TestHttp(unittest.TestCase):
|
|
17
|
+
"""Testcases for Http class."""
|
|
18
|
+
|
|
19
|
+
def setUp(self):
|
|
20
|
+
super().setUp()
|
|
21
|
+
|
|
22
|
+
# Mock the login response
|
|
23
|
+
responses.add(
|
|
24
|
+
responses.POST,
|
|
25
|
+
"https://auth.tado.com/oauth/token",
|
|
26
|
+
json={
|
|
27
|
+
"access_token": "value",
|
|
28
|
+
"expires_in": 1234,
|
|
29
|
+
"refresh_token": "another_value",
|
|
30
|
+
},
|
|
31
|
+
status=200,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
responses.add(
|
|
35
|
+
responses.GET,
|
|
36
|
+
"https://my.tado.com/api/v2/homes/1234/",
|
|
37
|
+
json={"homes": [{"id": 1234}]},
|
|
38
|
+
status=200,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
# Mock the get me response
|
|
42
|
+
responses.add(
|
|
43
|
+
responses.GET,
|
|
44
|
+
"https://my.tado.com/api/v2/me",
|
|
45
|
+
json={"homes": [{"id": 1234}]},
|
|
46
|
+
status=200,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
@responses.activate
|
|
50
|
+
def test_login_successful(self):
|
|
51
|
+
|
|
52
|
+
instance = Http(
|
|
53
|
+
username="test_user",
|
|
54
|
+
password="test_pass",
|
|
55
|
+
debug=True,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# Verify that the login was successful
|
|
59
|
+
self.assertEqual(instance._id, 1234)
|
|
60
|
+
self.assertEqual(instance.is_x_line, False)
|
|
61
|
+
|
|
62
|
+
@responses.activate
|
|
63
|
+
def test_login_failed(self):
|
|
64
|
+
|
|
65
|
+
responses.replace(
|
|
66
|
+
responses.POST,
|
|
67
|
+
"https://auth.tado.com/oauth/token",
|
|
68
|
+
json={"error": "invalid_grant"},
|
|
69
|
+
status=400,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
with self.assertRaises(
|
|
73
|
+
expected_exception=TadoWrongCredentialsException,
|
|
74
|
+
msg="Your username or password is invalid",
|
|
75
|
+
):
|
|
76
|
+
Http(
|
|
77
|
+
username="test_user",
|
|
78
|
+
password="test_pass",
|
|
79
|
+
debug=True,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
responses.replace(
|
|
83
|
+
responses.POST,
|
|
84
|
+
"https://auth.tado.com/oauth/token",
|
|
85
|
+
json={"error": "server failed"},
|
|
86
|
+
status=503,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
with self.assertRaises(
|
|
90
|
+
expected_exception=TadoException,
|
|
91
|
+
msg="Login failed for unknown reason with status code 503",
|
|
92
|
+
):
|
|
93
|
+
Http(
|
|
94
|
+
username="test_user",
|
|
95
|
+
password="test_pass",
|
|
96
|
+
debug=True,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
@responses.activate
|
|
100
|
+
def test_line_x(self):
|
|
101
|
+
|
|
102
|
+
responses.replace(
|
|
103
|
+
responses.GET,
|
|
104
|
+
"https://my.tado.com/api/v2/homes/1234/",
|
|
105
|
+
json=json.loads(common.load_fixture("tadox/homes_response.json")),
|
|
106
|
+
status=200,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
instance = Http(
|
|
110
|
+
username="test_user",
|
|
111
|
+
password="test_pass",
|
|
112
|
+
debug=True,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# Verify that the login was successful
|
|
116
|
+
self.assertEqual(instance._id, 1234)
|
|
117
|
+
self.assertEqual(instance.is_x_line, True)
|
|
118
|
+
|
|
119
|
+
@responses.activate
|
|
120
|
+
def test_refresh_token_success(self):
|
|
121
|
+
instance = Http(
|
|
122
|
+
username="test_user",
|
|
123
|
+
password="test_pass",
|
|
124
|
+
debug=True,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
expected_params = {
|
|
128
|
+
"client_id": CLIENT_ID,
|
|
129
|
+
"client_secret": CLIENT_SECRET,
|
|
130
|
+
"grant_type": "refresh_token",
|
|
131
|
+
"scope": "home.user",
|
|
132
|
+
"refresh_token": "another_value",
|
|
133
|
+
}
|
|
134
|
+
# Mock the refresh token response
|
|
135
|
+
refresh_token = responses.replace(
|
|
136
|
+
responses.POST,
|
|
137
|
+
"https://auth.tado.com/oauth/token",
|
|
138
|
+
match=[
|
|
139
|
+
responses.matchers.query_param_matcher(expected_params),
|
|
140
|
+
],
|
|
141
|
+
json={
|
|
142
|
+
"access_token": "new_value",
|
|
143
|
+
"expires_in": 1234,
|
|
144
|
+
"refresh_token": "new_refresh_value",
|
|
145
|
+
},
|
|
146
|
+
status=200,
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
# Force token refresh
|
|
150
|
+
instance._refresh_at = datetime.now() - timedelta(seconds=1)
|
|
151
|
+
instance._refresh_token()
|
|
152
|
+
|
|
153
|
+
assert refresh_token.call_count == 1
|
|
154
|
+
|
|
155
|
+
# Verify that the token was refreshed
|
|
156
|
+
self.assertEqual(instance._headers["Authorization"], "Bearer new_value")
|
|
157
|
+
|
|
158
|
+
@responses.activate
|
|
159
|
+
def test_refresh_token_failure(self):
|
|
160
|
+
instance = Http(
|
|
161
|
+
username="test_user",
|
|
162
|
+
password="test_pass",
|
|
163
|
+
debug=True,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
# Mock the refresh token response with failure
|
|
167
|
+
refresh_token = responses.replace(
|
|
168
|
+
responses.POST,
|
|
169
|
+
"https://auth.tado.com/oauth/token",
|
|
170
|
+
json={"error": "invalid_grant"},
|
|
171
|
+
status=400,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
# Force token refresh
|
|
175
|
+
instance._refresh_at = datetime.now() - timedelta(seconds=1)
|
|
176
|
+
|
|
177
|
+
with self.assertRaises(TadoException):
|
|
178
|
+
instance._refresh_token()
|
|
179
|
+
|
|
180
|
+
assert refresh_token.call_count == 1
|
|
@@ -16,7 +16,7 @@ class TadoTestCase(unittest.TestCase):
|
|
|
16
16
|
def setUp(self) -> None:
|
|
17
17
|
super().setUp()
|
|
18
18
|
login_patch = mock.patch(
|
|
19
|
-
"PyTado.http.Http._login", return_value=(1,
|
|
19
|
+
"PyTado.http.Http._login", return_value=(1, "foo")
|
|
20
20
|
)
|
|
21
21
|
get_me_patch = mock.patch("PyTado.interface.api.Tado.get_me")
|
|
22
22
|
login_patch.start()
|
|
@@ -10,13 +10,13 @@ from PyTado.http import Http
|
|
|
10
10
|
from PyTado.interface.api import Tado
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class
|
|
13
|
+
class TadoZoneTestCase(unittest.TestCase):
|
|
14
14
|
"""Test cases for zone class"""
|
|
15
15
|
|
|
16
16
|
def setUp(self) -> None:
|
|
17
17
|
super().setUp()
|
|
18
18
|
login_patch = mock.patch(
|
|
19
|
-
"PyTado.http.Http._login", return_value=(1,
|
|
19
|
+
"PyTado.http.Http._login", return_value=(1, "foo")
|
|
20
20
|
)
|
|
21
21
|
get_me_patch = mock.patch("PyTado.interface.api.Tado.get_me")
|
|
22
22
|
login_patch.start()
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import unittest
|
|
3
|
+
from unittest import mock
|
|
4
|
+
|
|
5
|
+
from . import common
|
|
6
|
+
|
|
7
|
+
from PyTado.http import Http
|
|
8
|
+
from PyTado.interface import Tado
|
|
9
|
+
import PyTado.interface.api as API
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TestTadoInterface(unittest.TestCase):
|
|
13
|
+
"""Test cases for main tado interface class"""
|
|
14
|
+
|
|
15
|
+
def test_interface_with_tado_api(self):
|
|
16
|
+
login_patch = mock.patch(
|
|
17
|
+
"PyTado.http.Http._login", return_value=(1, "foo")
|
|
18
|
+
)
|
|
19
|
+
login_mock = login_patch.start()
|
|
20
|
+
check_x_patch = mock.patch(
|
|
21
|
+
"PyTado.http.Http._check_x_line_generation", return_value=False
|
|
22
|
+
)
|
|
23
|
+
check_x_patch.start()
|
|
24
|
+
self.addCleanup(check_x_patch.stop)
|
|
25
|
+
|
|
26
|
+
with mock.patch("PyTado.interface.api.my_tado.Tado.get_me") as mock_it:
|
|
27
|
+
tado_interface = Tado("my@username.com", "mypassword")
|
|
28
|
+
tado_interface.get_me()
|
|
29
|
+
|
|
30
|
+
assert not tado_interface._http.is_x_line
|
|
31
|
+
mock_it.assert_called_once()
|
|
32
|
+
|
|
33
|
+
with mock.patch(
|
|
34
|
+
"PyTado.interface.api.hops_tado.TadoX.get_me"
|
|
35
|
+
) as mock_it:
|
|
36
|
+
tado_interface = Tado("my@username.com", "mypassword")
|
|
37
|
+
tado_interface.get_me()
|
|
38
|
+
|
|
39
|
+
mock_it.assert_not_called()
|
|
40
|
+
|
|
41
|
+
assert login_mock.call_count == 2
|
|
42
|
+
|
|
43
|
+
def test_interface_with_tadox_api(self):
|
|
44
|
+
login_patch = mock.patch(
|
|
45
|
+
"PyTado.http.Http._login", return_value=(1, "foo")
|
|
46
|
+
)
|
|
47
|
+
login_mock = login_patch.start()
|
|
48
|
+
check_x_patch = mock.patch(
|
|
49
|
+
"PyTado.http.Http._check_x_line_generation", return_value=True
|
|
50
|
+
)
|
|
51
|
+
check_x_patch.start()
|
|
52
|
+
self.addCleanup(check_x_patch.stop)
|
|
53
|
+
|
|
54
|
+
with mock.patch(
|
|
55
|
+
"PyTado.interface.api.hops_tado.TadoX.get_me"
|
|
56
|
+
) as mock_it:
|
|
57
|
+
tado_interface = Tado("my@username.com", "mypassword")
|
|
58
|
+
tado_interface.get_me()
|
|
59
|
+
|
|
60
|
+
mock_it.assert_called_once()
|
|
61
|
+
assert tado_interface._http.is_x_line
|
|
62
|
+
|
|
63
|
+
login_mock.assert_called_once()
|
|
64
|
+
|
|
65
|
+
def test_error_handling_on_api_calls(self):
|
|
66
|
+
login_patch = mock.patch(
|
|
67
|
+
"PyTado.http.Http._login", return_value=(1, "foo")
|
|
68
|
+
)
|
|
69
|
+
login_mock = login_patch.start()
|
|
70
|
+
check_x_patch = mock.patch(
|
|
71
|
+
"PyTado.http.Http._check_x_line_generation", return_value=False
|
|
72
|
+
)
|
|
73
|
+
check_x_patch.start()
|
|
74
|
+
self.addCleanup(check_x_patch.stop)
|
|
75
|
+
|
|
76
|
+
with mock.patch("PyTado.interface.api.my_tado.Tado.get_me") as mock_it:
|
|
77
|
+
mock_it.side_effect = Exception("API Error")
|
|
78
|
+
|
|
79
|
+
tado_interface = Tado("my@username.com", "mypassword")
|
|
80
|
+
|
|
81
|
+
with self.assertRaises(Exception) as context:
|
|
82
|
+
tado_interface.get_me()
|
|
83
|
+
|
|
84
|
+
self.assertIn("API Error", str(context.exception))
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|