Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-fritzconnection for 
openSUSE:Factory checked in at 2025-07-14 10:52:07
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-fritzconnection (Old)
 and      /work/SRC/openSUSE:Factory/.python-fritzconnection.new.7373 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-fritzconnection"

Mon Jul 14 10:52:07 2025 rev:12 rq:1292503 version:1.15.0

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-fritzconnection/python-fritzconnection.changes
    2025-06-17 18:23:43.978075940 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-fritzconnection.new.7373/python-fritzconnection.changes
  2025-07-14 10:57:53.512026949 +0200
@@ -1,0 +2,25 @@
+Sun Jul 13 13:09:15 UTC 2025 - Dirk Müller <dmuel...@suse.com>
+
+- update to 1.15.0:
+  * support added for Python 3.14
+  * FritzConnection:
+    - additional argument `redact_debug_log` (default: False) for
+      optional redacting response in debug output. (#238) (#241)
+    - new method `get_cpu_temperatures()` providing a list of the
+      last recent cpu-temperatures.
+   FritzCall:
+   - new attribute `Path` for the class `Call` to access an
+     optional phone message. (#231)
+   FritzStatus:
+   - new method `get_avm_device_log()` to access system events.
+     Requires FritzOS 8. (#234)
+   - bugfix: in rare cases a session id of None has prevented a
+     successfull request of the http-interface.
+   - 
`fritzconnection.lib.fritzhomeauto.FritzHomeAutomation.device_informations()`,
+      deprecated in 1.9.0
+   - `fritzconnection.lib.fritzstatus.FritzStatus.uptime()`,
+      deprecated in 1.9.0
+   - `fritzconnection.lib.fritzwlan.FritzWLAN.channel_infos()`,
+      deprecated in 1.9.0
+
+-------------------------------------------------------------------

Old:
----
  fritzconnection-1.14.0.tar.gz

New:
----
  fritzconnection-1.15.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-fritzconnection.spec ++++++
--- /var/tmp/diff_new_pack.0kQGSo/_old  2025-07-14 10:57:55.116093446 +0200
+++ /var/tmp/diff_new_pack.0kQGSo/_new  2025-07-14 10:57:55.132094109 +0200
@@ -18,7 +18,7 @@
 
 %global pythons python3
 Name:           python-fritzconnection
-Version:        1.14.0
+Version:        1.15.0
 Release:        0
 Summary:        A Python module to talk to a AVM fritzbox
 License:        MIT

++++++ fritzconnection-1.14.0.tar.gz -> fritzconnection-1.15.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fritzconnection-1.14.0/.gitignore 
new/fritzconnection-1.15.0/.gitignore
--- old/fritzconnection-1.14.0/.gitignore       2024-08-12 17:58:36.000000000 
+0200
+++ new/fritzconnection-1.15.0/.gitignore       2025-05-17 16:21:25.000000000 
+0200
@@ -16,7 +16,8 @@
 bin
 build/*
 dist/*
-docs/requirements.txt
+docs/requirements.out
+docs/requirements.local.txt
 fritzconnection.egg-info/*
 include
 lib_
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fritzconnection-1.14.0/.readthedocs.yml 
new/fritzconnection-1.15.0/.readthedocs.yml
--- old/fritzconnection-1.14.0/.readthedocs.yml 2024-08-12 17:58:36.000000000 
+0200
+++ new/fritzconnection-1.15.0/.readthedocs.yml 2025-05-17 16:21:25.000000000 
+0200
@@ -3,11 +3,13 @@
 build:
   os: ubuntu-22.04
   tools:
-    python: "3.11"
+    python: "3.12"
 
 python:
   install:
     - requirements: docs/requirements.txt
+    - method: pip
+      path: .
 
 sphinx:
   builder: html
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fritzconnection-1.14.0/CONTRIBUTING.md 
new/fritzconnection-1.15.0/CONTRIBUTING.md
--- old/fritzconnection-1.14.0/CONTRIBUTING.md  2024-08-12 17:58:36.000000000 
+0200
+++ new/fritzconnection-1.15.0/CONTRIBUTING.md  2025-05-17 16:21:25.000000000 
+0200
@@ -13,7 +13,9 @@
 
 In general pull requests are welcome. Please create an issue first before 
putting too much work into a pull request that may not get merged at the end, 
for whatever reason. An issue can help to clarify points of view and motivation.
 
-For pull requests there is a golden rule: **keep them small**. Smaller pull 
requests are easier to review and easier to merge – especially in cases when 
not every part of a larger changeset should get merged and has to get 
modifications.
+In case of providing a pull-request please do this for the 
**development-branch** and not for the master-branch.
+
+For pull-requests there is a golden rule: **keep them small**. Smaller 
pull-requests are easier to review and easier to merge – especially in cases 
when not every part of a larger changeset should get merged and has to get 
modifications.
 
 Please avoid to just change the formatting. The result is most often nothing 
else than git-diff pollution. This is especially true for `black` (or `blue` or 
the corresponding modes in `ruff`) – this project startet before `black`. It is 
ok to use these tools for modified code snippets, but not for a module.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fritzconnection-1.14.0/docs/conf.py 
new/fritzconnection-1.15.0/docs/conf.py
--- old/fritzconnection-1.14.0/docs/conf.py     2024-08-12 17:58:36.000000000 
+0200
+++ new/fritzconnection-1.15.0/docs/conf.py     2025-05-17 16:21:25.000000000 
+0200
@@ -12,9 +12,9 @@
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
 #
-# import os
-# import sys
-# sys.path.insert(0, os.path.abspath('..'))
+import os
+import sys
+sys.path.insert(0, os.path.abspath('..'))
 
 
 # -- Project information -----------------------------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fritzconnection-1.14.0/docs/requirements.in 
new/fritzconnection-1.15.0/docs/requirements.in
--- old/fritzconnection-1.14.0/docs/requirements.in     2024-08-12 
17:58:36.000000000 +0200
+++ new/fritzconnection-1.15.0/docs/requirements.in     1970-01-01 
01:00:00.000000000 +0100
@@ -1,4 +0,0 @@
-Sphinx==5.1.1
-sphinx-rtd-theme==1.2.2
-fritzconnection
-furo==2023.3.27
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fritzconnection-1.14.0/docs/requirements.local.in 
new/fritzconnection-1.15.0/docs/requirements.local.in
--- old/fritzconnection-1.14.0/docs/requirements.local.in       2024-08-12 
17:58:36.000000000 +0200
+++ new/fritzconnection-1.15.0/docs/requirements.local.in       1970-01-01 
01:00:00.000000000 +0100
@@ -1,3 +0,0 @@
-Sphinx==5.1.1
-sphinx-rtd-theme==1.2.2
-furo==2023.3.27
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fritzconnection-1.14.0/docs/requirements.txt 
new/fritzconnection-1.15.0/docs/requirements.txt
--- old/fritzconnection-1.14.0/docs/requirements.txt    2024-08-12 
17:58:36.000000000 +0200
+++ new/fritzconnection-1.15.0/docs/requirements.txt    2025-05-17 
16:21:25.000000000 +0200
@@ -1,69 +1,3 @@
-#
-# This file is autogenerated by pip-compile with Python 3.12
-# by the following command:
-#
-#    pip-compile --output-file=docs/requirements.txt --strip-extras 
docs/requirements.local.in
-#
-alabaster==0.7.16
-    # via sphinx
-babel==2.16.0
-    # via sphinx
-beautifulsoup4==4.12.3
-    # via furo
-certifi==2024.7.4
-    # via requests
-charset-normalizer==3.3.2
-    # via requests
-docutils==0.18.1
-    # via
-    #   sphinx
-    #   sphinx-rtd-theme
-furo==2023.3.27
-    # via -r docs/requirements.local.in
-idna==3.7
-    # via requests
-imagesize==1.4.1
-    # via sphinx
-jinja2==3.1.4
-    # via sphinx
-markupsafe==2.1.5
-    # via jinja2
-packaging==24.1
-    # via sphinx
-pygments==2.18.0
-    # via
-    #   furo
-    #   sphinx
-requests==2.32.3
-    # via sphinx
-snowballstemmer==2.2.0
-    # via sphinx
-soupsieve==2.5
-    # via beautifulsoup4
-sphinx==5.1.1
-    # via
-    #   -r docs/requirements.local.in
-    #   furo
-    #   sphinx-basic-ng
-    #   sphinx-rtd-theme
-    #   sphinxcontrib-jquery
-sphinx-basic-ng==1.0.0b2
-    # via furo
-sphinx-rtd-theme==1.2.2
-    # via -r docs/requirements.local.in
-sphinxcontrib-applehelp==2.0.0
-    # via sphinx
-sphinxcontrib-devhelp==2.0.0
-    # via sphinx
-sphinxcontrib-htmlhelp==2.1.0
-    # via sphinx
-sphinxcontrib-jquery==4.1
-    # via sphinx-rtd-theme
-sphinxcontrib-jsmath==1.0.1
-    # via sphinx
-sphinxcontrib-qthelp==2.0.0
-    # via sphinx
-sphinxcontrib-serializinghtml==2.0.0
-    # via sphinx
-urllib3==2.2.2
-    # via requests
+sphinx<7.4.0
+furo<2025.0.0
+#fritzconnection
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fritzconnection-1.14.0/docs/sources/version_history.rst 
new/fritzconnection-1.15.0/docs/sources/version_history.rst
--- old/fritzconnection-1.14.0/docs/sources/version_history.rst 2024-08-12 
17:58:36.000000000 +0200
+++ new/fritzconnection-1.15.0/docs/sources/version_history.rst 2025-05-17 
16:21:25.000000000 +0200
@@ -4,6 +4,32 @@
 ===============
 
 
+1.15.0 - 2025-05-17
+-------------------
+
+- support added for Python 3.14
+- FritzConnection:
+
+  - additional argument `redact_debug_log` (default: False) for optional 
redacting response in debug output. (#238) (#241)
+  - new method `get_cpu_temperatures()` providing a list of the last recent 
cpu-temperatures. (Rewrite of #232).
+
+- FritzCall:
+
+  - new attribute `Path` for the class `Call` to access an optional phone 
message. (#231)
+
+- FritzStatus:
+
+  - new method `get_avm_device_log()` to access system events. Requires 
FritzOS 8. (#234)
+
+- bugfix: in rare cases a session id of None has prevented a successfull 
request of the http-interface.
+
+- **removed**:
+
+  - 
`fritzconnection.lib.fritzhomeauto.FritzHomeAutomation.device_informations()`, 
deprecated in 1.9.0
+  - `fritzconnection.lib.fritzstatus.FritzStatus.uptime()`, deprecated in 1.9.0
+  - `fritzconnection.lib.fritzwlan.FritzWLAN.channel_infos()`, deprecated in 
1.9.0
+
+
 1.14.0 - 2024-08-12
 -------------------
 
@@ -23,7 +49,7 @@
 - bugfix: some devices may not return system-information the propper way, 
causing errors on the cli output. In these cases the system-information will 
get ignored. (#214)
 - documentation: some typos corrected. (#202, #204)
 - testing: `tox.ini` removed because of change to `nox`. Change from `pylint` 
to `ruff` for linting.
-- deprecation: use of the `json` cache-format is discouraged. Use the default 
pickle-format instead. The highly dynamic TR-064 parser may get an ouverhaul in 
the future and to reduce the complexity of the parser the support of `json` for 
caching will be removed.
+- **deprecation**: use of the `json` cache-format is discouraged. Use the 
default pickle-format instead. The highly dynamic TR-064 parser may get an 
ouverhaul in the future and to reduce the complexity of the parser the support 
of `json` for caching will be removed.
 
 
 1.13.2 - 2023-09-17
@@ -52,7 +78,7 @@
 - command-line interface: the check for a given password has been removed and 
substituted by a meaningfull error message in case of an authorization failure. 
Not every service is password-protected and passwords can optional provided by 
the environment. Therefore there is no need to require a password at cli level. 
(Motivated by #192)
 - bugfix: unneeded required password removed from the `fritzstatus` 
command-line interface. (#192)
 - bugfix: make `fritzwlan.get_beacon_security()` work with older router models 
not supporting the `NewX_AVM-DE_PossibleBeaconTypes` argument. (#191)
-- deprecation: `fritzconnection.lib.fritzphonebook.list_phonebooks()`
+- **deprecation**: `fritzconnection.lib.fritzphonebook.list_phonebooks()`
 
 
 1.12.2 - 2023-07-09
@@ -96,7 +122,7 @@
 
   - bugfix: create new socket on lost connection. (#179)
 
-- Deprecations:
+- **Deprecations**:
 
   - 
`fritzconnection.lib.fritzhomeauto.FritzHomeAutomation.device_information()`
 
@@ -186,7 +212,8 @@
   - New method `channel_info()` (#131)
 
 - FritzHomeAutomation: New method `device_information()` (#131)
-- Deprecations:
+
+- **Deprecations**:
 
   - 
`fritzconnection.lib.fritzhomeauto.FritzHomeAutomation.device_informations()`
   - `fritzconnection.lib.fritzstatus.FritzStatus.uptime()`
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fritzconnection-1.14.0/fritzconnection/__init__.py 
new/fritzconnection-1.15.0/fritzconnection/__init__.py
--- old/fritzconnection-1.14.0/fritzconnection/__init__.py      2024-08-12 
17:58:36.000000000 +0200
+++ new/fritzconnection-1.15.0/fritzconnection/__init__.py      2025-05-17 
16:21:25.000000000 +0200
@@ -13,7 +13,7 @@
 # unused shortcut import are intended:
 # ruff: noqa: F401
 
-__version__ = "1.14.0"
+__version__ = "1.15.0"
 
 # import shortcuts
 from .core.fritzconnection import FritzConnection
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fritzconnection-1.14.0/fritzconnection/core/fritzconnection.py 
new/fritzconnection-1.15.0/fritzconnection/core/fritzconnection.py
--- old/fritzconnection-1.14.0/fritzconnection/core/fritzconnection.py  
2024-08-12 17:58:36.000000000 +0200
+++ new/fritzconnection-1.15.0/fritzconnection/core/fritzconnection.py  
2025-05-17 16:21:25.000000000 +0200
@@ -170,6 +170,12 @@
     (json|pickle) and FRITZ_CACHEDIRECTORY (a path).
 
     .. versionadded:: 1.10
+
+    `redact_debug_log` accepts a boolean for enabling redacting sensitiv
+    data (i.e. phone numbers) in debug outputs. Default is `False`.
+
+    .. versionadded:: 1.15
+
     """
 
     def __init__(
@@ -186,6 +192,7 @@
         cache_format: str | None = None,
         pool_connections: int = DEFAULT_POOL_CONNECTIONS,
         pool_maxsize: int = DEFAULT_POOL_MAXSIZE,
+        redact_debug_log: bool = False
     ):
         """
         Initialisation of FritzConnection: reads all data from the box
@@ -237,6 +244,9 @@
         `pool_connections` and `pool_maxsize` accept integers for
         changing the default urllib3 settings in order to modify the
         number of reusable connections.
+
+        `redact_debug_log` accepts a boolean for enabling redacting some
+        sensitiv data in debug outputs. Default is `False`.
         """
         if address is None:
             address = FRITZ_IP_ADDRESS
@@ -279,7 +289,7 @@
         self.port = port
 
         self.soaper = Soaper(
-            address, port, user, password, timeout=timeout, session=session
+            address, port, user, password, timeout=timeout, session=session, 
redact_debug_log=redact_debug_log
         )
         self.device_manager = DeviceManager(timeout=timeout, session=session)
         self._load_router_api(
@@ -512,6 +522,18 @@
         """
         self.call_action("DeviceConfig1", "Reboot")
 
+    def get_cpu_temperatures(self) -> list[int]:
+        """
+        Returns a list of the last measured cpu-temperatures.
+        The most recent entry is the first one in the list.
+        NOTE: this function call is experimental as it is based on a
+        non-public API.
+        """
+        url = f"{self.http_interface.router_url}/query.lua"
+        payload = {"CPUTEMP": "cpu:status/StatTemperature"}
+        response = self.http_interface.call_url(url, payload)
+        return list(map(int, response.json()["CPUTEMP"].split(",")))
+
     # -------------------------------------------
     # internal methods to load router-api:
     # -------------------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fritzconnection-1.14.0/fritzconnection/core/fritzhttp.py 
new/fritzconnection-1.15.0/fritzconnection/core/fritzhttp.py
--- old/fritzconnection-1.14.0/fritzconnection/core/fritzhttp.py        
2024-08-12 17:58:36.000000000 +0200
+++ new/fritzconnection-1.15.0/fritzconnection/core/fritzhttp.py        
2025-05-17 16:21:25.000000000 +0200
@@ -54,14 +54,19 @@
         return HTTP_PORT
 
     @property
+    def router_url(self):
+        """Returns the combination of router address and port."""
+        return f"{self.fc.address}:{self.remote_port}"
+
+    @property
     def login_url(self):
         """The login-url including protocol and configurable port."""
-        return f"{self.fc.address}:{self.remote_port}{URL_LOGIN}"
+        return f"{self.router_url}{URL_LOGIN}"
 
     @property
     def homeauto_url(self):
         """The homeauto-url including protocol and configurable port."""
-        return f"{self.fc.address}:{self.remote_port}{URL_HOMEAUTOSWITCH}"
+        return f"{self.router_url}{URL_HOMEAUTOSWITCH}"
 
     def execute(self, command=None, identifier=None, **kwargs):
         """
@@ -78,13 +83,29 @@
         """
         payload = {"switchcmd": command, "ain": identifier}
         payload.update(kwargs)
+        response = self.call_url(self.homeauto_url, payload)
+        return response.headers.get('content-type'), response.text
+
+    def call_url(self, url, payload):
+        """
+        Makes a call to the router with the provided url. Returns the
+        request object in case of success. Otherwise a
+        FritzHttpInterfaceError will get raised.
+
+        Beside the public API documented by AVM this method allows calls
+        to undocumented APIs serving the router web-interface or
+        providing other data.
+
+        WARNING: For a reliable application it is highly discouraged to
+        use undocumented endpoints because they can change any time without
+        notice. So an application may not survive a router OS update.
+        """
         for sid in self._get_sid():
             payload['sid'] = sid
-            with self.fc.session.get(
-                self.homeauto_url, params=payload
-            ) as response:
+            with self.fc.session.get(url, params=payload) as response:
                 if response.status_code == HTTPStatus.OK:
-                    return response.headers.get('content-type'), response.text
+                    return response
+
         msg = f"Request failed: http error code '{response.status_code}'"
         if response.status_code == HTTPStatus.FORBIDDEN:
             # can happen if FritzConnection was initialized
@@ -102,6 +123,9 @@
         failed. This can happen on an invalide or expired sid. In this
         case the sid gets regenerated for the second try.
         """
+        if self.sid is None:
+            # a session id of None can lead to irritation
+            self._set_sid_from_box()
         yield self.sid
         self._set_sid_from_box()
         yield self.sid
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fritzconnection-1.14.0/fritzconnection/core/soaper.py 
new/fritzconnection-1.15.0/fritzconnection/core/soaper.py
--- old/fritzconnection-1.14.0/fritzconnection/core/soaper.py   2024-08-12 
17:58:36.000000000 +0200
+++ new/fritzconnection-1.15.0/fritzconnection/core/soaper.py   2025-05-17 
16:21:25.000000000 +0200
@@ -8,6 +8,7 @@
 
 
 import datetime
+from logging import DEBUG
 import html
 import re
 
@@ -190,6 +191,22 @@
     exception = FRITZ_ERRORS.get(error_code, FritzConnectionException)
     raise exception(message)
 
+def redact_response(redact: bool, input: str):
+    # avoid expansive regex matching, when not neccessary
+    if fritzlogger.level != DEBUG or not redact:
+        return input
+    # redact possible phone numbers
+    # numbers with len of 5 or more, sourounded by white spaces or bracket
+    redacted = re.sub(r"([\s\[\(])\d{5,}([\s\]\)])", r"\1******\2", input)
+
+    # redact external ip addresses
+    ext_ip_keys = 'New(ExternalIPAddress|ExternalIPv6Address)'
+    redacted = re.sub(r"(<{0}>)(.*)(</{0}>)".format(ext_ip_keys), 
r"\1******\4", redacted)
+
+    # redact wifi passwords
+    wifi_pwd_keys = 'New(WEPKey\d+|PreSharedKey|KeyPassphrase)'
+    redacted = re.sub(r"(<{0}>)(.*)(</{0}>)".format(wifi_pwd_keys), 
r"\1******\4", redacted)
+    return redacted
 
 class Soaper:
     """
@@ -238,13 +255,14 @@
         "ui4": int,
     }
 
-    def __init__(self, address, port, user, password, timeout=None, 
session=None):
+    def __init__(self, address, port, user, password, timeout=None, 
session=None, redact_debug_log=False):
         self.address = address
         self.port = port
         self.user = user
         self.password = password
         self.timeout = timeout
         self.session = session
+        self.redact_debug_log = redact_debug_log
 
     def get_body(self, service, action_name, arguments):
         """Returns the body by template substitution."""
@@ -263,7 +281,7 @@
 
         def handle_response(response):
             fritzlogger.debug(f"response status: {response.status_code}")
-            fritzlogger.debug(response.text)
+            fritzlogger.debug(redact_response(self.redact_debug_log, 
response.text))
             if response.status_code != 200:
                 raise_fritzconnection_error(response)
             return self.parse_response(response, service, action_name)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fritzconnection-1.14.0/fritzconnection/lib/fritzcall.py 
new/fritzconnection-1.15.0/fritzconnection/lib/fritzcall.py
--- old/fritzconnection-1.14.0/fritzconnection/lib/fritzcall.py 2024-08-12 
17:58:36.000000000 +0200
+++ new/fritzconnection-1.15.0/fritzconnection/lib/fritzcall.py 2025-05-17 
16:21:25.000000000 +0200
@@ -184,8 +184,9 @@
     """
     Represents a call with the attributes provided by AVM. Instance
     attributes are *Id*, *Type*, *Called*, *Caller*, *CallerNumber*,
-    *CalledNumber*, *Name*, *Device*, *Port*, *Date*, *Duration* and
-    *Count*. The spelling represents the original xml-node names.
+    *CalledNumber*, *Name*, *Device*, *Port*, *Date*, *Duration*,
+    *Count* and *Path* which can be set in case of an optional phone
+    message. The spelling represents the original xml-node names.
     Additionally, the following attributes can be accessed by lowercase
     names: *id* returning the Id as integer, *type* returning the Type
     as integer, *date* returning the Date as datetime-instance,
@@ -209,6 +210,7 @@
         self.Date = None
         self.Duration = None
         self.Count = None
+        self.Path = None
 
     def __str__(self):
         number = self.Called if self.type == 3 else self.Caller
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fritzconnection-1.14.0/fritzconnection/lib/fritzhomeauto.py 
new/fritzconnection-1.15.0/fritzconnection/lib/fritzhomeauto.py
--- old/fritzconnection-1.14.0/fritzconnection/lib/fritzhomeauto.py     
2024-08-12 17:58:36.000000000 +0200
+++ new/fritzconnection-1.15.0/fritzconnection/lib/fritzhomeauto.py     
2025-05-17 16:21:25.000000000 +0200
@@ -96,14 +96,6 @@
         """
         return self._action('GetSpecificDeviceInfos', NewAIN=identifier)
 
-    def device_informations(self) -> list[dict]:
-        """
-        .. deprecated:: 1.9.0
-           Use :func:`get_device_information_list` instead.
-        """
-        warn('This method is deprecated. Use "get_device_information_list" 
instead.', DeprecationWarning)
-        return self.get_device_information_list()
-
     def device_information(self) -> list[dict]:
         """
         .. deprecated:: 1.12.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fritzconnection-1.14.0/fritzconnection/lib/fritzstatus.py 
new/fritzconnection-1.15.0/fritzconnection/lib/fritzstatus.py
--- old/fritzconnection-1.14.0/fritzconnection/lib/fritzstatus.py       
2024-08-12 17:58:36.000000000 +0200
+++ new/fritzconnection-1.15.0/fritzconnection/lib/fritzstatus.py       
2025-05-17 16:21:25.000000000 +0200
@@ -2,11 +2,18 @@
 Module to read status-information from an AVM FritzBox.
 """
 
-
 from __future__ import annotations
 
+import datetime
 from collections import namedtuple
-from warnings import warn
+
+from fritzconnection.core.processor import (
+    Storage,
+    InstanceAttributeFactory,
+    processor,
+    process_node,
+)
+from fritzconnection.core.utils import get_xml_root
 
 from .fritzbase import AbstractLibraryBase
 from .fritztools import (
@@ -17,10 +24,10 @@
 )
 
 DefaultConnectionService = namedtuple(
-    "DefaultConnectionService",
-    "prefix connection_service postfix"
+    "DefaultConnectionService", "prefix connection_service postfix"
 )
 
+
 def _integer_or_original(value):
     """
     Tries to convert value to an integer. Returns this integer on
@@ -32,6 +39,44 @@
         return value
 
 
+@processor
+class Event:
+    """
+    Represents an AVM DeviceLog entry with the subnodes given as
+    class-attributes. The default types are strings as extracted from
+    the xml-source.
+    """
+
+    id = None
+    group = None
+    date = None
+    time = None
+    msg = None
+
+    @property
+    def datetime(self):
+        return datetime.datetime.strptime(f"{self.date}{self.time}", 
"%d.%m.%y%H:%M:%S")
+
+
+class DeviceLog(Storage):
+    """
+    The AVM DeviceLog is a list of Event-nodes stored in the `events`
+    instance attribute. But instances of DeviceLog are also iterables
+    for the events.
+    """
+
+    Event = InstanceAttributeFactory(Event)
+
+    def __init__(self, root):
+        self.events = list()
+        super().__init__(self.events)
+        process_node(self, root)
+
+    def __iter__(self):
+        for event in self.events:
+            yield event
+
+
 class FritzStatus(AbstractLibraryBase):
     """
     Class for requesting status-information: up, down, ip, activity
@@ -107,15 +152,6 @@
         return status["NewUptime"]
 
     @property
-    def uptime(self) -> int:
-        """
-        .. deprecated:: 1.9.0
-           Use :func:`connection_uptime` instead.
-        """
-        warn('This method is deprecated. Use "connection_uptime" instead.', 
DeprecationWarning)
-        return self.connection_uptime
-
-    @property
     def device_uptime(self) -> int:
         """Device uptime in seconds."""
         status = self.fc.call_action("DeviceInfo1", "GetInfo")
@@ -124,7 +160,7 @@
     @property
     def str_uptime(self) -> str:
         """Connection uptime in human-readable format."""
-        mins, secs = divmod(self.uptime, 60)
+        mins, secs = divmod(self.connection_uptime, 60)
         hours, mins = divmod(mins, 60)
         return "%02d:%02d:%02d" % (hours, mins, secs)
 
@@ -139,9 +175,7 @@
             value = status["NewX_AVM_DE_TotalBytesSent64"]
         except KeyError:
             # fallback for older FritzOS Versions not providing a 64 bit value:
-            status = self.fc.call_action(
-                "WANCommonIFC1", "GetTotalBytesSent"
-            )
+            status = self.fc.call_action("WANCommonIFC1", "GetTotalBytesSent")
             value = status["NewTotalBytesSent"]
         return _integer_or_original(value)
 
@@ -156,9 +190,7 @@
             value = status["NewX_AVM_DE_TotalBytesReceived64"]
         except KeyError:
             # fallback for older FritzOS Versions not providing a 64 bit value:
-            status = self.fc.call_action(
-                "WANCommonIFC1", "GetTotalBytesReceived"
-            )
+            status = self.fc.call_action("WANCommonIFC1", 
"GetTotalBytesReceived")
             value = status["NewTotalBytesReceived"]
         return _integer_or_original(value)
 
@@ -324,10 +356,7 @@
         # check for the corresponding action
         # whether mesh is supported
         try:
-            return (
-                "X_AVM-DE_GetMeshListPath"
-                in self.fc.services["Hosts1"].actions
-            )
+            return "X_AVM-DE_GetMeshListPath" in 
self.fc.services["Hosts1"].actions
         except KeyError:
             # can happen if "Hosts1" is not known
             return False
@@ -345,6 +374,43 @@
         """
         return ArgumentNamespace(self.fc.call_action("DeviceInfo1", "GetInfo"))
 
+    def get_avm_device_log(self, filter: str | None = None) -> DeviceLog:
+        """
+        The avm device log is a list of events with the attributes `id`,
+        `group`, `date`, `time` and `msg` holding information like "DSL
+        synchronization starting (training)" and other system messages.
+        The Method returns a DeviceLog instance holding a list of Event
+        instances. The DeviceLog instance is an iterable and can be
+        used on a FritzStatus instance like:
+
+        >>> device_log = fritzstatus.get_avm_device_log()
+        >>> for event in device_log:
+        >>>     print(event.datetime, event.msg)
+
+        The returned events can be filtered by groups like 'sys', 'net',
+        'fon', 'wlan' or 'usb'. To filter by a group provide the
+        group-name as filter-argument.
+        """
+        result = self.fc.call_action("DeviceInfo1", 
"X_AVM-DE_GetDeviceLogPath")
+        path = result["NewDeviceLogPath"]
+        if filter:
+            path = f"{path}&filter={filter}"
+        url = f"{self.fc.address}:{self.fc.port}{path}"
+        root_node = get_xml_root(url, session=self.fc.session)
+        return DeviceLog(root_node)
+
+    def get_cpu_temperatures(self) -> list[int]:
+        """
+        Returns a list of the last measured cpu-temperatures (Celsius).
+        The most recent entry is the first one in the list.
+        NOTE: this function call is experimental as it is based on a
+        non-public API.
+        """
+        url = f"{self.fc.http_interface.router_url}/query.lua"
+        payload = {"CPUTEMP": "cpu:status/StatTemperature"}
+        response = self.fc.http_interface.call_url(url, payload)
+        return list(map(int, response.json()["CPUTEMP"].split(",")))
+
     def get_default_connection_service(self) -> DefaultConnectionService:
         """
         Returns a namedtuple of type DefaultConnectionService:
@@ -352,14 +418,11 @@
         `device_connection` -> str (like "WANPPPConnection")
         `postfix` -> str
         """
-        result = self.fc.call_action(
-                "Layer3Forwarding1", "GetDefaultConnectionService"
-        )
-        prefix, connection_service, postfix = \
-            result["NewDefaultConnectionService"].split('.', 2)
-        return DefaultConnectionService(
-            prefix, connection_service, postfix
-        )
+        result = self.fc.call_action("Layer3Forwarding1", 
"GetDefaultConnectionService")
+        prefix, connection_service, postfix = result[
+            "NewDefaultConnectionService"
+        ].split(".", 2)
+        return DefaultConnectionService(prefix, connection_service, postfix)
 
     @property
     def connection_service(self) -> str:
@@ -388,7 +451,8 @@
     @property
     def has_wan_support(self) -> bool:
         """
-        True is the device supports a WAN interface.
+        True if the device supports a WAN interface.
         False otherwise.
         """
         return "Layer3Forwarding1" in self.fc.services
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fritzconnection-1.14.0/fritzconnection/lib/fritzwlan.py 
new/fritzconnection-1.15.0/fritzconnection/lib/fritzwlan.py
--- old/fritzconnection-1.14.0/fritzconnection/lib/fritzwlan.py 2024-08-12 
17:58:36.000000000 +0200
+++ new/fritzconnection-1.15.0/fritzconnection/lib/fritzwlan.py 2025-05-17 
16:21:25.000000000 +0200
@@ -13,7 +13,6 @@
 import itertools
 import random
 import string
-from warnings import warn
 
 from ..core.exceptions import FritzServiceError
 from .fritzbase import AbstractLibraryBase
@@ -208,14 +207,6 @@
         """Alternative channels (as string)"""
         return self.channel_info()['NewPossibleChannels']
 
-    def channel_infos(self) -> dict:
-        """
-        .. deprecated:: 1.9.0
-           Use :func:`channel_info` instead.
-        """
-        warn('This method is deprecated. Use "channel_info" instead.', 
DeprecationWarning)
-        return self.channel_info()
-
     def channel_info(self) -> dict:
         """
         Return a dictionary with the keys *NewChannel* and
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fritzconnection-1.14.0/fritzconnection/tests/test_soaper.py 
new/fritzconnection-1.15.0/fritzconnection/tests/test_soaper.py
--- old/fritzconnection-1.14.0/fritzconnection/tests/test_soaper.py     
2024-08-12 17:58:36.000000000 +0200
+++ new/fritzconnection-1.15.0/fritzconnection/tests/test_soaper.py     
2025-05-17 16:21:25.000000000 +0200
@@ -30,6 +30,7 @@
     get_html_safe_value,
     is_html_response,
     raise_fritzconnection_error,
+    redact_response,
     remove_html_tags,
 )
 
@@ -286,3 +287,146 @@
 def test_get_converted_value_fails(data_type, value):
     with pytest.raises(ValueError):
         get_converted_value(data_type, value)
+
+def test_redact_debug_log_phone_numbers():
+    response = """
+    <?xml version="1.0"?>
+    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"; 
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/";>
+    <s:Body>
+    <u:GetInfoResponse xmlns:u="urn:dslforum-org:service:DeviceInfo:1">
+    <NewManufacturerName>AVM</NewManufacturerName>
+    <NewManufacturerOUI>00040E</NewManufacturerOUI>
+    <NewModelName>FRITZ!Box 7530 AX</NewModelName>
+    <NewDescription>FRITZ!Box 7530 AX Release 256.08.00</NewDescription>
+    <NewProductClass>FRITZ!Box</NewProductClass>
+    <NewSerialNumber>aabbccddeeff</NewSerialNumber>
+    <NewSoftwareVersion>256.08.00</NewSoftwareVersion>
+    <NewHardwareVersion>FRITZ!Box 7530 AX</NewHardwareVersion>
+    <NewSpecVersion>1.0</NewSpecVersion>
+    <NewProvisioningCode></NewProvisioningCode>
+    <NewUpTime>86446</NewUpTime>
+    <NewDeviceLog>
+    23.11.24 12:28:10 Anmeldung der Internetrufnummer 491234567890 war nicht 
erfolgreich. Ursache: DNS-Fehler
+    23.11.24 12:28:10 Anmeldung der Internetrufnummer 491234567891 war nicht 
erfolgreich. Ursache: DNS-Fehler
+    23.11.24 12:28:10 Anmeldung der Internetrufnummer 491234567892 war nicht 
erfolgreich. Ursache: DNS-Fehler
+    23.11.24 12:28:10 Anmeldung der Internetrufnummer 491234567893 war nicht 
erfolgreich. Ursache: DNS-Fehler
+    </u:GetInfoResponse>
+    </s:Body>
+    </s:Envelope>
+    """
+
+    result = redact_response(False, response)
+    assert result == response
+
+    result = redact_response(True, response)
+    assert result == """
+    <?xml version="1.0"?>
+    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"; 
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/";>
+    <s:Body>
+    <u:GetInfoResponse xmlns:u="urn:dslforum-org:service:DeviceInfo:1">
+    <NewManufacturerName>AVM</NewManufacturerName>
+    <NewManufacturerOUI>00040E</NewManufacturerOUI>
+    <NewModelName>FRITZ!Box 7530 AX</NewModelName>
+    <NewDescription>FRITZ!Box 7530 AX Release 256.08.00</NewDescription>
+    <NewProductClass>FRITZ!Box</NewProductClass>
+    <NewSerialNumber>aabbccddeeff</NewSerialNumber>
+    <NewSoftwareVersion>256.08.00</NewSoftwareVersion>
+    <NewHardwareVersion>FRITZ!Box 7530 AX</NewHardwareVersion>
+    <NewSpecVersion>1.0</NewSpecVersion>
+    <NewProvisioningCode></NewProvisioningCode>
+    <NewUpTime>86446</NewUpTime>
+    <NewDeviceLog>
+    23.11.24 12:28:10 Anmeldung der Internetrufnummer ****** war nicht 
erfolgreich. Ursache: DNS-Fehler
+    23.11.24 12:28:10 Anmeldung der Internetrufnummer ****** war nicht 
erfolgreich. Ursache: DNS-Fehler
+    23.11.24 12:28:10 Anmeldung der Internetrufnummer ****** war nicht 
erfolgreich. Ursache: DNS-Fehler
+    23.11.24 12:28:10 Anmeldung der Internetrufnummer ****** war nicht 
erfolgreich. Ursache: DNS-Fehler
+    </u:GetInfoResponse>
+    </s:Body>
+    </s:Envelope>
+    """
+
+def test_redact_debug_log_external_ip_addresses():
+    response = """
+    <?xml version="1.0" encoding="utf-8"?>
+    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"; 
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/";>
+    <s:Body>
+    <u:GetExternalIPAddressResponse 
xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
+    <NewExternalIPAddress>12.34.56.78</NewExternalIPAddress>
+    </u:GetExternalIPAddressResponse>
+    </s:Body>
+    </s:Envelope>
+    <?xml version="1.0" encoding="utf-8"?>
+    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"; 
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/";>
+    <s:Body>
+    <u:X_AVM_DE_GetExternalIPv6AddressResponse 
xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
+    <NewExternalIPv6Address>0011:2233:4455:6677::0abcd</NewExternalIPv6Address>
+    <NewPrefixLength>64</NewPrefixLength>
+    <NewValidLifetime>0</NewValidLifetime>
+    <NewPreferedLifetime>0</NewPreferedLifetime>
+    </u:X_AVM_DE_GetExternalIPv6AddressResponse>
+    </s:Body>
+    </s:Envelope>
+    """
+
+    result = redact_response(False, response)
+    assert result == response
+
+    result = redact_response(True, response)
+    assert result == """
+    <?xml version="1.0" encoding="utf-8"?>
+    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"; 
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/";>
+    <s:Body>
+    <u:GetExternalIPAddressResponse 
xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
+    <NewExternalIPAddress>******</NewExternalIPAddress>
+    </u:GetExternalIPAddressResponse>
+    </s:Body>
+    </s:Envelope>
+    <?xml version="1.0" encoding="utf-8"?>
+    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"; 
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/";>
+    <s:Body>
+    <u:X_AVM_DE_GetExternalIPv6AddressResponse 
xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
+    <NewExternalIPv6Address>******</NewExternalIPv6Address>
+    <NewPrefixLength>64</NewPrefixLength>
+    <NewValidLifetime>0</NewValidLifetime>
+    <NewPreferedLifetime>0</NewPreferedLifetime>
+    </u:X_AVM_DE_GetExternalIPv6AddressResponse>
+    </s:Body>
+    </s:Envelope>
+    """
+
+def test_redact_debug_log_wifi_passwords():
+    response = """
+    <?xml version="1.0"?>
+    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"; 
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/";>
+    <s:Body>
+    <u:GetSecurityKeysResponse 
xmlns:u="urn:dslforum-org:service:WLANConfiguration:3">
+    <NewWEPKey0>0123456789</NewWEPKey0>
+    <NewWEPKey1></NewWEPKey1>
+    <NewWEPKey2>01234 6789</NewWEPKey2>
+    <NewWEPKey3></NewWEPKey3>
+    
<NewPreSharedKey>0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF</NewPreSharedKey>
+    <NewKeyPassphrase>MY_GREAT_WIFI_PSK</NewKeyPassphrase>
+    </u:GetSecurityKeysResponse>
+    </s:Body>
+    </s:Envelope>
+    """
+
+    result = redact_response(False, response)
+    assert result == response
+
+    result = redact_response(True, response)
+    assert result == """
+    <?xml version="1.0"?>
+    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"; 
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/";>
+    <s:Body>
+    <u:GetSecurityKeysResponse 
xmlns:u="urn:dslforum-org:service:WLANConfiguration:3">
+    <NewWEPKey0>******</NewWEPKey0>
+    <NewWEPKey1>******</NewWEPKey1>
+    <NewWEPKey2>******</NewWEPKey2>
+    <NewWEPKey3>******</NewWEPKey3>
+    <NewPreSharedKey>******</NewPreSharedKey>
+    <NewKeyPassphrase>******</NewKeyPassphrase>
+    </u:GetSecurityKeysResponse>
+    </s:Body>
+    </s:Envelope>
+    """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fritzconnection-1.14.0/noxfile.py 
new/fritzconnection-1.15.0/noxfile.py
--- old/fritzconnection-1.14.0/noxfile.py       2024-08-12 17:58:36.000000000 
+0200
+++ new/fritzconnection-1.15.0/noxfile.py       2025-05-17 16:21:25.000000000 
+0200
@@ -1,7 +1,7 @@
 import nox
 
 
-PYTHON_TEST_VERSIONS = ("3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13")
+PYTHON_TEST_VERSIONS = ("3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13", 
"3.14")
 PYTHON_DEVELOPMENT_VERSION = "3.11"
 
 
@@ -48,10 +48,11 @@
         "pip-compile",
         "--strip-extras",
         "-q",
-        "--output-file=docs/requirements.txt",
-        "docs/requirements.local.in"
+        "--output-file=docs/requirements.out",
+        "docs/requirements.txt"
+        #"docs/requirements.local.in"
     )
-    session.install("-r", "docs/requirements.txt")
+    session.install("-r", "docs/requirements.out")
     session.run("sphinx-build", "docs", "docs_out")
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fritzconnection-1.14.0/setup.py 
new/fritzconnection-1.15.0/setup.py
--- old/fritzconnection-1.14.0/setup.py 2024-08-12 17:58:36.000000000 +0200
+++ new/fritzconnection-1.15.0/setup.py 2025-05-17 16:21:25.000000000 +0200
@@ -44,6 +44,7 @@
         "Programming Language :: Python :: 3.11",
         "Programming Language :: Python :: 3.12",
         "Programming Language :: Python :: 3.13",
+        "Programming Language :: Python :: 3.14",
         "Topic :: Software Development :: Libraries :: Python Modules",
     ],
     keywords="AVM FRITZ!Box fritzbox fritz TR-064 AHA-HTTP homeautomation",

Reply via email to