Rev 6292: (jelmer) Allow registering custom error handlers for the HPSS remote client. in file:///srv/pqm.bazaar-vcs.org/archives/thelove/bzr/%2Btrunk/

Patch Queue Manager pqm at pqm.ubuntu.com
Thu Nov 24 17:50:22 UTC 2011


At file:///srv/pqm.bazaar-vcs.org/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 6292 [merge]
revision-id: pqm at pqm.ubuntu.com-20111124175022-so5nve7kjo1p8stx
parent: pqm at pqm.ubuntu.com-20111124172541-3y61o9wf6onqh84q
parent: jelmer at samba.org-20111123133705-cz3lqog2ydtmjsel
committer: Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2011-11-24 17:50:22 +0000
message:
  (jelmer) Allow registering custom error handlers for the HPSS remote client.
   (Jelmer Vernooij)
modified:
  bzrlib/remote.py               remote.py-20060720103555-yeeg2x51vn0rbtdp-1
  bzrlib/tests/test_remote.py    test_remote.py-20060720103555-yeeg2x51vn0rbtdp-2
  doc/en/release-notes/bzr-2.5.txt bzr2.5.txt-20110708125756-587p0hpw7oke4h05-1
=== modified file 'bzrlib/remote.py'
--- a/bzrlib/remote.py	2011-11-24 16:09:33 +0000
+++ b/bzrlib/remote.py	2011-11-24 17:50:22 +0000
@@ -27,6 +27,7 @@
     graph,
     lock,
     lockdir,
+    registry,
     repository as _mod_repository,
     revision as _mod_revision,
     static_tuple,
@@ -3457,6 +3458,10 @@
         tar.extract(tarinfo, to_dir)
 
 
+error_translators = registry.Registry()
+no_context_error_translators = registry.Registry()
+
+
 def _translate_error(err, **context):
     """Translate an ErrorFromSmartServer into a more useful error.
 
@@ -3491,67 +3496,91 @@
                     'Missing key %r in context %r', key_err.args[0], context)
                 raise err
 
-    if err.error_verb == 'NoSuchRevision':
-        raise NoSuchRevision(find('branch'), err.error_args[0])
-    elif err.error_verb == 'nosuchrevision':
-        raise NoSuchRevision(find('repository'), err.error_args[0])
-    elif err.error_verb == 'nobranch':
-        if len(err.error_args) >= 1:
-            extra = err.error_args[0]
-        else:
-            extra = None
-        raise errors.NotBranchError(path=find('bzrdir').root_transport.base,
-            detail=extra)
-    elif err.error_verb == 'norepository':
-        raise errors.NoRepositoryPresent(find('bzrdir'))
-    elif err.error_verb == 'UnlockableTransport':
-        raise errors.UnlockableTransport(find('bzrdir').root_transport)
-    elif err.error_verb == 'TokenMismatch':
-        raise errors.TokenMismatch(find('token'), '(remote token)')
-    elif err.error_verb == 'Diverged':
-        raise errors.DivergedBranches(find('branch'), find('other_branch'))
-    elif err.error_verb == 'NotStacked':
-        raise errors.NotStacked(branch=find('branch'))
-    elif err.error_verb == 'PermissionDenied':
-        path = get_path()
-        if len(err.error_args) >= 2:
-            extra = err.error_args[1]
-        else:
-            extra = None
-        raise errors.PermissionDenied(path, extra=extra)
-    elif err.error_verb == 'ReadError':
-        path = get_path()
-        raise errors.ReadError(path)
-    elif err.error_verb == 'NoSuchFile':
-        path = get_path()
-        raise errors.NoSuchFile(path)
-    _translate_error_without_context(err)
-
-
-def _translate_error_without_context(err):
-    """Translate any ErrorFromSmartServer values that don't require context"""
-    if err.error_verb == 'IncompatibleRepositories':
-        raise errors.IncompatibleRepositories(err.error_args[0],
-            err.error_args[1], err.error_args[2])
-    elif err.error_verb == 'LockContention':
-        raise errors.LockContention('(remote lock)')
-    elif err.error_verb == 'LockFailed':
-        raise errors.LockFailed(err.error_args[0], err.error_args[1])
-    elif err.error_verb == 'TipChangeRejected':
-        raise errors.TipChangeRejected(err.error_args[0].decode('utf8'))
-    elif err.error_verb == 'UnstackableBranchFormat':
-        raise errors.UnstackableBranchFormat(*err.error_args)
-    elif err.error_verb == 'UnstackableRepositoryFormat':
-        raise errors.UnstackableRepositoryFormat(*err.error_args)
-    elif err.error_verb == 'FileExists':
-        raise errors.FileExists(err.error_args[0])
-    elif err.error_verb == 'DirectoryNotEmpty':
-        raise errors.DirectoryNotEmpty(err.error_args[0])
-    elif err.error_verb == 'ShortReadvError':
-        args = err.error_args
-        raise errors.ShortReadvError(
-            args[0], int(args[1]), int(args[2]), int(args[3]))
-    elif err.error_verb in ('UnicodeEncodeError', 'UnicodeDecodeError'):
+    try:
+        translator = error_translators.get(err.error_verb)
+    except KeyError:
+        pass
+    else:
+        raise translator(err, find, get_path)
+    try:
+        translator = no_context_error_translators.get(err.error_verb)
+    except KeyError:
+        raise errors.UnknownErrorFromSmartServer(err)
+    else:
+        raise translator(err)
+
+
+error_translators.register('NoSuchRevision',
+    lambda err, find, get_path: NoSuchRevision(
+        find('branch'), err.error_args[0]))
+error_translators.register('nosuchrevision',
+    lambda err, find, get_path: NoSuchRevision(
+        find('repository'), err.error_args[0]))
+
+def _translate_nobranch_error(err, find, get_path):
+    if len(err.error_args) >= 1:
+        extra = err.error_args[0]
+    else:
+        extra = None
+    return errors.NotBranchError(path=find('bzrdir').root_transport.base,
+        detail=extra)
+
+error_translators.register('nobranch', _translate_nobranch_error)
+error_translators.register('norepository',
+    lambda err, find, get_path: errors.NoRepositoryPresent(
+        find('bzrdir')))
+error_translators.register('UnlockableTransport',
+    lambda err, find, get_path: errors.UnlockableTransport(
+        find('bzrdir').root_transport))
+error_translators.register('TokenMismatch',
+    lambda err, find, get_path: errors.TokenMismatch(
+        find('token'), '(remote token)'))
+error_translators.register('Diverged',
+    lambda err, find, get_path: errors.DivergedBranches(
+        find('branch'), find('other_branch')))
+error_translators.register('NotStacked',
+    lambda err, find, get_path: errors.NotStacked(branch=find('branch')))
+
+def _translate_PermissionDenied(err, find, get_path):
+    path = get_path()
+    if len(err.error_args) >= 2:
+        extra = err.error_args[1]
+    else:
+        extra = None
+    return errors.PermissionDenied(path, extra=extra)
+
+error_translators.register('PermissionDenied', _translate_PermissionDenied)
+error_translators.register('ReadError',
+    lambda err, find, get_path: errors.ReadError(get_path()))
+error_translators.register('NoSuchFile',
+    lambda err, find, get_path: errors.NoSuchFile(get_path()))
+no_context_error_translators.register('IncompatibleRepositories',
+    lambda err: errors.IncompatibleRepositories(
+        err.error_args[0], err.error_args[1], err.error_args[2]))
+no_context_error_translators.register('LockContention',
+    lambda err: errors.LockContention('(remote lock)'))
+no_context_error_translators.register('LockFailed',
+    lambda err: errors.LockFailed(err.error_args[0], err.error_args[1]))
+no_context_error_translators.register('TipChangeRejected',
+    lambda err: errors.TipChangeRejected(err.error_args[0].decode('utf8')))
+no_context_error_translators.register('UnstackableBranchFormat',
+    lambda err: errors.UnstackableBranchFormat(*err.error_args))
+no_context_error_translators.register('UnstackableRepositoryFormat',
+    lambda err: errors.UnstackableRepositoryFormat(*err.error_args))
+no_context_error_translators.register('FileExists',
+    lambda err: errors.FileExists(err.error_args[0]))
+no_context_error_translators.register('DirectoryNotEmpty',
+    lambda err: errors.DirectoryNotEmpty(err.error_args[0]))
+
+def _translate_short_readv_error(err):
+    args = err.error_args
+    return errors.ShortReadvError(args[0], int(args[1]), int(args[2]),
+        int(args[3]))
+
+no_context_error_translators.register('ShortReadvError',
+    _translate_short_readv_error)
+
+def _translate_unicode_error(err):
         encoding = str(err.error_args[0]) # encoding must always be a string
         val = err.error_args[1]
         start = int(err.error_args[2])
@@ -3565,9 +3594,13 @@
             raise UnicodeDecodeError(encoding, val, start, end, reason)
         elif err.error_verb == 'UnicodeEncodeError':
             raise UnicodeEncodeError(encoding, val, start, end, reason)
-    elif err.error_verb == 'ReadOnlyError':
-        raise errors.TransportNotPossible('readonly transport')
-    elif err.error_verb == 'MemoryError':
-        raise errors.BzrError("remote server out of memory\n"
-            "Retry non-remotely, or contact the server admin for details.")
-    raise errors.UnknownErrorFromSmartServer(err)
+
+no_context_error_translators.register('UnicodeEncodeError',
+    _translate_unicode_error)
+no_context_error_translators.register('UnicodeDecodeError',
+    _translate_unicode_error)
+no_context_error_translators.register('ReadOnlyError',
+    lambda err: errors.TransportNotPossible('readonly transport'))
+no_context_error_translators.register('MemoryError',
+    lambda err: errors.BzrError("remote server out of memory\n"
+        "Retry non-remotely, or contact the server admin for details."))

=== modified file 'bzrlib/tests/test_remote.py'
--- a/bzrlib/tests/test_remote.py	2011-11-22 13:27:04 +0000
+++ b/bzrlib/tests/test_remote.py	2011-11-23 13:37:05 +0000
@@ -3670,3 +3670,52 @@
         # interpretation
         self.make_master_and_checkout('mas~ter', 'checkout')
         self.assertUpdateSucceeds(self.bound_location.replace('%2E', '~', 1))
+
+
+class TestWithCustomErrorHandler(RemoteBranchTestCase):
+
+    def test_no_context(self):
+        class OutOfCoffee(errors.BzrError):
+            """A dummy exception for testing."""
+
+            def __init__(self, urgency):
+                self.urgency = urgency
+        remote.no_context_error_translators.register("OutOfCoffee",
+            lambda err: OutOfCoffee(err.error_args[0]))
+        transport = MemoryTransport()
+        client = FakeClient(transport.base)
+        client.add_expected_call(
+            'Branch.get_stacked_on_url', ('quack/',),
+            'error', ('NotStacked',))
+        client.add_expected_call(
+            'Branch.last_revision_info',
+            ('quack/',),
+            'error', ('OutOfCoffee', 'low'))
+        transport.mkdir('quack')
+        transport = transport.clone('quack')
+        branch = self.make_remote_branch(transport, client)
+        self.assertRaises(OutOfCoffee, branch.last_revision_info)
+        self.assertFinished(client)
+
+    def test_with_context(self):
+        class OutOfTea(errors.BzrError):
+            def __init__(self, branch, urgency):
+                self.branch = branch
+                self.urgency = urgency
+        remote.error_translators.register("OutOfTea",
+            lambda err, find, path: OutOfTea(err.error_args[0],
+                find("branch")))
+        transport = MemoryTransport()
+        client = FakeClient(transport.base)
+        client.add_expected_call(
+            'Branch.get_stacked_on_url', ('quack/',),
+            'error', ('NotStacked',))
+        client.add_expected_call(
+            'Branch.last_revision_info',
+            ('quack/',),
+            'error', ('OutOfTea', 'low'))
+        transport.mkdir('quack')
+        transport = transport.clone('quack')
+        branch = self.make_remote_branch(transport, client)
+        self.assertRaises(OutOfTea, branch.last_revision_info)
+        self.assertFinished(client)

=== modified file 'doc/en/release-notes/bzr-2.5.txt'
--- a/doc/en/release-notes/bzr-2.5.txt	2011-11-24 14:30:59 +0000
+++ b/doc/en/release-notes/bzr-2.5.txt	2011-11-24 17:50:22 +0000
@@ -101,6 +101,10 @@
   ``BzrDir.has_workingtree`` and ``Branch.put_config_file``.
   (Jelmer Vernooij)
 
+* Custom HPSS error handlers can now be installed in the smart server client
+  using the ``error_translators`` and ``no_context_error_translators``
+  registries. (Jelmer Vernooij)
+
 Testing
 *******
 




More information about the bazaar-commits mailing list