[Spambayes-checkins] spambayes/spambayes ImapUI.py, 1.16, 1.17 Options.py, 1.65, 1.66 ProxyUI.py, 1.18, 1.19 UserInterface.py, 1.17, 1.18

Tony Meyer anadelonbrin at users.sourceforge.net
Mon Aug 25 22:30:43 EDT 2003


Update of /cvsroot/spambayes/spambayes/spambayes
In directory sc8-pr-cvs1:/tmp/cvs-serv2659/spambayes

Modified Files:
	ImapUI.py Options.py ProxyUI.py UserInterface.py 
Log Message:
Implement #791254 Advanceconfiguration panel

Add an advanced configuration page to the pop3proxy and imapfilter web
interfaces.

Also fix the restoring of defaults, which had been broken for quite a long time.

Index: ImapUI.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/ImapUI.py,v
retrieving revision 1.16
retrieving revision 1.17
diff -C2 -d -r1.16 -r1.17
*** ImapUI.py	19 Aug 2003 08:52:04 -0000	1.16
--- ImapUI.py	26 Aug 2003 04:30:41 -0000	1.17
***************
*** 70,78 ****
      ('pop3proxy',             'notate_to'),
      ('pop3proxy',             'notate_subject'),
-     ('Headers',               'include_score'),
-     ('Headers',               'include_thermostat'),
-     ('Headers',               'include_evidence'),
-     ('pop3proxy',             'add_mailid_to'),
-     ('pop3proxy',             'strip_incoming_mailids'),
      ('Storage Options',       None),
      ('Storage',               'persistent_storage_file'),
--- 70,73 ----
***************
*** 81,85 ****
      ('Categorization',        'ham_cutoff'),
      ('Categorization',        'spam_cutoff'),
!     ('Classifier',            'experimental_ham_spam_imbalance_adjustment'),
  )
  
--- 76,106 ----
      ('Categorization',        'ham_cutoff'),
      ('Categorization',        'spam_cutoff'),
! )
! 
! # Like the above, but hese are the options that will be offered on the
! # advanced configuration page.
! adv_map = (
!     ('Statistics Options',  None),
!     ('Classifier',          'experimental_ham_spam_imbalance_adjustment'),
!     ('Classifier',          'max_discriminators'),
!     ('Classifier',          'minimum_prob_strength'),
!     ('Classifier',          'unknown_word_prob'),
!     ('Classifier',          'unknown_word_strength'),
!     ('Header Options',      None),
!     ('Headers',             'include_score'),
!     ('Headers',             'header_score_digits'),
!     ('Headers',             'header_score_logarithm'),
!     ('Headers',             'include_thermostat'),
!     ('Headers',             'include_evidence'),
!     ('Headers',             'clue_mailheader_cutoff'),
!     ('Storage Options',     None),
!     ('Storage',             'persistent_use_database'),
!     ('Tokenising Options',  None),
!     ('Tokenizer',           'extract_dow'),
!     ('Tokenizer',           'generate_time_buckets'),
!     ('Tokenizer',           'mine_received_headers'),
!     ('Tokenizer',           'replace_nonascii_chars'),
!     ('Tokenizer',           'summarize_email_prefixes'),
!     ('Tokenizer',           'summarize_email_suffixes'),
  )
  
***************
*** 95,99 ****
              parm_list.remove(("imap", "use_ssl"))
              parm_map = tuple(parm_list)
!         UserInterface.UserInterface.__init__(self, cls, parm_map)
          classifier = cls
          self.imap = imap
--- 116,120 ----
              parm_list.remove(("imap", "use_ssl"))
              parm_map = tuple(parm_list)
!         UserInterface.UserInterface.__init__(self, cls, parm_map, adv_map)
          classifier = cls
          self.imap = imap

Index: Options.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/Options.py,v
retrieving revision 1.65
retrieving revision 1.66
diff -C2 -d -r1.65 -r1.66
*** Options.py	26 Aug 2003 01:52:25 -0000	1.65
--- Options.py	26 Aug 2003 04:30:41 -0000	1.66
***************
*** 150,156 ****
      ("mine_received_headers", "Mine the received headers", False,
       """A lot of clues can be gotten from IP addresses and names in
!      Received: headers.  Again this can give spectacular results for bogus
!      reasons if your test corpora are from different sources. Else set this
!      to true.""",
       BOOLEAN, RESTORE),
  
--- 150,155 ----
      ("mine_received_headers", "Mine the received headers", False,
       """A lot of clues can be gotten from IP addresses and names in
!      Received: headers.  This can give spectacular results for bogus
!      reasons if your corpora are from different sources.""",
       BOOLEAN, RESTORE),
  
***************
*** 194,198 ****
       BOOLEAN, RESTORE),
  
!     ("replace_nonascii_chars", "", False,
       """If true, replace high-bit characters (ord(c) >= 128) and control
       characters with question marks.  This allows non-ASCII character
--- 193,197 ----
       BOOLEAN, RESTORE),
  
!     ("replace_nonascii_chars", "Replace non-ascii characters", False,
       """If true, replace high-bit characters (ord(c) >= 128) and control
       characters with question marks.  This allows non-ASCII character
***************
*** 393,399 ****
    "Classifier": (
      ("max_discriminators", "Maximum number of extreme words", 150,
!      """The maximum number of extreme words to look at in a msg, where
!      "extreme" means with spamprob farthest away from 0.5.  150 appears to
!      work well across all corpora tested.""",
       INTEGER, RESTORE),
  
--- 392,398 ----
    "Classifier": (
      ("max_discriminators", "Maximum number of extreme words", 150,
!      """The maximum number of extreme words to look at in a message, where
!      "extreme" means with spam probability farthest away from 0.5.  150
!      appears to work well across all corpora tested.""",
       INTEGER, RESTORE),
  
***************
*** 403,417 ****
       has never been seen before.  Nobody has reported an improvement via
       moving it away from 1/2, although Tim has measured a mean spamprob of
!      a bit over 0.5 (0.51-0.55) in 3 well-trained classifiers.
  
!      uknown_word_strength adjusts how much weight to give the prior
       assumption relative to the probabilities estimated by counting.  At 0,
       the counting estimates are believed 100%, even to the extent of
       assigning certainty (0 or 1) to a word that has appeared in only ham
!      or only spam.  This is a disaster.""",
!      REAL, RESTORE),
! 
!     ("unknown_word_strength", "Unknown word strength", 0.45,
!      """As unknown_word_strength tends toward infintity, all probabilities
       tend toward unknown_word_prob.  All reports were that a value near 0.4
       worked best, so this does not seem to be corpus-dependent.""",
--- 402,416 ----
       has never been seen before.  Nobody has reported an improvement via
       moving it away from 1/2, although Tim has measured a mean spamprob of
!      a bit over 0.5 (0.51-0.55) in 3 well-trained classifiers.""",
!      REAL, RESTORE),
  
!     ("unknown_word_strength", "Unknown word strength", 0.45,
!      """This adjusts how much weight to give the prior
       assumption relative to the probabilities estimated by counting.  At 0,
       the counting estimates are believed 100%, even to the extent of
       assigning certainty (0 or 1) to a word that has appeared in only ham
!      or only spam.  This is a disaster.
!      
!      As unknown_word_strength tends toward infintity, all probabilities
       tend toward unknown_word_prob.  All reports were that a value near 0.4
       worked best, so this does not seem to be corpus-dependent.""",
***************
*** 468,472 ****
  
      ("experimental_ham_spam_imbalance_adjustment", "Compensate for unequal numbers of spam and ham", False,
!      """If your training database has significantly (3 times) more ham than
       spam, or vice versa, you may start seeing an increase in incorrect
       classifications (messages put in the wrong category, not just marked
--- 467,471 ----
  
      ("experimental_ham_spam_imbalance_adjustment", "Compensate for unequal numbers of spam and ham", False,
!      """If your training database has significantly more ham than
       spam, or vice versa, you may start seeing an increase in incorrect
       classifications (messages put in the wrong category, not just marked
***************
*** 508,515 ****
    # loaded by the appropriate application only.
    "Storage" : (
!     ("persistent_use_database", "", True,
!      """hammiefilter can use either a database (quick to score one message)
       or a pickle (quick to train on huge amounts of messages). Set this to
!      True to use a database by default.""",
       BOOLEAN, RESTORE),
  
--- 507,514 ----
    # loaded by the appropriate application only.
    "Storage" : (
!     ("persistent_use_database", "Use database for storage", True,
!      """SpamBayes can use either a database (quick to score one message)
       or a pickle (quick to train on huge amounts of messages). Set this to
!      use a database by default.""",
       BOOLEAN, RESTORE),
  
***************
*** 579,583 ****
  
      ("header_score_logarithm", "Augment score with logarithm", False,
!      """Set this to "True", to augment scores of 1.00 or 0.00 by a
       logarithmic "one-ness" or "zero-ness" score (basically it shows the
       "number of zeros" or "number of nines" next to the score value).""",
--- 578,582 ----
  
      ("header_score_logarithm", "Augment score with logarithm", False,
!      """Set this option to augment scores of 1.00 or 0.00 by a
       logarithmic "one-ness" or "zero-ness" score (basically it shows the
       "number of zeros" or "number of nines" next to the score value).""",
***************
*** 674,694 ****
  
      ("cache_use_gzip", "Use gzip", False,
!      """""",
       BOOLEAN, RESTORE),
  
      ("cache_expiry_days", "Days before cached messages expire", 7,
!      """""",
       INTEGER, RESTORE),
  
      ("spam_cache", "Spam cache directory", "pop3proxy-spam-cache",
!      """""",
       PATH, DO_NOT_RESTORE),
  
      ("ham_cache", "Ham cache directory", "pop3proxy-ham-cache",
!      """""",
       PATH, DO_NOT_RESTORE),
  
      ("unknown_cache", "Unknown cache directory", "pop3proxy-unknown-cache",
!      """""",
       PATH, DO_NOT_RESTORE),
  
--- 673,699 ----
  
      ("cache_use_gzip", "Use gzip", False,
!      """Use gzip to compress the cache.""",
       BOOLEAN, RESTORE),
  
      ("cache_expiry_days", "Days before cached messages expire", 7,
!      """Messages will be expired from the cache after this many days.
!      After this time, you will no longer be able to train on these messages
!      (note this does not effect the copy of the message that you have in
!      your mail client).""",
       INTEGER, RESTORE),
  
      ("spam_cache", "Spam cache directory", "pop3proxy-spam-cache",
!      """Directory that SpamBayes should cache spam in.  If this does
!      not exist, it will be created.""",
       PATH, DO_NOT_RESTORE),
  
      ("ham_cache", "Ham cache directory", "pop3proxy-ham-cache",
!      """Directory that SpamBayes should cache ham in.  If this does
!      not exist, it will be created.""",
       PATH, DO_NOT_RESTORE),
  
      ("unknown_cache", "Unknown cache directory", "pop3proxy-unknown-cache",
!      """Directory that SpamBayes should cache unclassified messages in.
!      If this does not exist, it will be created.""",
       PATH, DO_NOT_RESTORE),
  

Index: ProxyUI.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/ProxyUI.py,v
retrieving revision 1.18
retrieving revision 1.19
diff -C2 -d -r1.18 -r1.19
*** ProxyUI.py	26 Aug 2003 00:24:16 -0000	1.18
--- ProxyUI.py	26 Aug 2003 04:30:41 -0000	1.19
***************
*** 83,89 ****
      ('pop3proxy',           'remote_servers'),
      ('pop3proxy',           'listen_ports'),
-     ('pop3proxy',           'cache_messages'),
-     ('pop3proxy',           'no_cache_bulk_ham'),
-     ('pop3proxy',           'no_cache_large_messages'),
      ('html_ui',             'display_to'),
      ('html_ui',             'allow_remote_connections'),
--- 83,86 ----
***************
*** 91,97 ****
      ('pop3proxy',           'notate_to'),
      ('pop3proxy',           'notate_subject'),
-     ('Headers',             'include_score'),
-     ('Headers',             'include_thermostat'),
-     ('Headers',             'include_evidence'),
      ('SMTP Proxy Options',  None),
      ('smtpproxy',           'remote_servers'),
--- 88,91 ----
***************
*** 99,109 ****
--- 93,138 ----
      ('smtpproxy',           'ham_address'),
      ('smtpproxy',           'spam_address'),
+     ('smtpproxy',           'use_cached_message'),
      ('Storage Options',  None),
      ('Storage',             'persistent_storage_file'),
      ('Storage',             'messageinfo_storage_file'),
+     ('pop3proxy',           'cache_messages'),
+     ('pop3proxy',           'no_cache_bulk_ham'),
+     ('pop3proxy',           'no_cache_large_messages'),
      ('Statistics Options',  None),
      ('Categorization',      'ham_cutoff'),
      ('Categorization',      'spam_cutoff'),
+ )
+ 
+ # Like the above, but hese are the options that will be offered on the
+ # advanced configuration page.
+ adv_map = (
+     ('Statistics Options',  None),
      ('Classifier',          'experimental_ham_spam_imbalance_adjustment'),
+     ('Classifier',          'max_discriminators'),
+     ('Classifier',          'minimum_prob_strength'),
+     ('Classifier',          'unknown_word_prob'),
+     ('Classifier',          'unknown_word_strength'),
+     ('Header Options',      None),
+     ('Headers',             'include_score'),
+     ('Headers',             'header_score_digits'),
+     ('Headers',             'header_score_logarithm'),
+     ('Headers',             'include_thermostat'),
+     ('Headers',             'include_evidence'),
+     ('Headers',             'clue_mailheader_cutoff'),
+     ('Storage Options',     None),
+     ('Storage',             'persistent_use_database'),
+     ('pop3proxy',           'cache_expiry_days'),
+     ('pop3proxy',           'cache_use_gzip'),
+     ('pop3proxy',           'ham_cache'),
+     ('pop3proxy',           'spam_cache'),
+     ('pop3proxy',           'unknown_cache'),
+     ('Tokenising Options',  None),
+     ('Tokenizer',           'extract_dow'),
+     ('Tokenizer',           'generate_time_buckets'),
+     ('Tokenizer',           'mine_received_headers'),
+     ('Tokenizer',           'replace_nonascii_chars'),
+     ('Tokenizer',           'summarize_email_prefixes'),
+     ('Tokenizer',           'summarize_email_suffixes'),
  )
  
***************
*** 114,118 ****
          global state
          UserInterface.UserInterface.__init__(self, proxy_state.bayes,
!                                              parm_ini_map)
          state = proxy_state
          self.state_recreator = state_recreator # ugly
--- 143,147 ----
          global state
          UserInterface.UserInterface.__init__(self, proxy_state.bayes,
!                                              parm_ini_map, adv_map)
          state = proxy_state
          self.state_recreator = state_recreator # ugly
***************
*** 485,493 ****
          state = self.state_recreator()
  
!     def verifyInput(self, parms):
          '''Check that the given input is valid.'''
          # Most of the work here is done by the parent class, but
          # we have a few extra checks
!         errmsg = UserInterface.UserInterface.verifyInput(self, parms)
  
          # check for equal number of pop3servers and ports
--- 514,525 ----
          state = self.state_recreator()
  
!     def verifyInput(self, parms, pmap):
          '''Check that the given input is valid.'''
          # Most of the work here is done by the parent class, but
          # we have a few extra checks
!         errmsg = UserInterface.UserInterface.verifyInput(self, parms, pmap)
! 
!         if pmap == adv_map:
!           return errmsg
  
          # check for equal number of pop3servers and ports

Index: UserInterface.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/spambayes/UserInterface.py,v
retrieving revision 1.17
retrieving revision 1.18
diff -C2 -d -r1.17 -r1.18
*** UserInterface.py	20 Aug 2003 08:33:25 -0000	1.17
--- UserInterface.py	26 Aug 2003 04:30:41 -0000	1.18
***************
*** 21,24 ****
--- 21,25 ----
    onSave - save the database and possibly shutdown
    onConfig - present the appropriate configuration page
+   onAdvancedconfig - present the appropriate advanced configuration page
  
  To Do:
***************
*** 80,84 ****
  import Dibbler
  import tokenizer
! from Options import options, optionsPathname, defaults
  
  IMAGES = ('helmet', 'status', 'config',
--- 81,85 ----
  import Dibbler
  import tokenizer
! from Options import options, optionsPathname, defaults, OptionsClass
  
  IMAGES = ('helmet', 'status', 'config',
***************
*** 226,230 ****
      """Serves the HTML user interface."""
  
!     def __init__(self, bayes, config_parms=()):
          """Load up the necessary resources: ui.html and helmet.gif."""
          global classifier
--- 227,231 ----
      """Serves the HTML user interface."""
  
!     def __init__(self, bayes, config_parms=(), adv_parms=()):
          """Load up the necessary resources: ui.html and helmet.gif."""
          global classifier
***************
*** 232,235 ****
--- 233,237 ----
          classifier = bayes
          self.parm_ini_map = config_parms
+         self.advanced_options_map = adv_parms
  
      def onClassify(self, file, text, which):
***************
*** 439,443 ****
--- 441,463 ----
          pass
  
+     def onAdvancedconfig(self):
+         html = self._buildConfigPage(self.advanced_options_map)
+         html.title = 'Home > Advanced Configuration'
+         html.pagename = '> Advanced Configuration'
+         html.adv_button.name.value = "Back to basic configuration"
+         html.adv_button.action = "config"
+         html.config_submit.value = "Save advanced options"
+         html.restore.value = "Restore advanced options defaults"
+         self.writeOKHeaders('text/html')
+         self.write(html)
+ 
      def onConfig(self):
+         html = self._buildConfigPage(self.parm_ini_map)
+         html.title = 'Home > Configure'
+         html.pagename = '> Configure'
+         self.writeOKHeaders('text/html')
+         self.write(html)
+ 
+     def _buildConfigPage(self, parm_map):
          # Start with an empty config form then add the sections.
          html = self._getHTMLClone()
***************
*** 452,459 ****
  
          # Loop though the sections.
!         for sect, opt in self.parm_ini_map:
              # We need a string to use as the html key that we can change to
              # and from the sect, opt pair.  We like irony, so we use '_' as
!             # the delimiter <wink>
              if opt is None:
                  if configTable is not None and section is not None:
--- 472,479 ----
  
          # Loop though the sections.
!         for sect, opt in parm_map:
              # We need a string to use as the html key that we can change to
              # and from the sect, opt pair.  We like irony, so we use '_' as
!             # the delimiter <wink>.
              if opt is None:
                  if configTable is not None and section is not None:
***************
*** 560,575 ****
              section.boxContent = configTable
              html.configFormContent += section
!         html.title = 'Home &gt; Configure'
!         html.pagename = '&gt; Configure'
!         self.writeOKHeaders('text/html')
!         self.write(html)
  
      def onChangeopts(self, **parms):
          if parms.has_key("how"):
              del parms["how"]
          html = self._getHTMLClone()
          html.shutdownTableCell = "&nbsp;"
          html.mainContent = self.html.headedBox.clone()
!         errmsg = self.verifyInput(parms)
  
          if errmsg != '':
--- 580,596 ----
              section.boxContent = configTable
              html.configFormContent += section
!         return html
  
      def onChangeopts(self, **parms):
          if parms.has_key("how"):
+             if parms["how"] == "Save advanced options":
+                 pmap = self.advanced_options_map
+             else:
+                 pmap = self.parm_ini_map
              del parms["how"]
          html = self._getHTMLClone()
          html.shutdownTableCell = "&nbsp;"
          html.mainContent = self.html.headedBox.clone()
!         errmsg = self.verifyInput(parms, pmap)
  
          if errmsg != '':
***************
*** 584,588 ****
          for name, value in parms.items():
              sect, opt = name.split('_', 1)
!             if (sect, opt) in self.parm_ini_map:
                  options.set(sect, opt, value)
              # If a section name has an underscore in it (like html_ui)
--- 605,609 ----
          for name, value in parms.items():
              sect, opt = name.split('_', 1)
!             if (sect, opt) in pmap:
                  options.set(sect, opt, value)
              # If a section name has an underscore in it (like html_ui)
***************
*** 605,609 ****
  
      def onRestoredefaults(self, how):
!         self.restoreConfigDefaults()
          self.reReadOptions()
  
--- 626,633 ----
  
      def onRestoredefaults(self, how):
!         if how == "Restore advanced options defaults":
!             self.restoreConfigDefaults(self.advanced_options_map)
!         else:
!             self.restoreConfigDefaults(self.parm_ini_map)
          self.reReadOptions()
  
***************
*** 619,623 ****
          self.write(html)
  
!     def verifyInput(self, parms):
          '''Check that the given input is valid.'''
          # Most of the work here is done by the options class, but
--- 643,647 ----
          self.write(html)
  
!     def verifyInput(self, parms, pmap):
          '''Check that the given input is valid.'''
          # Most of the work here is done by the options class, but
***************
*** 636,640 ****
                  del parms[name]
  
!         for sect, opt in self.parm_ini_map:
              if opt is None:
                  nice_section_name = sect
--- 660,664 ----
                  del parms[name]
  
!         for sect, opt in pmap:
              if opt is None:
                  nice_section_name = sect
***************
*** 672,691 ****
          return errmsg
  
!     def restoreConfigDefaults(self):
!         # note that the behaviour of this function has subtly changed
          # previously options were removed from the config file, now the
          # config file is updated to match the defaults
!         c = ConfigParser()
!         d = StringIO(defaults)
!         c.readfp(d)
!         del d
  
          # Only restore the settings that appear on the form.
!         for section, option in self.parm_ini_map:
              if option is not None:
                  if not options.no_restore(section, option):
!                     options.set(section, option, c.get(section,option))
  
!         op = open(optionsPathname, "r")
!         options.update_file(op)
!         op.close()
--- 696,711 ----
          return errmsg
  
!     def restoreConfigDefaults(self, parm_map):
!         # note that the behaviour of this function has subtly changed:
          # previously options were removed from the config file, now the
          # config file is updated to match the defaults
!         d = OptionsClass()
!         d.load_defaults(defaults)
  
          # Only restore the settings that appear on the form.
!         for section, option in parm_map:
              if option is not None:
                  if not options.no_restore(section, option):
!                     options.set(section, option, d.get(section,option))
  
!         options.update_file(optionsPathname)





More information about the Spambayes-checkins mailing list