extend base.Transporter class to full-blown HTTP transporter, thus eliminating the httpput module

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1901 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2007-08-10 09:55:45 +00:00
parent f0676ad208
commit f4449162a1
8 changed files with 64 additions and 112 deletions

View file

@ -73,6 +73,8 @@ class FileResource(object):
self.path = path self.path = path
self.metadata = metadata self.metadata = metadata
application = 'filesystem'
@property @property
def data(self): def data(self):
return open(self.path, 'r') return open(self.path, 'r')

View file

@ -27,7 +27,7 @@ transferred.
>>> from loops.agent.testing import transport >>> from loops.agent.testing import transport
>>> transporter = transport.Transporter(agent) >>> transporter = transport.Transporter(agent)
>>> transportJob = transporter.jobFactory(transporter) >>> transportJob = transporter.createJob()
>>> crawlJob.successors.append(transportJob) >>> crawlJob.successors.append(transportJob)
We are now ready to schedule the job and let the reactor execute it. We are now ready to schedule the job and let the reactor execute it.

View file

@ -30,7 +30,9 @@ class IAgent(Interface):
and transfers these to its server. and transfers these to its server.
""" """
scheduler = Attribute('IScheduler instance') scheduler = Attribute('IScheduler instance.')
transporter = Attribute('The transporter to be used for transferring '
'objects.')
class IScheduler(Interface): class IScheduler(Interface):
@ -111,13 +113,17 @@ class IResource(Interface):
data = Attribute("A string, file, or similar representation of the " data = Attribute("A string, file, or similar representation of the "
"resource's content") "resource's content")
path = Attribute('A filesystem path or some other information '
'uniquely identifying the resource on the client '
'machine for the current user.')
application = Attribute('The name of the application that provided '
'the resource.')
metadata = Attribute('Information describing this resource; ' metadata = Attribute('Information describing this resource; '
'should be an IMetadataSet object.') 'should be an IMetadataSet object.')
class IMetadataSet(Interface): class IMetadataSet(Interface):
""" Metadata associated with a resource; sort of a mapping. """ Metadata associated with a resource; a mapping.
""" """
def asXML(): def asXML():
@ -148,9 +154,13 @@ class ITransporter(Interface):
userName = Attribute('User name for logging in to the server.') userName = Attribute('User name for logging in to the server.')
password = Attribute('Password for logging in to the server.') password = Attribute('Password for logging in to the server.')
def createJob():
""" Return a transport job for this transporter.
"""
def transfer(resource): def transfer(resource):
""" Transfer the resource (an object providing IResource) """ Transfer the resource (an object providing IResource)
to the server. to the server and return a Deferred.
""" """
@ -185,6 +195,8 @@ class IConfigurator(Interface):
""" """
# future extensions
class IPackageManager(Interface): class IPackageManager(Interface):
""" Allows to install, update, or remove software packages (plugins, """ Allows to install, update, or remove software packages (plugins,
typically as Python eggs) from a server. typically as Python eggs) from a server.

View file

@ -26,7 +26,7 @@ from twisted.internet import reactor
from twisted.internet.defer import Deferred from twisted.internet.defer import Deferred
from zope.interface import implements from zope.interface import implements
from loops.agent.interfaces import ICrawlingJob, IResource from loops.agent.interfaces import IResource
from loops.agent.crawl.base import CrawlingJob as BaseCrawlingJob from loops.agent.crawl.base import CrawlingJob as BaseCrawlingJob
@ -47,4 +47,6 @@ class DummyResource(object):
implements(IResource) implements(IResource)
data = 'Dummy resource data for testing purposes.' data = 'Dummy resource data for testing purposes.'
path = '/dummy/data'
application = 'dummy'
metadata = None metadata = None

View file

@ -27,28 +27,11 @@ from twisted.internet.defer import Deferred
from zope.interface import implements from zope.interface import implements
from loops.agent.interfaces import ITransportJob, ITransporter from loops.agent.interfaces import ITransportJob, ITransporter
from loops.agent.schedule import Job
from loops.agent.transport.base import TransportJob as BaseJob
from loops.agent.transport.base import Transporter as BaseTransporter from loops.agent.transport.base import Transporter as BaseTransporter
class TransportJob(BaseJob):
def execute(self):
kw = self.params
result = kw.get('result')
if result is None:
print 'No data available.'
else:
for resource in result:
d = self.transporter.transfer(resource)
return Deferred()
class Transporter(BaseTransporter): class Transporter(BaseTransporter):
jobFactory = TransportJob
def transfer(self, resource): def transfer(self, resource):
data = resource.data data = resource.data
if type(data) is file: if type(data) is file:

View file

@ -23,7 +23,7 @@ $Id$
""" """
from twisted.internet import reactor from twisted.internet import reactor
from twisted.internet.defer import Deferred from twisted.internet.defer import Deferred, DeferredList, fail
from zope.interface import implements from zope.interface import implements
from loops.agent.interfaces import ITransporter, ITransportJob from loops.agent.interfaces import ITransporter, ITransportJob
@ -38,6 +38,22 @@ class TransportJob(Job):
super(TransportJob, self).__init__() super(TransportJob, self).__init__()
self.transporter = transporter self.transporter = transporter
def execute(self):
result = self.params.get('result')
if result is None:
return fail('No data available.')
transfers = []
for resource in result:
d = self.transporter.transfer(resource)
transfers.append(d)
d.addCallback(self.logTransfer)
return DeferredList(transfers)
def logTransfer(self, result):
# TODO: logging
# self.transporter.agent.logger.log(...)
pass
class Transporter(object): class Transporter(object):
@ -45,21 +61,37 @@ class Transporter(object):
jobFactory = TransportJob jobFactory = TransportJob
serverURL = None
method = None
machineName = None
userName = None
password = None
def __init__(self, agent): def __init__(self, agent):
self.agent = agent self.agent = agent
def createJob(self):
return self.jobFactory(self)
def transfer(self, resource): def transfer(self, resource):
""" Should be overridden by subclass - this is just an example
how it may look like.
"""
data = resource.data data = resource.data
if type(data) is file: if type(data) is file:
text = data.read() text = resource.read()
data.close() resource.close()
else: else:
text = data text = data
path = resource.path
app = resource.application
deferreds = []
metadata = resource.metadata metadata = resource.metadata
d = Deferred() # or call something that returns a deferred if metadata is not None:
return d url = self.makePath('meta', app, path)
deferreds.append(
getPage(url, method=self.method, postData=metadata.asXML()))
url = self.makePath('data', app, path)
deferreds.append(getPage(url, method=self.method, postData=text))
return DeferredList(deferreds)
def makePath(self, infoType, app, path):
return '/'.join((self.serverURL, infoType, app, path))

View file

@ -1,79 +0,0 @@
#
# Copyright (c) 2007 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
#
"""
Transferring of data/files to the server.
$Id$
"""
from twisted.internet import reactor
from twisted.web.client import getPage
from zope.interface import implements
from loops.agent.interfaces import ITransporter, ITransportJob
from loops.agent.schedule import Job
class TransportJob(Job):
implements(ITransportJob)
def __init__(self, transporter):
super(TransportJob, self).__init__()
self.transporter = transporter
def execute(self):
result = kw.get('result')
if result is None:
print 'No data available.'
else:
for resource, metadata in result:
d = self.transporter.transfer(resource.data, metadata)
return Deferred()
class Transporter(object):
implements(ITransporter)
jobFactory = TransportJob
serverURL = None
method = None
machineName = None
userName = None
password = None
def __init__(self, agent):
self.agent = agent
conf = agent.config
# TODO: get settings from conf
def transfer(self, resource):
data = resource.data
if type(data) is file:
text = resource.read()
resource.close()
else:
text = data
metadata = resource.metadata
url = self.serverURL + self.makePath(metadata)
d = getPage(url, method='PUT', postData=text)
return d

View file

@ -7,9 +7,9 @@ loops.agent.transport.httpput - The HTTP PUT Transport
>>> from time import time >>> from time import time
>>> from loops.agent.core import Agent >>> from loops.agent.core import Agent
>>> from loops.agent.transport.httpput import Transporter, TransportJob >>> from loops.agent.transport.base import Transporter
>>> agent = Agent() >>> agent = Agent()
>>> transporter = Transporter(agent) >>> transporter = Transporter(agent)
>>> job = TransportJob(transporter) >>> job = transporter.createJob()