PyViCare 2.60.0__tar.gz → 2.60.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.
Files changed (31) hide show
  1. {pyvicare-2.60.0 → pyvicare-2.60.2}/PKG-INFO +1 -1
  2. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCare.py +2 -2
  3. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareOAuthManager.py +76 -0
  4. {pyvicare-2.60.0 → pyvicare-2.60.2}/pyproject.toml +2 -1
  5. {pyvicare-2.60.0 → pyvicare-2.60.2}/LICENSE +0 -0
  6. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/Feature.py +0 -0
  7. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareAbstractOAuthManager.py +0 -0
  8. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareBrowserOAuthManager.py +0 -0
  9. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareCachedService.py +0 -0
  10. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareDevice.py +0 -0
  11. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareDeviceConfig.py +0 -0
  12. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareElectricalEnergySystem.py +0 -0
  13. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareFloorHeating.py +0 -0
  14. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareFuelCell.py +0 -0
  15. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareGateway.py +0 -0
  16. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareGazBoiler.py +0 -0
  17. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareHeatCurveCalculation.py +0 -0
  18. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareHeatPump.py +0 -0
  19. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareHeatingDevice.py +0 -0
  20. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareHybrid.py +0 -0
  21. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareOilBoiler.py +0 -0
  22. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCarePelletsBoiler.py +0 -0
  23. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareRadiatorActuator.py +0 -0
  24. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareRepeater.py +0 -0
  25. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareRoomControl.py +0 -0
  26. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareRoomSensor.py +0 -0
  27. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareService.py +0 -0
  28. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareUtils.py +0 -0
  29. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareVentilationDevice.py +0 -0
  30. {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/__init__.py +0 -0
  31. {pyvicare-2.60.0 → pyvicare-2.60.2}/README.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyViCare
3
- Version: 2.60.0
3
+ Version: 2.60.2
4
4
  Summary: Library to communicate with the Viessmann ViCare API.
5
5
  License: Apache-2.0
6
6
  License-File: LICENSE
@@ -8,7 +8,7 @@ from PyViCare.PyViCareDeviceConfig import PyViCareDeviceConfig
8
8
  from PyViCare.PyViCareOAuthManager import ViCareOAuthManager
9
9
  from PyViCare.PyViCareRoomControl import RoomControl
10
10
  from PyViCare.PyViCareService import ViCareDeviceAccessor, ViCareService
11
- from PyViCare.PyViCareUtils import PyViCareInvalidDataError, PyViCareNotSupportedFeatureError
11
+ from PyViCare.PyViCareUtils import PyViCareInvalidDataError
12
12
 
13
13
  logger = logging.getLogger(__name__)
14
14
  logger.addHandler(logging.NullHandler())
@@ -86,7 +86,7 @@ class PyViCare:
86
86
  room_control = RoomControl(device_config.service)
87
87
  try:
88
88
  actor_map = room_control.buildActorRoomMap()
89
- except (KeyError, IndexError, PyViCareNotSupportedFeatureError):
89
+ except Exception: # pylint: disable=broad-exception-caught
90
90
  logger.debug("Could not build actor map for %s", device_config.getModel(), exc_info=True)
91
91
  continue
92
92
 
@@ -1,16 +1,19 @@
1
1
  import logging
2
2
  import os
3
3
  import pickle
4
+ import warnings
4
5
  from contextlib import suppress
5
6
  from pickle import UnpicklingError
6
7
 
7
8
  import requests
8
9
  from authlib.common.security import generate_token
10
+ from authlib.integrations.base_client.errors import OAuthError
9
11
  from authlib.integrations.requests_client import OAuth2Session
10
12
 
11
13
  from PyViCare.PyViCareAbstractOAuthManager import (
12
14
  AUTHORIZE_URL,
13
15
  SCOPE_IOT,
16
+ SCOPE_OFFLINE_ACCESS,
14
17
  SCOPE_USER,
15
18
  TOKEN_URL,
16
19
  AbstractViCareOAuthManager,
@@ -24,6 +27,79 @@ logger.addHandler(logging.NullHandler())
24
27
  REDIRECT_URI = "vicare://oauth-callback/everest"
25
28
 
26
29
 
30
+ def obtain_token_via_basic_auth_pkce(
31
+ client_id: str, username: str, password: str
32
+ ) -> dict[str, object]:
33
+ """Obtain an OAuth2 token via PKCE auth-code flow with HTTP Basic auth.
34
+
35
+ .. deprecated::
36
+ One-shot migration helper for Home Assistant's password-to-OAuth2
37
+ migration (see home-assistant/core#165621). Scheduled for removal
38
+ once the migration window has closed. New code should use the
39
+ standard OAuth2 auth-code flow.
40
+
41
+ Viessmann's authorization endpoint accepts HTTP Basic auth and returns
42
+ the auth code in the redirect Location header (no browser involved).
43
+ Useful for one-shot migration from stored username/password to OAuth2,
44
+ so users don't need to re-authenticate interactively.
45
+
46
+ Requests scopes ``IoT`` and ``offline_access`` (sufficient for all
47
+ PyViCare API endpoints; ``offline_access`` is required to receive a
48
+ refresh token).
49
+
50
+ Returns the token dict (access_token, refresh_token, expires_at, etc.)
51
+ on success, or an empty dict on any failure (auth server unreachable,
52
+ credentials rejected, token exchange failed). Failures are logged at
53
+ WARNING level.
54
+ """
55
+ warnings.warn(
56
+ "obtain_token_via_basic_auth_pkce is a one-shot migration helper "
57
+ "for Home Assistant's password-to-OAuth2 migration and is scheduled "
58
+ "for removal. New code should use the standard OAuth2 auth-code flow.",
59
+ DeprecationWarning,
60
+ stacklevel=2,
61
+ )
62
+ oauth = OAuth2Session(
63
+ client_id,
64
+ redirect_uri=REDIRECT_URI,
65
+ scope=[SCOPE_IOT, SCOPE_OFFLINE_ACCESS],
66
+ code_challenge_method="S256",
67
+ )
68
+ code_verifier = generate_token(48)
69
+ auth_url, _ = oauth.create_authorization_url(
70
+ AUTHORIZE_URL, code_verifier=code_verifier
71
+ )
72
+
73
+ try:
74
+ response = requests.post(
75
+ auth_url,
76
+ headers={"Content-Type": "application/x-www-form-urlencoded"},
77
+ auth=(username, password),
78
+ allow_redirects=False,
79
+ timeout=15,
80
+ )
81
+ except requests.RequestException:
82
+ logger.warning("Failed to reach Viessmann auth server")
83
+ return {}
84
+
85
+ if response.status_code != 302 or "Location" not in response.headers:
86
+ logger.warning("Basic-auth authorization failed")
87
+ return {}
88
+
89
+ try:
90
+ oauth.fetch_token(
91
+ TOKEN_URL,
92
+ authorization_response=response.headers["Location"],
93
+ code_verifier=code_verifier,
94
+ timeout=15,
95
+ )
96
+ except (requests.RequestException, OAuthError, KeyError, ValueError):
97
+ logger.warning("Token exchange failed")
98
+ return {}
99
+
100
+ return dict(oauth.token)
101
+
102
+
27
103
  class ViCareOAuthManager(AbstractViCareOAuthManager):
28
104
  def __init__(self, username, password, client_id, token_file):
29
105
  self.username = username
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "PyViCare"
3
- version = "2.60.0"
3
+ version = "2.60.2"
4
4
  description = "Library to communicate with the Viessmann ViCare API."
5
5
  authors = [
6
6
  "Simon Gillet <mail+pyvicare@gillet.ninja>"
@@ -27,6 +27,7 @@ classifiers = [
27
27
  "Programming Language :: Python :: 3.11",
28
28
  "Programming Language :: Python :: 3.12",
29
29
  "Programming Language :: Python :: 3.13",
30
+ "Programming Language :: Python :: 3.14",
30
31
  "Programming Language :: Python :: 3",
31
32
  "License :: OSI Approved :: Apache Software License",
32
33
  "Topic :: Software Development :: Libraries :: Python Modules",
File without changes
File without changes
File without changes