[architecture] introduce adapter to ease transformation of errors before display to the end user. Use it for UniqueTogetherError first
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Tue, 12 Oct 2010 23:36:35 +0200
changeset 6465 6401a9d0b5aa
parent 6464 11f9fbf6a645
child 6466 43d71dd8a8ec
[architecture] introduce adapter to ease transformation of errors before display to the end user. Use it for UniqueTogetherError first
entities/adapters.py
selectors.py
server/repository.py
--- a/entities/adapters.py	Tue Oct 12 23:34:55 2010 +0200
+++ b/entities/adapters.py	Tue Oct 12 23:36:35 2010 +0200
@@ -28,7 +28,8 @@
 from logilab.common.decorators import cached
 
 from cubicweb.view import EntityAdapter, implements_adapter_compat
-from cubicweb.selectors import implements, is_instance, relation_possible
+from cubicweb.selectors import (implements, is_instance, relation_possible,
+                                match_exception)
 from cubicweb.interfaces import IDownloadable, ITree, IProgress, IMileStone
 
 
@@ -463,3 +464,24 @@
     def contractors(self):
         """returns the list of persons supposed to work on this task"""
         raise NotImplementedError
+
+
+# error handling adapters ######################################################
+
+from cubicweb import UniqueTogetherError
+
+class IUserFriendlyError(EntityAdapter):
+    __regid__ = 'IUserFriendlyError'
+    __abstract__ = True
+    def __init__(self, *args, **kwargs):
+        self.exc = kwargs.pop('exc')
+        super(IUserFriendlyError, self).__init__(*args, **kwargs)
+
+
+class IUserFriendlyUniqueTogether(IUserFriendlyError):
+    __select__ = match_exception(UniqueTogetherError)
+    def raise_user_exception(self):
+        etype, rtypes = self.exc.args
+        msg = self._cw._('violates unique_together constraints (%s)') % (
+            ', '.join(self._cw._(rtypes)))
+        raise ValidationError(self.entity.eid, dict((col, msg) for col in rtypes))
--- a/selectors.py	Tue Oct 12 23:34:55 2010 +0200
+++ b/selectors.py	Tue Oct 12 23:36:35 2010 +0200
@@ -1430,6 +1430,21 @@
         return 0
 
 
+class match_exception(ExpectedValueSelector):
+    """Return 1 if a view is specified an as its registry id is in one of the
+    expected view id given to the initializer.
+    """
+    def __init__(self, *expected):
+        assert expected, self
+        self.expected = expected
+
+    @lltrace
+    def __call__(self, cls, req, exc=None, **kwargs):
+        if exc is not None and isinstance(exc, self.expected):
+            return 1
+        return 0
+
+
 @objectify_selector
 def debug_mode(cls, req, rset=None, **kwargs):
     """Return 1 if running in debug mode."""
--- a/server/repository.py	Tue Oct 12 23:34:55 2010 +0200
+++ b/server/repository.py	Tue Oct 12 23:36:35 2010 +0200
@@ -1174,11 +1174,9 @@
         try:
             source.add_entity(session, entity)
         except UniqueTogetherError, exc:
-            etype, rtypes = exc.args
-            problems = {}
-            for col in rtypes:
-                problems[col] = session._('violates unique_together constraints (%s)') % (','.join(rtypes))
-            raise ValidationError(entity.eid, problems)
+            userhdlr = session.vreg['adapters'].select(
+                'IUserFriendlyError', session, entity=entity, exc=exc)
+            userhdlr.raise_user_exception()
         self.add_info(session, entity, source, extid, complete=False)
         edited.saved = entity._cw_is_saved = True
         # trigger after_add_entity after after_add_relation