Skip to content

Commit 6db3d30

Browse files
wmalgadeyMoritz-Schmidtinversedependabot[bot]erwindouna
authored
Add all changes for 1.0.0 to master (#148)
Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Moritz <88738242+Moritz-Schmidt@users.noreply.github.com> Co-authored-by: Malachi Soord <inverse.chi@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Erwin Douna <e.douna@gmail.com> Co-authored-by: Michael Scott <micsco@gmail.com>
1 parent 4e33fb4 commit 6db3d30

File tree

12 files changed

+1439
-505
lines changed

12 files changed

+1439
-505
lines changed

.vscode/settings.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
{
22
"python.linting.pylintEnabled": true,
33
"cSpell.words": [
4-
"Tado"
4+
"Tado",
5+
"Pythonize",
6+
"pypi",
7+
"pytado"
58
],
9+
"python.linting.flake8Enabled": true,
10+
"python.linting.enabled": true,
11+
"python.testing.autoTestDiscoverOnSaveEnabled": true,
612
"python.testing.pytestArgs": [
713
"."
814
],

MigrationV1.0.0.md

Lines changed: 502 additions & 0 deletions
Large diffs are not rendered by default.

PyTado/factory/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
"""Factory method for easy initialization."""
2+
3+
from ..interface.api.hops_tado import TadoX
4+
from ..interface.api.my_tado import Tado
5+
from .initializer import TadoClientInitializer
6+
7+
__all__ = ["Tado", "TadoX", "TadoClientInitializer"]

PyTado/factory/initializer.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
"""
2+
PyTado API factory to use app.tado.com or hops.tado.com
3+
"""
4+
5+
from typing import Self
6+
7+
import requests
8+
9+
import PyTado.interface.api as API
10+
from PyTado.exceptions import TadoException
11+
from PyTado.http import DeviceActivationStatus, Http
12+
13+
14+
class TadoClientInitializer:
15+
"""Class to authenticate and get the Tado client."""
16+
17+
http: Http
18+
debug: bool = False
19+
token_file_path: str | None = None
20+
saved_refresh_token: str | None = None
21+
http_session: requests.Session | None = None
22+
23+
def __init__(
24+
self,
25+
token_file_path: str | None = None,
26+
saved_refresh_token: str | None = None,
27+
http_session: requests.Session | None = None,
28+
debug: bool = False,
29+
):
30+
self.token_file_path = token_file_path
31+
self.saved_refresh_token = saved_refresh_token
32+
self.http_session = http_session
33+
self.debug = debug
34+
self.http = Http(
35+
token_file_path=token_file_path,
36+
saved_refresh_token=saved_refresh_token,
37+
http_session=http_session,
38+
debug=debug,
39+
)
40+
41+
def get_verification_url(self) -> str | None:
42+
"""Returns the URL for device verification."""
43+
if self.http.device_activation_status == DeviceActivationStatus.NOT_STARTED:
44+
self.device_activation()
45+
46+
return self.http.device_verification_url
47+
48+
def device_activation(self) -> Self:
49+
"""Activates the device.
50+
51+
Caution: this method will block until the device is activated or the timeout is reached.
52+
"""
53+
self.http.device_activation()
54+
55+
return self
56+
57+
def get_client(self) -> API.TadoX | API.Tado:
58+
"""Returns the client instance after device activation."""
59+
if self.http.device_activation_status == DeviceActivationStatus.COMPLETED:
60+
if self.http.is_x_line:
61+
return API.TadoX.from_http(http=self.http, debug=self.debug)
62+
63+
return API.Tado.from_http(http=self.http, debug=self.debug)
64+
65+
raise TadoException(
66+
"Authentication failed. Please check the device verification URL and try again."
67+
)
68+
69+
def authenticate_and_get_client(self) -> API.TadoX | API.Tado:
70+
"""Authenticate and get the client instance, prompting for device activation if needed."""
71+
print("Starting device activation process...")
72+
print("Device activation status: ", self.http.device_activation_status)
73+
74+
if self.http.device_activation_status != DeviceActivationStatus.COMPLETED:
75+
print("Click on the link to log in to your Tado account.")
76+
print("Device verification URL: ", self.get_verification_url())
77+
78+
self.device_activation()
79+
80+
if (
81+
self.http.device_activation_status == DeviceActivationStatus.COMPLETED
82+
): # pyright: ignore[reportUnnecessaryComparison]
83+
print("Device activation completed successfully.")
84+
else:
85+
raise TadoException(
86+
"Device activation failed. "
87+
"Please check the device verification URL and try again."
88+
)
89+
90+
return self.get_client()

PyTado/http.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ class TadoXRequest(TadoRequest):
100100
def __post_init__(self) -> None:
101101
self._action = self.action
102102

103-
@property
103+
@property # type: ignore
104104
def action(self) -> Action | str:
105105
"""Get request action for Tado X"""
106106
if self._action == Action.CHANGE:

PyTado/models/util.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,10 @@ def log_failed_validation(
6565
cls, data: Any, handler: ModelWrapValidatorHandler[Self]
6666
) -> Self:
6767
"""Model validation debug helper.
68-
6968
Logs in the following cases:
7069
- (Debug) Keys in data that are not in the model
7170
- (Debug) Keys in the model that are not in the data
7271
- (Error) Validation errors
73-
7472
(This is just for debugging and development, can be removed if not needed anymore)
7573
"""
7674
try:

PyTado/zone/hops_zone.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
from PyTado.interface.api.hops_tado import TadoX # pragma: no cover
4040

4141
_LOGGER = logging.getLogger(__name__)
42-
_LOGGER.setLevel(logging.DEBUG)
4342

4443

4544
@final

README.md

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ PyTado is a Python module implementing an interface to the Tado web API. It allo
1010
Tado heating system for the purposes of monitoring or controlling their heating system, beyond what Tado themselves
1111
currently offer.
1212

13-
It is hoped that this module might be used by those who wish to tweak their Tado systems, and further optimise their
13+
It is hoped that this module might be used by those who wish to tweak their Tado systems, and further optimize their
1414
heating setups.
1515

1616
---
1717

1818
Original author: Chris Jewell <chrism0dwk@gmail.com>
1919

20-
Licence: GPL v3
20+
License: GPL v3
2121

2222
Copyright: Chris Jewell 2016-2018
2323

@@ -26,7 +26,7 @@ Copyright: Chris Jewell 2016-2018
2626
Besides owning a Tado system, I have no connection with the Tado company themselves. PyTado was created for my own use,
2727
and for others who may wish to experiment with personal Internet of Things systems. I receive no help (financial or
2828
otherwise) from Tado, and have no business interest with them. This software is provided without warranty, according to
29-
the GNU Public Licence version 3, and should therefore not be used where it may endanger life, financial stakes, or
29+
the GNU Public License version 3, and should therefore not be used where it may endanger life, financial stakes, or
3030
cause discomfort and inconvenience to others.
3131

3232
## Usage
@@ -54,7 +54,7 @@ It is possible to save the refresh token and reuse to skip the next login.
5454

5555
The following code will use the `refresh_token` file to save the refresh-token after login, and load the refresh-token if you create the Tado interface class again.
5656

57-
If the file doesn't exists, the webbrowser is started and the device authentication url is automatically opened. You can activate the device in the browser. When you restart the program, the refresh-token is reused and no webbrowser will be opened.
57+
If the file doesn't exists, the web browser is started and the device authentication url is automatically opened. You can activate the device in the browser. When you restart the program, the refresh-token is reused and no web browser will be opened.
5858

5959
```python
6060
import webbrowser # only needed for direct web browser access
@@ -111,7 +111,6 @@ if __name__ == "__main__":
111111
Note: For developers, there is an `example.py` script in `examples/` which is configured to fetch data from your account.
112112
You can then invoke `python examples/example.py`.
113113

114-
115114
## Contributing
116115

117116
We are very open to the community's contributions - be it a quick fix of a typo, or a completely new feature!
@@ -143,20 +142,7 @@ git clone https://github.com/yourusername/PyTado.git
143142
cd PyTado
144143
```
145144

146-
Then, to create your development environment and install the project with its dependencies, execute the following
147-
commands in your terminal:
148-
149-
```bash
150-
# Create and activate a new virtual environment
151-
python3 -m venv venv
152-
source venv/bin/activate
153-
154-
# install all dependencies
155-
poetry install
156-
157-
# Install pre-commit hooks
158-
poetry run pre-commit install
159-
```
145+
Then, to create your development environment and install the project with its dependencies, execute the `./scripts/bootstrap` script.
160146

161147
### Coding Guidelines
162148

@@ -195,6 +181,5 @@ A message from the original author:
195181
>
196182
> Chris Jewell
197183
198-
199184
[devcontainer-shield]: https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=visualstudiocode
200185
[devcontainer]: https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/wmalgadey/PyTado

examples/example.py

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,14 @@
11
"""Example client for PyTado"""
22

3-
from PyTado.interface.interface import Tado
3+
from PyTado.factory import TadoClientInitializer
44

55

66
def main() -> None:
77
"""Retrieve all zones, once successfully logged in"""
8-
tado = Tado()
9-
10-
print("Device activation status: ", tado.device_activation_status())
11-
print("Device verification URL: ", tado.device_verification_url())
12-
13-
print("Starting device activation")
14-
tado.device_activation()
15-
16-
print("Device activation status: ", tado.device_activation_status())
8+
tado = TadoClientInitializer().authenticate_and_get_client()
179

1810
zones = tado.get_zones()
11+
1912
print(zones)
2013

2114

0 commit comments

Comments
 (0)