home *** CD-ROM | disk | FTP | other *** search
/ MacAddict 108 / MacAddict108.iso / Software / Internet & Communication / JunkMatcher 1.5.5.dmg / JunkMatcher.app / Contents / Resources / Engine / Pattern.py < prev    next >
Encoding:
Python Source  |  2005-06-01  |  6.0 KB  |  157 lines

  1. #
  2. #  Patterns.py
  3. #  JunkMatcher
  4. #
  5. #  Created by Benjamin Han on 2/1/05.
  6. #  Copyright (c) 2005 Benjamin Han. All rights reserved.
  7. #
  8.  
  9. # This program is free software; you can redistribute it and/or
  10. # modify it under the terms of the GNU General Public License
  11. # as published by the Free Software Foundation; either version 2
  12. # of the License, or (at your option) any later version.
  13.  
  14. # This program is distributed in the hope that it will be useful,
  15. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. # GNU General Public License for more details.
  18.  
  19. # You should have received a copy of the GNU General Public License
  20. # along with this program; if not, write to the Free Software
  21. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  22.  
  23. #!/usr/bin/env python
  24.  
  25. from time import time as now
  26.  
  27. from consts import *
  28. from GlobalObjects import *
  29. from TestRecord import *
  30.  
  31. VIEW_SUBJECT     = 'subject'
  32. VIEW_SENDER      = 'sender'
  33. VIEW_HEADERS     = 'headers'
  34. VIEW_BODY        = 'body'
  35. VIEW_FILENAMES   = 'filenames'
  36. VIEW_CHARSETS    = 'charsets'
  37. VIEW_RENDERING   = 'rendering'
  38.  
  39.  
  40. class Pattern (object):
  41.     """A pattern test to some aspect (view) of an email message
  42.        ----------------------------------------------------------
  43.        name: the name of this pattern test (can contain spaces, in Unicode)
  44.        testRecords: a dict of (view, TestRecord), where view is one of the VIEW_* defined above
  45.        origPattern: the original pattern, possibly with meta pattern names used in it (Unicode)
  46.        pattern: a regexp object compiled from an instantiated origPattern
  47.        isManaged: True if this pattern is managed
  48.        recipientPattern: the regex pattern for the recipient; only when this matches is this
  49.          pattern in effect
  50.        encodingPattern: the regex pattern for the encoding; only when this matches is this
  51.          pattern in effect
  52.  
  53.        * the following attributes are only set and used in the GUI
  54.        
  55.        viewsInUse: a set of views that are currently in use
  56.        metaPatterns: a set of names of meta patterns used
  57.     """
  58.     # improving performance by not having __dict__
  59.     __slots__ = ('_patTuple', 'name', 'testRecords', 'origPattern', 'pattern', 'isManaged',
  60.                  'recipientPattern', 'encodingPattern', 'viewsInUse', 'metaPatterns')
  61.             
  62.     def __init__ (self, name, testRecords, pattern, isManaged = False,
  63.                   recipientPattern = None, encodingPattern = None):
  64.         self.name = name
  65.         self.testRecords = testRecords  # thread-safe
  66.         self.origPattern = pattern
  67.         self.isManaged = isManaged
  68.         self._patTuple = (recipientPattern, encodingPattern)
  69.  
  70.     def __getattr__ (self, name):
  71.         # lazy initialization
  72.         if name == 'pattern':
  73.             self.pattern = re.compile(globalObjects.metaPatterns.instantiate(self.origPattern))
  74.             return self.pattern
  75.  
  76.         elif name == 'recipientPattern':
  77.             p = self._patTuple[0]
  78.             if p:
  79.                 self.recipientPattern = re.compile(p)
  80.             else:
  81.                 self.recipientPattern = None
  82.             return self.recipientPattern
  83.  
  84.         elif name == 'encodingPattern':
  85.             p = self._patTuple[1]
  86.             if p:
  87.                 self.encodingPattern = re.compile(p)
  88.             else:
  89.                 self.encodingPattern = None
  90.             return self.encodingPattern
  91.         
  92.         else:
  93.             raise AttributeError('No attribute %s in this %s instance.' % (name, self.__class__.__name__))
  94.  
  95.     def changePattern (self, newPattern):
  96.         del self.pattern
  97.         self.origPattern = newPattern
  98.         for testRecord in self.testRecords.values():
  99.             testRecord.reset()
  100.  
  101.     def changeRecipientPattern (self, newPattern):
  102.         # CAUTION: self._patTuple is left unchanged
  103.         self.recipientPattern = re.compile(newPattern)
  104.         
  105.     def changeEncodingPattern (self, newPattern):
  106.         # CAUTION: self._patTuple is left unchanged
  107.         self.encodingPattern = re.compile(newPattern)
  108.  
  109.     def run (self, msg, view):
  110.         """Run the pattern test over 'msg' for 'view'; returns tuple (bool, float);
  111.         where the bool is a matching object if a match is found, None otherwise;
  112.         the float is the CPU time spent (usec)."""
  113.         
  114.         #assert msg.m is not None    # must be a well-formed email!
  115.  
  116.         start = now()
  117.         isPositive = self.pattern.search(getattr(msg, view))
  118.         finish = now()
  119.  
  120.         return isPositive, (finish - start) * 1000000.0
  121.  
  122.     def runWithText (self, txt):
  123.         """Run the instantiated pattern over a given text; returns a list of text spans (i.e., tuples
  124.         (start, end) ); pattern statistics is not updated."""
  125.         return map(lambda mo: mo.span(0), self.pattern.finditer(txt))
  126.  
  127.     def getAttribute_ (self, name):
  128.         """This is basically for Obj-C side of PyObjC bridge so we can get at the instance variables"""
  129.         return getattr(self, name)
  130.  
  131.     def setAttribute_withValue_ (self, name, value):
  132.         """This is basically for Obj-C side of PyObjC bridge so we can set an instance variable"""
  133.         setattr(self, name, value)
  134.  
  135.  
  136. if __name__ == '__main__':
  137.     import sys
  138.  
  139.     if len(sys.argv) < 4:
  140.         print 'Usage: ./Pattern.py <filename> <pattern> <view>'
  141.         print '   * filename is the name of the file containing email raw source;'
  142.         print '   * pattern is a regex pattern surrounded by double quotes.'
  143.         print '   * view = one of subject, sender, headers, body, filenames, charsets and rednering.'
  144.         sys.exit(1)
  145.  
  146.     from Message import *
  147.  
  148.     view = sys.argv[3]    
  149.     aPattern = Pattern(u'Test pattern', {view:TestRecord()}, sys.argv[2])
  150.     msg = Message(open(sys.argv[1]).read())
  151.  
  152.     mo, cpuTime = aPattern.run(msg, view)
  153.     if mo:
  154.         print encodeText('* Pattern "%s" matches "%s": %f usec(s)' % (aPattern.name,
  155.                                                                       mo.group(0),
  156.                                                                       cpuTime))
  157.