[python-bugzilla] [PATCH] Expands ExternalTracker field support

bmbouter at gmail.com bmbouter at gmail.com
Wed Apr 1 22:20:04 UTC 2015


From: Brian Bouterse <bmbouter at gmail.com>

---
 HACKING                |  17 +++--
 bugzilla/rhbugzilla.py | 164 ++++++++++++++++++++++++++++++++++++++-----------
 tests/rw_functional.py | 110 ++++++++++++++++++++++++++-------
 3 files changed, 223 insertions(+), 68 deletions(-)

diff --git a/HACKING b/HACKING
index f597a97..c2015c0 100644
--- a/HACKING
+++ b/HACKING
@@ -26,17 +26,20 @@ Once you have already activated an environment, you can use the following.
 # Basic unit test suite
     python setup.py test
 
-# Functional tests
+# Read-Only Functional tests
 There are more comprehensive tests that are disabled by default. Readonly
 functional tests that run against several public bugzilla instances. No
 login account is required:
 
     python setup.py test --ro-functional
 
-And read/write functional tests. These currently run against the test
-bugzilla instance at partner-bugzilla.redhat.com, and requires a valid
-login there:
+# Read/Write Functional Tests.
 
+Before running rw-functional tests, make sure you have logged into bugzilla
+using. These currently run against the test bugzilla instance at
+partner-bugzilla.redhat.com, and requires a valid login there:
+
+    bugzilla-cli --bugzilla=partner-bugzilla.redhat.com --user=$USER login
     python setup.py test --rw-functional
 
 # Testing across python versions
@@ -46,12 +49,6 @@ To test all supported python versions, run tox using any of the following.
     tox -- --ro-functional
     tox -- --rw-functional
 
-Note: Before running rw-functional tests, make sure you have logged into
-bugzilla using:
-    python bugzilla-cli \
-        --bugzilla=partner-bugzilla.redhat.com \
-        --user=$USER login
-
 
 3. pylint and pep8
 ------------------
diff --git a/bugzilla/rhbugzilla.py b/bugzilla/rhbugzilla.py
index 0903ff2..7300296 100644
--- a/bugzilla/rhbugzilla.py
+++ b/bugzilla/rhbugzilla.py
@@ -133,7 +133,10 @@ class RHBugzilla(_parent):
 
         return vals
 
-    def add_external_tracker(self, bug_ids, type_desc, external_id):
+    def add_external_tracker(self, bug_ids, ext_bz_bug_id, ext_type_id=None,
+                             ext_type_description=None, ext_type_url=None,
+                             ext_status=None, ext_description=None,
+                             ext_priority=None):
         """
         Wrapper method to allow adding of external tracking bugs using the
         ExternalBugs::WebService::add_external_bug method.
@@ -141,23 +144,87 @@ class RHBugzilla(_parent):
         This is documented at
         https://bugzilla.redhat.com/docs/en/html/api/extensions/ExternalBugs/lib/WebService.html#add_external_bug
 
-        bug_ids: A single bug id or list if bug ids to add the tracker to.
-        type_desc: The external tracker description as used by Bugzilla. This
-            value maps to the ext_type_description parameter of the XMLRPC
-            method.
-        external_id: The id as used by the external tracker. This value maps to
-            the ext_bz_bug_id parameter of the XMLRPC method.
+        bug_ids: A single bug id or list of bug ids to have external trackers
+            added.
+        ext_bz_bug_id: The external bug id (ie: the bug number in the
+            external tracker).
+        ext_type_id: The external tracker id as used by Bugzilla.
+        ext_type_description: The external tracker description as used by
+            Bugzilla.
+        ext_type_url: The external tracker url as used by Bugzilla.
+        ext_status: The status of the external bug.
+        ext_description: The description of the external bug.
+        ext_priority: The priority of the external bug.
         """
-        kwargs = {
+        param_dict = {'ext_bz_bug_id': ext_bz_bug_id}
+        if ext_type_id is not None:
+            param_dict['ext_type_id'] = ext_type_id
+        if ext_type_description is not None:
+            param_dict['ext_type_description'] = ext_type_description
+        if ext_type_url is not None:
+            param_dict['ext_type_url'] = ext_type_url
+        if ext_status is not None:
+            param_dict['ext_status'] = ext_status
+        if ext_description is not None:
+            param_dict['ext_description'] = ext_description
+        if ext_priority is not None:
+            param_dict['ext_priority'] = ext_priority
+        params = {
             'bug_ids': self._listify(bug_ids),
-            'external_bugs': [{
-                'ext_type_description': type_desc,
-                'ext_bz_bug_id': external_id,
-            }],
+            'external_bugs': [param_dict],
         }
-        return self._proxy.ExternalBugs.add_external_bug(kwargs)
+        return self._proxy.ExternalBugs.add_external_bug(params)
 
-    def remove_external_tracker(self, bug_ids, type_desc, external_ids):
+    def update_external_tracker(self, ids=None, ext_type_id=None,
+                                ext_type_description=None, ext_type_url=None,
+                                ext_bz_bug_id=None, bug_ids=None,
+                                ext_status=None, ext_description=None,
+                                ext_priority=None):
+        """
+        Wrapper method to allow adding of external tracking bugs using the
+        ExternalBugs::WebService::update_external_bug method.
+
+        This is documented at
+        https://bugzilla.redhat.com/docs/en/html/api/extensions/ExternalBugs/lib/WebService.html#update_external_bug
+
+        ids: A single external tracker bug id or list of external tracker bug
+            ids.
+        ext_type_id: The external tracker id as used by Bugzilla.
+        ext_type_description: The external tracker description as used by
+            Bugzilla.
+        ext_type_url: The external tracker url as used by Bugzilla.
+        ext_bz_bug_id: A single external bug id or list of external bug ids
+            (ie: the bug number in the external tracker).
+        bug_ids: A single bug id or list of bug ids to have external tracker
+            info updated.
+        ext_status: The status of the external bug.
+        ext_description: The description of the external bug.
+        ext_priority: The priority of the external bug.
+        """
+        params = {}
+        if ids is not None:
+            params['ids'] = self._listify(ids)
+        if ext_type_id is not None:
+            params['ext_type_id'] = ext_type_id
+        if ext_type_description is not None:
+            params['ext_type_description'] = ext_type_description
+        if ext_type_url is not None:
+            params['ext_type_url'] = ext_type_url
+        if ext_bz_bug_id is not None:
+            params['ext_bz_bug_id'] = self._listify(ext_bz_bug_id)
+        if bug_ids is not None:
+            params['bug_ids'] = self._listify(bug_ids)
+        if ext_status is not None:
+            params['ext_status'] = ext_status
+        if ext_description is not None:
+            params['ext_description'] = ext_description
+        if ext_priority is not None:
+            params['ext_priority'] = ext_priority
+        return self._proxy.ExternalBugs.update_external_bug(params)
+
+    def remove_external_tracker(self, ids=None, ext_type_id=None,
+                                ext_type_description=None, ext_type_url=None,
+                                ext_bz_bug_id=None, bug_ids=None):
         """
         Wrapper method to allow removal of external tracking bugs using the
         ExternalBugs::WebService::remove_external_bug method.
@@ -165,20 +232,31 @@ class RHBugzilla(_parent):
         This is documented at
         https://bugzilla.redhat.com/docs/en/html/api/extensions/ExternalBugs/lib/WebService.html#remove_external_bug
 
-        bug_ids: A single bug id or list if bug ids to remove the tracker from.
-        type_desc: The external tracker description as used by Bugzilla. This
-            value maps to the ext_type_description parameter of the XMLRPC
-            method.
-        external_ids: The id or list of ids as used by the external tracker.
-            This value maps to the ext_bz_bug_id parameter of the XMLRPC
-            method.
+        ids: A single external tracker bug id or list of external tracker bug
+            ids.
+        ext_type_id: The external tracker id as used by Bugzilla.
+        ext_type_description: The external tracker description as used by
+            Bugzilla.
+        ext_type_url: The external tracker url as used by Bugzilla.
+        ext_bz_bug_id: A single external bug id or list of external bug ids
+            (ie: the bug number in the external tracker).
+        bug_ids: A single bug id or list of bug ids to have external tracker
+            info updated.
         """
-        kwargs = {
-            'bug_ids': self._listify(bug_ids),
-            'ext_type_description': type_desc,
-            'ext_bz_bug_id': self._listify(external_ids),
-        }
-        return self._proxy.ExternalBugs.remove_external_bug(kwargs)
+        params = {}
+        if ids is not None:
+            params['ids'] = self._listify(ids)
+        if ext_type_id is not None:
+            params['ext_type_id'] = ext_type_id
+        if ext_type_description is not None:
+            params['ext_type_description'] = ext_type_description
+        if ext_type_url is not None:
+            params['ext_type_url'] = ext_type_url
+        if ext_bz_bug_id is not None:
+            params['ext_bz_bug_id'] = self._listify(ext_bz_bug_id)
+        if bug_ids is not None:
+            params['bug_ids'] = self._listify(bug_ids)
+        return self._proxy.ExternalBugs.remove_external_bug(params)
 
 
     #################
@@ -285,29 +363,41 @@ class RHBugzilla(_parent):
             bug['groups'] = tmp
 
     def build_external_tracker_boolean_query(
-            self, type_desc=None, external_id=None):
+            self, ext_type_description=None, ext_type_url=None,
+            ext_bz_bug_id=None, ext_status=None):
         """
         Helper method to build a boolean query to find bugs that contain an
-        external tracker with the 'type_desc' and 'external_id' combination.
+        external tracker.
 
         All parameters that are None will be ignored when building the query.
 
-        type_desc: The external tracker description as used by Bugzilla. This
-            value maps to the external_bugzilla.description field.
-        external_ids: The id as used by the external tracker. This value maps
-            to the ext_bz_bug_map.ext_bz_bug_id field.
+        ext_type_description: The external tracker description as used by
+            Bugzilla.
+        ext_type_url: The external tracker url as used by Bugzilla.
+        ext_bz_bug_id: The external bug id (ie: the bug number in the
+            external tracker).
+        ext_status: The status of the external bug.
         """
         parts = []
 
-        if type_desc is not None:
+        if ext_type_description is not None:
+            parts.append(
+                'external_bugzilla.description-equals-{0:s}'.format(
+                    ext_type_description))
+
+        if ext_type_url is not None:
             parts.append(
-                'external_bugzilla.description-equals-{0:s}'.format(type_desc))
+                'external_bugzilla.url-equals-{0:s}'.format(ext_type_url))
 
-        if external_id is not None:
-            id_str = str(external_id)
+        if ext_bz_bug_id is not None:
+            id_str = str(ext_bz_bug_id)
             parts.append(
                 'ext_bz_bug_map.ext_bz_bug_id-equals-{0:s}'.format(id_str))
 
+        if ext_status is not None:
+            parts.append(
+                'ext_bz_bug_map.ext_status-equals-{0:s}'.format(ext_status))
+
         return ' & '.join(parts)
 
     def build_query(self, **kwargs):
diff --git a/tests/rw_functional.py b/tests/rw_functional.py
index fd89613..480835a 100644
--- a/tests/rw_functional.py
+++ b/tests/rw_functional.py
@@ -773,35 +773,103 @@ class RHPartnerTest(BaseTest):
         bug.refresh()
         self.assertEqual(bug.sub_components, {})
 
-    def _test14ExternalTrackersQuery(self, bz, ext_type_desc, ext_bug_id):
-        boolean_query = bz.build_external_tracker_boolean_query(
-            ext_type_desc, ext_bug_id)
-        query = bz.build_query(
-            boolean_query=boolean_query, include_fields=['id'])
-        return [bug.bug_id for bug in bz.query(query)]
+    def _deleteAllExistingExternalTrackers(self, bugid):
+        bz = self.bzclass(url=self.url, cookiefile=cf, tokenfile=tf)
+        ids = [bug['id'] for bug in bz.getbug(bugid).external_bugs]
+        if ids != []:
+            bz.remove_external_tracker(ids=ids)
 
     def test14ExternalTrackersQuery(self):
         bz = self.bzclass(url=self.url, cookiefile=cf, tokenfile=tf)
-        ext_type_desc = "FreeDesktop.org"
-        ext_bug_id = 64714
+        bugid = 461686
+        ext_bug_id = 1234659
 
-        # Closed RH Bugzilla bug with external tracker
-        bugid = 973374
-        assert bugid in \
-            self._test14ExternalTrackersQuery(bz, ext_type_desc, ext_bug_id)
+        # Delete any existing external trackers to get to a known state
+        self._deleteAllExistingExternalTrackers(bugid)
+
+        # test adding tracker
+        kwargs = {
+            'ext_type_url': 'http://bugzilla.mozilla.org',
+            'ext_type_description': 'Mozilla Foundation',
+            'ext_status': 'Original Status',
+        }
 
-    def test14ExternalTrackersAddRemove(self):
+        # Add a tracker that we can query for
+        bz.add_external_tracker(bugid, ext_bug_id, **kwargs)
+
+        kwargs['ext_bz_bug_id'] = ext_bug_id
+
+        boolean_query = bz.build_external_tracker_boolean_query(
+            ext_bz_bug_id=ext_bug_id)
+        query_results = bz.query(bz.build_query(boolean_query=boolean_query))
+        if len(query_results) != 1:
+            raise AssertionError(
+                'external tracker query by bug id should return 1 result.')
+        for key, value in kwargs.iteritems():
+            assert kwargs[key] == value
+
+        boolean_query = bz.build_external_tracker_boolean_query(
+            ext_type_description=kwargs['ext_type_description'])
+        query_results = bz.query(bz.build_query(boolean_query=boolean_query))
+        assert bugid in [qr.id for qr in query_results]
+
+        boolean_query = bz.build_external_tracker_boolean_query(
+            ext_status=kwargs['ext_status'])
+        query_results = bz.query(bz.build_query(boolean_query=boolean_query))
+        if len(query_results) != 1:
+            raise AssertionError(
+                'external tracker query by status should return 1 result.')
+        for key, value in kwargs.iteritems():
+            assert kwargs[key] == value
+
+        boolean_query = bz.build_external_tracker_boolean_query(
+            ext_type_url=kwargs['ext_type_url'])
+        query_results = bz.query(bz.build_query(boolean_query=boolean_query))
+        assert bugid in [qr.id for qr in query_results]
+
+    def test14ExternalTrackersAddUpdateRemoveQuery(self):
         bz = self.bzclass(url=self.url, cookiefile=cf, tokenfile=tf)
-        ext_type_desc = "Mozilla Foundation"
-        ext_bug_id = 380489
         bugid = 461686
+        ext_bug_id = 380489
+
+        # Delete any existing external trackers to get to a known state
+        self._deleteAllExistingExternalTrackers(bugid)
 
         # test adding tracker
-        bz.add_external_tracker(bugid, ext_type_desc, ext_bug_id)
-        assert bugid in \
-            self._test14ExternalTrackersQuery(bz, ext_type_desc, ext_bug_id)
+        kwargs = {
+            'ext_type_id': 6,
+            'ext_type_url': 'http://bugzilla.mozilla.org',
+            'ext_type_description': 'Mozilla Foundation',
+            'ext_status': 'Original Status',
+            'ext_description': 'the description',
+            'ext_priority': 'the priority'
+        }
+        bz.add_external_tracker(bugid, ext_bug_id, **kwargs)
+        added_bug = bz.getbug(bugid).external_bugs[0]
+        assert added_bug['type']['id'] == kwargs['ext_type_id']
+        assert added_bug['type']['url'] == kwargs['ext_type_url']
+        assert added_bug['type']['description'] == kwargs['ext_type_description']
+        assert added_bug['ext_status'] == kwargs['ext_status']
+        assert added_bug['ext_description'] == kwargs['ext_description']
+        assert added_bug['ext_priority'] == kwargs['ext_priority']
+
+        # test updating status, description, and priority by id
+        kwargs = {
+            'ids': bz.getbug(bugid).external_bugs[0]['id'],
+            'ext_status': 'New Status',
+            'ext_description': 'New Description',
+            'ext_priority': 'New Priority'
+        }
+        bz.update_external_tracker(**kwargs)
+        updated_bug = bz.getbug(bugid).external_bugs[0]
+        assert updated_bug['ext_bz_bug_id'] == str(ext_bug_id)
+        assert updated_bug['ext_status'] == kwargs['ext_status']
+        assert updated_bug['ext_description'] == kwargs['ext_description']
+        assert updated_bug['ext_priority'] == kwargs['ext_priority']
 
         # test removing tracker
-        bz.remove_external_tracker(bugid, ext_type_desc, ext_bug_id)
-        assert bugid not in \
-            self._test14ExternalTrackersQuery(bz, ext_type_desc, ext_bug_id)
+        ids = [bug['id'] for bug in bz.getbug(bugid).external_bugs]
+        assert len(ids) == 1
+        bz.remove_external_tracker(ids=ids)
+        ids = [bug['id'] for bug in bz.getbug(bugid).external_bugs]
+        assert len(ids) == 0
-- 
1.9.3



More information about the python-bugzilla mailing list