Hello community,

here is the log from the commit of package python-osc-tiny for 
openSUSE:Leap:15.2 checked in at 2020-03-29 14:56:31
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Leap:15.2/python-osc-tiny (Old)
 and      /work/SRC/openSUSE:Leap:15.2/.python-osc-tiny.new.3160 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-osc-tiny"

Sun Mar 29 14:56:31 2020 rev:2 rq:789311 version:0.2.2

Changes:
--------
--- /work/SRC/openSUSE:Leap:15.2/python-osc-tiny/python-osc-tiny.changes        
2020-02-16 18:29:30.262755189 +0100
+++ 
/work/SRC/openSUSE:Leap:15.2/.python-osc-tiny.new.3160/python-osc-tiny.changes  
    2020-03-29 14:56:32.239197390 +0200
@@ -1,0 +2,9 @@
+Fri Mar 27 13:45:55 UTC 2020 - [email protected]
+
+- version update to 0.2.2
+ * Added the `issues` extension
+ * Give (read only) access to issues and issue trackers known to BuildService
+ * Set version to 0.2.2
+ * Dirty hacks for Python2 compatibility
+
+-------------------------------------------------------------------

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

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

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

Other differences:
------------------
++++++ python-osc-tiny.spec ++++++
--- /var/tmp/diff_new_pack.GYiO2A/_old  2020-03-29 14:56:33.495198369 +0200
+++ /var/tmp/diff_new_pack.GYiO2A/_new  2020-03-29 14:56:33.539198403 +0200
@@ -18,7 +18,7 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-osc-tiny
-Version:        0.2.1
+Version:        0.2.2
 Release:        0
 Summary:        Client API for openSUSE BuildService
 License:        MIT
@@ -27,6 +27,7 @@
 Source:         
https://files.pythonhosted.org/packages/source/o/osc-tiny/osc-tiny-%{version}.tar.gz
 BuildRequires:  %{python_module devel}
 BuildRequires:  %{python_module lxml}
+BuildRequires:  %{python_module pytest}
 BuildRequires:  %{python_module python-dateutil}
 BuildRequires:  %{python_module pytz}
 BuildRequires:  %{python_module requests}
@@ -41,11 +42,11 @@
 Requires:       python-python-dateutil
 Requires:       python-pytz
 Requires:       python-requests
+Requires:       python-responses
 Requires:       python-six
 BuildArch:      noarch
 %ifpython2
 Requires:       python-mock
-Requires:       python-unittest2
 %endif
 %python_subpackages
 
@@ -66,7 +67,7 @@
 %python_build
 
 %check
-%python_exec -m unittest discover -v
+%pytest
 
 %install
 %python_install

++++++ osc-tiny-0.2.1.tar.gz -> osc-tiny-0.2.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-tiny-0.2.1/PKG-INFO new/osc-tiny-0.2.2/PKG-INFO
--- old/osc-tiny-0.2.1/PKG-INFO 2020-01-10 09:32:27.000000000 +0100
+++ new/osc-tiny-0.2.2/PKG-INFO 2020-02-04 09:22:19.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: osc-tiny
-Version: 0.2.1
+Version: 0.2.2
 Summary: Client API for openSUSE BuildService
 Home-page: http://github.com/crazyscientist/osc-tiny
 Author: Andreas Hasenkopf
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-tiny-0.2.1/osc_tiny.egg-info/PKG-INFO 
new/osc-tiny-0.2.2/osc_tiny.egg-info/PKG-INFO
--- old/osc-tiny-0.2.1/osc_tiny.egg-info/PKG-INFO       2020-01-10 
09:32:27.000000000 +0100
+++ new/osc-tiny-0.2.2/osc_tiny.egg-info/PKG-INFO       2020-02-04 
09:22:19.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: osc-tiny
-Version: 0.2.1
+Version: 0.2.2
 Summary: Client API for openSUSE BuildService
 Home-page: http://github.com/crazyscientist/osc-tiny
 Author: Andreas Hasenkopf
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-tiny-0.2.1/osc_tiny.egg-info/SOURCES.txt 
new/osc-tiny-0.2.2/osc_tiny.egg-info/SOURCES.txt
--- old/osc-tiny-0.2.1/osc_tiny.egg-info/SOURCES.txt    2020-01-10 
09:32:27.000000000 +0100
+++ new/osc-tiny-0.2.2/osc_tiny.egg-info/SOURCES.txt    2020-02-04 
09:22:19.000000000 +0100
@@ -17,6 +17,7 @@
 osctiny/extensions/bs_requests.py
 osctiny/extensions/buildresults.py
 osctiny/extensions/comments.py
+osctiny/extensions/issues.py
 osctiny/extensions/packages.py
 osctiny/extensions/projects.py
 osctiny/extensions/search.py
@@ -28,6 +29,7 @@
 osctiny/tests/test_cache.py
 osctiny/tests/test_comments.py
 osctiny/tests/test_datadir.py
+osctiny/tests/test_issues.py
 osctiny/tests/test_packages.py
 osctiny/tests/test_projects.py
 osctiny/tests/test_requests.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-tiny-0.2.1/osctiny/__init__.py 
new/osc-tiny-0.2.2/osctiny/__init__.py
--- old/osc-tiny-0.2.1/osctiny/__init__.py      2020-01-10 09:32:12.000000000 
+0100
+++ new/osc-tiny-0.2.2/osctiny/__init__.py      2020-02-04 09:21:59.000000000 
+0100
@@ -6,4 +6,4 @@
 
 __all__ = ['Osc', 'bs_requests', 'buildresults', 'comments', 'packages',
            'projects', 'search', 'users']
-__version__ = "0.2.1"
+__version__ = "0.2.2"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-tiny-0.2.1/osctiny/extensions/issues.py 
new/osc-tiny-0.2.2/osctiny/extensions/issues.py
--- old/osc-tiny-0.2.1/osctiny/extensions/issues.py     1970-01-01 
01:00:00.000000000 +0100
+++ new/osc-tiny-0.2.2/osctiny/extensions/issues.py     2020-02-04 
09:21:59.000000000 +0100
@@ -0,0 +1,89 @@
+"""
+Issues extension
+------------------
+"""
+from __future__ import unicode_literals
+import os
+
+from six.moves.urllib.parse import urljoin
+from six import text_type
+
+from ..utils.base import ExtensionBase
+
+try:
+    from functools import lru_cache
+except ImportError:
+    # Whoever had the grandiose idea to backport this to Python2?
+    # pylint: disable=unused-argument, missing-function-docstring
+    def lru_cache(*args, **kwargs):
+        def wrapper(fun):
+            return fun
+
+        return wrapper
+
+
+class Issue(ExtensionBase):
+    """
+    The BuildService issue(-tracker) API is accessible through this object.
+
+    .. versionadded:: 0.2.2
+    """
+    base_path = "/issue_trackers/"
+
+    @staticmethod
+    def _validate(value):
+        return text_type(value)
+
+    @lru_cache(maxsize=1)
+    def get_trackers(self):
+        """
+        Get all issue trackers with data
+        """
+        response = self.osc.request(
+            url=urljoin(self.osc.url, self.base_path),
+            method="GET",
+        )
+        return self.osc.get_objectified_xml(response)
+
+    def get_tracker(self, name):
+        """
+        Get information on one issue tracker
+
+        :param str name: issue tracker name
+        :return: Objectified XML element
+        :rtype: lxml.objectify.ObjectifiedElement
+        """
+        response = self.osc.request(
+            url=urljoin(self.osc.url, os.path.join(self.base_path, name)),
+            method="GET",
+        )
+        return self.osc.get_objectified_xml(response)
+
+    def get(self, tracker, name, force_update=None):
+        """
+        Get details for an issue
+
+        :param str tracker: issue tracker name
+        :param str name: issue name
+        :param force_update: If ``True``, BuildService will update the issue
+                             details internally prior to returning the response
+        :return: Objectified XML element
+        :rtype: lxml.objectify.ObjectifiedElement
+        """
+        tracker, name = [self._validate(x) for x in [tracker, name]]
+        trackers = self.get_trackers()
+        can_get_details = trackers.xpath(
+            "issue-tracker/name[text()='{}']/../enable-fetch".format(tracker))
+
+        response = self.osc.request(
+            url=urljoin(self.osc.url,
+                        os.path.join(self.base_path, tracker, "issues", name)),
+            method="GET",
+            params={'force_update': force_update}
+        )
+
+        if not force_update and can_get_details and all(can_get_details):
+            if not getattr(getattr(response, "summary", None), "text", None):
+                return self.get(tracker, name, force_update=True)
+
+        return self.osc.get_objectified_xml(response)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-tiny-0.2.1/osctiny/extensions/search.py 
new/osc-tiny-0.2.2/osctiny/extensions/search.py
--- old/osc-tiny-0.2.1/osctiny/extensions/search.py     2020-01-10 
09:32:12.000000000 +0100
+++ new/osc-tiny-0.2.2/osctiny/extensions/search.py     2020-02-04 
09:21:59.000000000 +0100
@@ -26,7 +26,16 @@
 
             .. code:: python
 
-                Osc.search.request("starts-with(@name,'SUSE:Maintenance')")
+                Osc.search.project("starts-with(@name,'SUSE:Maintenance')")
+
+        .. note:: Pagination
+
+            Search results can be paginated using ``limit`` and ``offset``, 
e.g.
+
+            .. code:: python
+
+                Osc.search.project("starts-with(@name,'SUSE:Maintenance')",
+                                   limit=10, offset=30)
 
         :param path: object type / relative URL
         :param xpath: XPath expression to filter results
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-tiny-0.2.1/osctiny/osc.py 
new/osc-tiny-0.2.2/osctiny/osc.py
--- old/osc-tiny-0.2.1/osctiny/osc.py   2020-01-10 09:32:12.000000000 +0100
+++ new/osc-tiny-0.2.2/osctiny/osc.py   2020-02-04 09:21:59.000000000 +0100
@@ -19,6 +19,7 @@
 
 from .extensions.buildresults import Build
 from .extensions.comments import Comment
+from .extensions.issues import Issue
 from .extensions.packages import Package
 from .extensions.projects import Project
 from .extensions.bs_requests import Request as BsRequest
@@ -79,6 +80,9 @@
     .. versionadded:: 0.1.8
         The ``comments`` extension
 
+    .. versionadded:: 0.2.2
+        The `issues`` extension
+
     .. _SSL Cert Verification:
         http://docs.python-requests.org/en/master/user/advanced/
         #ssl-cert-verification
@@ -107,6 +111,7 @@
         self.build = Build(osc_obj=self)
         self.comments = Comment(osc_obj=self)
         self.groups = Group(osc_obj=self)
+        self.issues = Issue(osc_obj=self)
         self.packages = Package(osc_obj=self)
         self.projects = Project(osc_obj=self)
         self.requests = BsRequest(osc_obj=self)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-tiny-0.2.1/osctiny/tests/base.py 
new/osc-tiny-0.2.2/osctiny/tests/base.py
--- old/osc-tiny-0.2.1/osctiny/tests/base.py    2020-01-10 09:32:12.000000000 
+0100
+++ new/osc-tiny-0.2.2/osctiny/tests/base.py    2020-02-04 09:21:59.000000000 
+0100
@@ -8,7 +8,7 @@
 from io import IOBase
 
 import responses
-from six.moves.urllib_parse import parse_qs
+from six.moves.urllib_parse import parse_qs, urlparse
 
 from osctiny import Osc
 
@@ -42,6 +42,8 @@
         if hasattr(body, "decode"):
             body = body.decode('utf-8')
         params = parse_qs(body) if body else {}
+        parsed = urlparse(request.url)
+        params.update(parse_qs(parsed.query))
         headers = {
             "Cache-Control": "max-age=0, private, must-revalidate",
             "Connection": "Keep-Alive",
@@ -65,6 +67,8 @@
             username="foobar",
             password="helloworld",
         )
+        cls.osc.default_connection_retries = 0
+        cls.osc.default_retry_timeout = 0
 
     @staticmethod
     def mock_request(**kwargs):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-tiny-0.2.1/osctiny/tests/test_issues.py 
new/osc-tiny-0.2.2/osctiny/tests/test_issues.py
--- old/osc-tiny-0.2.1/osctiny/tests/test_issues.py     1970-01-01 
01:00:00.000000000 +0100
+++ new/osc-tiny-0.2.2/osctiny/tests/test_issues.py     2020-02-04 
09:21:59.000000000 +0100
@@ -0,0 +1,152 @@
+# -*- coding: utf8 -*-
+from __future__ import unicode_literals
+import re
+from sys import version_info
+
+from lxml.objectify import ObjectifiedElement
+from requests.exceptions import HTTPError
+import responses
+
+from .base import OscTest, CallbackFactory
+
+
+class TestIssue(OscTest):
+    def setUp(self):
+        super(TestIssue, self).setUpClass()
+
+        def callback(headers, params, request):
+            status, body = 200, """
+            <issue-trackers>
+              <issue-tracker>
+                <name>boost</name>
+                <kind>trac</kind>
+                <description>Boost Trac</description>
+                <url>https://svn.boost.org/trac/boost/</url>
+                
<show-url>https://svn.boost.org/trac/boost/ticket/@@@</show-url>
+                <regex>boost#(\d+)</regex>
+                <label>boost#@@@</label>
+                <enable-fetch>false</enable-fetch>
+              </issue-tracker>
+              <issue-tracker>
+                <name>bco</name>
+                <kind>bugzilla</kind>
+                <description>Clutter Project Bugzilla</description>
+                <url>http://bugzilla.clutter-project.org/</url>
+                
<show-url>http://bugzilla.clutter-project.org/show_bug.cgi?id=@@@</show-url>
+                <regex>bco#(\d+)</regex>
+                <label>bco#@@@</label>
+                <enable-fetch>false</enable-fetch>
+              </issue-tracker>
+              <issue-tracker>
+                <name>bnc</name>
+                <kind>bugzilla</kind>
+                <description>SUSE Bugzilla</description>
+                <url>https://apibugzilla.novell.com/</url>
+                
<show-url>https://bugzilla.suse.com/show_bug.cgi?id=@@@</show-url>
+                <regex>(?:bnc|BNC|bsc|BSC|boo|BOO)\s*[#:]\s*(\d+)</regex>
+                <label>bsc#@@@</label>
+                <enable-fetch>true</enable-fetch>
+              </issue-tracker>
+            </issue-trackers>"""
+            return status, headers, body
+
+        self.mock_request(
+            method=responses.GET,
+            url=re.compile(self.osc.url + '/issue_trackers/?$'),
+            callback=CallbackFactory(callback)
+        )
+
+    @responses.activate
+    def test_get_trackers(self):
+        response = self.osc.issues.get_trackers()
+        self.assertTrue(isinstance(response, ObjectifiedElement))
+        self.assertEqual(response.countchildren(), 3)
+        self.assertEqual(
+            {x.text for x in response.xpath("issue-tracker/name")},
+            {'boost', 'bco', 'bnc'}
+        )
+
+    @responses.activate
+    def test_get_tracker(self):
+        def callback(headers, params, request):
+            if re.search("bnc/?$", request.url):
+                status, body = 200, """
+                <issue-tracker>
+                  <name>bnc</name>
+                  <kind>bugzilla</kind>
+                  <description>SUSE Bugzilla</description>
+                  <url>https://apibugzilla.novell.com/</url>
+                  
<show-url>https://bugzilla.suse.com/show_bug.cgi?id=@@@</show-url>
+                  <regex>(?:bnc|BNC|bsc|BSC|boo|BOO)\s*[#:]\s*(\d+)</regex>
+                  <label>bsc#@@@</label>
+                  <enable-fetch>true</enable-fetch>
+                </issue-tracker>"""
+            else:
+                status, body = 404, """
+                <status code="not_found">
+                  <summary>Unable to find issue tracker 'bnc2'</summary>
+                </status>"""
+            return status, headers, body
+
+        self.mock_request(
+            method=responses.GET,
+            url=re.compile(self.osc.url + r'/issue_trackers/[^/]+/?$'),
+            callback=CallbackFactory(callback)
+        )
+
+        with self.subTest("Valid tracker"):
+            response = self.osc.issues.get_tracker("bnc")
+            self.assertEqual(response.name.text, "bnc")
+
+        with self.subTest("Invalid tracker"):
+            self.assertRaises(HTTPError, self.osc.issues.get_tracker, "nemo")
+
+    @responses.activate
+    def test_get(self):
+        def callback(headers, params, request):
+            if params.get("force_update", ["0"]) == ["1"]:
+                status, body = 200, u"""
+                <issue>
+                  <created_at>2020-01-04 14:12:00 UTC</created_at>
+                  <name>1160086</name>
+                  <tracker>bnc</tracker>
+                  <label>bsc#1160086</label>
+                  <url>https://bugzilla.suse.com/show_bug.cgi?id=1160086</url>
+                  <state>OPEN</state>
+                  <summary>føø bar</summary>
+                  <owner>
+                    <login>nemo</login>
+                    <email>[email protected]</email>
+                    <realname>Caþtæn Nemo</realname>
+                  </owner>
+                </issue>"""
+            else:
+                status, body = 200, """
+                <issue>
+                  <created_at>2020-01-04 14:12:00 UTC</created_at>
+                  <name>1160086</name>
+                  <tracker>bnc</tracker>
+                  <label>bsc#1160086</label>
+                  <url>https://bugzilla.suse.com/show_bug.cgi?id=1160086</url>
+                </issue>"""
+            return status, headers, body
+
+        self.mock_request(
+            method=responses.GET,
+            url=re.compile(self.osc.url +
+                           r'/issue_trackers/bnc/issues/1160086/?.*'),
+            callback=CallbackFactory(callback)
+        )
+
+        with self.subTest("Manual force update"):
+            response = self.osc.issues.get("bnc", 1160086, True)
+            self.assertTrue(hasattr(response, "summary"))
+            self.assertEqual(len(responses.calls), 2)
+
+        with self.subTest("Manual force update"):
+            response = self.osc.issues.get("bnc", 1160086, False)
+            self.assertTrue(hasattr(response, "summary"))
+            # to whom it may concern: `responses.calls` does not get reset
+            # between sub-tests
+            self.assertEqual(len(responses.calls),
+                             6 if version_info.major < 3 else 4)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-tiny-0.2.1/setup.py new/osc-tiny-0.2.2/setup.py
--- old/osc-tiny-0.2.1/setup.py 2020-01-10 09:32:12.000000000 +0100
+++ new/osc-tiny-0.2.2/setup.py 2020-02-04 09:21:59.000000000 +0100
@@ -22,7 +22,7 @@
 
 setup(
     name='osc-tiny',
-    version='0.2.1',
+    version='0.2.2',
     description='Client API for openSUSE BuildService',
     long_description=long_description,
     long_description_content_type="text/markdown",


Reply via email to