temboz - Check-in [418]
Not logged in
[Honeypot]  [Browse]  [Help]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline]  [Wiki
  [Patchset]  [Tagging/Branching
Check-in Number: 418
Date: 2009-Sep-18 01:33:49 (local)
2009-Sep-18 08:33:49 (UTC)
User:majid
Branch:
Comment: added optional display of item tags and the ability to filter on them
Tickets:
Inspections:
Files:
temboz/filters.py      1.4 -> 1.5     28 inserted, 2 deleted
temboz/pages/add.tmpl      1.12 -> 1.13     4 inserted, 3 deleted
temboz/pages/catch_up.tmpl      1.14 -> 1.15     3 inserted, 2 deleted
temboz/pages/feed_debug.tmpl      1.3 -> 1.4     5 inserted, 2 deleted
temboz/pages/feed_info.tmpl      1.20 -> 1.21     45 inserted, 36 deleted
temboz/pages/feeds.tmpl      1.31 -> 1.32     6 inserted, 3 deleted
temboz/pages/hard_purge.tmpl      1.4 -> 1.5     4 inserted, 3 deleted
temboz/pages/rules.tmpl      1.17 -> 1.18     3 inserted, 3 deleted
temboz/pages/rules_common.tmpl      1.4 -> 1.5     4 inserted, 3 deleted
temboz/pages/temboz_css.tmpl      1.22 -> 1.23     22 inserted, 14 deleted
temboz/pages/view.tmpl      1.64 -> 1.65     67 inserted, 9 deleted
temboz/server.py      1.40 -> 1.41     2 inserted, 2 deleted

temboz/filters.py 1.4 -> 1.5
--- /tmp/T0mgaOl5	Mon Sep  6 18:23:08 2010
+++ /tmp/T1ngaOl5	Mon Sep  6 18:23:08 2010
@@ -28,6 +28,10 @@
     return self.__str__()
   def check_expires(self):
     return self.expires and time.time() > self.expires
+  def highlight_title(self, html):
+    return html
+  def highlight_content(self, html):
+    return html
 
 class KeywordRule(Rule):
   def __init__(self, uid, expires, rule, rtype):
@@ -80,6 +84,20 @@
       return  self.highlight(html)
     return html
 
+class TagRule(Rule):
+  def __init__(self, uid, expires, rule):
+    Rule.__init__(self, uid, expires)
+    self.rule = rule
+  def __str__(self):
+    return '<TagRule %s %s>' % (self.uid, self.rule)
+  def test(self, item, feed, feed_uid):
+    if self.check_expires():
+      return False
+    return self.rule in item['item_tags']
+  def highlight_content(self, html):
+    return '%s<br><p>Filtered for tag <span class="item_tag highlighted">%s</span></p>' \
+           % (html, self.rule)
+
 ########################################################################
 # functions used inside Python rules
 def link_already(url):
@@ -194,6 +212,9 @@
         if rtype == 'python':
           rule = PythonRule(uid, expires, rule)
           container.append(rule)
+        elif rtype == 'tag':
+          rule = TagRule(uid, expires, rule)
+          container.append(rule)
         elif rtype.startswith('union_'):
           # XXX this convention of adding a second rule object with UID -uid
           # XXX is a ugly hack
@@ -250,7 +271,9 @@
     item_uid = None
 
   if not kw: return
-  if match == 'word':
+  if match == 'tag':
+    words = [normalize.lower(kw)]
+  elif match == 'word':
     words = normalize.get_words(kw)
   elif match == 'all':
     words = [' '.join(normalize.get_words(kw))]
@@ -261,7 +284,10 @@
   else:
     return
   
-  rule_type = target + '_' + match
+  if match == 'tag':
+    rule_type = 'tag'
+  else:
+    rule_type = target + '_' + match
 
   for word in words:
     print >> param.log, 'ADD_KW_RULES', rule_type, item_uid, word

temboz/pages/add.tmpl 1.12 -> 1.13
--- /tmp/T0bhaym5	Mon Sep  6 18:23:08 2010
+++ /tmp/T1chaym5	Mon Sep  6 18:23:08 2010
@@ -6,8 +6,9 @@
 <META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
 <link rel="stylesheet" type="text/css" href="temboz.css">
 </head>
-<body>
-<p class="menu"><a href="view">All unread</a>&nbsp;&nbsp;<a href="feeds">All feeds</a></p>
+<body class="unpadded">
+<div class="menu"><a href="view">All unread</a>&nbsp;&nbsp;<a
+href="feeds">All feeds</a></div>
 
 Subscribe to a RSS feed:<br>
 <form action="add" method="POST">
@@ -42,7 +43,7 @@
 #except urllib2.URLError, e
 <p>Error loading URL during autodiscovery attempt:<p>
 <pre>
-<%=e.args[0]%>
+<%=e%>
 </pre>
 #except update.UnknownError, e
 <p>Unknown error:<p>

temboz/pages/catch_up.tmpl 1.14 -> 1.15
--- /tmp/T0Dhaqn5	Mon Sep  6 18:23:08 2010
+++ /tmp/T1Ehaqn5	Mon Sep  6 18:23:08 2010
@@ -54,8 +54,9 @@
   #end if
 #else
 </head>
-<body>
-<p class="menu"><a href="view">All unread</a>&nbsp;&nbsp;<a href="feeds">All feeds</a></p>
+<body class="unpadded">
+<div class="menu"><a href="view">All unread</a>&nbsp;&nbsp;<a
+href="feeds">All feeds</a></div>
 <form method="POST">
   #echo self.regurgitate_except()
   <input type="hidden" name="referrer" value="$referrer">

temboz/pages/feed_debug.tmpl 1.3 -> 1.4
--- /tmp/T0aia4n5	Mon Sep  6 18:23:08 2010
+++ /tmp/T1bia4n5	Mon Sep  6 18:23:08 2010
@@ -6,8 +6,11 @@
 <META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
 <link rel="stylesheet" type="text/css" href="temboz.css">
 </head>
-<body>
-<p class="menu"><a href="view">All unread</a>&nbsp;&nbsp;<a href="add">Add feed</a>&nbsp;&nbsp;<a href="feeds">All feeds</a> <span class="help"><a href="http://www.temboz.com/temboz/wiki?p=FeedDebugPage" target="_blank">Help</a></span></p>
+<body class="unpadded">
+<div class="menu"><a href="view">All unread</a>&nbsp;&nbsp;<a href="add">Add
+feed</a>&nbsp;&nbsp;<a href="feeds">All feeds</a> <span class="help"><a
+href="http://www.temboz.com/temboz/wiki?p=FeedDebugPage"
+target="_blank">Help</a></span></div>
 #set $feed_uid = $getVar('feed_uid')
 #from singleton import db
 #import time, pprint

temboz/pages/feed_info.tmpl 1.20 -> 1.21
--- /tmp/T0piaGo5	Mon Sep  6 18:23:08 2010
+++ /tmp/T1qiaGo5	Mon Sep  6 18:23:08 2010
@@ -8,9 +8,51 @@
 <script language="JavaScript" src="temboz.js"></script>
 $rule_head
 </head>
-<body>
-<p class="menu"><a href="view">All unread</a>&nbsp;&nbsp;<a href="add">Add feed</a>&nbsp;&nbsp;<a href="feeds">All feeds</a> <span class="help"><a href="http://www.temboz.com/temboz/wiki?p=FeedDetailsPage" target="_blank">Help</a></span></p>
+<body class="unpadded">
+<div class="menu"><a href="view">All unread</a>&nbsp;&nbsp;<a href="add">Add
+feed</a>&nbsp;&nbsp;<a href="feeds">All feeds</a> <span class="help"><a
+href="http://www.temboz.com/temboz/wiki?p=FeedDetailsPage"
+target="_blank">Help</a></span></div>
 #set $feed_uid = $getVar('feed_uid')
+########################################################################
+##
+## Suspend or activate feed, mark it private/public or set duplicate title
+## checking if requested
+##
+########################################################################
+#if $getVar('change_op', None)
+#if $getVar('change_op') == 'Activate'
+<% status = 0 %>
+<% update.set_status(feed_uid, status) %>
+#elif $getVar('change_op') == 'Suspend'
+<% status = 1 %>
+<% update.set_status(feed_uid, status) %>
+#elif $getVar('change_op') == 'Private'
+<% private = 1 %>
+<% update.update_feed_private(feed_uid, private) %>
+#elif $getVar('change_op') == 'Public'
+<% private = 0 %>
+<% update.update_feed_private(feed_uid, private) %>
+#elif $getVar('change_op') == 'Dupcheck'
+<% dupcheck = 1 %>
+<% update.update_feed_dupcheck(feed_uid, dupcheck) %>
+#elif $getVar('change_op') == 'NoDupcheck'
+<% dupcheck = 0 %>
+<% update.update_feed_dupcheck(feed_uid, dupcheck) %>
+#elif $getVar('change_op') == 'Exempt'
+<% exempt = 1 %>
+<% update.update_feed_exempt(feed_uid, exempt) %>
+#elif $getVar('change_op') == 'Reinstate'
+<% exempt = 0 %>
+<% update.update_feed_exempt(feed_uid, exempt) %>
+#end if
+#end if
+
+########################################################################
+##
+## Get feed statistics
+##
+########################################################################
 #from singleton import db
 #import time, pprint, update, filters
 #set c = db.cursor()
@@ -108,7 +150,7 @@
 #end try
 #end if
 
-<h1><a href="<%=feed_html%>"><%=feed_title%></a></h2>
+<h1><a href="<%=feed_html%>"><%=feed_title%></a></h1>
 
 ########################################################################
 ##
@@ -150,39 +192,6 @@
 
 ########################################################################
 ##
-## Suspend or activate feed, mark it private/public or set duplicate title
-## checking if requested
-##
-########################################################################
-#if $getVar('change_op', None)
-#if $getVar('change_op') == 'Activate'
-<% status = 0 %>
-<% update.set_status(feed_uid, status) %>
-#elif $getVar('change_op') == 'Suspend'
-<% status = 1 %>
-<% update.set_status(feed_uid, status) %>
-#elif $getVar('change_op') == 'Private'
-<% private = 1 %>
-<% update.update_feed_private(feed_uid, private) %>
-#elif $getVar('change_op') == 'Public'
-<% private = 0 %>
-<% update.update_feed_private(feed_uid, private) %>
-#elif $getVar('change_op') == 'Dupcheck'
-<% dupcheck = 1 %>
-<% update.update_feed_dupcheck(feed_uid, dupcheck) %>
-#elif $getVar('change_op') == 'NoDupcheck'
-<% dupcheck = 0 %>
-<% update.update_feed_dupcheck(feed_uid, dupcheck) %>
-#elif $getVar('change_op') == 'Exempt'
-<% exempt = 1 %>
-<% update.update_feed_exempt(feed_uid, exempt) %>
-#elif $getVar('change_op') == 'Reinstate'
-<% exempt = 0 %>
-<% update.update_feed_exempt(feed_uid, exempt) %>
-#end if
-#end if
-########################################################################
-##
 ## Display feed flags with option to change it
 ##
 ########################################################################

temboz/pages/feeds.tmpl 1.31 -> 1.32
--- /tmp/T0Giaip5	Mon Sep  6 18:23:08 2010
+++ /tmp/T1Hiaip5	Mon Sep  6 18:23:08 2010
@@ -6,8 +6,11 @@
 <META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
 <link rel="stylesheet" type="text/css" href="temboz.css">
 </head>
-<body>
-<p class="menu"><a href="view">All unread</a>&nbsp;&nbsp;<a href="add">Add feed</a>&nbsp;&nbsp;<a href="opml">as OPML</a>&nbsp;&nbsp;<a href="rules">Filtering</a> <span class="help"><a href="http://www.temboz.com/temboz/wiki?p=AllFeedsPage" target="_blank">Help</a></span></p>
+<body class="unpadded">
+<div class="menu"><a href="view">All unread</a>&nbsp;&nbsp;<a href="add">Add
+feed</a>&nbsp;&nbsp;<a href="opml">as OPML</a>&nbsp;&nbsp;<a
+href="rules">Filtering</a> <span class="help"><a
+href="http://www.temboz.com/temboz/wiki?p=AllFeedsPage" target="_blank">Help</a></span></div>
 #set sort_key = $getVar('sort', '(unread > 0) DESC, snr')
 #if sort_key == 'feed_title'
 #set sort_key = 'lower(feed_title)'
@@ -22,7 +25,7 @@
 from v_feeds_snr order by feed_status ASC, """ \
     + sort_key + ' ' + order + """, lower(feed_title)""")
 <table>
-<tr>
+<tr class="header">
 ########################################################################
 ##
 ## Produce column headings with appropriate sort order

temboz/pages/hard_purge.tmpl 1.4 -> 1.5
--- /tmp/T0ViaWp5	Mon Sep  6 18:23:08 2010
+++ /tmp/T1WiaWp5	Mon Sep  6 18:23:08 2010
@@ -24,7 +24,7 @@
 #set $status = update.hard_purge($feed_uid)
 #if $status
 </head>
-<body>
+<body class="unpadded">
 Error: $status
 #else
 <meta http-equiv="refresh" content="0; URL=/feeds">
@@ -34,8 +34,9 @@
 #end if
 #else
 </head>
-<body>
-<p class="menu"><a href="view">All unread</a>&nbsp;&nbsp;<a href="feeds">All feeds</a></p>
+<body class="unpadded">
+<div class="menu"><a href="view">All unread</a>&nbsp;&nbsp;<a
+href="feeds">All feeds</a></div>
 <form action="hard_purge?feed_uid=$feed_uid" method="POST">
 <input type="hidden" name="confirm" value="yes">
 Please confirm you want to completely delete all articles and the feed itself

temboz/pages/rules.tmpl 1.17 -> 1.18
--- /tmp/T0Ejayq5	Mon Sep  6 18:23:08 2010
+++ /tmp/T1Fjayq5	Mon Sep  6 18:23:08 2010
@@ -11,10 +11,10 @@
     <script language="JavaScript" src="temboz.js"></script>
     $rule_head
   </head>
-  <body>
-    <p class="menu"><a href="view">All unread</a>&nbsp;&nbsp;<a
+  <body class="unpadded>
+    <div class="menu"><a href="view">All unread</a>&nbsp;&nbsp;<a
     href="view?show=filtered">All filtered</a>&nbsp;&nbsp;<a href="feeds">All
-    feeds</a></p>
+    feeds</a></div>
 
     #if $getVar("uid", None)
       #set $status = filters.update_rule(db, c, $uid, $expires, $text,

temboz/pages/rules_common.tmpl 1.4 -> 1.5
--- /tmp/T0gkaar5	Mon Sep  6 18:23:08 2010
+++ /tmp/T1hkaar5	Mon Sep  6 18:23:08 2010
@@ -14,7 +14,7 @@
 #end def
 
 #def rule_tabset(c, feed_uid)
-<div id="tabset">
+<div id="tabset" class="ui-tabs">
   #set $rownum = 0
   #if feed_uid
     #silent c.execute("""select rule_uid, rule_type, date(rule_expires),
@@ -50,7 +50,7 @@
     #if not tabs[$initial]
       #continue
     #end if
-    <div id="keyword_$initial">
+    <div id="keyword_$initial" class="ui-tabs-hide">
       <table>
         <tr>
           <th>Rule</th><th>Type</th><th>Text</th><th>Filtered articles</th>
@@ -141,6 +141,7 @@
       </td></tr>
       <tr class="odd"><td>category</td><td>If present, set of categories for
       the article</td></tr>
+      <tr class="even"><td>author</td><td>Author of the article</td></tr>
     </table>
 
     <p>In addition, the convenience functions <tt>title_any</tt>,
@@ -206,6 +207,6 @@
   </div>
 </div>
 <script type="text/javascript">
-  \$(document).ready(function() { \$("div#tabset > ul").tabs(); });
+  \$(document).ready(function() { \$("div#tabset").tabs(); });
 </script>
 #end def

temboz/pages/temboz_css.tmpl 1.22 -> 1.23
--- /tmp/T0vkaOr5	Mon Sep  6 18:23:08 2010
+++ /tmp/T1wkaOr5	Mon Sep  6 18:23:08 2010
@@ -20,7 +20,7 @@
   right: 0px;
   padding:0px;
   margin:0px;
-  margin-top: 1cm;
+  margin-top: 3em;
 }
 a.headline {
   font-size:12pt;
@@ -86,6 +86,21 @@
 span.filter-highlight {
   background-color: #fcc;
 }
+div.tag_info {
+  display: none;
+}
+span.item_tag {
+  background-color: #bfff80;
+  padding-left: 1ex;
+  padding-right: 1ex;
+  -moz-border-radius: 1ex;
+  -webkit-border-radius: 1ex;
+  border-radius: 1ex;
+}
+span.item_tag.highlighted {
+  color: white;
+  background-color: red;
+}
 ########################################################################
 ## SCREEN ONLY
 #if $media == 'screen'
@@ -95,28 +110,21 @@
 ## work-around IE
 body>div.menu {
   position: fixed;
-  height: 1cm;
+  height: 2em;
 }
 div.menu {
-  padding: 0px;
+  padding: .5em;
   top: 0; left: 0; width: 100%;
-  background: #BFFF80;
+  background: #bfff80;
   z-index: 2;
 }
-p.menu {
-  margin-top: 5px;
-  margin-bottom: 0px;
-  margin-left: 0px;
-  margin-right: 0px;
-  background: #BFFF80;
-  width: 100%;
-}
-p.menu span.help {
+div.menu span.help {
   position: absolute;
-  right: 10px;
+  right: 2em;
 }
 form.inline {
   display: inline;
+  margin-bottom: 0px;
 }
 body.unpadded p.menu {
   padding-top: 0px;

temboz/pages/view.tmpl 1.64 -> 1.65
--- /tmp/T0Mkaqs5	Mon Sep  6 18:23:08 2010
+++ /tmp/T1Nkaqs5	Mon Sep  6 18:23:08 2010
@@ -1,5 +1,5 @@
 ## -*- html -*-
-#extends TembozTemplate
+#extends menubar
 #implements respond
 ########################################################################
 ##
@@ -119,7 +119,7 @@
   }
   return jQuery.trim(userSelection);
 }
-function kw_dialog(id, kw) {
+function kw_dialog(id, kw, context) {
   var tmpl = \$("div#kw_form_tmpl");
   var body = '<div title="Add a keyword rule">' + tmpl.html() + '</div>';
   body = body.replace(/__item_uid__/, id);
@@ -142,9 +142,25 @@
 ##      background: "black"
 ##    }
   }).find(":text").val(kw);
+  \$('.ui-dialog-content select[name="match"]').change(function() {
+    if(\$(this).val() == "tag") {
+      \$('.ui-dialog-content select[name="target"]').hide();
+    } else {
+      \$('.ui-dialog-content select[name="target"]').show();
+    }
+  })
   if(kw.search(" ") != -1 || kw.search("-") != -1) {
-    \$('.ui-dialog-content select[@name="match"]').val('phrase_lc');
+    \$('.ui-dialog-content select[name="match"]').val('phrase_lc');
   }
+  if(context) {
+    if(context == "tag") {
+      \$('.ui-dialog-content select[name="match"]').val(context);
+      \$('.ui-dialog-content select[name="target"]').hide();
+      \$('.ui-dialog-content :checkbox').val(["feed_only"]);
+    } else if(context == "title") {
+      \$('.ui-dialog-content select[name="target"]').val(context);
+    }
+  }
 }
 ## hide tag layer until it is ready
 #set taglayer_visibility = "none"
@@ -157,9 +173,18 @@
       elt.taglayer.style.display = "none";
     }
   } else {
-    var kw = $.trim(get_selection());
-    if(kw!="") {
-      kw_dialog(id, kw);
+    var kw = \$.trim(get_selection());
+    if(kw!="" && elt.innerHTML.indexOf(kw)!=-1) {
+      if (\$(elt).find("a.headline").html().indexOf(kw)!=-1) {
+        kw_dialog(id, kw, "title");
+      } else {
+        kw_dialog(id, kw);
+      }
+    } else {
+      var tags = \$(elt).find("span.item_tag.highlighted").html();
+      if(tags) {
+        kw_dialog(id, tags, 'tag');
+      }
     }
     hidden[hidden.length] = elt;
     elt.style.display = "none";
@@ -176,6 +201,15 @@
     document.getElementById('ctarrow' + id).innerHTML = '<img width="14" height="14" alt="hidden" src="<%=img_prefix%>a_dn.gif" />&nbsp;';
   }
 }
+function toggle_tags(id) {
+  \$("div#tags_" + id).toggle();
+}
+function toggle_tag() {
+  \$(this).toggleClass("highlighted");
+}
+\$(document).ready(function() {
+  \$("span.item_tag").click(toggle_tag);
+});
 function highlight(id) {
   var elt = document.getElementById('art' + id);
   elt.style.backgroundColor = "yellow";
@@ -310,7 +344,7 @@
 #set count = 0
 #if not mobile
 <div id="menu" class="menu">
-<p class="menu">$num_items 
+$num_items 
 #if not public
 <span><form id="show_select" class="inline" method="GET">
   #echo self.regurgitate_except('show')
@@ -364,9 +398,9 @@
     <input type="submit" value="Search">
   </form>
 </span>
-</p>
 #end if
 </div>
+##$menubar
 #else
 #set overload_threshold = 50
 #end if
@@ -383,6 +417,7 @@
       <option value="all">All words</option>
       <option value="phrase_lc">Phrase</option>
       <option value="phrase">Phrase (case-sensitive)</option>
+      <option value="tag">Tag</option>
       </select></td></tr>
       <tr><td>Match on</td><td><select name="target">
       <option value="union" selected>Title or content</option>
@@ -403,6 +438,19 @@
 ## Fetch overload_threshold (default 200) items
 ##
 ########################################################################
+#set tag_dict = {}
+#silent c.execute("""select tag_item_uid, tag_name, tag_by
+from  fm_tags, (
+  select item_uid from fm_items, fm_feeds
+  where item_feed_uid=feed_uid
+  and """ + where_clause + ' and feed_private = 0' * public + """
+  order by item_created DESC, item_uid DESC
+  limit ? offset ?)
+where tag_item_uid=item_uid""", params + [overload_threshold, offset])
+#for item_uid, tag_name, tag_by in c
+#silent tag_dict.setdefault(item_uid, []).append(tag_name)
+#end for
+########################################################################
 #silent c.execute("""select item_uid, item_creator, item_title, item_link,
 item_content, datetime(item_loaded), date(item_created), feed_uid,
 feed_title, feed_html, feed_xml, julianday('now') - julianday(item_created),
@@ -455,6 +503,15 @@
     #set content = content + '<br><p>Filtered by feed-specific Python rule</p>'
   #end if
 #end if
+#if $uid in tag_dict
+## XXX should probably escape the Unicode here
+#set $tag_info = ' '.join('<span class="item_tag">%s</span>' % t for t in tag_dict[$uid])
+#set $tag_info = '<div class="tag_info" id="tags_%s">' % $uid + $tag_info + '</div>'
+#set $tag_call = '<a href="javascript:toggle_tags(%s);">tags</a>' % $uid
+#else
+#set $tag_info = ''
+#set $tag_call = '(no tags)'
+#end if
 <div class="article" id="art$uid"><div class="headline"><span
 class="buttons"><img width="32" height="32" alt="down"
 src="<%=img_prefix%>down.gif" class="down" onclick="hide('$uid')"
@@ -463,6 +520,7 @@
 target="_blank" title="by $creator, cached at $loaded">$title</a><br><a
 href="feed_info?feed_uid=$feed_uid" title="" class="source screen" id="feed$uid">$feed_title</a><a href="$feed_html" title="" class="source print" id="feedprint$uid">$feed_title</a>
 $since_when
+$tag_call
 #if not public
 <a href="edit?uid=$uid" class="screen">edit</a>
 #else
@@ -472,7 +530,7 @@
 #set $content = $content.replace($magic, ' ...') + '<a href="' + link + '">(more after the jump)</a>'
 #end if
 #end if
-<br></div><div class="content" id="content$uid">
+<br></div>$tag_info<div class="content" id="content$uid">
 $content
 </div>
 #if getattr(param, 'thumbs_bottom', False)

temboz/server.py 1.40 -> 1.41
--- /tmp/T05ka4s5	Mon Sep  6 18:23:08 2010
+++ /tmp/T16ka4s5	Mon Sep  6 18:23:08 2010
@@ -1,5 +1,5 @@
 #!/usr/local/bin/python
-# $Id: server.py,v 1.40 2009/07/08 00:57:36 majid Exp $
+# $Id: server.py,v 1.41 2009/09/18 08:33:49 majid Exp $
 import sys, os, stat, logging, base64, time, imp, gzip, imp
 import BaseHTTPServer, SocketServer, cgi, cStringIO, urlparse
 import param, update, filters, util
@@ -371,7 +371,7 @@
       # add the module to tmpl_cache
       self.tmpl_cache[page] = module
     else:
-      raise('Error loading compiled template: %s' % compiled,tmpl)
+      raise Exception('Error loading compiled template: %s' % compiled,tmpl)
     return getattr(self.tmpl_cache[page], tmpl)
   
   def use_template(self, tmpl, searchlist):