python-tado 0.18.1__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.1/python_tado.egg-info → python_tado-0.18.2}/PKG-INFO +2 -1
- {python_tado-0.18.1 → python_tado-0.18.2}/PyTado/const.py +6 -0
- {python_tado-0.18.1 → python_tado-0.18.2}/PyTado/exceptions.py +0 -4
- {python_tado-0.18.1 → python_tado-0.18.2}/PyTado/http.py +19 -10
- {python_tado-0.18.1 → python_tado-0.18.2}/PyTado/interface/api/hops_tado.py +1 -1
- {python_tado-0.18.1 → python_tado-0.18.2}/PyTado/interface/api/my_tado.py +1 -1
- {python_tado-0.18.1 → python_tado-0.18.2}/pyproject.toml +2 -2
- {python_tado-0.18.1 → python_tado-0.18.2/python_tado.egg-info}/PKG-INFO +2 -1
- {python_tado-0.18.1 → python_tado-0.18.2}/python_tado.egg-info/SOURCES.txt +2 -1
- {python_tado-0.18.1 → python_tado-0.18.2}/python_tado.egg-info/requires.txt +1 -0
- python_tado-0.18.2/tests/test_http.py +180 -0
- {python_tado-0.18.1 → python_tado-0.18.2}/tests/test_my_tado.py +1 -1
- {python_tado-0.18.1 → python_tado-0.18.2}/tests/test_my_zone.py +1 -1
- {python_tado-0.18.1 → python_tado-0.18.2}/tests/test_tado_interface.py +19 -7
- {python_tado-0.18.1 → python_tado-0.18.2}/AUTHORS +0 -0
- {python_tado-0.18.1 → python_tado-0.18.2}/LICENSE +0 -0
- {python_tado-0.18.1 → python_tado-0.18.2}/PyTado/__init__.py +0 -0
- {python_tado-0.18.1 → python_tado-0.18.2}/PyTado/__main__.py +0 -0
- {python_tado-0.18.1 → python_tado-0.18.2}/PyTado/interface/__init__.py +0 -0
- {python_tado-0.18.1 → python_tado-0.18.2}/PyTado/interface/api/__init__.py +0 -0
- {python_tado-0.18.1 → python_tado-0.18.2}/PyTado/interface/interface.py +0 -0
- /python_tado-0.18.1/PyTado/logging.py → /python_tado-0.18.2/PyTado/logger.py +0 -0
- {python_tado-0.18.1 → python_tado-0.18.2}/PyTado/zone/__init__.py +0 -0
- {python_tado-0.18.1 → python_tado-0.18.2}/PyTado/zone/hops_zone.py +0 -0
- {python_tado-0.18.1 → python_tado-0.18.2}/PyTado/zone/my_zone.py +0 -0
- {python_tado-0.18.1 → python_tado-0.18.2}/README.md +0 -0
- {python_tado-0.18.1 → python_tado-0.18.2}/python_tado.egg-info/dependency_links.txt +0 -0
- {python_tado-0.18.1 → python_tado-0.18.2}/python_tado.egg-info/entry_points.txt +0 -0
- {python_tado-0.18.1 → python_tado-0.18.2}/python_tado.egg-info/not-zip-safe +0 -0
- {python_tado-0.18.1 → python_tado-0.18.2}/python_tado.egg-info/top_level.txt +0 -0
- {python_tado-0.18.1 → 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,6 +699,7 @@ 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"
|
|
702
703
|
Requires-Dist: coverage; extra == "dev"
|
|
703
704
|
Requires-Dist: pytest; extra == "dev"
|
|
704
705
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
@@ -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
|
|
@@ -250,10 +252,8 @@ class Http:
|
|
|
250
252
|
|
|
251
253
|
url = "https://auth.tado.com/oauth/token"
|
|
252
254
|
data = {
|
|
253
|
-
"client_id":
|
|
254
|
-
"client_secret":
|
|
255
|
-
"wZaRN7rpjn3FoNyF5IFuxg9uMzYJcvOoQ8QWiIqS3hfk6gLhVlG57j5YNoZL2Rtc"
|
|
256
|
-
),
|
|
255
|
+
"client_id": CLIENT_ID,
|
|
256
|
+
"client_secret": CLIENT_SECRET,
|
|
257
257
|
"grant_type": "refresh_token",
|
|
258
258
|
"scope": "home.user",
|
|
259
259
|
"refresh_token": self._token_refresh,
|
|
@@ -274,7 +274,13 @@ class Http:
|
|
|
274
274
|
},
|
|
275
275
|
)
|
|
276
276
|
|
|
277
|
-
|
|
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
|
+
)
|
|
278
284
|
|
|
279
285
|
def _login(self) -> tuple[int, bool, str] | None:
|
|
280
286
|
|
|
@@ -311,9 +317,12 @@ class Http:
|
|
|
311
317
|
if response.status_code == 200:
|
|
312
318
|
refresh_token = self._set_oauth_header(response.json())
|
|
313
319
|
id_ = self._get_id()
|
|
314
|
-
x_api_ = self._check_x_line_generation()
|
|
315
320
|
|
|
316
|
-
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
|
+
)
|
|
317
326
|
|
|
318
327
|
def _get_id(self) -> int:
|
|
319
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", "coverage", "pytest", "pytest-cov"]
|
|
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,6 +699,7 @@ 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"
|
|
702
703
|
Requires-Dist: coverage; extra == "dev"
|
|
703
704
|
Requires-Dist: pytest; extra == "dev"
|
|
704
705
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
@@ -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,6 +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
28
|
tests/test_my_zone.py
|
|
28
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()
|
|
@@ -16,7 +16,7 @@ class TadoZoneTestCase(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()
|
|
@@ -14,10 +14,14 @@ class TestTadoInterface(unittest.TestCase):
|
|
|
14
14
|
|
|
15
15
|
def test_interface_with_tado_api(self):
|
|
16
16
|
login_patch = mock.patch(
|
|
17
|
-
"PyTado.http.Http._login", return_value=(1,
|
|
17
|
+
"PyTado.http.Http._login", return_value=(1, "foo")
|
|
18
18
|
)
|
|
19
19
|
login_mock = login_patch.start()
|
|
20
|
-
|
|
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)
|
|
21
25
|
|
|
22
26
|
with mock.patch("PyTado.interface.api.my_tado.Tado.get_me") as mock_it:
|
|
23
27
|
tado_interface = Tado("my@username.com", "mypassword")
|
|
@@ -38,10 +42,14 @@ class TestTadoInterface(unittest.TestCase):
|
|
|
38
42
|
|
|
39
43
|
def test_interface_with_tadox_api(self):
|
|
40
44
|
login_patch = mock.patch(
|
|
41
|
-
"PyTado.http.Http._login", return_value=(1,
|
|
45
|
+
"PyTado.http.Http._login", return_value=(1, "foo")
|
|
42
46
|
)
|
|
43
47
|
login_mock = login_patch.start()
|
|
44
|
-
|
|
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)
|
|
45
53
|
|
|
46
54
|
with mock.patch(
|
|
47
55
|
"PyTado.interface.api.hops_tado.TadoX.get_me"
|
|
@@ -56,10 +64,14 @@ class TestTadoInterface(unittest.TestCase):
|
|
|
56
64
|
|
|
57
65
|
def test_error_handling_on_api_calls(self):
|
|
58
66
|
login_patch = mock.patch(
|
|
59
|
-
"PyTado.http.Http._login", return_value=(1,
|
|
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
|
|
60
72
|
)
|
|
61
|
-
|
|
62
|
-
self.addCleanup(
|
|
73
|
+
check_x_patch.start()
|
|
74
|
+
self.addCleanup(check_x_patch.stop)
|
|
63
75
|
|
|
64
76
|
with mock.patch("PyTado.interface.api.my_tado.Tado.get_me") as mock_it:
|
|
65
77
|
mock_it.side_effect = Exception("API Error")
|
|
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
|
|
File without changes
|