[Python-checkins] r56582 - in tracker/instances/python-dev: detectors/busybody.py detectors/config.ini.template detectors/no_texthtml.py detectors/spambayes.py detectors/spamcheck.py detectors/tellteam.py detectors/userauditor.py extensions/spambayes.py html/file.item.html html/issue.item.html html/msg.item.html schema.py

erik.forsberg python-checkins at python.org
Fri Jul 27 18:26:27 CEST 2007


Author: erik.forsberg
Date: Fri Jul 27 18:26:26 2007
New Revision: 56582

Added:
   tracker/instances/python-dev/detectors/spambayes.py
      - copied unchanged from r56581, tracker/instances/python-dev-spambayes-integration/detectors/spambayes.py
   tracker/instances/python-dev/extensions/spambayes.py
      - copied unchanged from r56581, tracker/instances/python-dev-spambayes-integration/extensions/spambayes.py
Removed:
   tracker/instances/python-dev/detectors/spamcheck.py
Modified:
   tracker/instances/python-dev/detectors/busybody.py
   tracker/instances/python-dev/detectors/config.ini.template
   tracker/instances/python-dev/detectors/no_texthtml.py
   tracker/instances/python-dev/detectors/tellteam.py
   tracker/instances/python-dev/detectors/userauditor.py
   tracker/instances/python-dev/html/file.item.html
   tracker/instances/python-dev/html/issue.item.html
   tracker/instances/python-dev/html/msg.item.html
   tracker/instances/python-dev/schema.py
Log:
Merged python-dev-spambayes-integration rev 56581 down to python-dev

Modified: tracker/instances/python-dev/detectors/busybody.py
==============================================================================
--- tracker/instances/python-dev/detectors/busybody.py	(original)
+++ tracker/instances/python-dev/detectors/busybody.py	Fri Jul 27 18:26:26 2007
@@ -22,6 +22,16 @@
 
 from roundup import roundupdb, hyperdb
 
+def is_spam(db, msgid):
+    cutoff_score = float(db.config.detectors['SPAMBAYES_SPAM_CUTOFF'])    
+
+    msg = db.getnode("msg", msgid)
+    if msg.has_key('spambayes_score') and \
+           msg['spambayes_score'] > cutoff_score:
+        return False
+    return True
+
+
 def busyreaction(db, cl, nodeid, oldvalues):
     ''' busybody mail
     '''
@@ -36,7 +46,7 @@
     else:
         note = cl.generateChangeNote(nodeid, oldvalues)
 
-    for msgid in msgIDS:
+    for msgid in filter(lambda x: is_spam(db, x), msgIDS):
         try:
             cl.send_message(nodeid, msgid, note, sendto)
         except roundupdb.MessageSendError, message:

Modified: tracker/instances/python-dev/detectors/config.ini.template
==============================================================================
--- tracker/instances/python-dev/detectors/config.ini.template	(original)
+++ tracker/instances/python-dev/detectors/config.ini.template	Fri Jul 27 18:26:26 2007
@@ -12,3 +12,6 @@
 spambayes_ham_cutoff = 0.2
 spambayes_spam_cutoff = 0.85
 
+spambayes_may_view_spam = User,Coordinator,Developer
+spambayes_may_classify = Coordinator
+spambayes_may_report_misclassified = User,Coordinator,Developer

Modified: tracker/instances/python-dev/detectors/no_texthtml.py
==============================================================================
--- tracker/instances/python-dev/detectors/no_texthtml.py	(original)
+++ tracker/instances/python-dev/detectors/no_texthtml.py	Fri Jul 27 18:26:26 2007
@@ -1,6 +1,6 @@
 
 def audit_html_files(db, cl, nodeid, newvalues):
-    if newvalues['type'] == 'text/html':
+    if newvalues.has_key('type') and newvalues['type'] == 'text/html':
         newvalues['type'] = 'text/plain'
     
 

Deleted: /tracker/instances/python-dev/detectors/spamcheck.py
==============================================================================
--- /tracker/instances/python-dev/detectors/spamcheck.py	Fri Jul 27 18:26:26 2007
+++ (empty file)
@@ -1,38 +0,0 @@
-"""
-spamcheck.py - Auditor that consults a SpamBayes server and scores all form
-submissions.  Submissions which are deemed to be spam are rejected.  For the
-time being only reject submissions which are assumed to be spam (score >=
-SPAM_CUTOFF).  Once a reasonable body of ham and spam submissions have been
-built up you can consider whether to also reject unsure submissions (score >
-HAM_CUTOFF).  The current settings make it less likely that you'll reject
-valid submissions at the expense of manual checks to correct spammy items
-which snuck by the screen.
-"""
-
-import xmlrpclib
-import socket
-
-from roundup.exceptions import Reject
-
-def check_spam(_db, _klass, _nodeid, newvalues):
-    """Auditor to score a website submission."""
-
-    spambayes_uri = _db.config.detectors['SPAMBAYES_URI']
-    spam_cutoff = float(_db.config.detectors['SPAMBAYES_SPAM_CUTOFF'])
-
-
-    server = xmlrpclib.ServerProxy(spambayes_uri, verbose=False)
-    try:
-        prob = server.score(newvalues, [], {})
-    except (socket.error, xmlrpclib.Error), e:
-        pass
-    else:
-        if prob >= spam_cutoff:
-            raise Reject("Looks like spam to me - prob=%.3f" % prob)
-
-def init(database):
-    """Initialize auditor."""
-    database.issue.audit('create', check_spam)
-    database.issue.audit('set', check_spam)
-    database.file.audit('create', check_spam)
-    database.file.audit('set', check_spam)

Modified: tracker/instances/python-dev/detectors/tellteam.py
==============================================================================
--- tracker/instances/python-dev/detectors/tellteam.py	(original)
+++ tracker/instances/python-dev/detectors/tellteam.py	Fri Jul 27 18:26:26 2007
@@ -1,5 +1,14 @@
 from roundup import roundupdb
 
+def is_spam(db, msgid):
+    cutoff_score = float(db.config.detectors['SPAMBAYES_SPAM_CUTOFF'])    
+
+    msg = db.getnode("msg", msgid)
+    if msg.has_key('spambayes_score') and \
+           msg['spambayes_score'] > cutoff_score:
+        return False
+    return True
+
 def newissuetriage(db, cl, nodeid, oldvalues):
     ''' Copy a message about new issues to a triage address, 
         set in detectors/config.ini
@@ -14,9 +23,10 @@
         triage_email = []
     if not triage_email:
         return
-    for msgid in cl.get(nodeid, 'messages'):
+    for msgid in filter(lambda x: is_spam(db, x), cl.get(nodeid, 'messages')):
         try:
             # note: last arg must be a list
+            
             cl.send_message(nodeid, msgid, change_note, triage_email)
         except roundupdb.MessageSendError, message:
             raise roundupdb.DetectorError, message

Modified: tracker/instances/python-dev/detectors/userauditor.py
==============================================================================
--- tracker/instances/python-dev/detectors/userauditor.py	(original)
+++ tracker/instances/python-dev/detectors/userauditor.py	Fri Jul 27 18:26:26 2007
@@ -36,7 +36,7 @@
                 raise ValueError, 'Role "%s" does not exist'%rolename
 
         if None != nodeid and "admin" in roles:
-            if not "admin" in [x.lower().strip() for x in cl.get(nodeid, 'roles')]:
+            if not "admin" in [x.lower().strip() for x in cl.get(nodeid, 'roles').split(",")]:
                 raise ValueError, "Only Admins may assign the Admin role!"
 
 

Modified: tracker/instances/python-dev/html/file.item.html
==============================================================================
--- tracker/instances/python-dev/html/file.item.html	(original)
+++ tracker/instances/python-dev/html/file.item.html	Fri Jul 27 18:26:26 2007
@@ -29,8 +29,17 @@
   <td style="border: none" tal:condition="python: context.is_edit_ok()">Please note that
   for security reasons, it's not permitted to set content type to <i>text/html</i>.</td>
  </tr>
+ <tr>
+  <th i18n:translate="">SpamBayes Score</th>
+  <td tal:content="structure context/spambayes_score/plain"></td>
+ </tr>
 
  <tr>
+  <th i18n:translate="">Marked as misclassified</th>
+  <td tal:content="structure context/spambayes_misclassified/plain"></td>
+ </tr>
+
+ <tr tal:condition="python:context.is_edit_ok()">
   <td>
    &nbsp;
    <input type="hidden" name="@template" value="item">
@@ -44,10 +53,30 @@
 </table>
 </form>
 
-<a tal:condition="python:context.id and context.is_view_ok()"
+<p tal:condition="python:utils.sb_is_spam(context)" class="error-message">
+   File has been classified as spam.</p>
+
+<a tal:condition="python:context.id and utils.sb_is_view_ok(context)"
  tal:attributes="href string:file${context/id}/${context/name}"
  i18n:translate="">download</a>
 
+<p tal:condition="python:context.id and not utils.sb_is_view_ok(context)">
+   Files classified as spam are not available for download by
+   unathorized users. If you think the file has been misclassified,
+   please login and click on the button for reclassification.
+</p>
+
+
+     <form method="POST" onSubmit="return submit_once()"
+       enctype="multipart/form-data"
+       tal:attributes="action context/designator"
+       tal:condition="python:utils.sb_may_classify(context)">
+ 
+      <input type="hidden" name="@action" value="spambayes_classify">
+      <input type="submit" name="trainspam" value="Mark as SPAM" i18n:attributes="value">
+      <input type="submit" name="trainham" value="Mark as HAM (not SPAM)" i18n:attributes="value">
+     </form>
+
 <tal:block tal:condition="context/id" tal:replace="structure context/history" />
 
 </td>

Modified: tracker/instances/python-dev/html/issue.item.html
==============================================================================
--- tracker/instances/python-dev/html/issue.item.html	(original)
+++ tracker/instances/python-dev/html/issue.item.html	Fri Jul 27 18:26:26 2007
@@ -243,7 +243,12 @@
   </tr>
   <tr>
    <td colspan="4" class="content">
-    <pre tal:content="structure msg/content/hyperlinked">content</pre>
+    <p class="error-message"
+       tal:condition="python:utils.sb_is_spam(msg)">
+       Message has been classified as spam.
+    </p>
+    <pre tal:condition="python:utils.sb_is_view_ok(msg)"
+         tal:content="structure msg/content/hyperlinked">content</pre>
    </td>
   </tr>
  </tal:block>

Modified: tracker/instances/python-dev/html/msg.item.html
==============================================================================
--- tracker/instances/python-dev/html/msg.item.html	(original)
+++ tracker/instances/python-dev/html/msg.item.html	Fri Jul 27 18:26:26 2007
@@ -47,12 +47,50 @@
  <th i18n:translate="">Date</th>
  <td tal:content="context/date"></td>
 </tr>
+
+ <tr>
+  <th i18n:translate="">SpamBayes Score</th>
+  <td tal:content="structure context/spambayes_score/plain"></td>
+ </tr>
+
+ <tr>
+  <th i18n:translate="">Marked as misclassified</th>
+  <td tal:content="structure context/spambayes_misclassified/plain"></td>
+ </tr>
+
 </table>
 
+<p tal:condition="python:utils.sb_is_spam(context)" class="error-message">
+   Message has been classified as spam</p>
+
 <table class="messages">
- <tr><th colspan=2 class="header" i18n:translate="">Content</th></tr>
+
+ <tr>
+   <th class="header" i18n:translate="">Content</th>
+   <th class="header" tal:condition="python:utils.sb_may_classify(context)">
+     <form method="POST" onSubmit="return submit_once()"
+       enctype="multipart/form-data"
+       tal:attributes="action context/designator">
+ 
+      <input type="hidden" name="@action" value="spambayes_classify">
+      <input type="submit" name="trainspam" value="Mark as SPAM" i18n:attributes="value">
+      <input type="submit" name="trainham" value="Mark as HAM (not SPAM)" i18n:attributes="value">
+     </form>
+   </th>
+
+</tr>
+
  <tr>
-  <td class="content" colspan=2><pre tal:content="structure context/content/hyperlinked"></pre></td>
+  <td class="content" colspan=2
+      tal:condition="python:utils.sb_is_view_ok(context)"><pre
+      tal:content="structure context/content/hyperlinked"></pre></td>
+  <td class="content" colspan=2
+      tal:condition="python:not utils.sb_is_view_ok(context)">
+            Message has been classified as spam and is therefore not
+      available to unathorized users. If you think this is
+      incorrect, please login and report the message as being
+      misclassified. 
+  </td> 
  </tr>
 </table>
 

Modified: tracker/instances/python-dev/schema.py
==============================================================================
--- tracker/instances/python-dev/schema.py	(original)
+++ tracker/instances/python-dev/schema.py	Fri Jul 27 18:26:26 2007
@@ -97,10 +97,14 @@
                 summary=String(),
                 files=Multilink("file"),
                 messageid=String(),
-                inreplyto=String())
+                inreplyto=String(),
+                spambayes_score=Number(),
+                spambayes_misclassified=Boolean(),)
 
 file = FileClass(db, "file",
-                name=String())
+                name=String(),
+                spambayes_score=Number(),
+                spambayes_misclassified=Boolean(),)
 
 # IssueClass automatically gets these properties in addition to the Class ones:
 #   title = String()
@@ -141,12 +145,59 @@
 ##########################
 # User permissions
 ##########################
+
 for cl in ('issue_type', 'severity', 'component',
            'version', 'priority', 'status', 'resolution',
-           'issue', 'file', 'msg', 'keyword'):
+           'issue', 'keyword'):
     db.security.addPermissionToRole('User', 'View', cl)
     db.security.addPermissionToRole('Anonymous', 'View', cl)
 
+class may_view_spam:
+    def __init__(self, klassname):
+        self.klassname = klassname
+
+    def __call__(self, db, userid, itemid):
+        cutoff_score = float(db.config.detectors['SPAMBAYES_SPAM_CUTOFF'])
+        klass = db.getclass(self.klassname)
+
+        try:
+            score = klass.get(itemid, 'spambayes_score')
+        except KeyError:
+            return True
+
+        if score > cutoff_score:
+            roles = set(db.user.get(userid, "roles").lower().split(","))
+            allowed = set(db.config.detectors['SPAMBAYES_MAY_VIEW_SPAM'].lower().split(","))
+            return bool(roles.intersection(allowed))
+
+        return True
+
+for cl in ('file', 'msg'):
+    p = db.security.addPermission(name='View', klass=cl,
+                                  description="allowed to see metadata of file object regardless of spam status",
+                                  properties=('creation', 'activity',
+                                              'creator', 'actor',
+                                              'name', 'spambayes_score',
+                                              'spambayes_misclassified',
+                                              'author', 'recipients',
+                                              'date', 'files', 'messageid',
+                                              'inreplyto', 'type',
+                                              ))
+
+    db.security.addPermissionToRole('Anonymous', p)
+    db.security.addPermissionToRole('User', p)    
+    
+    
+    spamcheck = db.security.addPermission(name='View', klass=cl,
+                                          description="allowed to see metadata of file object regardless of spam status",
+                                          properties=('content', 'summary'),
+                                          check=may_view_spam(cl))
+    
+    db.security.addPermissionToRole('User', spamcheck)    
+    db.security.addPermissionToRole('Anonymous', spamcheck)
+
+    
+
 for cl in 'file', 'msg':
     db.security.addPermissionToRole('User', 'Create', cl)
 
@@ -264,7 +315,7 @@
 
 # Allow anonymous users access to view issues (and the related, linked
 # information)
-for cl in 'issue', 'file', 'msg', 'severity', 'status', 'resolution':
+for cl in 'issue', 'severity', 'status', 'resolution':
     db.security.addPermissionToRole('Anonymous', 'View', cl)
 
 # [OPTIONAL]


More information about the Python-checkins mailing list