[Mpuls-commits] r277 - in wasko/trunk: . waskaweb/controllers waskaweb/lib waskaweb/model waskaweb/templates/casemanagement

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Fri Feb 20 16:02:38 CET 2009


Author: teichmann
Date: 2009-02-20 16:02:29 +0100 (Fri, 20 Feb 2009)
New Revision: 277

Modified:
   wasko/trunk/ChangeLog.txt
   wasko/trunk/waskaweb/controllers/CaseBase.py
   wasko/trunk/waskaweb/controllers/case.py
   wasko/trunk/waskaweb/lib/base.py
   wasko/trunk/waskaweb/lib/db.py
   wasko/trunk/waskaweb/lib/helpers.py
   wasko/trunk/waskaweb/model/casedocument.py
   wasko/trunk/waskaweb/model/data.py
   wasko/trunk/waskaweb/model/datapage.py
   wasko/trunk/waskaweb/model/expr.py
   wasko/trunk/waskaweb/model/navigation.py
   wasko/trunk/waskaweb/model/semantic.py
   wasko/trunk/waskaweb/templates/casemanagement/formular.mako
Log:
Bring new error system to work.

-- Diesr und die folgenden Zeilen werden ignoriert --

M    waskaweb/model/navigation.py
M    waskaweb/model/semantic.py
M    waskaweb/model/datapage.py
M    waskaweb/model/data.py
M    waskaweb/model/casedocument.py
M    waskaweb/model/expr.py
M    waskaweb/controllers/CaseBase.py
M    waskaweb/controllers/case.py
M    waskaweb/lib/helpers.py
M    waskaweb/lib/base.py
M    waskaweb/lib/db.py
M    waskaweb/templates/casemanagement/formular.mako
M    ChangeLog.txt


Modified: wasko/trunk/ChangeLog.txt
===================================================================
--- wasko/trunk/ChangeLog.txt	2009-02-20 14:16:00 UTC (rev 276)
+++ wasko/trunk/ChangeLog.txt	2009-02-20 15:02:29 UTC (rev 277)
@@ -1,3 +1,39 @@
+2009-02-20	Sascha L. Teichmann <teichmann at intevation.de>
+
+	Bring new error system to work.
+
+	* waskaweb/lib/db.py, waskaweb/lib/base.py: Removed needless import.
+
+	* waskaweb/templates/casemanagement/formular.mako: Use new ErrorRenderer
+	  to render errors and warnings on page.
+
+	* waskaweb/lib/helpers.py: New helper function to call ErrorRenderer to
+	  display the errors.
+
+	* waskaweb/controllers/case.py: New select_item method for navigation.
+	  Removed some 'page in [list]' code.
+
+	* waskaweb/controllers/CaseBase.py: use the select_item method instead
+	  of edit/show.
+
+	* waskaweb/model/expr.py: Upstream expression engine from offline client
+	  supporting the 'isset' function.
+
+	* waskaweb/model/casedocument.py: Implemented a caching mechanism to
+	  allow case wide access to variables not only on page.
+
+	* waskaweb/model/data.py: Enable marks in RuleLeafs.
+
+	* waskaweb/model/datapage.py: Ported some enhancements from data model
+	  of the Offline Client. Fixed problems with errors which weren't descripted 
+	  correctly.
+
+	* waskaweb/model/semantic.py: Upstream version of Offline Client. Enables
+	  usage of 'unbekannt' in dates and integers.
+
+	* waskaweb/model/navigation.py: Some more tweaks on its stony way to the
+	  much better version of the Offline Client. It is still broken. :-(
+
 2009-02-20	Torsten Irlaender  <torsten.irlaender at intevation.de>
 
 	Changed labeling of "Agentur" to "Einrichtung"

Modified: wasko/trunk/waskaweb/controllers/CaseBase.py
===================================================================
--- wasko/trunk/waskaweb/controllers/CaseBase.py	2009-02-20 14:16:00 UTC (rev 276)
+++ wasko/trunk/waskaweb/controllers/CaseBase.py	2009-02-20 15:02:29 UTC (rev 277)
@@ -83,9 +83,9 @@
             redirect_to(h.url_for(controller='/case_overview'))
         errors = case.getFormErrors()
         id     = case.id
-        mode   = case.getMode()
+        #mode   = case.getMode()
         self.navigation.setErrors([err.page for err in errors.itervalues()])
-        select_url = lambda t: '/case/%s/%s/%s' % (mode, id, t.key)
+        select_url = lambda t: '/case/select_item/%s/%s' % (id, t.key)
         toggle_url = lambda r: '/navigation/toggle/%s/%s' % (id, r.key)
         return self.navigation.render(select_url, toggle_url, selected_key) 
 

Modified: wasko/trunk/waskaweb/controllers/case.py
===================================================================
--- wasko/trunk/waskaweb/controllers/case.py	2009-02-20 14:16:00 UTC (rev 276)
+++ wasko/trunk/waskaweb/controllers/case.py	2009-02-20 15:02:29 UTC (rev 277)
@@ -351,6 +351,7 @@
 
     @checkRole('cm_ka')
     def edit(self, ds_id, page_id):
+        case_session = session.get('case')
         ds_id        = self._checkInt(ds_id)
         page_id      = self._checkInt(page_id)
         ti           = self.getNavigation().getTreeItem(page_id)
@@ -374,6 +375,19 @@
         return render('/casemanagement/formular.mako')
 
     @checkRole(('admin_ka', 'cm_ka', 'pt_dlr'))
+    def select_item(self, ds_id, page_id):
+        try:
+            case_session = session.get('case')
+        except KeyError:
+            raise HTTPNotFound()
+
+        if case_session.getMode() == "show":
+            return self.show(ds_id, page_id)
+
+        return self.edit(ds_id, page_id)
+
+
+    @checkRole(('admin_ka', 'cm_ka', 'pt_dlr'))
     def show(self, ds_id, page_id):
         ds_id        = self._checkInt(ds_id)
         page_id      = self._checkInt(page_id)
@@ -462,19 +476,6 @@
         # Only proceed to next page if the page does not contain errors
         if request.params.get('__formular_next') and len(h.getFormularErrors(ti.page)) <= 0:
 
-            # XXX: This ultra ugly!
-            if int(ti.key) in [27,28,29,30]:
-                try:
-                    nds = int(case_session.id)
-                except:
-                    print >> sys.stderr, "Case id not found"
-                    nds = None
-                if not nds is None:
-                    ti.showPath()
-                    ds_id   = ti.realId(int(nds))
-                    page_id = "14"
-                    return self.edit(ds_id, page_id) 
-
             nkey = ti.nextKey()
             if not nkey is None:
                 nti = self.getNavigation().getTreeItem(nkey)

Modified: wasko/trunk/waskaweb/lib/base.py
===================================================================
--- wasko/trunk/waskaweb/lib/base.py	2009-02-20 14:16:00 UTC (rev 276)
+++ wasko/trunk/waskaweb/lib/base.py	2009-02-20 15:02:29 UTC (rev 277)
@@ -29,7 +29,6 @@
 from pylons                     import c, cache, config, g, request, response, session
 from pylons.controllers         import WSGIController
 from pylons.controllers.util    import abort, etag_cache, redirect_to
-from pylons.decorators          import jsonify, validate
 from pylons.i18n                import _, ungettext, N_
 from pylons.templating          import render
 

Modified: wasko/trunk/waskaweb/lib/db.py
===================================================================
--- wasko/trunk/waskaweb/lib/db.py	2009-02-20 14:16:00 UTC (rev 276)
+++ wasko/trunk/waskaweb/lib/db.py	2009-02-20 15:02:29 UTC (rev 277)
@@ -32,7 +32,6 @@
 import psycopg2 as dbapi
 
 import sys
-import traceback
 
 db = StackedObjectProxy(name="waska.db")
 

Modified: wasko/trunk/waskaweb/lib/helpers.py
===================================================================
--- wasko/trunk/waskaweb/lib/helpers.py	2009-02-20 14:16:00 UTC (rev 276)
+++ wasko/trunk/waskaweb/lib/helpers.py	2009-02-20 15:02:29 UTC (rev 277)
@@ -38,6 +38,11 @@
 
 import datetime
 
+from waskaweb.lib.renderer  import ErrorRenderer
+from waskaweb.lib.filecache import FileCache
+
+from waskaweb.model.data    import PageNode
+
 VALID_DATE = re.compile(r'^([0-9]{1,2})\.([0-9]{1,2})\.([0-9]{4})$')
 VALID_TIME = re.compile(r'^([0-9]{1,2}):([0-9]{2})')
 
@@ -195,6 +200,25 @@
     except:
         pass
 
+def getErrorsAndWarningsOnPage(page_id):
+    case = session.get('case')
+    if not case: return ""
+    navigation = session.get('navigation.tree')
+    if not navigation: return ""
+    tree_item = navigation.getTreeItem(page_id)
+    if not tree_item: return ""
+    page_name = tree_item.page
+    if not page_name: return ""
+    case_id  = case.id
+    errors   = case.getFormErrors()
+    formed   = g.formedTree
+    page     = formed.findByClassAndName(PageNode, page_name)
+    if not page: return ""
+    warnings = formed.warningsOnPage(page, case_id)
+    renderer = ErrorRenderer(errors, warnings, FileCache())
+    out = renderer.render(page)
+    return out
+
 def getFormularErrors(page_id):
     errors_on_page = {}
     # Get treeitem

Modified: wasko/trunk/waskaweb/model/casedocument.py
===================================================================
--- wasko/trunk/waskaweb/model/casedocument.py	2009-02-20 14:16:00 UTC (rev 276)
+++ wasko/trunk/waskaweb/model/casedocument.py	2009-02-20 15:02:29 UTC (rev 277)
@@ -30,11 +30,18 @@
 #
 
 from waskaweb.model.nodecomponents import Document
-from waskaweb.model.data           import PageNode
+from waskaweb.model.data           import PageNode, WidgetCollector, RuleLeaf
 from waskaweb.model.datapage       import PageStore, EmptyPageStore
 
 from paste.registry import StackedObjectProxy
 
+from traceback import print_exc
+
+import re
+import sys
+
+WARNING    = re.compile(r"warning\s*:\s*([^\s]+)")
+
 page_cache = StackedObjectProxy(name="waska.pagecache")
 
 def enter(cache):
@@ -53,24 +60,83 @@
             return self.pages[name]
         except KeyError:
             nc = formed.findByClassAndName(PageNode, name)
-            db_view = "%s_view" % name
+            db_view = "%s_view" % name.replace('-', '_')
             page = PageStore(db_view, nc, ds_id)
             self.pages[name] = page
             return page
 
 
 class CaseDocument(Document):
+
     def __init__(self, root=None):
         Document.__init__(self, root)
+        collector = WidgetCollector()
+        self.visit(collector.visitor)
 
-    #def getPageStore(self, name, ds_id=None, proxy=None, no_data=False):
+        widgets2pages = {}
+        for widget in collector.widgets:
+            page = widget
+            while page and not isinstance(page, PageStore):
+                page = page.parent
+            if page:
+                widgets2pages[widget.getName()] = page.getName()
+
+        self.widgets2pages = widgets2pages
+        self.widgets = dict([(w.getName(), w) for w in collector.widgets if w.getName()])
+
     def getPageStore(self, name, ds_id=None, no_data=False):
 
         if no_data: # XXX: urcan mode!
-            db_view = "%s_view" % name
+            db_view = "%s_view" % name.replace('-', '_')
             nc = self.findByClassAndName(PageNode, name)
             return EmptyPageStore(db_view, nc, ds_id)
 
         return page_cache.getPageStore(self, name, ds_id)
 
+    def getPageOfWidget(self, name):
+        return self.widgets2pages[name]
+
+    def getData(self, name, ds_id):
+        page_name = self.widgets2pages.get(name)
+        if not page_name: return None
+        page_store = self.getPageStore(page_name, ds_id)
+        return page_store.getData(name)
+
+    def warningsOnPage(self, page, ds_id):
+        """ Generates a dictionary of warnings that should be displayed
+            on a given page.
+        """
+        # widgets on page
+        used_fields = set([
+            w.getName() for w in page.allWidgets() if w.getName()])
+
+        warnings = {}
+
+        for r in self.findAllByClass(RuleLeaf):
+            mark, expr = r.getMark(), r.getExpr()
+            if not mark or not expr: continue
+            # warnings only
+            mark = WARNING.search(mark)
+            if not mark: continue
+            mark = mark.group(1)
+            # only mark if field is on current page
+            if not mark in used_fields: continue
+
+            try:
+                okay = expr.evaluate(dict([
+                    (n, self.getData(n, ds_id)) for n in expr.getDependencies()]))
+            except:
+                print_exc(file=sys.stderr)
+                okay = False
+
+            if not okay:
+                try:
+                    t = warnings[mark]
+                except KeyError:
+                    t = (self.widgets[mark], [])
+                    warnings[mark] = t
+                t[1].append(r.getValue())
+
+        return warnings
+
 # vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:

Modified: wasko/trunk/waskaweb/model/data.py
===================================================================
--- wasko/trunk/waskaweb/model/data.py	2009-02-20 14:16:00 UTC (rev 276)
+++ wasko/trunk/waskaweb/model/data.py	2009-02-20 15:02:29 UTC (rev 277)
@@ -255,6 +255,7 @@
     def __init__(self):
         Leaf.__init__(self)
         self.attributes["expr"] = ""
+        self.attributes["mark"] = ""
         self.expr = None
 
     def shallowCopy(self):
@@ -273,4 +274,10 @@
     def getExpr(self):
         return self.expr
 
+    def getMark(self):
+        return self.getAttribute("mark")
+
+    def setMark(self, mark):
+        self.setAttribute("mark", mark)
+
 # vim:set ts=4 sw=4 si et sta sts=4:

Modified: wasko/trunk/waskaweb/model/datapage.py
===================================================================
--- wasko/trunk/waskaweb/model/datapage.py	2009-02-20 14:16:00 UTC (rev 276)
+++ wasko/trunk/waskaweb/model/datapage.py	2009-02-20 15:02:29 UTC (rev 277)
@@ -34,6 +34,7 @@
 from waskaweb.lib.db         import db
 
 import sys
+import traceback
 
 def convert(x):
     if isinstance(x, str): return unicode(x, 'utf-8') 
@@ -124,6 +125,7 @@
                 v[1] = False
 
         except StandardError, err:
+            traceback.print_exc(file=sys.stderr)
             print >> sys.stderr, "DB error: %s" % str(err)
 
     def __lazyCheck(self):
@@ -141,6 +143,8 @@
         rel = self.relation.replace('-', '_')
         stmnt = "SELECT %s FROM %s WHERE id = %%(id)s;" % (
             fields, rel)
+
+        #print >> sys.stderr, "select: %s" % stmnt
         try:
             con, cur = None, None
             try:
@@ -155,7 +159,9 @@
                     zip(self.items, [[convert(item), False] for item in res]))
 
         except StandardError, err:
-            print >> sys.stderr, "DB error: %s" % str(err)
+            pass
+            #traceback.print_exc(file=sys.stderr)
+            #print >> sys.stderr, "DB error: %s" % str(err)
 
     def save(self, params, old_errors, document):
 
@@ -171,13 +177,11 @@
         widgets = dict([
             (widget.getName(), widget) for widget in nwidgets if widget.getName()])
 
+        widgets_clone = widgets.copy()
+
         # empty parameters will nullify values
         delete_vars = []
 
-        # for updating the errors
-        #old_errors = session.setdefault("$ERRORS", {})
-        # Note: old_errors is now passed as argument
-
         # vars that passed lexical and syntactic check
         to_be_set = {}
 
@@ -194,7 +198,10 @@
                     # Hopefully this one causes no trouble any more
                     old_errors.pop(k, None)
                     # the empty array is for the rules
-                    to_be_set[k] = (checkAndConvert(widget, value), [])
+                    nv = checkAndConvert(widget, value)
+                    ov = self.getData(k)
+                    if nv != ov:
+                        to_be_set[k] = (nv, [])
             except SematicError, inst:
                 ei = ErrorItem(pageName, value, widget.getDescription())
                 ei.addMessage(inst.value)
@@ -207,7 +214,7 @@
         dirty = False
 
         # remove variable from dataset which are set to ""
-        for wname in list(widgets.iterkeys()) + delete_vars:
+        for wname in widgets.keys() + delete_vars:
             dbPage.setData(wname, None)
             dirty = True
             # an unset value causes no problems.
@@ -216,6 +223,11 @@
         # find all rules that depend on variables to be set.
         # build up a lookup var-name -> list of rules
         for r in document.findAllByClass(RuleLeaf):
+            mark = r.getMark()
+            # warning rules are evaluated at page rendering
+            if mark and mark.find("warning:") >= 0:
+                #print "Ignore warning rule '%s'" % r.getName()
+                continue
             expr = r.getExpr()
             if not expr: continue
             for var in expr.getDependencies():
@@ -246,14 +258,17 @@
                     vars[k] = v # test it with new value from web
                     isOkay = expr.evaluate(vars)
                 except:
-                    print_exc()
                     isOkay = False
                 if not isOkay:
                     hasNoProblems = False
                     ie = old_errors.get(k, None)
                     if ie is None:
-                        ie = ErrorItem(pageName, v)
-                        old_errors[k] = ie
+                        try:
+                            desc = widgets_clone[k].getDescription()
+                        except KeyError:
+                            desc = ""
+                        ie = ErrorItem(pageName, v, desc)
+                        old_errors[k] = ie                        
                     msg = rule.getValue()
                     if msg: ie.addMessage(msg)
                     else:   ie.addMessage("There is a problem with '%s'." % k)

Modified: wasko/trunk/waskaweb/model/expr.py
===================================================================
--- wasko/trunk/waskaweb/model/expr.py	2009-02-20 14:16:00 UTC (rev 276)
+++ wasko/trunk/waskaweb/model/expr.py	2009-02-20 15:02:29 UTC (rev 277)
@@ -64,6 +64,10 @@
             stack = self.stack
             stack.append(stack.pop() * stack.pop())
 
+        def _ISSET(self):
+            stack = self.stack
+            stack.append(stack.pop() is not None)
+
         def _MINUS(self):
             stack = self.stack
             b = stack.pop()
@@ -149,6 +153,9 @@
             day   = stack.pop()
             stack.append(date(year, month, day))
 
+        def _TODAY(self):
+            self.stack.append(date.today())
+
         def _TYPE(self):
             stack = self.stack
             stack.append(type(stack.pop()))
@@ -212,11 +219,13 @@
             '>=':    _GE,
             '<=':    _LE,
             'not':   _NOT,
+            'isset': _ISSET,
             'or':    _OR,
             'and':   _AND,
             'type':  _TYPE,
             'DUP':   _DUP,
             'date':  _DATE,
+            'today': _TODAY,
             #'=':     _ASSIGN,
             '?':     _QUESTION,
         }
@@ -276,7 +285,8 @@
     def evaluate(self, vars=None):
         if self.prog is None:
             self.compile()
-        return Expr.EvalContext(vars).evaluate(self.prog)
+        result = Expr.EvalContext(vars).evaluate(self.prog)
+        return result
 
 #def main():
 #    for arg in sys.argv[1:]:

Modified: wasko/trunk/waskaweb/model/navigation.py
===================================================================
--- wasko/trunk/waskaweb/model/navigation.py	2009-02-20 14:16:00 UTC (rev 276)
+++ wasko/trunk/waskaweb/model/navigation.py	2009-02-20 15:02:29 UTC (rev 277)
@@ -135,6 +135,9 @@
             current.displayChildren = True
             current = current.parent
 
+    def getPageName(self):
+        return get_page(self)
+
 def get_page(nc):
     while nc:
         if isinstance(nc, PageNode):

Modified: wasko/trunk/waskaweb/model/semantic.py
===================================================================
--- wasko/trunk/waskaweb/model/semantic.py	2009-02-20 14:16:00 UTC (rev 276)
+++ wasko/trunk/waskaweb/model/semantic.py	2009-02-20 15:02:29 UTC (rev 277)
@@ -36,9 +36,12 @@
 
 from sys import maxint
 
-from waskaweb.lib.helpers import safe_unicode
+#from waskaweb.lib.helpers import safe_unicode
 
+def safe_unicode(s):
+    return s
 
+
 UNKNOWN_INT  = -9999999
 UNKNOWN_DATE = date(1, 1, 1)
 

Modified: wasko/trunk/waskaweb/templates/casemanagement/formular.mako
===================================================================
--- wasko/trunk/waskaweb/templates/casemanagement/formular.mako	2009-02-20 14:16:00 UTC (rev 276)
+++ wasko/trunk/waskaweb/templates/casemanagement/formular.mako	2009-02-20 15:02:29 UTC (rev 277)
@@ -35,17 +35,8 @@
 	<li><a href="/case/${session.get('case').getMode()}/${c.ds_id}/${c.page_id}" onclick="return checkModification();">${h.getFormularName(c.page_id)}</a></li>
 </%def>
 
-<%def name="buildFormErrors()">
-% if len(h.getFormularErrors(c.page_id)) > 0:
-  <div class="form_errors">
-    <h1><a name="error_list">${_('cm_error_header_false_forminput')}</a></h1>
-    <ul>
-    % for key, error in h.getFormularErrors(c.page_id).iteritems():
-      <li><a href="#f_${key}">${error.getName()}</a>:  ${"<br>".join(error.getMessages())}</li>
-    % endfor
-    </ul>
-  </div>
-% endif
+<%def name="buildFormErrors()">A
+    ${h.getErrorsAndWarningsOnPage(c.page_id)}
 </%def>
 
 <%def name="buildContentHeader()">



More information about the Mpuls-commits mailing list