Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-osc-tiny for openSUSE:Factory
checked in at 2022-12-13 18:55:24
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-osc-tiny (Old)
and /work/SRC/openSUSE:Factory/.python-osc-tiny.new.1835 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-osc-tiny"
Tue Dec 13 18:55:24 2022 rev:25 rq:1042475 version:0.7.9
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-osc-tiny/python-osc-tiny.changes
2022-11-03 19:14:28.724111325 +0100
+++
/work/SRC/openSUSE:Factory/.python-osc-tiny.new.1835/python-osc-tiny.changes
2022-12-13 18:55:41.899277236 +0100
@@ -1,0 +2,8 @@
+Mon Dec 12 09:09:04 UTC 2022 - Andreas Hasenkopf <[email protected]>
+
+- Release 0.7.9
+ * Simplified handling of SSH keys (fixes #114)
+ * Replaced `Request.cmd` with `Request.update` (fixes #113)
+ * Added a comment parameter to project and package `set_meta`
+
+-------------------------------------------------------------------
Old:
----
osc-tiny-0.7.7.tar.gz
New:
----
osc-tiny-0.7.9.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-osc-tiny.spec ++++++
--- /var/tmp/diff_new_pack.BzirB0/_old 2022-12-13 18:55:44.019288551 +0100
+++ /var/tmp/diff_new_pack.BzirB0/_new 2022-12-13 18:55:44.027288594 +0100
@@ -18,7 +18,7 @@
%define skip_python2 1
Name: python-osc-tiny
-Version: 0.7.7
+Version: 0.7.9
Release: 0
Summary: Client API for openSUSE BuildService
License: MIT
++++++ osc-tiny-0.7.7.tar.gz -> osc-tiny-0.7.9.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/osc-tiny-0.7.7/PKG-INFO new/osc-tiny-0.7.9/PKG-INFO
--- old/osc-tiny-0.7.7/PKG-INFO 2022-11-02 13:06:41.584857200 +0100
+++ new/osc-tiny-0.7.9/PKG-INFO 2022-12-12 13:21:46.650442600 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: osc-tiny
-Version: 0.7.7
+Version: 0.7.9
Summary: Client API for openSUSE BuildService
Home-page: http://github.com/crazyscientist/osc-tiny
Download-URL: http://github.com/crazyscientist/osc-tiny/tarball/master
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/osc-tiny-0.7.7/osc_tiny.egg-info/PKG-INFO
new/osc-tiny-0.7.9/osc_tiny.egg-info/PKG-INFO
--- old/osc-tiny-0.7.7/osc_tiny.egg-info/PKG-INFO 2022-11-02
13:06:41.000000000 +0100
+++ new/osc-tiny-0.7.9/osc_tiny.egg-info/PKG-INFO 2022-12-12
13:21:46.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: osc-tiny
-Version: 0.7.7
+Version: 0.7.9
Summary: Client API for openSUSE BuildService
Home-page: http://github.com/crazyscientist/osc-tiny
Download-URL: http://github.com/crazyscientist/osc-tiny/tarball/master
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/osc-tiny-0.7.7/osctiny/__init__.py
new/osc-tiny-0.7.9/osctiny/__init__.py
--- old/osc-tiny-0.7.7/osctiny/__init__.py 2022-11-02 13:06:32.000000000
+0100
+++ new/osc-tiny-0.7.9/osctiny/__init__.py 2022-12-12 13:21:36.000000000
+0100
@@ -6,4 +6,4 @@
__all__ = ['Osc', 'bs_requests', 'buildresults', 'comments', 'packages',
'projects', 'search', 'users']
-__version__ = "0.7.7"
+__version__ = "0.7.9"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/osc-tiny-0.7.7/osctiny/extensions/bs_requests.py
new/osc-tiny-0.7.9/osctiny/extensions/bs_requests.py
--- old/osc-tiny-0.7.7/osctiny/extensions/bs_requests.py 2022-11-02
13:06:32.000000000 +0100
+++ new/osc-tiny-0.7.9/osctiny/extensions/bs_requests.py 2022-12-12
13:21:36.000000000 +0100
@@ -4,6 +4,8 @@
"""
from urllib.parse import urljoin
+from lxml.etree import XMLSyntaxError
+
from ..utils.base import ExtensionBase
@@ -63,6 +65,37 @@
return self.osc.get_objectified_xml(response)
+ def update(self, request_id, **kwargs):
+ """
+ Update request or execute command
+
+ .. note::
+
+ In most cases, the API returns an XML response, so this method
will try to return an
+ objectified XML element. Otherwise, if parsing fails due to a
syntax error, the response
+ body is returned as plain text. In case of all other errors, this
method lets the
+ caller handle the exception.
+
+ :param request_id: ID of the request
+ :param kwargs: See Build Service
+ `API documentation
<https://build.opensuse.org/apidocs/index>`_ for accepted
+ keys and values.
+ :return: Response content
+ :rtype: lxml.objectify.ObjectifiedElement or plain text
+
+ .. versionadded:: 0.7.8
+ """
+ request_id = self._validate_id(request_id)
+ response = self.osc.request(
+ url=urljoin(self.osc.url, self.base_path + request_id),
+ method="POST",
+ params=kwargs
+ )
+ try:
+ return self.osc.get_objectified_xml(response)
+ except XMLSyntaxError:
+ return response.text
+
def cmd(self, request_id, cmd="diff", **kwargs):
"""
Get the result of the specified command
@@ -88,34 +121,14 @@
* Added ``addreview`` to list of allowed commands
* Added validation for arguments of command ``changereviewstate``
- """
- allowed_cmds = ['diff', 'changereviewstate', 'addreview']
- allowed_review_states = ['new', 'accepted', 'declined', 'deleted',
- 'revoked', 'superseded']
- if cmd not in allowed_cmds:
- raise ValueError("Invalid command: '{}'. Use one of: {}".format(
- cmd, ", ".join(allowed_cmds)
- ))
- if cmd == "changereviewstate"\
- and kwargs.get("newstate", None) not in allowed_review_states:
- raise ValueError(
- "Invalid review state: '{}'. Use one of: {}".format(
- kwargs.get("newstate", None), allowed_review_states
- )
- )
+ .. deprecated:: 0.7.8
+ * Replaced by :py:meth:`update`
+ """
kwargs["cmd"] = cmd
request_id = self._validate_id(request_id)
- response = self.osc.request(
- url=urljoin(self.osc.url, self.base_path + request_id),
- method="POST",
- params=kwargs
- )
-
- if kwargs.get("view", "plain") == "xml":
- return self.osc.get_objectified_xml(response)
- return response.text
+ return self.update(request_id=request_id, **kwargs)
def add_comment(self, request_id, comment, parent_id=None):
"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/osc-tiny-0.7.7/osctiny/extensions/packages.py
new/osc-tiny-0.7.9/osctiny/extensions/packages.py
--- old/osc-tiny-0.7.7/osctiny/extensions/packages.py 2022-11-02
13:06:32.000000000 +0100
+++ new/osc-tiny-0.7.9/osctiny/extensions/packages.py 2022-12-12
13:21:36.000000000 +0100
@@ -115,7 +115,7 @@
# pylint: disable=too-many-arguments,protected-access
def set_meta(self, project, package, title=None, description=None,
- meta=None):
+ meta=None, comment=None):
"""
Set package metadata
@@ -130,12 +130,17 @@
.. versionadded:: 0.1.2
+ .. versionchanged:: 0.7.8
+
+ Added an optional ``comment`` argument to be used as commit message
+
:param project: Project name
:param package: New package name
:param title: Title for meta
:param description: Description for meta
:param meta: New content for meta
:type meta: str or lxml.objectify.ObjectifiedElement
+ :param comment: Optional comment to use as commit message
:return:
"""
if isinstance(meta, (str, bytes)):
@@ -157,6 +162,7 @@
"/".join((self.base_path, project, package, "_meta"))
),
data=tounicode(meta_xml),
+ params={"comment": comment},
method="PUT"
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/osc-tiny-0.7.7/osctiny/extensions/projects.py
new/osc-tiny-0.7.9/osctiny/extensions/projects.py
--- old/osc-tiny-0.7.7/osctiny/extensions/projects.py 2022-11-02
13:06:32.000000000 +0100
+++ new/osc-tiny-0.7.9/osctiny/extensions/projects.py 2022-12-12
13:21:36.000000000 +0100
@@ -72,6 +72,7 @@
.. deprecated:: 0.7.2
Use :meth:`set_meta` instead
+
:param project: name of project
:param metafile: Complete metafile
:type metafile: str or ElementTree
@@ -85,11 +86,11 @@
warn("Deprecated. Use projects.set_meta instead")
return self.set_meta(project, metafile, title, description, bugowner,
- maintainer)
+ maintainer)
# pylint: disable=too-many-arguments
def set_meta(self, project, metafile=None, title=None, description=None,
- bugowner=None, maintainer=None):
+ bugowner=None, maintainer=None, comment=None):
"""
Edit project meta data or create a new project
@@ -97,6 +98,10 @@
.. versionadded:: 0.7.2
+ .. versionchanged:: 0.7.8
+
+ Added an optional ``comment`` argument to be used as commit message
+
:param project: name of project
:param metafile: Complete metafile
:type metafile: str or ElementTree
@@ -104,6 +109,7 @@
:param description: Description for meta file
:param bugowner: Bugowner for meta file
:param maintainer: Maintainer for meta file
+ :param comment: Optional comment to use as commit message
:return: ``True``, if successful. Otherwise API response
:rtype: bool or lxml.objectify.ObjectifiedElement
"""
@@ -143,7 +149,8 @@
url=urljoin(self.osc.url,
"/".join((self.base_path, project, "_meta"))),
method="PUT",
- data=tounicode(metafile)
+ data=tounicode(metafile),
+ params={"comment": comment}
)
parsed = self.osc.get_objectified_xml(response)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/osc-tiny-0.7.7/osctiny/tests/test_packages.py
new/osc-tiny-0.7.9/osctiny/tests/test_packages.py
--- old/osc-tiny-0.7.7/osctiny/tests/test_packages.py 2022-11-02
13:06:32.000000000 +0100
+++ new/osc-tiny-0.7.9/osctiny/tests/test_packages.py 2022-12-12
13:21:36.000000000 +0100
@@ -336,6 +336,23 @@
self.assertEqual(bodies[-1], expected)
@responses.activate
+ def test_set_meta_with_comment(self):
+ def callback(headers, params, request):
+ status, body = 200, ""
+
+ return status, headers, body
+
+ self.mock_request(
+ method=responses.PUT,
+ url=re.compile(self.osc.url + '/source/(?P<project>[^/]+)/'
+ '(?P<package>[^/]+)/_meta'),
+ callback=CallbackFactory(callback)
+ )
+ self.osc.packages.set_meta("test:project", "test.package", "test
title", "test description",
+ comment="test comment")
+ self.assertEqual(responses.calls[-1].request.params["comment"], "test
comment")
+
+ @responses.activate
def test_push_file(self):
content = """
á(ಠçಠ)á á(ಠçಠ)á
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/osc-tiny-0.7.7/osctiny/tests/test_projects.py
new/osc-tiny-0.7.9/osctiny/tests/test_projects.py
--- old/osc-tiny-0.7.7/osctiny/tests/test_projects.py 2022-11-02
13:06:32.000000000 +0100
+++ new/osc-tiny-0.7.9/osctiny/tests/test_projects.py 2022-12-12
13:21:36.000000000 +0100
@@ -177,6 +177,14 @@
self.assertEqual(sent_meta.description.text, "test description")
self.assertEqual(len(sent_meta.xpath("person")), 2)
+ with self.subTest("Valid Metafile with comment"):
+ meta = fromstring(TEMPLATE_META)
+ meta.set("name", "project:foo")
+ meta.title._setText("Hello World")
+ self.assertTrue(self.osc.projects.set_meta(project="project:foo",
metafile=meta,
+ comment="Test"))
+ self.assertEqual(responses.calls[-1].request.params["comment"],
"Test")
+
@responses.activate
def test_get_files(self):
def callback(headers, params, request):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/osc-tiny-0.7.7/osctiny/tests/test_requests.py
new/osc-tiny-0.7.9/osctiny/tests/test_requests.py
--- old/osc-tiny-0.7.7/osctiny/tests/test_requests.py 2022-11-02
13:06:32.000000000 +0100
+++ new/osc-tiny-0.7.9/osctiny/tests/test_requests.py 2022-12-12
13:21:36.000000000 +0100
@@ -372,20 +372,16 @@
self.assertEqual(len(response.xpath("//request/history")), 5)
@responses.activate
- def test_cmd(self):
- with self.subTest("plain diff"):
- response = self.osc.requests.cmd(30902, "diff")
- self.assertTrue(isinstance(response, str))
- self.assertIn("changes files:", response)
- self.assertIn("+++ perl-XML-DOM-XPath.changes", response)
- with self.subTest("xml diff"):
- response = self.osc.requests.cmd(30902, "diff", view="xml")
- self.assertTrue(isinstance(response, ObjectifiedElement))
- with self.subTest("changereviewstate"):
- self.assertRaises(
- ValueError,
- self.osc.requests.cmd, 30902, "changereviewstate"
- )
+ def test_update(self):
+ for method in (self.osc.requests.update, self.osc.requests.cmd):
+ with self.subTest(f"{method}, cmd=diff, plain"):
+ response = method(30902, cmd="diff")
+ self.assertTrue(isinstance(response, str))
+ self.assertIn("changes files:", response)
+ self.assertIn("+++ perl-XML-DOM-XPath.changes", response)
+ with self.subTest(f"{method}, cmd=diff, xml"):
+ response = method(30902, cmd="diff", view="xml")
+ self.assertTrue(isinstance(response, ObjectifiedElement))
@responses.activate
def test_comment(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/osc-tiny-0.7.7/osctiny/tests/test_utils.py
new/osc-tiny-0.7.9/osctiny/tests/test_utils.py
--- old/osc-tiny-0.7.7/osctiny/tests/test_utils.py 2022-11-02
13:06:32.000000000 +0100
+++ new/osc-tiny-0.7.9/osctiny/tests/test_utils.py 2022-12-12
13:21:36.000000000 +0100
@@ -396,7 +396,8 @@
@mock.patch("osctiny.utils.auth.time", return_value=123456)
class TestAuth(TestCase):
- def setUp(self):
+ @mock.patch("osctiny.utils.auth.is_ssh_key_readable", return_value=True)
+ def setUp(self, *_):
super().setUp()
mocked_path = mock.MagicMock(spec=Path)
mocked_path.configure_mock(**{"is_file.return_value": True})
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/osc-tiny-0.7.7/osctiny/utils/auth.py
new/osc-tiny-0.7.9/osctiny/utils/auth.py
--- old/osc-tiny-0.7.7/osctiny/utils/auth.py 2022-11-02 13:06:32.000000000
+0100
+++ new/osc-tiny-0.7.9/osctiny/utils/auth.py 2022-12-12 13:21:36.000000000
+0100
@@ -7,9 +7,8 @@
import typing
from base64 import b64decode, b64encode
import logging
-import os
from pathlib import Path
-from subprocess import Popen, PIPE
+from subprocess import Popen, PIPE, DEVNULL
import re
import sys
from time import time
@@ -55,6 +54,32 @@
return None
+def is_ssh_key_readable(ssh_key_file: Path, password: typing.Optional[str]) ->
bool:
+ """
+ Check whether SSH key can be read/unlocked
+
+ :param ssh_key_file: Path to SSH key
+ :param password: Passphrase
+ :return: ``True``, if SSH key is accessible
+
+ .. versionadded:: 0.6.3
+
+ .. versionchanged:: 0.7.8
+
+ * Moved from ``HttpSignatureAuth.is_ssh_agent_available``
+ """
+ cmd = ['ssh-keygen', '-y', '-f', ssh_key_file.as_posix()]
+ if password:
+ cmd += ['-P', password]
+
+ with Popen(cmd, stdin=DEVNULL, stderr=DEVNULL, stdout=DEVNULL) as proc:
+ proc.communicate()
+ if proc.returncode == 0:
+ return True
+
+ return False
+
+
class HttpSignatureAuth(HTTPDigestAuth):
"""
Implementation of the "Signature authentication scheme"
@@ -70,17 +95,24 @@
.. _reference implementation for osc:
https://github.com/openSUSE/osc/pull/1032
+ .. note::
+
+ 1. It is recommended to use SSH keys with a passphrase.
+ 2. If ``ssh-agent`` is running, the passphrase is not required at
initialization of this
+ class.
+ 3. If you use an SSH key without passphrase, you don't need to specify
it.
+
:param username: The username
- :param password: Passphrase for SSH key. This can be omitted, if
``ssh-agent`` is also installed
- :param ssh_key_file: Path of SSK key
+ :param password: Passphrase for SSH key
+ :param ssh_key_file: Path of SSH key
"""
def __init__(self, username: str, password: typing.Optional[str],
ssh_key_file: Path):
super().__init__(username=username, password=password)
if not ssh_key_file.is_file():
raise FileNotFoundError(f"SSH key at location does not exist:
{ssh_key_file}")
- if not password and not self.is_ssh_agent_available():
- raise RuntimeError("SSH signing impossible: No password/passphrase
provided and no SSH "
- "agent running! ")
+ if not is_ssh_key_readable(ssh_key_file=ssh_key_file,
password=password):
+ raise RuntimeError("SSH signing impossible: Unable to decrypt
key.")
+
self.ssh_key_file = ssh_key_file
self.pattern = re.compile(r"(?<=\)) (?=\()")
@@ -96,19 +128,6 @@
parts = self.pattern.split(headers)
return [part.strip("()") for part in parts]
- @staticmethod
- def is_ssh_agent_available() -> bool:
- """
- Check whether SSH agent is running/available
-
- :return: ``True``, if agent is running
-
- .. versionadded:: 0.6.3
- """
- relevant_keys = {'SSH_AUTH_SOCK', 'SSH_AGENT_PID'}
- overlap = os.environ.keys() & relevant_keys
- return len(overlap) > 0
-
def ssh_sign(self) -> str:
"""
Solve the challenge via SSH signing
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/osc-tiny-0.7.7/osctiny/utils/changelog.py
new/osc-tiny-0.7.9/osctiny/utils/changelog.py
--- old/osc-tiny-0.7.7/osctiny/utils/changelog.py 2022-11-02
13:06:32.000000000 +0100
+++ new/osc-tiny-0.7.9/osctiny/utils/changelog.py 2022-12-12
13:21:36.000000000 +0100
@@ -118,6 +118,7 @@
cl.write()
.. py:attribute:: entry_factory
+ :noindex:
A class used to store entry data.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/osc-tiny-0.7.7/setup.py new/osc-tiny-0.7.9/setup.py
--- old/osc-tiny-0.7.7/setup.py 2022-11-02 13:06:32.000000000 +0100
+++ new/osc-tiny-0.7.9/setup.py 2022-12-12 13:21:36.000000000 +0100
@@ -26,7 +26,7 @@
setup(
name='osc-tiny',
- version='0.7.7',
+ version='0.7.9',
description='Client API for openSUSE BuildService',
long_description=long_description,
long_description_content_type="text/markdown",