Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-proton-keyring-linux for
openSUSE:Factory checked in at 2026-08-13 13:16:38
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-proton-keyring-linux (Old)
and /work/SRC/openSUSE:Factory/.python-proton-keyring-linux.new.17972
(New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-proton-keyring-linux"
Thu Aug 13 13:16:38 2026 rev:2 rq:1370888 version:0.2.3
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-proton-keyring-linux/python-proton-keyring-linux.changes
2026-03-23 17:12:52.936464374 +0100
+++
/work/SRC/openSUSE:Factory/.python-proton-keyring-linux.new.17972/python-proton-keyring-linux.changes
2026-08-13 13:17:25.065611180 +0200
@@ -1,0 +2,7 @@
+Tue Jul 28 08:07:14 UTC 2026 - Ákos Szőts <[email protected]>
+
+- Update to v0.2.3
+- Fixed --cov handling in tests by adding a missing dependency. This allowed
+ to remove patch "fix-tests.patch"
+
+-------------------------------------------------------------------
Old:
----
fix-tests.patch
python-proton-keyring-linux-0.2.0.tar.gz
New:
----
python-proton-keyring-linux-0.2.3.tar.gz
----------(Old B)----------
Old:- Fixed --cov handling in tests by adding a missing dependency. This
allowed
to remove patch "fix-tests.patch"
----------(Old E)----------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-proton-keyring-linux.spec ++++++
--- /var/tmp/diff_new_pack.6kwcgJ/_old 2026-08-13 13:17:26.237660406 +0200
+++ /var/tmp/diff_new_pack.6kwcgJ/_new 2026-08-13 13:17:26.241660574 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-proton-keyring-linux
#
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -16,26 +16,27 @@
#
-%{?sle15_python_module_pythons}
%define _modname proton_keyring_linux
+%{?sle15_python_module_pythons}
Name: python-proton-keyring-linux
-Version: 0.2.0
+Version: 0.2.3
Release: 0
-Summary: Proton keyring linux library
+Summary: Proton keyring Linux library
License: GPL-3.0-or-later
URL: https://github.com/ProtonVPN/python-proton-keyring-linux
Source0: %{url}/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz
-Patch0: fix-tests.patch
BuildRequires: %{python_module SecretStorage}
BuildRequires: %{python_module keyring}
BuildRequires: %{python_module pip}
BuildRequires: %{python_module proton-core}
+BuildRequires: %{python_module pytest-cov}
BuildRequires: %{python_module pytest}
BuildRequires: %{python_module setuptools}
BuildRequires: %{python_module wheel}
BuildRequires: fdupes
-Requires: python-proton-core
+BuildRequires: python-rpm-macros
Requires: python-keyring
+Requires: python-proton-core
Obsoletes: python-proton-keyring-linux-secretservice <= 0.1.0
Provides: python-proton-keyring-linux-secretservice = %{version}
BuildArch: noarch
@@ -52,7 +53,7 @@
%install
%pyproject_install
-%python_expand %fdupes %{buildroot}%{python_sitelib}
+%python_expand %fdupes %{buildroot}/%{$python_sitelib}/proton/keyring_linux/
%check
%pytest
++++++ python-proton-keyring-linux-0.2.0.tar.gz ->
python-proton-keyring-linux-0.2.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-proton-keyring-linux-0.2.0/CODEOWNERS
new/python-proton-keyring-linux-0.2.3/CODEOWNERS
--- old/python-proton-keyring-linux-0.2.0/CODEOWNERS 1970-01-01
01:00:00.000000000 +0100
+++ new/python-proton-keyring-linux-0.2.3/CODEOWNERS 2026-06-11
12:56:42.000000000 +0200
@@ -0,0 +1,6 @@
+# ownership: loose
+* @ProtonVPN/groups/linux-developers
+/debian/ @ProtonVPN/groups/linux-developers
+/proton/ @ProtonVPN/groups/linux-developers
+/rpmbuild/ @ProtonVPN/groups/linux-developers
+/tests/ @ProtonVPN/groups/linux-developers
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-proton-keyring-linux-0.2.0/debian/changelog
new/python-proton-keyring-linux-0.2.3/debian/changelog
--- old/python-proton-keyring-linux-0.2.0/debian/changelog 2024-11-19
15:07:58.000000000 +0100
+++ new/python-proton-keyring-linux-0.2.3/debian/changelog 2026-06-11
12:56:42.000000000 +0200
@@ -1,3 +1,21 @@
+proton-keyring-linux (0.2.3) unstable; urgency=medium
+
+ * Restrict libsecret backend to Snap only.
+
+ -- Elena Švilpė <[email protected]> Mon, 11 Jun 2026 11:00:00 +0100
+
+proton-keyring-linux (0.2.2) unstable; urgency=medium
+
+ * Add libsecret backend.
+
+ -- Elena Švilpė <[email protected]> Mon, 1 Jun 2026 15:00:00 +0100
+
+proton-keyring-linux (0.2.1) unstable; urgency=medium
+
+ * Update spec file.
+
+ -- Alexandru Cheltuitor <[email protected]> Mon, 22 Sep 2025
10:00:00 +0100
+
proton-keyring-linux (0.2.0) unstable; urgency=medium
* Drop Ubuntu 20.04 support.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python-proton-keyring-linux-0.2.0/proton/keyring_linux/libsecret/__init__.py
new/python-proton-keyring-linux-0.2.3/proton/keyring_linux/libsecret/__init__.py
---
old/python-proton-keyring-linux-0.2.0/proton/keyring_linux/libsecret/__init__.py
1970-01-01 01:00:00.000000000 +0100
+++
new/python-proton-keyring-linux-0.2.3/proton/keyring_linux/libsecret/__init__.py
2026-06-11 12:56:42.000000000 +0200
@@ -0,0 +1,21 @@
+"""
+Copyright (c) 2026 Proton AG
+
+This file is part of Proton VPN.
+
+Proton VPN is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Proton VPN is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with ProtonVPN. If not, see <https://www.gnu.org/licenses/>.
+"""
+from .libsecret_backend import LibsecretKeyringBackend
+
+__all__ = ["LibsecretKeyringBackend"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python-proton-keyring-linux-0.2.0/proton/keyring_linux/libsecret/libsecret_backend.py
new/python-proton-keyring-linux-0.2.3/proton/keyring_linux/libsecret/libsecret_backend.py
---
old/python-proton-keyring-linux-0.2.0/proton/keyring_linux/libsecret/libsecret_backend.py
1970-01-01 01:00:00.000000000 +0100
+++
new/python-proton-keyring-linux-0.2.3/proton/keyring_linux/libsecret/libsecret_backend.py
2026-06-11 12:56:42.000000000 +0200
@@ -0,0 +1,140 @@
+"""
+Copyright (c) 2026 Proton AG
+
+This file is part of Proton VPN.
+
+Proton VPN is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Proton VPN is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with ProtonVPN. If not, see <https://www.gnu.org/licenses/>.
+"""
+import os
+import logging
+from proton.keyring_linux.core import KeyringBackendLinux
+
+logger = logging.getLogger(__name__)
+
+
+class LibsecretKeyringBackend(KeyringBackendLinux):
+ """
+ Libsecret backend using high-level password APIs (no explicit Service).
+
https://gnome.pages.gitlab.gnome.org/libsecret/libsecret-python-examples.html
+ """
+
+ _secret_cache = None
+
+ # We are using the same schema and application name
+ # as the other keyring backend to be compatible
+ SCHEMA = "org.freedesktop.Secret.Generic"
+ APPLICATION_NAME = "Python keyring library"
+
+ @classmethod
+ def _get_priority(cls):
+ return 4.0 # lower than secretservice
+
+ @staticmethod
+ def _import_secret():
+ import gi # pylint: disable=import-outside-toplevel,import-error
+ gi.require_version('Secret', '1')
+ from gi.repository import Secret # pylint:
disable=import-outside-toplevel,import-error
+ return Secret
+
+ @classmethod
+ def _get_secret(cls):
+ # The import is not top level because the app shouldn't crash
+ # when the optional dependency is not available.
+ # It's only imported the first time it's used and then cached
+ if cls._secret_cache is None:
+ cls._secret_cache = cls._import_secret()
+ return cls._secret_cache
+
+ @classmethod
+ def _validate(cls):
+ # libsecret backend should only be available for Snap
+ #
https://snapcraft.io/docs/reference/development/environment-variables/#snap
+ if os.environ.get("SNAP") is None:
+ return False
+ try:
+ secret = cls._get_secret()
+ except ValueError:
+ logger.warning("Libsecret not available")
+ return False
+ test_schema = secret.Schema.new(
+ "test",
+ secret.SchemaFlags.NONE,
+ {"key": secret.SchemaAttributeType.STRING}
+ )
+ secret.password_lookup_sync(test_schema, {"key": "test"}, None)
+ logger.info("Using libsecret backend")
+ return True
+
+ def __init__(self):
+
+ secret = self._get_secret()
+ # These keys are used to find the keyring entry later.
+ # They are being kept compatible with existing keys from secret
service backend
+ # so that the backends can be used interchangeably without losing user
data.
+ self.schema = secret.Schema.new(
+ LibsecretKeyringBackend.SCHEMA,
+ secret.SchemaFlags.NONE, # pylint: disable=no-member
+ {
+ "application": secret.SchemaAttributeType.STRING,
+ "service": secret.SchemaAttributeType.STRING,
+ "username": secret.SchemaAttributeType.STRING
+ }
+ )
+
+ super().__init__(self)
+
+ def get_password(self, service_name, key):
+ "Retrieve a password"
+ secret = self._get_secret()
+ result = secret.password_lookup_sync(
+ self.schema,
+ {
+ "application": LibsecretKeyringBackend.APPLICATION_NAME,
+ "service": service_name,
+ "username": key
+ },
+ None
+ )
+ if result is None:
+ return None
+ return result
+
+ def set_password(self, service_name, key, password):
+ """Store a password"""
+ secret = self._get_secret()
+ secret.password_store_sync(
+ self.schema,
+ {
+ "application": LibsecretKeyringBackend.APPLICATION_NAME,
+ "service": service_name,
+ "username": key
+ },
+ None,
+ key, # this is the title of the keyring entry
+ password,
+ None
+ )
+
+ def delete_password(self, service_name, key):
+ """Delete a password"""
+ secret = self._get_secret()
+ secret.password_clear_sync(
+ self.schema,
+ {
+ "application": LibsecretKeyringBackend.APPLICATION_NAME,
+ "service": service_name,
+ "username": key
+ },
+ None
+ )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python-proton-keyring-linux-0.2.0/proton/keyring_linux/secretservice/secretservice_backend.py
new/python-proton-keyring-linux-0.2.3/proton/keyring_linux/secretservice/secretservice_backend.py
---
old/python-proton-keyring-linux-0.2.0/proton/keyring_linux/secretservice/secretservice_backend.py
2024-11-19 15:07:58.000000000 +0100
+++
new/python-proton-keyring-linux-0.2.3/proton/keyring_linux/secretservice/secretservice_backend.py
2026-06-11 12:56:42.000000000 +0200
@@ -19,6 +19,7 @@
along with ProtonVPN. If not, see <https://www.gnu.org/licenses/>.
"""
import json
+import os
import logging
import keyring
@@ -37,6 +38,9 @@
@classmethod
def _validate(cls):
+ # this keyring doesn't work with snap containment
+ if os.environ.get("SNAP") is not None:
+ return False
try:
# pylint: disable=import-outside-toplevel
from keyring.backends import SecretService
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python-proton-keyring-linux-0.2.0/rpmbuild/SPECS/package.spec
new/python-proton-keyring-linux-0.2.3/rpmbuild/SPECS/package.spec
--- old/python-proton-keyring-linux-0.2.0/rpmbuild/SPECS/package.spec
2024-11-19 15:07:58.000000000 +0100
+++ new/python-proton-keyring-linux-0.2.3/rpmbuild/SPECS/package.spec
2026-06-11 12:56:42.000000000 +0200
@@ -1,5 +1,6 @@
%define unmangled_name proton-keyring-linux
-%define version 0.2.0
+%define pep_625_name proton_keyring_linux
+%define version 0.2.3
%define release 1
Prefix: %{_prefix}
@@ -13,10 +14,11 @@
License: GPLv3
Vendor: Proton AG <[email protected]>
URL: https://github.com/ProtonVPN/python-%{unmangled_name}
-Source0: %{unmangled_name}-%{version}.tar.gz
+Source0: %{pep_625_name}-%{version}.tar.gz
BuildArch: noarch
-BuildRoot: %{_tmppath}/%{unmangled_name}-%{version}-%{release}-buildroot
+BuildRoot: %{_tmppath}/%{pep_625_name}-%{version}-%{release}-buildroot
+BuildRequires: python3-devel
BuildRequires: python3-setuptools
BuildRequires: gnome-keyring
BuildRequires: python3-keyring
@@ -36,23 +38,31 @@
%description
Package %{unmangled_name} library.
-
%prep
-%setup -n %{unmangled_name}-%{version} -n %{unmangled_name}-%{version}
+%setup -q -n %{pep_625_name}-%{version}
%build
-python3 setup.py build
+%pyproject_wheel
%install
-python3 setup.py install --single-version-externally-managed -O1
--root=$RPM_BUILD_ROOT --record=INSTALLED_FILES
+%pyproject_install
+%pyproject_save_files proton
+%check
+%pyproject_check_import
-%files -f INSTALLED_FILES
-%{python3_sitelib}/proton/
-%{python3_sitelib}/proton_keyring_linux-%{version}*.egg-info/
-%defattr(-,root,root)
+%files -n %{name} -f %{pyproject_files}
%changelog
+* Mon Jun 11 2026 Elena Švilpė <[email protected]> 0.2.3
+- Restrict libsecret backend to Snap only.
+
+* Mon Jun 1 2026 Elena Švilpė <[email protected]> 0.2.2
+- Add libsecret backend.
+
+* Mon Sep 22 2025 Alexandru Cheltuitor <[email protected]> 0.2.1
+- Update spec file.
+
* Tue Nov 19 2024 Alexandru Cheltuitor <[email protected]> 0.2.0
- Drop Ubuntu 20.04 support.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-proton-keyring-linux-0.2.0/setup.py
new/python-proton-keyring-linux-0.2.3/setup.py
--- old/python-proton-keyring-linux-0.2.0/setup.py 2024-11-19
15:07:58.000000000 +0100
+++ new/python-proton-keyring-linux-0.2.3/setup.py 2026-06-11
12:56:42.000000000 +0200
@@ -4,7 +4,7 @@
setup(
name="proton-keyring-linux",
- version="0.2.0",
+ version="0.2.3",
description="Proton Technologies keyring plugins for linux",
author="Proton AG",
author_email="[email protected]",
@@ -14,11 +14,12 @@
"development": ["pytest", "pytest-coverage", "pylint", "flake8"]
},
packages=find_namespace_packages(include=[
- "proton.keyring_linux.core*", "proton.keyring_linux.secretservice*"]),
+ "proton.keyring_linux.core*",
"proton.keyring_linux.secretservice*","proton.keyring_linux.libsecret*"]),
include_package_data=True,
entry_points={
"proton_loader_keyring": [
- "secret_service =
proton.keyring_linux.secretservice:KeyringBackendLinuxSecretService"
+ "secret_service =
proton.keyring_linux.secretservice:KeyringBackendLinuxSecretService",
+ "libsecret =
proton.keyring_linux.libsecret:LibsecretKeyringBackend"
]
},
python_requires=">=3.9",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/python-proton-keyring-linux-0.2.0/tests/test_libsecret_backend.py
new/python-proton-keyring-linux-0.2.3/tests/test_libsecret_backend.py
--- old/python-proton-keyring-linux-0.2.0/tests/test_libsecret_backend.py
1970-01-01 01:00:00.000000000 +0100
+++ new/python-proton-keyring-linux-0.2.3/tests/test_libsecret_backend.py
2026-06-11 12:56:42.000000000 +0200
@@ -0,0 +1,128 @@
+"""
+Copyright (c) 2026 Proton AG
+
+This file is part of Proton VPN.
+
+Proton VPN is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Proton VPN is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with ProtonVPN. If not, see <https://www.gnu.org/licenses/>.
+"""
+import os
+import pytest
+from unittest.mock import MagicMock
+from proton.keyring_linux.libsecret import LibsecretKeyringBackend
+from proton.keyring_linux.secretservice import KeyringBackendLinuxSecretService
+
[email protected]
+def mock_secret():
+ mock_secret = MagicMock()
+ mock_secret.SchemaFlags.NONE = 0
+ mock_secret.SchemaAttributeType.STRING = "string"
+ mock_secret.Schema.new.return_value = MagicMock()
+ return mock_secret
+
+def raise_value_error():
+ raise ValueError
+
+def test_libsecret_priority_is_lower_than_secretservice():
+ assert LibsecretKeyringBackend._get_priority() <
KeyringBackendLinuxSecretService._get_priority()
+
+def test_validation_fails_when_libsecret_not_available():
+ LibsecretKeyringBackend._secret_module = None
+ LibsecretKeyringBackend._import_secret = staticmethod(raise_value_error)
+
+ assert not LibsecretKeyringBackend._validate()
+
+def test_validate_succeeds_with_snap_path(mock_secret, monkeypatch):
+ monkeypatch.setenv("SNAP", "test_value")
+ LibsecretKeyringBackend._secret_cache = mock_secret
+
+ assert LibsecretKeyringBackend._validate()
+
+def test_validate_fails_without_snap_path(mock_secret, monkeypatch):
+ # libsecret dependency is available but the app is not packaged in snap
+ monkeypatch.delenv("SNAP", raising=False)
+ LibsecretKeyringBackend._secret_cache = mock_secret
+
+ assert not LibsecretKeyringBackend._validate()
+
+def test_get_secret_lazy_imports_when_not_cached(mock_secret):
+ LibsecretKeyringBackend._secret_cache = None
+ LibsecretKeyringBackend._import_secret = staticmethod(lambda: mock_secret)
+
+ result = LibsecretKeyringBackend._get_secret()
+
+ assert result is mock_secret
+
+def test_get_secret_returns_cached_module_without_importing(mock_secret):
+ LibsecretKeyringBackend._secret_cache = mock_secret
+
+ result = LibsecretKeyringBackend._get_secret()
+
+ assert result is mock_secret
+
+def test_init_creates_correct_schema(mock_secret):
+ #this test is a reminder to keep the schema compatible with secretservice
+ LibsecretKeyringBackend._secret_cache = mock_secret
+ backend = LibsecretKeyringBackend()
+
+ mock_secret.Schema.new.assert_called_once_with(
+ LibsecretKeyringBackend.SCHEMA,
+ mock_secret.SchemaFlags.NONE,
+ {
+ "application": mock_secret.SchemaAttributeType.STRING,
+ "service": mock_secret.SchemaAttributeType.STRING,
+ "username": mock_secret.SchemaAttributeType.STRING,
+ },
+ )
+
+def test_set_password_calls_sync_with_correct_args(mock_secret):
+ LibsecretKeyringBackend._secret_cache = mock_secret
+ backend = LibsecretKeyringBackend()
+ backend.set_password("test-service", "test-key", "test-pass")
+
+ mock_secret.password_store_sync.assert_called_once_with(
+ backend.schema,
+ {"application": "Python keyring library", "service": "test-service",
"username": "test-key"},
+ None,
+ "test-key",
+ "test-pass",
+ None,
+ )
+
+def test_get_password_returns_password_when_found(mock_secret):
+ mock_secret.password_lookup_sync.return_value = "test-password"
+ LibsecretKeyringBackend._secret_cache = mock_secret
+ backend = LibsecretKeyringBackend()
+
+ assert backend.get_password("test-service", "test-key") == "test-password"
+
+def test_get_password_returns_None_when_not_found(mock_secret):
+ mock_secret.password_lookup_sync.return_value = None
+ LibsecretKeyringBackend._secret_cache = mock_secret
+ backend = LibsecretKeyringBackend()
+
+ assert backend.get_password("test-service", "test-key") == None
+
+def test_delete_password_calls_clear_sync_with_correct_args(mock_secret):
+ LibsecretKeyringBackend._secret_cache = mock_secret
+ backend = LibsecretKeyringBackend()
+
+ backend.delete_password("test-service", "test-key")
+
+ mock_secret.password_clear_sync.assert_called_once_with(
+ backend.schema,
+ {"application": "Python keyring library", "service": "test-service",
"username": "test-key"},
+ None,
+ )
+
+