Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-proton-vpn-api-core for 
openSUSE:Factory checked in at 2025-04-17 16:10:14
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-proton-vpn-api-core (Old)
 and      /work/SRC/openSUSE:Factory/.python-proton-vpn-api-core.new.30101 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-proton-vpn-api-core"

Thu Apr 17 16:10:14 2025 rev:8 rq:1270228 version:0.42.4

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-proton-vpn-api-core/python-proton-vpn-api-core.changes
    2025-04-02 17:12:15.286558967 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-proton-vpn-api-core.new.30101/python-proton-vpn-api-core.changes
 2025-04-20 20:08:01.813266380 +0200
@@ -1,0 +2,7 @@
+Mon Apr 14 10:57:23 UTC 2025 - Richard Rahl <rra...@opensuse.org>
+
+- update to 0.42.4:
+  * fix: [VPNLINUX-1191] swallow&re-schedule server refresh when we receive 
HTTP code 429
+  * fix: [VPNLINUX-1191] swallow&re-schedule when we receive HTTP code 429 
from refreshers
+
+-------------------------------------------------------------------

Old:
----
  v0.42.3.tar.gz

New:
----
  v0.42.4.tar.gz

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

Other differences:
------------------
++++++ python-proton-vpn-api-core.spec ++++++
--- /var/tmp/diff_new_pack.cSuHT1/_old  2025-04-20 20:08:02.557297651 +0200
+++ /var/tmp/diff_new_pack.cSuHT1/_new  2025-04-20 20:08:02.557297651 +0200
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-proton-vpn-api-core
-Version:        0.42.3
+Version:        0.42.4
 Release:        0
 Summary:        Proton VPN API library
 License:        GPL-3.0-or-later

++++++ v0.42.3.tar.gz -> v0.42.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-proton-vpn-api-core-0.42.3/proton/vpn/core/refresher/certificate_refresher.py
 
new/python-proton-vpn-api-core-0.42.4/proton/vpn/core/refresher/certificate_refresher.py
--- 
old/python-proton-vpn-api-core-0.42.3/proton/vpn/core/refresher/certificate_refresher.py
    2025-02-24 15:38:38.000000000 +0100
+++ 
new/python-proton-vpn-api-core-0.42.4/proton/vpn/core/refresher/certificate_refresher.py
    2025-04-07 13:04:16.000000000 +0200
@@ -27,6 +27,7 @@
 from proton.vpn.session.credentials import VPNPubkeyCredentials
 from proton.session.exceptions import (
     ProtonAPINotReachable, ProtonAPINotAvailable,
+    ProtonAPIError
 )
 
 logger = logging.getLogger(__name__)
@@ -64,6 +65,13 @@
             next_refresh_delay = certificate.remaining_time_to_next_refresh
             self._number_of_failed_refresh_attempts = 0
             await self._notify()
+        except ProtonAPIError as error:
+            if error.http_code != 429:
+                raise
+
+            logger.warning(f"Certificate refresh failed {error}")
+            next_refresh_delay = self._get_next_refresh_delay()
+            self._number_of_failed_refresh_attempts += 1
         except (ProtonAPINotReachable, ProtonAPINotAvailable) as error:
             logger.warning(f"Certificate refresh failed: {error}")
             next_refresh_delay = self._get_next_refresh_delay()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-proton-vpn-api-core-0.42.3/proton/vpn/core/refresher/client_config_refresher.py
 
new/python-proton-vpn-api-core-0.42.4/proton/vpn/core/refresher/client_config_refresher.py
--- 
old/python-proton-vpn-api-core-0.42.3/proton/vpn/core/refresher/client_config_refresher.py
  2025-02-24 15:38:38.000000000 +0100
+++ 
new/python-proton-vpn-api-core-0.42.4/proton/vpn/core/refresher/client_config_refresher.py
  2025-04-07 13:04:16.000000000 +0200
@@ -25,6 +25,7 @@
 from proton.vpn import logging
 from proton.session.exceptions import (
     ProtonAPINotReachable, ProtonAPINotAvailable,
+    ProtonAPIError
 )
 
 logger = logging.getLogger(__name__)
@@ -54,6 +55,12 @@
         try:
             new_client_config = await self._session.fetch_client_config()
             next_refresh_delay = new_client_config.seconds_until_expiration
+        except ProtonAPIError as error:
+            if error.http_code != 429:
+                raise
+
+            logger.warning(f"Client config refresh failed: {error}")
+            next_refresh_delay = ClientConfig.get_refresh_interval_in_seconds()
         except (ProtonAPINotReachable, ProtonAPINotAvailable) as error:
             logger.warning(f"Client config refresh failed: {error}")
             next_refresh_delay = ClientConfig.get_refresh_interval_in_seconds()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-proton-vpn-api-core-0.42.3/proton/vpn/core/refresher/feature_flags_refresher.py
 
new/python-proton-vpn-api-core-0.42.4/proton/vpn/core/refresher/feature_flags_refresher.py
--- 
old/python-proton-vpn-api-core-0.42.3/proton/vpn/core/refresher/feature_flags_refresher.py
  2025-02-24 15:38:38.000000000 +0100
+++ 
new/python-proton-vpn-api-core-0.42.4/proton/vpn/core/refresher/feature_flags_refresher.py
  2025-04-07 13:04:16.000000000 +0200
@@ -25,6 +25,7 @@
 from proton.vpn import logging
 from proton.session.exceptions import (
     ProtonAPINotReachable, ProtonAPINotAvailable,
+    ProtonAPIError
 )
 
 logger = logging.getLogger(__name__)
@@ -53,6 +54,12 @@
         try:
             feature_flags = await self._session.fetch_feature_flags()
             next_refresh_delay = feature_flags.seconds_until_expiration
+        except ProtonAPIError as error:
+            if error.http_code != 429:
+                raise
+
+            logger.warning(f"Feature flag refresh failed {error}")
+            next_refresh_delay = FeatureFlags.get_refresh_interval_in_seconds()
         except (ProtonAPINotReachable, ProtonAPINotAvailable) as error:
             logger.warning(f"Feature flag refresh failed: {error}")
             next_refresh_delay = FeatureFlags.get_refresh_interval_in_seconds()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-proton-vpn-api-core-0.42.3/proton/vpn/core/refresher/server_list_refresher.py
 
new/python-proton-vpn-api-core-0.42.4/proton/vpn/core/refresher/server_list_refresher.py
--- 
old/python-proton-vpn-api-core-0.42.3/proton/vpn/core/refresher/server_list_refresher.py
    2025-02-24 15:38:38.000000000 +0100
+++ 
new/python-proton-vpn-api-core-0.42.4/proton/vpn/core/refresher/server_list_refresher.py
    2025-04-07 13:04:16.000000000 +0200
@@ -21,6 +21,7 @@
 
 from proton.session.exceptions import (
     ProtonAPINotReachable, ProtonAPINotAvailable,
+    ProtonAPIError
 )
 
 from proton.vpn import logging
@@ -62,6 +63,12 @@
                 next_refresh_delay = server_list.seconds_until_expiration
             else:
                 next_refresh_delay = 
self._session.server_list.seconds_until_expiration
+        except ProtonAPIError as error:
+            if error.http_code != 429:
+                raise
+
+            logger.warning(f"Server list refresh failed: {error}")
+            next_refresh_delay = 
ServerList.get_loads_refresh_interval_in_seconds()
         except (ProtonAPINotReachable, ProtonAPINotAvailable) as error:
             logger.warning(f"Server list refresh failed: {error}")
             next_refresh_delay = 
ServerList.get_loads_refresh_interval_in_seconds()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-proton-vpn-api-core-0.42.3/tests/core/refresher/test_certificate_refresher.py
 
new/python-proton-vpn-api-core-0.42.4/tests/core/refresher/test_certificate_refresher.py
--- 
old/python-proton-vpn-api-core-0.42.3/tests/core/refresher/test_certificate_refresher.py
    2025-02-24 15:38:38.000000000 +0100
+++ 
new/python-proton-vpn-api-core-0.42.4/tests/core/refresher/test_certificate_refresher.py
    2025-04-07 13:04:16.000000000 +0200
@@ -22,6 +22,25 @@
 
 from proton.vpn.core.refresher.certificate_refresher import 
CertificateRefresher, generate_backoff_value
 from proton.vpn.core.refresher.scheduler import RunAgain
+from proton.session.exceptions import ProtonAPIError
+
+
+@pytest.mark.asyncio
+async def 
test_refresh_schedules_next_refresh_if_certificate_is_expired_and_api_error_exception_is_raised():
+    session_holder = Mock()
+    session = session_holder.session
+
+    refresher = CertificateRefresher(session_holder=session_holder)
+
+    session.fetch_certificate = AsyncMock(side_effect=ProtonAPIError(
+        http_code=429,
+        http_headers={},
+        json_data={"Code": 429, "Error": "Error message"}
+    ))
+    new_certificate = Mock()
+    new_certificate.remaining_time_to_next_refresh = 600
+
+    next_refresh_delay = await refresher.refresh()
 
 
 @pytest.mark.asyncio
@@ -59,4 +78,4 @@
         random_component=random_component
     )
 
-    assert backoff == expected_backoff
\ No newline at end of file
+    assert backoff == expected_backoff
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-proton-vpn-api-core-0.42.3/tests/core/refresher/test_client_config_refresher.py
 
new/python-proton-vpn-api-core-0.42.4/tests/core/refresher/test_client_config_refresher.py
--- 
old/python-proton-vpn-api-core-0.42.3/tests/core/refresher/test_client_config_refresher.py
  2025-02-24 15:38:38.000000000 +0100
+++ 
new/python-proton-vpn-api-core-0.42.4/tests/core/refresher/test_client_config_refresher.py
  2025-04-07 13:04:16.000000000 +0200
@@ -22,6 +22,7 @@
 
 from proton.vpn.core.refresher.client_config_refresher import 
ClientConfigRefresher
 from proton.vpn.core.refresher.scheduler import RunAgain
+from proton.session.exceptions import ProtonAPIError
 
 
 @pytest.mark.asyncio
@@ -40,3 +41,20 @@
     session.fetch_client_config.assert_called_once()
 
     assert next_refresh_delay == 
RunAgain.after_seconds(new_client_config.seconds_until_expiration)
+
+
+@pytest.mark.asyncio
+async def 
test_refresh_schedules_next_refresh_if_client_config_is_expired_and_api_error_exception_is_raised():
+    session_holder = Mock()
+    session = session_holder.session
+    refresher = ClientConfigRefresher(session_holder=session_holder)
+
+    new_client_config = Mock()
+    new_client_config.seconds_until_expiration = 60
+    session.fetch_client_config = AsyncMock(side_effect=ProtonAPIError(
+        http_code=429,
+        http_headers={},
+        json_data={"Code": 429, "Error": "Error message"}
+    ))
+
+    next_refresh_delay = await refresher.refresh()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-proton-vpn-api-core-0.42.3/tests/core/refresher/test_feature_flags_refresher.py
 
new/python-proton-vpn-api-core-0.42.4/tests/core/refresher/test_feature_flags_refresher.py
--- 
old/python-proton-vpn-api-core-0.42.3/tests/core/refresher/test_feature_flags_refresher.py
  2025-02-24 15:38:38.000000000 +0100
+++ 
new/python-proton-vpn-api-core-0.42.4/tests/core/refresher/test_feature_flags_refresher.py
  2025-04-07 13:04:16.000000000 +0200
@@ -22,6 +22,7 @@
 
 from proton.vpn.core.refresher.feature_flags_refresher import 
FeatureFlagsRefresher
 from proton.vpn.core.refresher.scheduler import RunAgain
+from proton.session.exceptions import ProtonAPIError
 
 
 @pytest.mark.asyncio
@@ -41,3 +42,21 @@
     session.fetch_feature_flags.assert_called_once()
 
     assert next_refresh_delay == 
RunAgain.after_seconds(new_feature_flags.seconds_until_expiration)
+
+
+@pytest.mark.asyncio
+async def 
test_refresh_schedules_next_refresh_if_feature_flags_is_expired_and_api_error_exception_is_raised():
+    session_holder = Mock()
+    session = session_holder.session
+
+    refresher = FeatureFlagsRefresher(session_holder=session_holder)
+
+    new_feature_flags = Mock()
+    new_feature_flags.seconds_until_expiration = 60
+    session.fetch_feature_flags = AsyncMock(side_effect=ProtonAPIError(
+        http_code=429,
+        http_headers={},
+        json_data={"Code": 429, "Error": "Error message"}
+    ))
+
+    next_refresh_delay = await refresher.refresh()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-proton-vpn-api-core-0.42.3/tests/core/refresher/test_server_list_refresher.py
 
new/python-proton-vpn-api-core-0.42.4/tests/core/refresher/test_server_list_refresher.py
--- 
old/python-proton-vpn-api-core-0.42.3/tests/core/refresher/test_server_list_refresher.py
    2025-02-24 15:38:38.000000000 +0100
+++ 
new/python-proton-vpn-api-core-0.42.4/tests/core/refresher/test_server_list_refresher.py
    2025-04-07 13:04:16.000000000 +0200
@@ -16,13 +16,16 @@
 You should have received a copy of the GNU General Public License
 along with ProtonVPN.  If not, see <https://www.gnu.org/licenses/>.
 """
-from unittest.mock import Mock, AsyncMock
+from unittest.mock import Mock, AsyncMock, patch
 
 import pytest
 
 from proton.vpn.core.refresher.scheduler import RunAgain
 from proton.vpn.core.refresher.server_list_refresher import ServerListRefresher
 
+from proton.session.exceptions import ProtonAPIError
+
+
 
 @pytest.mark.asyncio
 async def 
test_refresh_fetches_server_list_if_expired_and_returns_next_refresh_delay():
@@ -107,3 +110,28 @@
     # And the next refresh should've been scheduled when the current
     # server list expires.
     assert next_refresh_delay == 
RunAgain.after_seconds(session.server_list.seconds_until_expiration)
+
+
+@pytest.mark.asyncio
+@patch("proton.vpn.core.refresher.server_list_refresher.ServerList.get_loads_refresh_interval_in_seconds")
+async def 
test_refresh_schedules_next_refresh_if_server_list_is_expired_and_api_error_exception_is_raised(mock_get_loads_refresh_interval_in_seconds):
+    get_loads_refresh_interval_in_seconds = 10
+    mock_get_loads_refresh_interval_in_seconds.return_value = 
get_loads_refresh_interval_in_seconds
+    session_holder = Mock()
+    session = session_holder.session
+
+    # The current server list is expired.
+    session.server_list.expired = True
+
+    # Mock a 429 response from the server
+    session.fetch_server_list = AsyncMock(side_effect=ProtonAPIError(
+        http_code=429,
+        http_headers={},
+        json_data={"Code": 429, "Error": "Error message"}
+    ))
+
+    refresher = ServerListRefresher(session_holder=session_holder)
+    refresher.server_list_updated_callback = Mock()
+
+    # No error message should be raised since it's been swallowed
+    next_refresh_delay = await refresher.refresh()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-proton-vpn-api-core-0.42.3/versions.yml 
new/python-proton-vpn-api-core-0.42.4/versions.yml
--- old/python-proton-vpn-api-core-0.42.3/versions.yml  2025-02-24 
15:38:38.000000000 +0100
+++ new/python-proton-vpn-api-core-0.42.4/versions.yml  2025-04-07 
13:04:16.000000000 +0200
@@ -1,3 +1,12 @@
+version: 0.42.4
+time: 2025/04/04 13:00
+author: Alexandru Cheltuitor
+email: alexandru.cheltui...@proton.ch
+urgency: low
+stability: unstable
+description:
+- Swallow and re-schedule server refresh when we receive HTTP code 429.
+---
 version: 0.42.3
 time: 2025/02/24 12:00
 author: Alexandru Cheltuitor

Reply via email to