1
# -*- test-case-name: twisted.test.test_application -*-
3
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
4
# See LICENSE for details.
7
"""Backwards compatibility module
9
This module allows Applications to behave (partially) like old Application
10
objects, and converts olds Applications to new ones.
12
API Stability: unstable
14
Maintainer: U{Moshe Zadka<mailto:moshez@twistedmatrix.com>}
19
from zope.interface import implements
21
from twisted.python import components
22
from twisted.application import internet, service
24
class IOldApplication(components.Interface):
26
"""A subset of the interface old Application objects had implicitly
28
This interface defines a subset of the interface old Application
29
objects had, so that new objects can support it for compatibility
32
def listenWith(self, portType, *args, **kw):
33
"""Add a service that starts an instance of C{portType} listening.
35
@type portType: type which implements C{IListeningPort}
36
@param portType: The object given by C{portType(*args, **kw)}
37
will be started listening.
40
def listenTCP(self, port, factory, backlog=50, interface=''):
41
"""Add a service that connects a given protocol factory to the port.
43
@param port: a port number on which to listen
45
@param factory: a twisted.internet.protocol.ServerFactory instance
47
@param backlog: size of the listen queue
49
@param interface: the hostname to bind to, defaults to '' (all)
52
def listenUNIX(self, filename, factory, backlog=50, mode=0666):
53
"""Add a service that listens on a UNIX socket.
55
@param address: a path to a unix socket on the filesystem.
57
@param factory: a L{twisted.internet.protocol.Factory} instance.
59
@param backlog: number of connections to allow in backlog.
61
@param mode: mode to set on the unix socket.
64
def listenUDP(self, port, proto, interface='', maxPacketSize=8192):
65
"""Add a service that connects a given DatagramProtocol to the port.
68
def listenSSL(self, port, factory, ctxFactory, backlog=50, interface=''):
69
"""Add a service that connects a given protocol factory to the port.
71
The connection is a SSL one, using contexts created by the context
74
@param port: a port number on which to listen
76
@param factory: a L{twisted.internet.protocol.ServerFactory} instance
78
@param contextFactory: a L{twisted.internet.ssl.ContextFactory} instance
80
@param backlog: size of the listen queue
82
@param interface: the hostname to bind to, defaults to '' (all)
85
def connectWith(self, connectorType, *args, **kw):
86
"""Add a service that starts an instance of C{connectorType} connecting.
88
@type connectorType: type which implements C{IConnector}
89
@param connectorType: The object given by C{connectorType(*args, **kw)}
90
will be started connecting.
93
def connectUDP(self, remotehost, remoteport, protocol, localport=0,
94
interface='', maxPacketSize=8192):
95
"""Add a service that connects a L{ConnectedDatagramProtocol} to a port.
98
def connectTCP(self, host, port, factory, timeout=30, bindAddress=None):
99
"""Add a service that connects a TCP client.
101
@param host: a host name
103
@param port: a port number
105
@param factory: a twisted.internet.protocol.ClientFactory instance
107
@param timeout: number of seconds to wait before assuming the
108
connection has failed.
110
@param bindAddress: a (host, port) tuple of local address to bind
114
def connectSSL(self, host, port, factory, ctxFactory, timeout=30,
116
"""Add a service that connects a client Protocol to a remote SSL socket.
118
@param host: a host name
120
@param port: a port number
122
@param factory: a L{twisted.internet.protocol.ClientFactory} instance
124
@param contextFactory: a L{twisted.internet.ssl.ClientContextFactory}
126
@param timeout: number of seconds to wait before assuming the connection
129
@param bindAddress: a (host, port) tuple of local address to bind to, or
133
def connectUNIX(self, address, factory, timeout=30):
134
"""Add a service that connects a client protocol to a UNIX socket.
136
@param address: a path to a unix socket on the filesystem.
138
@param factory: a L{twisted.internet.protocol.ClientFactory} instance
140
@param timeout: number of seconds to wait before assuming the connection
144
def addService(self, service):
145
"""Add a service to this collection.
148
def getServiceNamed(self, name):
149
"""Retrieve the named service from this application.
151
Raise a KeyError if there is no such service name.
154
def removeService(self, service):
155
"""Remove a service from this collection."""
157
def unlistenWith(self, portType, *args, **kw):
158
"""Maybe remove a listener
160
This function is inherently unreliable, and may or may
161
not remove a service.
164
def unlistenTCP(self, port, interface=''):
165
"""Maybe remove a listener
167
This function is inherently unreliable, and may or may
168
not remove a service.
171
def unlistenUNIX(self, filename):
172
"""Maybe remove a listener
174
This function is inherently unreliable, and may or may
175
not remove a service.
178
def unlistenUDP(self, port, interface=''):
179
"""Maybe remove a listener
181
This function is inherently unreliable, and may or may
182
not remove a service.
185
def unlistenSSL(self, port, interface=''):
186
"""Maybe remove a listener
188
This function is inherently unreliable, and may or may
189
not remove a service.
194
"""Wrap a twisted.internet.app.ApplicationService in new service API."""
196
implements(service.IService)
200
def __init__(self, service):
201
self.service = service
202
self.name = service.serviceName
204
def setName(self, name):
207
def setServiceParent(self, parent):
208
self.service.setServiceParent(parent)
210
def disownServiceParent(self):
211
self.service.disownServiceParent()
213
def startService(self):
215
self.service.startService()
217
def stopService(self):
219
return self.service.stopService()
221
def privilegedStartService(self):
225
return self.service.serviceName
227
name = property(get_name)
230
def __cmp__(self, other):
231
return cmp(self.service, other)
234
return hash(self.service)
237
class _ServiceNetwork:
239
implements(IOldApplication)
241
def __init__(self, app):
242
self.app = service.IServiceCollection(app)
244
def listenWith(self, portType, *args, **kw):
245
s = internet.GenericServer(portType, *args, **kw)
247
s.setServiceParent(self.app)
249
def listenTCP(self, port, factory, backlog=50, interface=''):
250
s = internet.TCPServer(port, factory, backlog, interface)
252
s.setServiceParent(self.app)
254
def listenUNIX(self, filename, factory, backlog=50, mode=0666):
255
s = internet.UNIXServer(filename, factory, backlog, mode)
257
s.setServiceParent(self.app)
259
def listenUDP(self, port, proto, interface='', maxPacketSize=8192):
260
s = internet.UDPServer(port, proto, interface, maxPacketSize)
262
s.setServiceParent(self.app)
264
def listenSSL(self, port, factory, ctxFactory, backlog=50, interface=''):
265
s = internet.SSLServer(port, factory, ctxFactory, backlog, interface)
267
s.setServiceParent(self.app)
269
def connectWith(self, connectorType, *args, **kw):
270
s = internet.GenericClient(connectorType, *args, **kw)
271
s.setServiceParent(self.app)
273
def connectUDP(self, remotehost, remoteport, protocol, localport=0,
274
interface='', maxPacketSize=8192):
275
s = internet.UDPClient(remotehost, remoteport, protocol, localport,
276
interface, maxPacketSize)
277
s.setServiceParent(self.app)
279
def connectTCP(self, host, port, factory, timeout=30, bindAddress=None):
280
s = internet.TCPClient(host, port, factory, timeout, bindAddress)
281
s.setServiceParent(self.app)
283
def connectSSL(self, host, port, factory, ctxFactory, timeout=30,
285
s = internet.SSLClient(host, port, factory, ctxFactory, timeout,
287
s.setServiceParent(self.app)
289
def connectUNIX(self, address, factory, timeout=30):
290
s = internet.UNIXClient(address, factory, timeout)
291
s.setServiceParent(self.app)
293
def addService(self, service):
294
if 'twisted.internet.app' in sys.modules:
295
from twisted.internet import app as oldapp
296
if isinstance(service, oldapp.ApplicationService):
297
service = _NewService(service)
298
self.app.addService(service)
300
def removeService(self, service):
301
if 'twisted.internet.app' in sys.modules:
302
from twisted.internet import app as oldapp
303
if isinstance(service, oldapp.ApplicationService):
304
service = _NewService(service)
305
self.app.removeService(service)
307
def getServiceNamed(self, name):
308
result = self.app.getServiceNamed(name)
309
if isinstance(result, _NewService):
310
result = result.service
313
def unlistenWith(self, portType, *args, **kw):
314
warnings.warn("unlisten* does not work anymore. Name services "
315
"that you want to be able to remove",
316
category=RuntimeWarning)
318
def unlistenTCP(self, port, interface=''):
319
warnings.warn("unlisten* does not work anymore. Name services "
320
"that you want to be able to remove",
321
category=RuntimeWarning)
323
def unlistenUNIX(self, filename):
324
warnings.warn("unlisten* does not work anymore. Name services "
325
"that you want to be able to remove",
326
category=RuntimeWarning)
328
def unlistenUDP(self, port, interface=''):
329
warnings.warn("unlisten* does not work anymore. Name services "
330
"that you want to be able to remove",
331
category=RuntimeWarning)
333
def unlistenSSL(self, port, interface=''):
334
warnings.warn("unlisten* does not work anymore. Name services "
335
"that you want to be able to remove",
336
category=RuntimeWarning)
339
components.registerAdapter(_ServiceNetwork,
340
service.IServiceCollection, IOldApplication)
344
for tran in 'tcp unix udp ssl'.split():
345
_mapping.append((tran+'Ports', getattr(internet, tran.upper()+'Server')))
346
_mapping.append((tran+'Connectors',getattr(internet,tran.upper()+'Client')))
349
'''Convert an C{i.app.Application} to a C{application.service.Application}
351
@type oldApp: C{twisted.internet.app.Application}
352
@rtype C{twisted.application.service.Application}
354
This function might damage oldApp beyond repair: services
355
that other parts might be depending on might be missing.
356
It is not safe to use oldApp after it has been converted.
357
In case this behaviour is not desirable, pass a deep copy
358
of the old application
360
ret = service.Application(oldApp.name, getattr(oldApp, "uid", None), getattr(oldApp, "gid", None))
361
c = service.IServiceCollection(ret)
362
service.IProcess(ret).processName = oldApp.processName
363
for (pList, klass) in [(oldApp.extraPorts, internet.GenericServer),
364
(oldApp.extraConnectors, internet.GenericClient),]:
365
for (portType, args, kw) in pList:
366
klass(portType, *args, **kw).setServiceParent(c)
367
for (name, klass) in _mapping:
368
for args in getattr(oldApp, name):
369
klass(*args).setServiceParent(c)
371
if hasattr(s, 'privileged'):
373
for s in oldApp.services.values():
374
if not service.IService.providedBy(s):
375
s.serviceParent = None
377
s.setServiceParent(IOldApplication(c))
379
s.serviceParent = None
380
s.setServiceParent(c)
384
__all__ = ['IOldApplication', 'convert']