check-in. At the moment problem with doctests for README.txt in cybertools/agent and cybertools/agent/crawl.Outlook.txt

Problem Nr. 1 in /agent/README.txt:
    master.config
Expected:
    controller.names = ['base.sample']
    logger.name = 'default'
    logger.standard = 30
    scheduler.name = 'sample'
Got:
    logger.name = 'default'
    logger.standard = 30
    scheduler.name = 'sample'


Problem Nr. 2 in /agent/crawl/Outlook.txt:
self.agent.setupAgents(self, [spec])
File "[..]\cybertools\agent\base\agent.py", line 85, in setupAgents
        agent.name = spec.name
    AttributeError: 'NoneType' object has no attribute 'name'


git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@2499 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
scrat 2008-04-06 17:28:30 +00:00
parent 770a983a7f
commit 5aee688a12
7 changed files with 276 additions and 5 deletions

View file

@ -1,4 +1,4 @@
================================================
================================================
Agents for Job Execution and Communication Tasks
================================================

51
agent/crawl/Outlook.txt Normal file
View file

@ -0,0 +1,51 @@
================================================
Agents for Job Execution and Communication Tasks
================================================
>>> from cybertools.agent.base.agent import Master
>>> config = '''
... controller(names=['core.sample'])
... scheduler(name='core')
... logger(name='default', standard=30)
... '''
>>> master = Master(config)
>>> master.setup()
OutlookCrawler
==============
The agent uses Twisted's cooperative multitasking model.
OutlookCrawler is derived from MailCrawler. The OutlookCrawler returns a deferred
which itself holds a list of MailResource Objects.
Returns a deferred that must be supplied with a callback method (and in
most cases also an errback method).
The TestCase here is using subsidiary methods which replace calls to the "real Outlook
dlls".
>>> controller = master.controllers[0]
>>> controller.createAgent('crawl.outlook', 'sample02')
In the next step we request the start of a job, again via the controller.
>>> controller.enterJob('outlook', 'sample02')
The job is not executed immediately - we have to hand over control to
the twisted reactor first.
>>> from cybertools.agent.crawl.outlook import OutlookCrawler
>>> from cybertools.agent.crawl.outlookstub import OutlookCrawlerStub
>>> OutlookCrawler.findOutlook = OutlookCrawlerStub.findOutlook
>>> OutlookCrawler = OutlookCrawlerStub
>>> from cybertools.agent.tests import tester
>>> tester.iterate()
Returning reference to Outlook Application
Retrieving Parameters
Crawling Folders
loading mails from folder
Job 00001 completed; result: [];

View file

@ -27,6 +27,7 @@ from zope.interface import implements
from cybertools.agent.base.agent import Master
from cybertools.agent.core.agent import QueueableAgent
from cybertools.agent.interfaces import ICrawler
from cybertools.agent.interfaces import IResource
from cybertools.agent.components import agents
from twisted.internet.defer import succeed
@ -50,5 +51,23 @@ class SampleCrawler(Crawler):
d = succeed([])
return d
class Resource(object):
implements(IResource)
data = None
path = ""
application = ""
metadata = None
def __init__(self, data, path="", application="", metadata=None):
self.data = data
self.path = path
self.application = application
self.metadata = metadata
agents.register(SampleCrawler, Master, name='crawl.sample')

View file

@ -24,7 +24,8 @@ $Id$
from zope.interface import implements
from cybertools.agent.agent import Agent
from cybertools.agent.base.agent import Agent, Master
from cybertools.agent.crawl.base import Resource
from cybertools.agent.crawl.base import Crawler
from cybertools.agent.components import agents
from twisted.internet.defer import succeed
@ -41,6 +42,9 @@ class MailCrawler(Crawler):
# d = self.crawlFolders()
d = succeed([])
return d
def fetchCriteria(self):
pass
def crawlFolders(self):
pass
@ -48,11 +52,15 @@ class MailCrawler(Crawler):
def loadMailsFromFolder(self, folder):
pass
def createResource(self, mail):
resource = mail
# do the real processing
def createResource(self, mail, path="", application="", metadata=None):
resource = MailResource(mail, path, application, metadata)
self.result.append(resource)
def login(self):
pass
class MailResource(Resource):
pass
agents.register(MailCrawler, Master, name='crawl.mail')

172
agent/crawl/outlook.py Normal file
View file

@ -0,0 +1,172 @@
#
# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Outlook Crawler Class.
$Id: mail.py 2493 2008-04-03 11:17:37Z helmutm $
"""
import re
from zope.interface import implements
from twisted.internet import defer
import win32com.client
import ctypes
import win32api, win32process, win32con
from cybertools.agent.base.agent import Agent, Master
from cybertools.agent.crawl.mail import MailCrawler
from cybertools.agent.crawl.mail import MailResource
from cybertools.agent.components import agents
# some constants
COMMASPACE = ', '
class OutlookCrawler(MailCrawler):
keys = ""
inbox = ""
subfolders = ""
pattern = ""
def collect(self, filter=None):
self.d = defer.Deferred()
self.oOutlookApp = None
if self.findOutlook():
self.fetchCriteria()
self.d.addCallback(self.crawlFolders)
else:
pass
#self.d.addErrback([])
return d
def fetchCriteria(self):
criteria = self.params
self.keys = criteria.get('keys')
self.inbox = criteria.get('inbox') #boolean
self.subfolders = criteria.get('subfolders') #boolean
self.pattern = criteria.get('pattern')
if self.pattern != '':
self.pattern = re.compile(criteria.get('pattern') or '.*')
def crawlFolders(self):
onMAPI = self.oOutlookApp.GetNamespace("MAPI")
ofInbox = \
onMAPI.GetDefaultFolder(win32com.client.constants.olFolderInbox)
# fetch mails from inbox
if self.inbox:
self.loadMailsFromFolder(ofInbox)
# fetch mails of inbox subfolders
if self.subfolders and self.pattern is None:
lInboxSubfolders = getattr(ofInbox, 'Folders')
for of in range(lInboxSubfolders.__len__()):
# get a MAPI-subfolder object and load its emails
self.loadMailsFromFolder(lInboxSubfolders.Item(of + 1))
elif self.subfolders and self.pattern:
lInboxSubfolders = getattr(ofInbox, 'Folders')
for of in range(lInboxSubfolders.__len__()):
# get specified MAPI-subfolder object and load its emails
if self.pattern.match(getattr(lInboxSubfolders.Item(of + 1), 'Name')):
self.loadMailsFromFolder(lInboxSubfolders.Item(of + 1))
return self.result
def loadMailsFromFolder(self, folder):
# get items of the folder
folderItems = getattr(folder, 'Items')
for item in range(len(folderItems)):
mail = folderItems.Item(item+1)
if mail.Class == win32com.client.constants.olMail:
if self.keys is None:
self.keys = []
for key in mail._prop_map_get_:
if isinstance(getattr(mail, key), (int, str, unicode)):
self.keys.append(key)
record = {}
for key in self.keys:
record[key] = getattr(mail, key)
# Create the mime email object
msg = self.createEmailMime(record)
# Create a resource and append it to the result list
self.createResource(msg, folder, "Microsoft Office Outlook")
def login(self):
pass
def handleOutlookDialog(self):
"""
This function handles the outlook dialog, which appears if someone
tries to access to MS Outlook.
"""
hwnd = None
while True:
hwnd = ctypes.windll.user32.FindWindowExA(None, hwnd, None, None)
if hwnd == None:
break
else:
val = u"\0" * 1024
ctypes.windll.user32.GetWindowTextW(hwnd, val, len(val))
val = val.replace(u"\000", u"")
if val and repr(val) == "u'Microsoft Office Outlook'":
print repr(val)
# get the Main Control
form = findTopWindow(wantedText='Microsoft Office Outlook')
controls = findControls(form)
# get the check box
checkBox = findControl(form, wantedText='Zugriff')
setCheckBox(checkBox, 1)
# get the combo box
comboBox = findControl(form, wantedClass='ComboBox')
items = getComboboxItems(comboBox)
selectComboboxItem(comboBox, items[3])#'10 Minuten'
# finally get the button and click it
button = findControl(form, wantedText = 'Erteilen')
clickButton(button)
break
def findOutlook(self):
outlookFound = 0
try:
self.oOutlookApp = \
win32com.client.gencache.EnsureDispatch("Outlook.Application")
outlookFound = 1
except:
pass
return outlookFound
def createEmailMime(self, emails):
# Create the container (outer) email message.
msg = MIMEMultipart()
msg['Subject'] = emails['Subject'].encode('utf-8')
if emails.has_key('SenderEmailAddress'):
sender = str(emails['SenderEmailAddress'].encode('utf-8'))
else:
sender = str(emails['SenderName'].encode('utf-8'))
msg['From'] = sender
recipients = []
if emails.has_key('Recipients'):
for rec in range(emails['Recipients'].__len__()):
recipients.append(getattr(emails['Recipients'].Item(rec+1), 'Address'))
msg['To'] = COMMASPACE.join(recipients)
else:
recipients.append(emails['To'])
msg['To'] = COMMASPACE.join(recipients)
msg.preamble = emails['Body'].encode('utf-8')
return msg
agents.register(OutlookCrawler, Master, name='crawl.outlook')

View file

@ -0,0 +1,20 @@
from cybertools.agent.crawl.mail import MailCrawler
class OutlookCrawlerStub(MailCrawler):
def __init__(self):
pass
def findOutlook(self):
print "Returning reference to Outlook Application"
def fetchCriteria(self):
print "Retrieving Parameters"
def crawlFolders(self):
print "Crawling Folders"
self.loadMailsFromFolder()
def loadMailsFromFolder(self):
print "loading mails from folder"
self.createResource("SampleMail", "OutlookStubFolder", "OutlookStub")

View file

@ -43,6 +43,7 @@ def test_suite():
unittest.makeSuite(Test),
DocFileSuite('README.txt', optionflags=flags),
DocFileSuite('crawl/README.txt', optionflags=flags),
DocFileSuite('crawl/Outlook.txt', optionflags=flags),
))
return testSuite