Rev 3770: (robertc) Fix two api versioning related bugs - 279447 and 279451. in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Wed Oct 8 03:01:08 BST 2008


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 3770
revision-id: pqm at pqm.ubuntu.com-20081008020104-e68hyxx45qo19nzx
parent: pqm at pqm.ubuntu.com-20081007110356-zmp1x6pyx5lnlh5k
parent: robertc at robertcollins.net-20081008012840-kn5u1944l4ls60t8
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Wed 2008-10-08 03:01:04 +0100
message:
  (robertc) Fix two api versioning related bugs - 279447 and 279451.
  	(Robert Collins)
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/api.py                  api.py-20070626082640-35lspz7j0ys7a8ld-1
  bzrlib/plugin.py               plugin.py-20050622060424-829b654519533d69
  bzrlib/tests/test_api.py       testapi.py-20051027033546-6f9be2d308d18a52
  bzrlib/tests/test_plugins.py   plugins.py-20050622075746-32002b55e5e943e9
    ------------------------------------------------------------
    revno: 3766.3.4
    revision-id: robertc at robertcollins.net-20081008012840-kn5u1944l4ls60t8
    parent: robertc at robertcollins.net-20081007205400-3i63hng0m9a2qwjf
    parent: pqm at pqm.ubuntu.com-20081007110356-zmp1x6pyx5lnlh5k
    committer: Robert Collins <robertc at robertcollins.net>
    branch nick: integration
    timestamp: Wed 2008-10-08 12:28:40 +1100
    message:
      NEWS conflicts.
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzr                            bzr.py-20050313053754-5485f144c7006fa6
      bzrlib/__init__.py             __init__.py-20050309040759-33e65acf91bbcd5d
      bzrlib/_readdir_pyx.pyx        readdir.pyx-20060609152855-rm6v321vuaqyh9tu-1
    ------------------------------------------------------------
    revno: 3766.3.3
    revision-id: robertc at robertcollins.net-20081007205400-3i63hng0m9a2qwjf
    parent: robertc at robertcollins.net-20081007064146-d1w8jhf0zqn1mb3y
    committer: Robert Collins <robertc at robertcollins.net>
    branch nick: api
    timestamp: Wed 2008-10-08 07:54:00 +1100
    message:
      Review tweaks.
    modified:
      bzrlib/api.py                  api.py-20070626082640-35lspz7j0ys7a8ld-1
    ------------------------------------------------------------
    revno: 3766.3.2
    revision-id: robertc at robertcollins.net-20081007064146-d1w8jhf0zqn1mb3y
    parent: robertc at robertcollins.net-20081007045125-4h9com3yii5h6zpx
    committer: Robert Collins <robertc at robertcollins.net>
    branch nick: api
    timestamp: Tue 2008-10-07 17:41:46 +1100
    message:
      Fix reporting of incompatible api plugin load errors, fixing bug 279451.
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzrlib/plugin.py               plugin.py-20050622060424-829b654519533d69
      bzrlib/tests/test_plugins.py   plugins.py-20050622075746-32002b55e5e943e9
    ------------------------------------------------------------
    revno: 3766.3.1
    revision-id: robertc at robertcollins.net-20081007045125-4h9com3yii5h6zpx
    parent: pqm at pqm.ubuntu.com-20081006223227-11nq4m186th9ljeq
    committer: Robert Collins <robertc at robertcollins.net>
    branch nick: api
    timestamp: Tue 2008-10-07 15:51:25 +1100
    message:
      Add bzrlib.api.require_any_api, fixing bug 279447.
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzrlib/api.py                  api.py-20070626082640-35lspz7j0ys7a8ld-1
      bzrlib/tests/test_api.py       testapi.py-20051027033546-6f9be2d308d18a52
=== modified file 'NEWS'
--- a/NEWS	2008-10-07 10:00:40 +0000
+++ b/NEWS	2008-10-08 01:28:40 +0000
@@ -89,10 +89,16 @@
 
   BUG FIXES:
 
+    * API versioning support now has a multiple-version checking api
+      ``require_any_api``. (Robert Collins, #279447)
+
     * Avoid random failures arising from misinterpreted ``errno`` values
       in ``_readdir_pyx.read_dir``.
       (Martin Pool, #279381)
 
+    * A failure to load a plugin due to an IncompatibleAPI exception is
+      now correctly reported. (Robert Collins, #279451)
+
     * Branching from a shared repository on a smart server into a new
       repository now preserves the repository format.
       (Andrew Bennetts, #269214)

=== modified file 'bzrlib/api.py'
--- a/bzrlib/api.py	2007-06-26 08:52:20 +0000
+++ b/bzrlib/api.py	2008-10-07 20:54:00 +0000
@@ -70,7 +70,7 @@
         version. See get_minimum_api_version and get_current_api_version for
         details.
     :param wanted_api: The API version for which support is required.
-    :return None:
+    :return: None
     :raises IncompatibleAPI: When the wanted_api is not supported by
         object_with_api.
 
@@ -80,3 +80,25 @@
     minimum = get_minimum_api_version(object_with_api)
     if wanted_api < minimum or wanted_api > current:
         raise IncompatibleAPI(object_with_api, wanted_api, minimum, current)
+
+
+def require_any_api(object_with_api, wanted_api_list):
+    """Check if object_with_api supports the api version wanted_api.
+
+    :param object_with_api: An object which exports an API minimum and current
+        version. See get_minimum_api_version and get_current_api_version for
+        details.
+    :param wanted_api: A list of API versions, any of which being available is
+        sufficent.
+    :return: None
+    :raises IncompatibleAPI: When the wanted_api is not supported by
+        object_with_api.
+
+    Added in bzrlib 1.9.
+    """
+    for api in wanted_api_list[:-1]:
+        try:
+            return require_api(object_with_api, api)
+        except IncompatibleAPI:
+            pass
+    require_api(object_with_api, wanted_api_list[-1])

=== modified file 'bzrlib/plugin.py'
--- a/bzrlib/plugin.py	2008-09-08 12:59:00 +0000
+++ b/bzrlib/plugin.py	2008-10-07 06:41:46 +0000
@@ -43,6 +43,7 @@
 from bzrlib import (
     config,
     debug,
+    errors,
     osutils,
     trace,
     )
@@ -172,7 +173,10 @@
 
 
 def load_from_dir(d):
-    """Load the plugins in directory d."""
+    """Load the plugins in directory d.
+    
+    d must be in the plugins module path already.
+    """
     # Get the list of valid python suffixes for __init__.py?
     # this includes .py, .pyc, and .pyo (depending on if we are running -O)
     # but it doesn't include compiled modules (.so, .dll, etc)
@@ -210,7 +214,13 @@
             exec "import bzrlib.plugins.%s" % name in {}
         except KeyboardInterrupt:
             raise
+        except errors.IncompatibleAPI, e:
+            trace.warning("Unable to load plugin %r. It requested API version "
+                "%s of module %s but the minimum exported version is %s, and "
+                "the maximum is %s" %
+                (name, e.wanted, e.api, e.minimum, e.current))
         except Exception, e:
+            trace.warning("%s" % e)
             ## import pdb; pdb.set_trace()
             if re.search('\.|-| ', name):
                 sanitised_name = re.sub('[-. ]', '_', name)

=== modified file 'bzrlib/tests/test_api.py'
--- a/bzrlib/tests/test_api.py	2007-06-26 08:52:20 +0000
+++ b/bzrlib/tests/test_api.py	2008-10-07 04:51:25 +0000
@@ -71,6 +71,31 @@
         self.assertEqual(bzrlib.version_info[0:3],
             bzrlib.api.get_current_api_version(an_object))
 
+    def test_require_any_api_wanted_one(self):
+        an_object = TrivialObject()
+        an_object.api_minimum_version = (1, 2, 3)
+        an_object.api_current_version = (4, 5, 6)
+        bzrlib.api.require_any_api(an_object, [(1, 2, 3)])
+
+    def test_require_any_api_wanted_first_compatible(self):
+        an_object = TrivialObject()
+        an_object.api_minimum_version = (1, 2, 3)
+        an_object.api_current_version = (4, 5, 6)
+        bzrlib.api.require_any_api(an_object, [(1, 2, 3), (5, 6, 7)])
+
+    def test_require_any_api_wanted_second_compatible(self):
+        an_object = TrivialObject()
+        an_object.api_minimum_version = (1, 2, 3)
+        an_object.api_current_version = (4, 5, 6)
+        bzrlib.api.require_any_api(an_object, [(5, 6, 7), (1, 2, 3)])
+
+    def test_require_any_api_wanted_none_compatible(self):
+        an_object = TrivialObject()
+        an_object.api_minimum_version = (1, 2, 3)
+        an_object.api_current_version = (4, 5, 6)
+        self.assertRaises(IncompatibleAPI, bzrlib.api.require_any_api,
+            an_object, [(1, 2, 2), (5, 6, 7)])
+
     def test_require_api_wanted_is_minimum_is_ok(self):
         an_object = TrivialObject()
         an_object.api_minimum_version = (1, 2, 3)

=== modified file 'bzrlib/tests/test_plugins.py'
--- a/bzrlib/tests/test_plugins.py	2008-08-11 12:50:16 +0000
+++ b/bzrlib/tests/test_plugins.py	2008-10-07 06:41:46 +0000
@@ -193,30 +193,60 @@
                 del bzrlib.plugins.ts_plugin
         self.failIf(getattr(bzrlib.plugins, 'ts_plugin', None))
 
-    def test_plugin_with_bad_name_does_not_load(self):
-        # Create badly-named plugin
-        file('bzr-bad plugin-name..py', 'w').close()
-
+    def load_and_capture(self, name):
+        """Load plugins from '.' capturing the output.
+        
+        :param name: The name of the plugin.
+        :return: A string with the log from the plugin loading call.
+        """
         # Capture output
         stream = StringIO()
-        handler = logging.StreamHandler(stream)
-        log = logging.getLogger('bzr')
-        log.addHandler(handler)
-
-        bzrlib.plugin.load_from_dir('.')
-
-        # Stop capturing output
-        handler.flush()
-        handler.close()
-        log.removeHandler(handler)
-
-        self.assertContainsRe(stream.getvalue(),
+        try:
+            handler = logging.StreamHandler(stream)
+            log = logging.getLogger('bzr')
+            log.addHandler(handler)
+            try:
+                try:
+                    bzrlib.plugin.load_from_path(['.'])
+                finally:
+                    if 'bzrlib.plugins.%s' % name in sys.modules:
+                        del sys.modules['bzrlib.plugins.%s' % name]
+                    if getattr(bzrlib.plugins, name, None):
+                        delattr(bzrlib.plugins, name)
+            finally:
+                # Stop capturing output
+                handler.flush()
+                handler.close()
+                log.removeHandler(handler)
+            return stream.getvalue()
+        finally:
+            stream.close()
+    
+    def test_plugin_with_bad_api_version_reports(self):
+        # This plugin asks for bzrlib api version 1.0.0, which is not supported
+        # anymore.
+        name = 'wants100.py'
+        f = file(name, 'w')
+        try:
+            f.write("import bzrlib.api\n"
+                "bzrlib.api.require_any_api(bzrlib, [(1, 0, 0)])\n")
+        finally:
+            f.close()
+
+        log = self.load_and_capture(name)
+        self.assertContainsRe(log,
+            r"It requested API version")
+
+    def test_plugin_with_bad_name_does_not_load(self):
+        # The file name here invalid for a python module.
+        name = 'bzr-bad plugin-name..py'
+        file(name, 'w').close()
+        log = self.load_and_capture(name)
+        self.assertContainsRe(log,
             r"Unable to load 'bzr-bad plugin-name\.' in '\.' as a plugin "
             "because the file path isn't a valid module name; try renaming "
             "it to 'bad_plugin_name_'\.")
 
-        stream.close()
-
 
 class TestPlugins(TestCaseInTempDir):
 




More information about the bazaar-commits mailing list