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 2024-06-28 15:47:44
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-osc-tiny (Old)
 and      /work/SRC/openSUSE:Factory/.python-osc-tiny.new.18349 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-osc-tiny"

Fri Jun 28 15:47:44 2024 rev:34 rq:1183801 version:0.10.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-osc-tiny/python-osc-tiny.changes  
2024-05-22 21:32:44.714567797 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-osc-tiny.new.18349/python-osc-tiny.changes   
    2024-06-28 15:51:23.487491514 +0200
@@ -1,0 +2,7 @@
+Thu Jun 27 15:45:09 UTC 2024 - Chen Huang <chhu...@suse.com>
+
+- Release 0.10.0
+  * Added capability to create requests (#165)
+  * Install the theme for the docs (#163)
+
+-------------------------------------------------------------------

Old:
----
  osc-tiny-0.9.1.tar.gz

New:
----
  osc-tiny-0.10.0.tar.gz

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

Other differences:
------------------
++++++ python-osc-tiny.spec ++++++
--- /var/tmp/diff_new_pack.Iu2a4S/_old  2024-06-28 15:51:28.563677205 +0200
+++ /var/tmp/diff_new_pack.Iu2a4S/_new  2024-06-28 15:51:28.567677352 +0200
@@ -19,7 +19,7 @@
 %define skip_python2 1
 %{?sle15allpythons}
 Name:           python-osc-tiny
-Version:        0.9.1
+Version:        0.10.0
 Release:        0
 Summary:        Client API for openSUSE BuildService
 License:        MIT

++++++ osc-tiny-0.9.1.tar.gz -> osc-tiny-0.10.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-tiny-0.9.1/PKG-INFO new/osc-tiny-0.10.0/PKG-INFO
--- old/osc-tiny-0.9.1/PKG-INFO 2024-05-22 10:58:11.398337600 +0200
+++ new/osc-tiny-0.10.0/PKG-INFO        2024-06-27 13:00:45.511684400 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: osc-tiny
-Version: 0.9.1
+Version: 0.10.0
 Summary: Client API for openSUSE BuildService
 Home-page: https://github.com/SUSE/osc-tiny
 Author: Andreas Hasenkopf
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-tiny-0.9.1/osc_tiny.egg-info/PKG-INFO 
new/osc-tiny-0.10.0/osc_tiny.egg-info/PKG-INFO
--- old/osc-tiny-0.9.1/osc_tiny.egg-info/PKG-INFO       2024-05-22 
10:58:11.000000000 +0200
+++ new/osc-tiny-0.10.0/osc_tiny.egg-info/PKG-INFO      2024-06-27 
13:00:45.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: osc-tiny
-Version: 0.9.1
+Version: 0.10.0
 Summary: Client API for openSUSE BuildService
 Home-page: https://github.com/SUSE/osc-tiny
 Author: Andreas Hasenkopf
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-tiny-0.9.1/osc_tiny.egg-info/SOURCES.txt 
new/osc-tiny-0.10.0/osc_tiny.egg-info/SOURCES.txt
--- old/osc-tiny-0.9.1/osc_tiny.egg-info/SOURCES.txt    2024-05-22 
10:58:11.000000000 +0200
+++ new/osc-tiny-0.10.0/osc_tiny.egg-info/SOURCES.txt   2024-06-27 
13:00:45.000000000 +0200
@@ -26,6 +26,7 @@
 osctiny/extensions/staging.py
 osctiny/extensions/users.py
 osctiny/models/__init__.py
+osctiny/models/request.py
 osctiny/models/staging.py
 osctiny/tests/__init__.py
 osctiny/tests/base.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-tiny-0.9.1/osctiny/__init__.py 
new/osc-tiny-0.10.0/osctiny/__init__.py
--- old/osc-tiny-0.9.1/osctiny/__init__.py      2024-05-22 10:58:07.000000000 
+0200
+++ new/osc-tiny-0.10.0/osctiny/__init__.py     2024-06-27 13:00:41.000000000 
+0200
@@ -6,4 +6,4 @@
 
 __all__ = ['Osc', 'bs_requests', 'buildresults', 'comments', 'packages',
            'projects', 'search', 'users']
-__version__ = "0.9.1"
+__version__ = "0.10.0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-tiny-0.9.1/osctiny/extensions/bs_requests.py 
new/osc-tiny-0.10.0/osctiny/extensions/bs_requests.py
--- old/osc-tiny-0.9.1/osctiny/extensions/bs_requests.py        2024-05-22 
10:58:07.000000000 +0200
+++ new/osc-tiny-0.10.0/osctiny/extensions/bs_requests.py       2024-06-27 
13:00:41.000000000 +0200
@@ -8,7 +8,8 @@
 from lxml.etree import XMLSyntaxError
 from lxml.objectify import ObjectifiedElement
 
-from ..models import IntOrString, ParamsType
+from ..models import E, IntOrString, ParamsType
+from ..models.request import Action, Review
 from ..utils.base import ExtensionBase
 
 
@@ -27,6 +28,41 @@
             )
         return request_id
 
+    # pylint: disable=too-many-arguments
+    def create(self, actions: typing.Iterable[Action],
+               reviewers: typing.Optional[typing.Iterable[Review]] = None,
+               addrevision: bool = False, ignore_delegate: bool = False,
+               ignore_build_state: bool = False) -> int:
+        """
+        Create a request
+
+        :param actions: Actions to be included in request
+        :param reviewers: Reviewers to be assigned
+        :param addrevision: Ask the server to add revisions of the current 
sources to the request.
+        :param ignore_delegate: Enforce a new package instance in a project 
which has
+                                ``OBS:DelegateRequestTarget`` set
+        :param ignore_build_state: Skip the build state check
+        :return: Request ID
+
+        .. versionadded:: 0.10.0
+        """
+        request = E.request(*(action.asxml() for action in actions),
+                            *(review.asxml() for review in reviewers or []))
+
+        response = self.osc.request(
+            url=urljoin(self.osc.url, self.base_path),
+            method="POST",
+            data=request,
+            params={
+                "cmd": "create",
+                "addrevision": addrevision,
+                "ignore_delegate": ignore_delegate,
+                "ignore_build_state": ignore_build_state
+            },
+        )
+        data = self.osc.get_objectified_xml(response)
+        return int(data.get("id"))
+
     def get_list(self, **params: ParamsType) -> ObjectifiedElement:
         """
         Get a list or request objects
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-tiny-0.9.1/osctiny/models/__init__.py 
new/osc-tiny-0.10.0/osctiny/models/__init__.py
--- old/osc-tiny-0.9.1/osctiny/models/__init__.py       2024-05-22 
10:58:07.000000000 +0200
+++ new/osc-tiny-0.10.0/osctiny/models/__init__.py      2024-06-27 
13:00:41.000000000 +0200
@@ -5,8 +5,13 @@
 from io import BufferedReader, BytesIO, StringIO
 import typing
 
-from lxml.objectify import ObjectifiedElement
+from lxml.objectify import ElementMaker, ObjectifiedElement
 
+#: XML maker without python type annotations
+E = ElementMaker(annotate=False)
 
+#: Acceptable types for HTTP parameters
 ParamsType = typing.Union[bytes, str, StringIO, BytesIO, BufferedReader, dict, 
ObjectifiedElement]
+
+#: Int or string with only numbers
 IntOrString = typing.Union[int, str]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-tiny-0.9.1/osctiny/models/request.py 
new/osc-tiny-0.10.0/osctiny/models/request.py
--- old/osc-tiny-0.9.1/osctiny/models/request.py        1970-01-01 
01:00:00.000000000 +0100
+++ new/osc-tiny-0.10.0/osctiny/models/request.py       2024-06-27 
13:00:41.000000000 +0200
@@ -0,0 +1,105 @@
+"""
+Models for requests
+^^^^^^^^^^^^^^^^^^^
+
+.. versionadded:: 0.10.0
+"""
+# pylint: disable=missing-function-docstring,no-member
+# Note: The `no-member` rule needs to be disabled due to this bug:
+#       https://github.com/pylint-dev/pylint/issues/7891
+import enum
+import typing
+
+from lxml.objectify import ObjectifiedElement
+
+from . import E
+
+
+class ActionType(enum.Enum):
+    """
+    Request action types as defined in OpenBuildService
+    """
+    ADD_ROLE = "add_role"
+    CHANGE_DEVEL = "change_devel"
+    DELETE = "delete"
+    MAINTENANCE_INCIDENT = "maintenance_incident"
+    MAINTENANCE_RELEASE = "maintenance_release"
+    RELEASE = "release"
+    SET_BUGOWNER = "set_bugowner"
+    SUBMIT = "submit"
+
+
+class Person(typing.NamedTuple):
+    """
+    Person model for use in actions
+    """
+    name: str
+
+    def asxml(self) -> ObjectifiedElement:
+        return E.person(name=self.name)
+
+
+class Source(typing.NamedTuple):
+    """
+    Source for an action
+    """
+    project: str
+    package: str
+    rev: typing.Optional[str] = None
+
+    def asxml(self) -> ObjectifiedElement:
+        return E.source(**{field: getattr(self, field)
+                           for field in self._fields
+                           if getattr(self, field, None) is not None})
+
+
+class Target(typing.NamedTuple):
+    """
+    Target for an action
+    """
+    project: str
+    package: str
+    releaseproject: typing.Optional[str] = None
+
+    def asxml(self) -> ObjectifiedElement:
+        return E.target(**{field: getattr(self, field)
+                           for field in self._fields
+                           if getattr(self, field, None) is not None})
+
+
+class Action(typing.NamedTuple):
+    """
+    Request action
+    """
+    type: ActionType
+    target: Target
+    person: typing.Optional[Person] = None
+    source: typing.Optional[Source] = None
+
+    def asxml(self) -> ObjectifiedElement:
+        sub_elems = [self.target.asxml()]
+        for field in (self.person, self.source):
+            if field is not None:
+                sub_elems.append(field.asxml())
+        return E.action(*sub_elems, type=self.type.value)
+
+
+class By(enum.Enum):
+    """
+    Types by which reviews can be assigned
+    """
+    USER = "by_user"
+    GROUP = "by_group"
+    PROJECT = "by_project"
+    PACKAGE = "by_package"
+
+
+class Review(typing.NamedTuple):
+    """
+    Assign a review
+    """
+    by: By
+    name: str
+
+    def asxml(self) -> ObjectifiedElement:
+        return E.review(**{self.by.value: self.name})
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-tiny-0.9.1/osctiny/models/staging.py 
new/osc-tiny-0.10.0/osctiny/models/staging.py
--- old/osc-tiny-0.9.1/osctiny/models/staging.py        2024-05-22 
10:58:07.000000000 +0200
+++ new/osc-tiny-0.10.0/osctiny/models/staging.py       2024-06-27 
13:00:41.000000000 +0200
@@ -1,15 +1,16 @@
 """
 Models for Staging
 ^^^^^^^^^^^^^^^^^^
+
+.. versionadded:: 0.9.0
 """
 # pylint: disable=missing-class-docstring,missing-function-docstring
 import enum
 import typing
 
-from lxml.objectify import ObjectifiedElement, ElementMaker
-
+from lxml.objectify import ObjectifiedElement
 
-E = ElementMaker(annotate=False)
+from ..models import E
 
 
 class ExcludedRequest(typing.NamedTuple):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-tiny-0.9.1/osctiny/tests/test_requests.py 
new/osc-tiny-0.10.0/osctiny/tests/test_requests.py
--- old/osc-tiny-0.9.1/osctiny/tests/test_requests.py   2024-05-22 
10:58:07.000000000 +0200
+++ new/osc-tiny-0.10.0/osctiny/tests/test_requests.py  2024-06-27 
13:00:41.000000000 +0200
@@ -1,10 +1,13 @@
 # -*- coding: utf-8 -*-
 import re
+from unittest import mock
 from urllib.parse import urlparse, parse_qs
 
 from lxml.objectify import ObjectifiedElement
+from requests.models import Response
 import responses
 
+from ..models.request import Action, ActionType, Person, Review, Source, 
Target, By
 from .base import OscTest, CallbackFactory
 
 
@@ -304,6 +307,9 @@
           and "changereviewstate" in params.get("cmd", [])):
         status = 403
         body = "Forbidden for url: http://api.example.com/request/30902";
+    elif request.method == "POST" and re.search("/request/?\?", request.url):
+        status = 200
+        body = """<request id="42"/>"""
     else:
         status = 404
         body = """
@@ -343,6 +349,91 @@
         )
 
     @responses.activate
+    def test_create(self):
+        target = Target(project="Foo:Bar:Factory", package="hello-world")
+        actions = [
+            Action(
+                type=ActionType.SUBMIT,
+                source=Source(project="Foo:Bar", package="hello-world"),
+                target=target
+            ),
+            Action(
+                type=ActionType.DELETE,
+                target=target
+            )
+        ]
+        reviewers = [
+            Review(by=By.USER, name="nemo"),
+            Review(by=By.GROUP, name="superusers")
+        ]
+
+        with self.subTest("HTTP Request, only Actions"):
+            self.assertEqual(42, self.osc.requests.create(actions=actions))
+
+        with self.subTest("HTTP Request, with Reviewers"):
+            self.assertEqual(42, self.osc.requests.create(actions=actions,
+                                                          reviewers=reviewers))
+
+        mock_response = Response()
+        mock_response.status_code = 200
+        mock_response._content = b"""<request id="42"/>"""
+
+        with self.subTest("XML content, only Actions"), \
+                mock.patch.object(self.osc.session, "send",
+                                  return_value=mock_response) as mock_session:
+            self.osc.requests.create(actions=actions)
+            self.assertEqual(
+                mock_session.call_args[0][0].body,
+                b"<?xml version='1.0' encoding='utf-8'?>\n"
+                b'<request>'
+                b'<action type="submit">'
+                b'<target project="Foo:Bar:Factory" package="hello-world"/>'
+                b'<source project="Foo:Bar" package="hello-world"/>'
+                b'</action>'
+                b'<action type="delete">'
+                b'<target project="Foo:Bar:Factory" package="hello-world"/>'
+                b'</action>'
+                b'</request>'
+            )
+
+        with self.subTest("XML content, with Reviewers"), \
+                mock.patch.object(self.osc.session, "send",
+                                  return_value=mock_response) as mock_session:
+            self.osc.requests.create(actions=actions, reviewers=reviewers)
+            self.assertEqual(
+                mock_session.call_args[0][0].body,
+                b"<?xml version='1.0' encoding='utf-8'?>\n"
+                b'<request>'
+                b'<action type="submit">'
+                b'<target project="Foo:Bar:Factory" package="hello-world"/>'
+                b'<source project="Foo:Bar" package="hello-world"/>'
+                b'</action>'
+                b'<action type="delete">'
+                b'<target project="Foo:Bar:Factory" package="hello-world"/>'
+                b'</action>'
+                b'<review by_user="nemo"/>'
+                b'<review by_group="superusers"/>'
+                b'</request>'
+            )
+
+        with self.subTest("XML content, set bugowner"), \
+                mock.patch.object(self.osc.session, "send",
+                                  return_value=mock_response) as mock_session:
+            
self.osc.requests.create(actions=[Action(type=ActionType.SET_BUGOWNER,
+                                                     
target=Target(project="Foo:Bar", package="p"),
+                                                     
person=Person(name="nemo"))])
+            self.assertEqual(
+                mock_session.call_args[0][0].body,
+                b"<?xml version='1.0' encoding='utf-8'?>\n"
+                b'<request>'
+                b'<action type="set_bugowner">'
+                b'<target project="Foo:Bar" package="p"/>'
+                b'<person name="nemo"/>'
+                b'</action>'
+                b'</request>'
+            )
+
+    @responses.activate
     def test_get_list(self):
         response = self.osc.requests.get_list()
         self.assertEqual(response.tag, "directory")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-tiny-0.9.1/setup.py new/osc-tiny-0.10.0/setup.py
--- old/osc-tiny-0.9.1/setup.py 2024-05-22 10:58:07.000000000 +0200
+++ new/osc-tiny-0.10.0/setup.py        2024-06-27 13:00:41.000000000 +0200
@@ -26,7 +26,7 @@
 
 setup(
     name='osc-tiny',
-    version='0.9.1',
+    version='0.10.0',
     description='Client API for openSUSE BuildService',
     long_description=long_description,
     long_description_content_type="text/markdown",

Reply via email to