Update of /cvsroot/spambayes/spambayes/spambayes
In directory sc8-pr-cvs8.sourceforge.net:/tmp/cvs-serv7512/spambayes

Modified Files:
        Options.py ProxyUI.py UserInterface.py dnscache.py storage.py 
Added Files:
        CorePlugin.py CoreUI.py XMLRPCPlugin.py 
Log Message:

Merge CORESVR branch to HEAD.  This adds a new app, scripts/core_server.py
and attendant bits, such as an XML-RPC plugin.  The web interface is
straight from the POP3 proxy server.






Index: Options.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/Options.py,v
retrieving revision 1.141
retrieving revision 1.142
diff -C2 -d -r1.141 -r1.142
*** Options.py  26 Mar 2007 07:57:13 -0000      1.141
--- Options.py  10 Jun 2007 15:27:36 -0000      1.142
***************
*** 653,656 ****
--- 653,671 ----
       PATH, DO_NOT_RESTORE),
  
+     ("core_spam_cache", _("Spam cache directory"), "core-spam-cache",
+      _("""Directory that SpamBayes should cache spam in.  If this does
+      not exist, it will be created."""),
+      PATH, DO_NOT_RESTORE),
+ 
+     ("core_ham_cache", _("Ham cache directory"), "core-ham-cache",
+      _("""Directory that SpamBayes should cache ham in.  If this does
+      not exist, it will be created."""),
+      PATH, DO_NOT_RESTORE),
+ 
+     ("core_unknown_cache", _("Unknown cache directory"), "core-unknown-cache",
+      _("""Directory that SpamBayes should cache unclassified messages in.
+      If this does not exist, it will be created."""),
+      PATH, DO_NOT_RESTORE),
+ 
      ("cache_messages", _("Cache messages"), True,
       _("""You can disable the pop3proxy caching of messages.  This
***************
*** 1280,1283 ****
--- 1295,1309 ----
       r"\w\w(?:_\w\w)?", RESTORE),
    ),
+   "Plugin": (
+     ("xmlrpc_path", _("XML-RPC path"), "/sbrpc",
+      _("""The path to respond to."""),
+      r"[\w]+", RESTORE),
+     ("xmlrpc_host", _("XML-RPC host"), "localhost",
+      _("""The host to listen on."""),
+      SERVER, RESTORE),
+     ("xmlrpc_port", _("XML-RPC port"), 8001,
+      _("""The port to listen on."""),
+      r"[\d]+", RESTORE),
+     ),
  }
  

Index: ProxyUI.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/ProxyUI.py,v
retrieving revision 1.64
retrieving revision 1.65
diff -C2 -d -r1.64 -r1.65
*** ProxyUI.py  28 Nov 2005 10:54:18 -0000      1.64
--- ProxyUI.py  10 Jun 2007 15:27:36 -0000      1.65
***************
*** 54,58 ****
      True, False = 1, 0
  
- import re
  import cgi
  import time
--- 54,57 ----
***************
*** 72,81 ****
          from spambayes.compatsets import Set
  
- import tokenizer
  import UserInterface
  from spambayes.Options import options, _
- from email.Iterators import typed_subpart_iterator
  
! global state
  
  # These are the options that will be offered on the configuration page.
--- 71,78 ----
          from spambayes.compatsets import Set
  
  import UserInterface
  from spambayes.Options import options, _
  
! state = None
  
  # These are the options that will be offered on the configuration page.
***************
*** 111,115 ****
  )
  
! # Like the above, but hese are the options that will be offered on the
  # advanced configuration page.
  adv_map = (
--- 108,112 ----
  )
  
! # Like the above, but these are the options that will be offered on the
  # advanced configuration page.
  adv_map = (
***************
*** 174,178 ****
          self.state_recreator = state_recreator # ugly
          self.app_for_version = "SpamBayes Proxy"
-         self.previous_sort = None
          if not proxy_state.can_stop:
              self.html._readonly = False
--- 171,174 ----
***************
*** 221,241 ****
          self.write(_("<p>OK. Return <a href='home'>Home</a>.</p>"))
  
-     def _keyToTimestamp(self, key):
-         """Given a message key (as seen in a Corpus), returns the timestamp
-         for that message.  This is the time that the message was received,
-         not the Date header."""
-         return long(key[:10])
- 
-     def _getTimeRange(self, timestamp):
-         """Given a unix timestamp, returns a 3-tuple: the start timestamp
-         of the given day, the end timestamp of the given day, and the
-         formatted date of the given day."""
-         this = time.localtime(timestamp)
-         start = (this[0], this[1], this[2], 0, 0, 0, this[6], this[7], 
this[8])
-         end = time.localtime(time.mktime(start) + 36*60*60)
-         end = (end[0], end[1], end[2], 0, 0, 0, end[6], end[7], end[8])
-         date = time.strftime("%A, %B %d, %Y", start)
-         return time.mktime(start), time.mktime(end), date
- 
      def _buildReviewKeys(self, timestamp):
          """Builds an ordered list of untrained message keys, ready for output
--- 217,220 ----
***************
*** 278,382 ****
          return keys, date, prior, start, end
  
-     def _sortMessages(self, messages, sort_order, reverse=False):
-         """Sorts the message by the appropriate attribute.  If this was the
-         previous sort order, then reverse it."""
-         if sort_order is None or sort_order == "received":
-             # Default sorting, which is in reverse order of appearance.
-             # This is complicated because the 'received' info is the key.
-             messages.sort()
-             if self.previous_sort == sort_order:
-                 messages.reverse()
-                 self.previous_sort = None
-             else:
-                 self.previous_sort = 'received'
-             return messages
-         tmplist = [(getattr(x[1], sort_order), x) for x in messages]
-         tmplist.sort()
-         if reverse:
-             tmplist.reverse()
-         return [x for (key, x) in tmplist]
- 
-     def _appendMessages(self, table, keyedMessageInfo, label, sort_order,
-                         reverse=False):
-         """Appends the rows of a table of messages to 'table'."""
-         stripe = 0
- 
-         keyedMessageInfo = self._sortMessages(keyedMessageInfo, sort_order,
-                                               reverse)
-         nrows = options["html_ui", "rows_per_section"]
-         for key, messageInfo in keyedMessageInfo[:nrows]:
-             unused, unused, messageInfo.received = \
-                     self._getTimeRange(self._keyToTimestamp(key))
-             row = self.html.reviewRow.clone()
-             try:
-                 score = messageInfo.score
-             except ValueError:
-                 score = None
-             if label == _('Spam'):
-                 if score is not None \
-                    and score > options["html_ui", "spam_discard_level"]:
-                     r_att = getattr(row, 'discard')
-                 else:
-                     r_att = getattr(row, options["html_ui",
-                                            "default_spam_action"])
-             elif label == _('Ham'):
-                 if score is not None \
-                    and score < options["html_ui", "ham_discard_level"]:
-                     r_att = getattr(row, 'discard')
-                 else:
-                     r_att = getattr(row, options["html_ui",
-                                            "default_ham_action"])
-             else:
-                 r_att = getattr(row, options["html_ui",
-                                            "default_unsure_action"])
-             setattr(r_att, "checked", 1)
- 
-             row.optionalHeadersValues = '' # make way for real list
-             for header in options["html_ui", "display_headers"]:
-                 header = header.lower()
-                 text = getattr(messageInfo, "%sHeader" % (header,))
-                 if header == "subject":
-                     # Subject is special, because it links to the body.
-                     # If the user doesn't display the subject, then there
-                     # is no link to the body.
-                     h = self.html.reviewRow.linkedHeaderValue.clone()
-                     h.text.title = messageInfo.bodySummary
-                     h.text.href = "view?key=%s&corpus=%s" % (key, label)
-                 else:
-                     h = self.html.reviewRow.headerValue.clone()
-                 h.text = text
-                 row.optionalHeadersValues += h
- 
-             # Apart from any message headers, we may also wish to display
-             # the message score, and the time the message was received.
-             if options["html_ui", "display_score"]:
-                 if isinstance(messageInfo.score, types.StringTypes):
-                     # Presumably either "?" or "Err".
-                     row.score_ = messageInfo.score
-                 else:
-                     row.score_ = "%.2f%%" % (messageInfo.score,)
-             else:
-                 del row.score_
-             if options["html_ui", "display_received_time"]:
-                 row.received_ = messageInfo.received
-             else:
-                 del row.received_
- 
-             # Many characters can't go in the URL or they cause problems
-             # (&, ;, ?, etc).  So we use the hex values for them all.
-             subj_list = []
-             for c in messageInfo.subjectHeader:
-                 subj_list.append("%%%s" % (hex(ord(c))[2:],))
-             subj = "".join(subj_list)
-             row.classify.href="showclues?key=%s&subject=%s" % (key, subj)
-             row.tokens.href="showclues?key=%s&subject=%s&tokens=1" % (key, 
subj)
-             setattr(row, 'class', ['stripe_on', 'stripe_off'][stripe]) # Grr!
-             setattr(row, 'onMouseOut',
-                     ["this.className='stripe_on';",
-                      "this.className='stripe_off';"][stripe])
-             row = str(row).replace('TYPE', label).replace('KEY', key)
-             table += row
-             stripe = stripe ^ 1
- 
      def onReview(self, **params):
          """Present a list of message for (re)training."""
--- 257,260 ----
***************
*** 619,626 ****
                      sh.optionalHeaders = ''
                      h = self.html.headerHeader.clone()
!                     for header in options["html_ui", "display_headers"]:
                          h.headerLink.href = 'review?sort=%sHeader' % \
!                                             (header.lower(),)
!                         h.headerName = header.title()
                          sh.optionalHeaders += h
                      if not options["html_ui", "display_score"]:
--- 497,504 ----
                      sh.optionalHeaders = ''
                      h = self.html.headerHeader.clone()
!                     for disp_header in options["html_ui", "display_headers"]:
                          h.headerLink.href = 'review?sort=%sHeader' % \
!                                             (disp_header.lower(),)
!                         h.headerName = disp_header.title()
                          sh.optionalHeaders += h
                      if not options["html_ui", "display_score"]:
***************
*** 649,661 ****
          self._writePostamble(help_topic="review")
  
-     def _contains(self, a, b, ignore_case=False):
-         """Return true if substring b is part of string a."""
-         assert isinstance(a, types.StringTypes)
-         assert isinstance(b, types.StringTypes)
-         if ignore_case:
-             a = a.lower()
-             b = b.lower()
-         return a.find(b) >= 0
- 
      def onView(self, key, corpus):
          """View a message - linked from the Review page."""
--- 527,530 ----
***************
*** 702,769 ****
          self._writePostamble()
  
-     def _makeMessageInfo(self, message):
-         """Given an email.Message, return an object with subjectHeader,
-         bodySummary and other header (as needed) attributes.  These objects
-         are passed into appendMessages by onReview - passing email.Message
-         objects directly uses too much memory.
-         """
-         # Remove notations before displaying - see:
-         # [ 848365 ] Remove subject annotations from message review page
-         message.delNotations()
-         subjectHeader = message["Subject"] or "(none)"
-         headers = {"subject" : subjectHeader}
-         for header in options["html_ui", "display_headers"]:
-             headers[header.lower()] = (message[header] or "(none)")
-         score = message[options["Headers", "score_header_name"]]
-         if score:
-             # the score might have the log info at the end
-             op = score.find('(')
-             if op >= 0:
-                 score = score[:op]
-             try:
-                 score = float(score) * 100
-             except ValueError:
-                 # Hmm.  The score header should only contain a floating
-                 # point number.  What's going on here, then?
-                 score = "Err"  # Let the user know something is wrong.
-         else:
-             # If the lookup fails, this means that the "include_score"
-             # option isn't activated. We have the choice here to either
-             # calculate it now, which is pretty inefficient, since we have
-             # already done so, or to admit that we don't know what it is.
-             # We'll go with the latter.
-             score = "?"
-         try:
-             part = typed_subpart_iterator(message, 'text', 'plain').next()
-             text = part.get_payload()
-         except StopIteration:
-             try:
-                 part = typed_subpart_iterator(message, 'text', 'html').next()
-                 text = part.get_payload()
-                 text, unused = tokenizer.crack_html_style(text)
-                 text, unused = tokenizer.crack_html_comment(text)
-                 text = tokenizer.html_re.sub(' ', text)
-                 text = _('(this message only has an HTML body)\n') + text
-             except StopIteration:
-                 text = _('(this message has no text body)')
-         if type(text) == type([]):  # gotta be a 'right' way to do this
-             text = _("(this message is a digest of %s messages)") % 
(len(text))
-         elif text is None:
-             text = _("(this message has no body)")
-         else:
-             text = text.replace('&nbsp;', ' ')      # Else they'll be quoted
-             text = re.sub(r'(\s)\s+', r'\1', text)  # Eg. multiple blank lines
-             text = text.strip()
- 
-         class _MessageInfo:
-             pass
-         messageInfo = _MessageInfo()
-         for headerName, headerValue in headers.items():
-             headerValue = self._trimHeader(headerValue, 45, True)
-             setattr(messageInfo, "%sHeader" % (headerName,), headerValue)
-         messageInfo.score = score
-         messageInfo.bodySummary = self._trimHeader(text, 200)
-         return messageInfo
- 
      def close_database(self):
          state.close()
--- 571,574 ----

Index: UserInterface.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/UserInterface.py,v
retrieving revision 1.61
retrieving revision 1.62
diff -C2 -d -r1.61 -r1.62
*** UserInterface.py    28 Nov 2005 10:53:12 -0000      1.61
--- UserInterface.py    10 Jun 2007 15:27:36 -0000      1.62
***************
*** 80,83 ****
--- 80,84 ----
  import types
  import StringIO
+ from email.Iterators import typed_subpart_iterator
  
  import oe_mailbox
***************
*** 277,280 ****
--- 278,282 ----
          self.stats = stats
          self.app_for_version = None # subclasses must fill this in
+         self.previous_sort = None
  
      def onClassify(self, file, text, which):
***************
*** 820,823 ****
--- 822,827 ----
              elif parms["how"] == _("Save experimental options"):
                  pmap = experimental_ini_map
+             elif parms["how"] == _("Save plugin options"):
+                 pmap = self.plugin_ini_map
              del parms["how"]
          html = self._getHTMLClone()
***************
*** 1251,1252 ****
--- 1255,1448 ----
                  lines.append(''.join(cur_line))
          return lines
+ 
+     def _keyToTimestamp(self, key):
+         """Given a message key (as seen in a Corpus), returns the timestamp
+         for that message.  This is the time that the message was received,
+         not the Date header."""
+         return long(key[:10])
+ 
+     def _getTimeRange(self, timestamp):
+         """Given a unix timestamp, returns a 3-tuple: the start timestamp
+         of the given day, the end timestamp of the given day, and the
+         formatted date of the given day."""
+         this = time.localtime(timestamp)
+         start = (this[0], this[1], this[2], 0, 0, 0, this[6], this[7], 
this[8])
+         end = time.localtime(time.mktime(start) + 36*60*60)
+         end = (end[0], end[1], end[2], 0, 0, 0, end[6], end[7], end[8])
+         date = time.strftime("%A, %B %d, %Y", start)
+         return time.mktime(start), time.mktime(end), date
+ 
+     def _sortMessages(self, messages, sort_order, reverse=False):
+         """Sorts the message by the appropriate attribute.  If this was the
+         previous sort order, then reverse it."""
+         if sort_order is None or sort_order == "received":
+             # Default sorting, which is in reverse order of appearance.
+             # This is complicated because the 'received' info is the key.
+             messages.sort()
+             if self.previous_sort == sort_order:
+                 messages.reverse()
+                 self.previous_sort = None
+             else:
+                 self.previous_sort = 'received'
+             return messages
+         tmplist = [(getattr(x[1], sort_order), x) for x in messages]
+         tmplist.sort()
+         if reverse:
+             tmplist.reverse()
+         return [x for (key, x) in tmplist]
+ 
+     def _appendMessages(self, table, keyedMessageInfo, label, sort_order,
+                         reverse=False):
+         """Appends the rows of a table of messages to 'table'."""
+         stripe = 0
+ 
+         keyedMessageInfo = self._sortMessages(keyedMessageInfo, sort_order,
+                                               reverse)
+         nrows = options["html_ui", "rows_per_section"]
+         for key, messageInfo in keyedMessageInfo[:nrows]:
+             unused, unused, messageInfo.received = \
+                     self._getTimeRange(self._keyToTimestamp(key))
+             row = self.html.reviewRow.clone()
+             try:
+                 score = messageInfo.score
+             except ValueError:
+                 score = None
+             if label == _('Spam'):
+                 if score is not None \
+                    and score > options["html_ui", "spam_discard_level"]:
+                     r_att = getattr(row, 'discard')
+                 else:
+                     r_att = getattr(row, options["html_ui",
+                                            "default_spam_action"])
+             elif label == _('Ham'):
+                 if score is not None \
+                    and score < options["html_ui", "ham_discard_level"]:
+                     r_att = getattr(row, 'discard')
+                 else:
+                     r_att = getattr(row, options["html_ui",
+                                            "default_ham_action"])
+             else:
+                 r_att = getattr(row, options["html_ui",
+                                            "default_unsure_action"])
+             setattr(r_att, "checked", 1)
+ 
+             row.optionalHeadersValues = '' # make way for real list
+             for header in options["html_ui", "display_headers"]:
+                 header = header.lower()
+                 text = getattr(messageInfo, "%sHeader" % (header,))
+                 if header == "subject":
+                     # Subject is special, because it links to the body.
+                     # If the user doesn't display the subject, then there
+                     # is no link to the body.
+                     h = self.html.reviewRow.linkedHeaderValue.clone()
+                     h.text.title = messageInfo.bodySummary
+                     h.text.href = "view?key=%s&corpus=%s" % (key, label)
+                 else:
+                     h = self.html.reviewRow.headerValue.clone()
+                 h.text = text
+                 row.optionalHeadersValues += h
+ 
+             # Apart from any message headers, we may also wish to display
+             # the message score, and the time the message was received.
+             if options["html_ui", "display_score"]:
+                 if isinstance(messageInfo.score, types.StringTypes):
+                     # Presumably either "?" or "Err".
+                     row.score_ = messageInfo.score
+                 else:
+                     row.score_ = "%.2f%%" % (messageInfo.score,)
+             else:
+                 del row.score_
+             if options["html_ui", "display_received_time"]:
+                 row.received_ = messageInfo.received
+             else:
+                 del row.received_
+ 
+             # Many characters can't go in the URL or they cause problems
+             # (&, ;, ?, etc).  So we use the hex values for them all.
+             subj_list = []
+             for c in messageInfo.subjectHeader:
+                 subj_list.append("%%%s" % (hex(ord(c))[2:],))
+             subj = "".join(subj_list)
+             row.classify.href = "showclues?key=%s&subject=%s" % (key, subj)
+             row.tokens.href = ("showclues?key=%s&subject=%s&tokens=1" %
+                                (key, subj))
+             setattr(row, 'class', ['stripe_on', 'stripe_off'][stripe]) # Grr!
+             setattr(row, 'onMouseOut',
+                     ["this.className='stripe_on';",
+                      "this.className='stripe_off';"][stripe])
+             row = str(row).replace('TYPE', label).replace('KEY', key)
+             table += row
+             stripe = stripe ^ 1
+ 
+     def _contains(self, a, b, ignore_case=False):
+         """Return true if substring b is part of string a."""
+         assert isinstance(a, types.StringTypes)
+         assert isinstance(b, types.StringTypes)
+         if ignore_case:
+             a = a.lower()
+             b = b.lower()
+         return a.find(b) >= 0
+ 
+     def _makeMessageInfo(self, message):
+         """Given an email.Message, return an object with subjectHeader,
+         bodySummary and other header (as needed) attributes.  These objects
+         are passed into appendMessages by onReview - passing email.Message
+         objects directly uses too much memory.
+         """
+         # Remove notations before displaying - see:
+         # [ 848365 ] Remove subject annotations from message review page
+         message.delNotations()
+         subjectHeader = message["Subject"] or "(none)"
+         headers = {"subject" : subjectHeader}
+         for header in options["html_ui", "display_headers"]:
+             headers[header.lower()] = (message[header] or "(none)")
+         score = message[options["Headers", "score_header_name"]]
+         if score:
+             # the score might have the log info at the end
+             op = score.find('(')
+             if op >= 0:
+                 score = score[:op]
+             try:
+                 score = float(score) * 100
+             except ValueError:
+                 # Hmm.  The score header should only contain a floating
+                 # point number.  What's going on here, then?
+                 score = "Err"  # Let the user know something is wrong.
+         else:
+             # If the lookup fails, this means that the "include_score"
+             # option isn't activated. We have the choice here to either
+             # calculate it now, which is pretty inefficient, since we have
+             # already done so, or to admit that we don't know what it is.
+             # We'll go with the latter.
+             score = "?"
+         try:
+             part = typed_subpart_iterator(message, 'text', 'plain').next()
+             text = part.get_payload()
+         except StopIteration:
+             try:
+                 part = typed_subpart_iterator(message, 'text', 'html').next()
+                 text = part.get_payload()
+                 text, unused = tokenizer.crack_html_style(text)
+                 text, unused = tokenizer.crack_html_comment(text)
+                 text = tokenizer.html_re.sub(' ', text)
+                 text = _('(this message only has an HTML body)\n') + text
+             except StopIteration:
+                 text = _('(this message has no text body)')
+         if type(text) == type([]):  # gotta be a 'right' way to do this
+             text = _("(this message is a digest of %s messages)") % 
(len(text))
+         elif text is None:
+             text = _("(this message has no body)")
+         else:
+             text = text.replace('&nbsp;', ' ')      # Else they'll be quoted
+             text = re.sub(r'(\s)\s+', r'\1', text)  # Eg. multiple blank lines
+             text = text.strip()
+ 
+         class _MessageInfo:
+             pass
+         messageInfo = _MessageInfo()
+         for headerName, headerValue in headers.items():
+             headerValue = self._trimHeader(headerValue, 45, True)
+             setattr(messageInfo, "%sHeader" % (headerName,), headerValue)
+         messageInfo.score = score
+         messageInfo.bodySummary = self._trimHeader(text, 200)
+         return messageInfo

Index: dnscache.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/dnscache.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** dnscache.py 13 Aug 2006 02:05:43 -0000      1.3
--- dnscache.py 10 Jun 2007 15:27:36 -0000      1.4
***************
*** 23,29 ****
  
  kCheckForPruneEvery=20
! kMaxTTL=60 * 60 * 24 * 7 # One week
! kPruneThreshold=1500 # May go over slightly; numbers chosen at random
! kPruneDownTo=1000
  
  
--- 23,32 ----
  
  kCheckForPruneEvery=20
! kMaxTTL=60 * 60 * 24 * 7                # One week
! # Some servers always return a TTL of zero.  We'll hold onto data a bit
! # longer.
! kMinTTL=24 * 60 * 60 * 1                # one day
! kPruneThreshold=5000 # May go over slightly; numbers chosen at random
! kPruneDownTo=2500
  
  
***************
*** 89,97 ****
          self.dnsTimeout=10
  
-         # Some servers always return a TTL of zero.
-         # In those cases, turning this up a bit is
-         # probably reasonable.
-         self.minTTL=0
- 
          # end of user-settable attributes
  
--- 92,95 ----
***************
*** 160,164 ****
              c=self.caches[answer.qType]
              c[answer.question].remove(answer)
!             if len(c[answer.question])==0:
                  del c[answer.question]
  
--- 158,162 ----
              c=self.caches[answer.qType]
              c[answer.question].remove(answer)
!             if  not c[answer.question]:
                  del c[answer.question]
  
***************
*** 180,184 ****
              c=self.caches[answer.qType]
              c[answer.question].remove(answer)
!             if len(c[answer.question])==0:
                  del c[answer.question]
  
--- 178,182 ----
              c=self.caches[answer.qType]
              c[answer.question].remove(answer)
!             if not c[answer.question]:
                  del c[answer.question]
  
***************
*** 218,233 ****
              pass
          else:
!             assert len(answers)>0
!             ind=0
!             # No guarantee that expire has already been done
!             while ind<len(answers):
!                 thisAnswer=answers[ind]
!                 if thisAnswer.expiresAt<now:
!                     del answers[ind]
!                 else:
!                     thisAnswer.lastUsed=now
!                     ind+=1
  
!             if len(answers)==0:
                  del cacheToLookIn[question]
              else:
--- 216,233 ----
              pass
          else:
!             if answers:
!                 ind=0
!                 # No guarantee that expire has already been done
!                 while ind<len(answers):
!                     thisAnswer=answers[ind]
!                     if thisAnswer.expiresAt<now:
!                         del answers[ind]
!                     else:
!                         thisAnswer.lastUsed=now
!                         ind+=1
!             else:
!                 print >> sys.stderr, "lookup failure:", question
  
!             if not answers:
                  del cacheToLookIn[question]
              else:
***************
*** 250,275 ****
          except DNS.Base.DNSError,detail:
              if detail.args[0]<>"Timeout":
!                 print "Error, fixme",detail
!                 print "Question was",queryQuestion
!                 print "Origianal question was",question
!                 print "Type was",qType
              objs=[ 
lookupResult(qType,None,question,self.cacheErrorSecs+now,now) ]
              cacheToLookIn[question]=objs # Add to format for return?
              return self.formatForReturn(objs)
          except socket.gaierror,detail:
!             print "DNS connection failure:", self.queryObj.ns, detail
!             print "Defaults:", DNS.defaults
  
          objs=[]
          for answer in reply.answers:
              if answer["typename"]==qType:
!                 # PyDNS returns TTLs as longs but RFC 1035 says that the
!                 # TTL value is a signed 32-bit value and must be positive,
!                 # so it should be safe to coerce it to a Python integer.
!                 # And anyone who sets a time to live of more than 2^31-1
!                 # seconds (68 years and change) is drunk.
!                 # Arguably, I ought to impose a maximum rather than continuing
!                 # with longs (int(long) returns long in recent versions of 
Python).
!                 ttl=max(min(int(answer["ttl"]),kMaxTTL),self.minTTL)
                  # RFC 2308 says that you should cache an NXDOMAIN for the
                  # minimum of the minimum field of the SOA record and the TTL
--- 250,275 ----
          except DNS.Base.DNSError,detail:
              if detail.args[0]<>"Timeout":
!                 print >> sys.stderr, "Error, fixme", detail
!                 print >> sys.stderr, "Question was", queryQuestion
!                 print >> sys.stderr, "Original question was", question
!                 print >> sys.stderr, "Type was", qType
              objs=[ 
lookupResult(qType,None,question,self.cacheErrorSecs+now,now) ]
              cacheToLookIn[question]=objs # Add to format for return?
              return self.formatForReturn(objs)
          except socket.gaierror,detail:
!             print >> sys.stderr, "DNS connection failure:", self.queryObj.ns, 
detail
!             print >> sys.stderr, "Defaults:", DNS.defaults
  
          objs=[]
          for answer in reply.answers:
              if answer["typename"]==qType:
!                 # PyDNS returns TTLs as longs but RFC 1035 says that the TTL
!                 # value is a signed 32-bit value and must be positive, so it
!                 # should be safe to coerce it to a Python integer.  And
!                 # anyone who sets a time to live of more than 2^31-1 seconds
!                 # (68 years and change) is drunk.  Arguably, I ought to
!                 # impose a maximum rather than continuing with longs
!                 # (int(long) returns long in recent versions of Python).
!                 ttl=max(min(int(answer["ttl"]),kMaxTTL),kMinTTL)
                  # RFC 2308 says that you should cache an NXDOMAIN for the
                  # minimum of the minimum field of the SOA record and the TTL
***************
*** 279,288 ****
                      objs.append(item)
  
!         if len(objs)>0:
              cacheToLookIn[question]=objs
              return self.formatForReturn(objs)
  
          # Probably SERVFAIL or the like
!         if len(reply.authority)==0:
              objs=[ 
lookupResult(qType,None,question,self.cacheErrorSecs+now,now) ]
              cacheToLookIn[question]=objs
--- 279,288 ----
                      objs.append(item)
  
!         if objs:
              cacheToLookIn[question]=objs
              return self.formatForReturn(objs)
  
          # Probably SERVFAIL or the like
!         if not reply.authority:
              objs=[ 
lookupResult(qType,None,question,self.cacheErrorSecs+now,now) ]
              cacheToLookIn[question]=objs
***************
*** 319,329 ****
                   "www.seeputofor.com", "www.completegarbage.tv",
                   "www.tradelinkllc.com"]:
!         print "checking", host
          now=time.time()
          ips=c.lookup(host)
!         print ips,time.time()-now
          now=time.time()
          ips=c.lookup(host)
!         print ips,time.time()-now
  
          if ips:
--- 319,329 ----
                   "www.seeputofor.com", "www.completegarbage.tv",
                   "www.tradelinkllc.com"]:
!         print >> sys.stderr, "checking", host
          now=time.time()
          ips=c.lookup(host)
!         print >> sys.stderr, ips,time.time()-now
          now=time.time()
          ips=c.lookup(host)
!         print >> sys.stderr, ips,time.time()-now
  
          if ips:
***************
*** 331,340 ****
              now=time.time()
              name=c.lookup(ip,qType="PTR")
!             print name,time.time()-now
              now=time.time()
              name=c.lookup(ip,qType="PTR")
!             print name,time.time()-now
          else:
!             print "unknown"
  
      c.close()
--- 331,340 ----
              now=time.time()
              name=c.lookup(ip,qType="PTR")
!             print >> sys.stderr, name,time.time()-now
              now=time.time()
              name=c.lookup(ip,qType="PTR")
!             print >> sys.stderr, name,time.time()-now
          else:
!             print >> sys.stderr, "unknown"
  
      c.close()

Index: storage.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/storage.py,v
retrieving revision 1.63
retrieving revision 1.64
diff -C2 -d -r1.63 -r1.64
*** storage.py  11 May 2007 00:23:08 -0000      1.63
--- storage.py  10 Jun 2007 15:27:36 -0000      1.64
***************
*** 721,726 ****
          import ZODB
          from ZODB.FileStorage import FileStorage
!         self.storage = FileStorage(self.db_filename,
!                                    read_only=self.mode=='r')
  
      def load(self):
--- 721,731 ----
          import ZODB
          from ZODB.FileStorage import FileStorage
!         try:
!             self.storage = FileStorage(self.db_filename,
!                                        read_only=self.mode=='r')
!         except IOError, msg:
!             print >> sys.stderr, ("Could not create FileStorage from",
!                                   self.db_filename)
!             raise
  
      def load(self):
***************
*** 774,778 ****
          from ZODB.POSException import ReadOnlyError
  
!         assert self.closed == False, "Can't store a closed database"
  
          if options["globals", "verbose"]:
--- 779,783 ----
          from ZODB.POSException import ReadOnlyError
  
!         assert not self.closed, "Can't store a closed database"
  
          if options["globals", "verbose"]:

_______________________________________________
Spambayes-checkins mailing list
[email protected]
http://mail.python.org/mailman/listinfo/spambayes-checkins

Reply via email to