summaryrefslogtreecommitdiffstats
path: root/tools/buildbot/pylibs/twisted/web
diff options
context:
space:
mode:
authormaruel@google.com <maruel@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-21 23:00:58 +0000
committermaruel@google.com <maruel@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-21 23:00:58 +0000
commitfb1234375c142c49d28ddbf1fdac5ee9a0f444bc (patch)
treec52c0dabf0320ffa513f115b3dc3a3537b87a5f3 /tools/buildbot/pylibs/twisted/web
parent090b98d8ea1c8c5099a6ff010d39ccf6088e9ed1 (diff)
downloadchromium_src-fb1234375c142c49d28ddbf1fdac5ee9a0f444bc.zip
chromium_src-fb1234375c142c49d28ddbf1fdac5ee9a0f444bc.tar.gz
chromium_src-fb1234375c142c49d28ddbf1fdac5ee9a0f444bc.tar.bz2
Move the buildbot code to trunk/tools/buildbot so it is not included in a default source checkout.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@3698 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools/buildbot/pylibs/twisted/web')
-rw-r--r--tools/buildbot/pylibs/twisted/web/__init__.py14
-rw-r--r--tools/buildbot/pylibs/twisted/web/_version.py3
-rw-r--r--tools/buildbot/pylibs/twisted/web/client.py434
-rw-r--r--tools/buildbot/pylibs/twisted/web/demo.py29
-rw-r--r--tools/buildbot/pylibs/twisted/web/distrib.py303
-rw-r--r--tools/buildbot/pylibs/twisted/web/domhelpers.py260
-rw-r--r--tools/buildbot/pylibs/twisted/web/error.py61
-rw-r--r--tools/buildbot/pylibs/twisted/web/google.py75
-rw-r--r--tools/buildbot/pylibs/twisted/web/guard.py217
-rw-r--r--tools/buildbot/pylibs/twisted/web/html.py49
-rw-r--r--tools/buildbot/pylibs/twisted/web/http.py1244
-rw-r--r--tools/buildbot/pylibs/twisted/web/microdom.py873
-rw-r--r--tools/buildbot/pylibs/twisted/web/monitor.py85
-rw-r--r--tools/buildbot/pylibs/twisted/web/proxy.py283
-rw-r--r--tools/buildbot/pylibs/twisted/web/resource.py204
-rw-r--r--tools/buildbot/pylibs/twisted/web/rewrite.py52
-rw-r--r--tools/buildbot/pylibs/twisted/web/script.py163
-rw-r--r--tools/buildbot/pylibs/twisted/web/server.py571
-rw-r--r--tools/buildbot/pylibs/twisted/web/soap.py154
-rw-r--r--tools/buildbot/pylibs/twisted/web/static.py466
-rw-r--r--tools/buildbot/pylibs/twisted/web/sux.py657
-rw-r--r--tools/buildbot/pylibs/twisted/web/tap.py201
-rw-r--r--tools/buildbot/pylibs/twisted/web/test/__init__.py1
-rw-r--r--tools/buildbot/pylibs/twisted/web/test/test_cgi.py121
-rw-r--r--tools/buildbot/pylibs/twisted/web/test/test_distrib.py64
-rw-r--r--tools/buildbot/pylibs/twisted/web/test/test_domhelpers.py234
-rw-r--r--tools/buildbot/pylibs/twisted/web/test/test_http.py548
-rw-r--r--tools/buildbot/pylibs/twisted/web/test/test_mvc.py122
-rw-r--r--tools/buildbot/pylibs/twisted/web/test/test_proxy.py407
-rw-r--r--tools/buildbot/pylibs/twisted/web/test/test_soap.py114
-rw-r--r--tools/buildbot/pylibs/twisted/web/test/test_static.py64
-rw-r--r--tools/buildbot/pylibs/twisted/web/test/test_tap.py33
-rw-r--r--tools/buildbot/pylibs/twisted/web/test/test_web.py611
-rw-r--r--tools/buildbot/pylibs/twisted/web/test/test_webclient.py475
-rw-r--r--tools/buildbot/pylibs/twisted/web/test/test_woven.py570
-rw-r--r--tools/buildbot/pylibs/twisted/web/test/test_xml.py760
-rw-r--r--tools/buildbot/pylibs/twisted/web/test/test_xmlrpc.py452
-rw-r--r--tools/buildbot/pylibs/twisted/web/topfiles/NEWS107
-rw-r--r--tools/buildbot/pylibs/twisted/web/topfiles/README1
-rw-r--r--tools/buildbot/pylibs/twisted/web/topfiles/setup.py28
-rw-r--r--tools/buildbot/pylibs/twisted/web/trp.py15
-rw-r--r--tools/buildbot/pylibs/twisted/web/twcgi.py256
-rw-r--r--tools/buildbot/pylibs/twisted/web/util.py390
-rw-r--r--tools/buildbot/pylibs/twisted/web/vhost.py141
-rw-r--r--tools/buildbot/pylibs/twisted/web/widgets.py1050
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/FlashConduit.flabin20992 -> 0 bytes
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/FlashConduit.swfbin882 -> 0 bytes
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/FlashConduitGlue.html25
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/WebConduit2_mozilla.js82
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/WebConduit2_msie.js105
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/WebConduitGlue.html11
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/__init__.py3
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/controller.py436
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/dirlist.py114
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/flashconduit.py35
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/form.py575
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/guard.py383
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/input.py347
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/interfaces.py198
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/model.py487
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/page.py105
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/simpleguard.py82
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/tapestry.py170
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/template.py374
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/utils.py198
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/view.py687
-rw-r--r--tools/buildbot/pylibs/twisted/web/woven/widgets.py1036
-rw-r--r--tools/buildbot/pylibs/twisted/web/xmlrpc.py414
68 files changed, 0 insertions, 18829 deletions
diff --git a/tools/buildbot/pylibs/twisted/web/__init__.py b/tools/buildbot/pylibs/twisted/web/__init__.py
deleted file mode 100644
index 976b2db..0000000
--- a/tools/buildbot/pylibs/twisted/web/__init__.py
+++ /dev/null
@@ -1,14 +0,0 @@
-
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""
-
-Twisted Web: a Twisted Web Server.
-
-"""
-
-from twisted.web._version import version
-__version__ = version.short()
-
diff --git a/tools/buildbot/pylibs/twisted/web/_version.py b/tools/buildbot/pylibs/twisted/web/_version.py
deleted file mode 100644
index 9c9f80a..0000000
--- a/tools/buildbot/pylibs/twisted/web/_version.py
+++ /dev/null
@@ -1,3 +0,0 @@
-# This is an auto-generated file. Do not edit it.
-from twisted.python import versions
-version = versions.Version('twisted.web', 8, 1, 0)
diff --git a/tools/buildbot/pylibs/twisted/web/client.py b/tools/buildbot/pylibs/twisted/web/client.py
deleted file mode 100644
index bdc50b7..0000000
--- a/tools/buildbot/pylibs/twisted/web/client.py
+++ /dev/null
@@ -1,434 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_webclient -*-
-# Copyright (c) 2001-2008 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-"""
-HTTP client.
-"""
-
-import os, types
-from urlparse import urlunparse
-
-from twisted.web import http
-from twisted.internet import defer, protocol, reactor
-from twisted.python import failure
-from twisted.python.util import InsensitiveDict
-from twisted.web import error
-
-
-class PartialDownloadError(error.Error):
- """Page was only partially downloaded, we got disconnected in middle.
-
- The bit that was downloaded is in the response attribute.
- """
-
-
-class HTTPPageGetter(http.HTTPClient):
-
- quietLoss = 0
- followRedirect = 1
- failed = 0
-
- def connectionMade(self):
- method = getattr(self.factory, 'method', 'GET')
- self.sendCommand(method, self.factory.path)
- self.sendHeader('Host', self.factory.headers.get("host", self.factory.host))
- self.sendHeader('User-Agent', self.factory.agent)
- if self.factory.cookies:
- l=[]
- for cookie, cookval in self.factory.cookies.items():
- l.append('%s=%s' % (cookie, cookval))
- self.sendHeader('Cookie', '; '.join(l))
- data = getattr(self.factory, 'postdata', None)
- if data is not None:
- self.sendHeader("Content-Length", str(len(data)))
- for (key, value) in self.factory.headers.items():
- if key.lower() != "content-length":
- # we calculated it on our own
- self.sendHeader(key, value)
- self.endHeaders()
- self.headers = {}
-
- if data is not None:
- self.transport.write(data)
-
- def handleHeader(self, key, value):
- key = key.lower()
- l = self.headers[key] = self.headers.get(key, [])
- l.append(value)
-
- def handleStatus(self, version, status, message):
- self.version, self.status, self.message = version, status, message
- self.factory.gotStatus(version, status, message)
-
- def handleEndHeaders(self):
- self.factory.gotHeaders(self.headers)
- m = getattr(self, 'handleStatus_'+self.status, self.handleStatusDefault)
- m()
-
- def handleStatus_200(self):
- pass
-
- handleStatus_201 = lambda self: self.handleStatus_200()
- handleStatus_202 = lambda self: self.handleStatus_200()
-
- def handleStatusDefault(self):
- self.failed = 1
-
- def handleStatus_301(self):
- l = self.headers.get('location')
- if not l:
- self.handleStatusDefault()
- return
- url = l[0]
- if self.followRedirect:
- scheme, host, port, path = \
- _parse(url, defaultPort=self.transport.getPeer().port)
- self.factory.setURL(url)
-
- if self.factory.scheme == 'https':
- from twisted.internet import ssl
- contextFactory = ssl.ClientContextFactory()
- reactor.connectSSL(self.factory.host, self.factory.port,
- self.factory, contextFactory)
- else:
- reactor.connectTCP(self.factory.host, self.factory.port,
- self.factory)
- else:
- self.handleStatusDefault()
- self.factory.noPage(
- failure.Failure(
- error.PageRedirect(
- self.status, self.message, location = url)))
- self.quietLoss = 1
- self.transport.loseConnection()
-
- handleStatus_302 = lambda self: self.handleStatus_301()
-
- def handleStatus_303(self):
- self.factory.method = 'GET'
- self.handleStatus_301()
-
- def connectionLost(self, reason):
- if not self.quietLoss:
- http.HTTPClient.connectionLost(self, reason)
- self.factory.noPage(reason)
-
- def handleResponse(self, response):
- if self.quietLoss:
- return
- if self.failed:
- self.factory.noPage(
- failure.Failure(
- error.Error(
- self.status, self.message, response)))
- if self.factory.method.upper() == 'HEAD':
- # Callback with empty string, since there is never a response
- # body for HEAD requests.
- self.factory.page('')
- elif self.length != None and self.length != 0:
- self.factory.noPage(failure.Failure(
- PartialDownloadError(self.status, self.message, response)))
- else:
- self.factory.page(response)
- # server might be stupid and not close connection. admittedly
- # the fact we do only one request per connection is also
- # stupid...
- self.transport.loseConnection()
-
- def timeout(self):
- self.quietLoss = True
- self.transport.loseConnection()
- self.factory.noPage(defer.TimeoutError("Getting %s took longer than %s seconds." % (self.factory.url, self.factory.timeout)))
-
-
-class HTTPPageDownloader(HTTPPageGetter):
-
- transmittingPage = 0
-
- def handleStatus_200(self, partialContent=0):
- HTTPPageGetter.handleStatus_200(self)
- self.transmittingPage = 1
- self.factory.pageStart(partialContent)
-
- def handleStatus_206(self):
- self.handleStatus_200(partialContent=1)
-
- def handleResponsePart(self, data):
- if self.transmittingPage:
- self.factory.pagePart(data)
-
- def handleResponseEnd(self):
- if self.transmittingPage:
- self.factory.pageEnd()
- self.transmittingPage = 0
- if self.failed:
- self.factory.noPage(
- failure.Failure(
- error.Error(
- self.status, self.message, None)))
- self.transport.loseConnection()
-
-
-class HTTPClientFactory(protocol.ClientFactory):
- """Download a given URL.
-
- @type deferred: Deferred
- @ivar deferred: A Deferred that will fire when the content has
- been retrieved. Once this is fired, the ivars `status', `version',
- and `message' will be set.
-
- @type status: str
- @ivar status: The status of the response.
-
- @type version: str
- @ivar version: The version of the response.
-
- @type message: str
- @ivar message: The text message returned with the status.
-
- @type response_headers: dict
- @ivar response_headers: The headers that were specified in the
- response from the server.
- """
-
- protocol = HTTPPageGetter
-
- url = None
- scheme = None
- host = ''
- port = None
- path = None
-
- def __init__(self, url, method='GET', postdata=None, headers=None,
- agent="Twisted PageGetter", timeout=0, cookies=None,
- followRedirect=1):
- self.protocol.followRedirect = followRedirect
- self.timeout = timeout
- self.agent = agent
-
- if cookies is None:
- cookies = {}
- self.cookies = cookies
- if headers is not None:
- self.headers = InsensitiveDict(headers)
- else:
- self.headers = InsensitiveDict()
- if postdata is not None:
- self.headers.setdefault('Content-Length', len(postdata))
- # just in case a broken http/1.1 decides to keep connection alive
- self.headers.setdefault("connection", "close")
- self.postdata = postdata
- self.method = method
-
- self.setURL(url)
-
- self.waiting = 1
- self.deferred = defer.Deferred()
- self.response_headers = None
-
- def __repr__(self):
- return "<%s: %s>" % (self.__class__.__name__, self.url)
-
- def setURL(self, url):
- self.url = url
- scheme, host, port, path = _parse(url)
- if scheme and host:
- self.scheme = scheme
- self.host = host
- self.port = port
- self.path = path
-
- def buildProtocol(self, addr):
- p = protocol.ClientFactory.buildProtocol(self, addr)
- if self.timeout:
- timeoutCall = reactor.callLater(self.timeout, p.timeout)
- self.deferred.addBoth(self._cancelTimeout, timeoutCall)
- return p
-
- def _cancelTimeout(self, result, timeoutCall):
- if timeoutCall.active():
- timeoutCall.cancel()
- return result
-
- def gotHeaders(self, headers):
- self.response_headers = headers
- if headers.has_key('set-cookie'):
- for cookie in headers['set-cookie']:
- cookparts = cookie.split(';')
- cook = cookparts[0]
- cook.lstrip()
- k, v = cook.split('=', 1)
- self.cookies[k.lstrip()] = v.lstrip()
-
- def gotStatus(self, version, status, message):
- self.version, self.status, self.message = version, status, message
-
- def page(self, page):
- if self.waiting:
- self.waiting = 0
- self.deferred.callback(page)
-
- def noPage(self, reason):
- if self.waiting:
- self.waiting = 0
- self.deferred.errback(reason)
-
- def clientConnectionFailed(self, _, reason):
- if self.waiting:
- self.waiting = 0
- self.deferred.errback(reason)
-
-
-class HTTPDownloader(HTTPClientFactory):
- """Download to a file."""
-
- protocol = HTTPPageDownloader
- value = None
-
- def __init__(self, url, fileOrName,
- method='GET', postdata=None, headers=None,
- agent="Twisted client", supportPartial=0):
- self.requestedPartial = 0
- if isinstance(fileOrName, types.StringTypes):
- self.fileName = fileOrName
- self.file = None
- if supportPartial and os.path.exists(self.fileName):
- fileLength = os.path.getsize(self.fileName)
- if fileLength:
- self.requestedPartial = fileLength
- if headers == None:
- headers = {}
- headers["range"] = "bytes=%d-" % fileLength
- else:
- self.file = fileOrName
- HTTPClientFactory.__init__(self, url, method=method, postdata=postdata, headers=headers, agent=agent)
- self.deferred = defer.Deferred()
- self.waiting = 1
-
- def gotHeaders(self, headers):
- if self.requestedPartial:
- contentRange = headers.get("content-range", None)
- if not contentRange:
- # server doesn't support partial requests, oh well
- self.requestedPartial = 0
- return
- start, end, realLength = http.parseContentRange(contentRange[0])
- if start != self.requestedPartial:
- # server is acting wierdly
- self.requestedPartial = 0
-
- def openFile(self, partialContent):
- if partialContent:
- file = open(self.fileName, 'rb+')
- file.seek(0, 2)
- else:
- file = open(self.fileName, 'wb')
- return file
-
- def pageStart(self, partialContent):
- """Called on page download start.
-
- @param partialContent: tells us if the download is partial download we requested.
- """
- if partialContent and not self.requestedPartial:
- raise ValueError, "we shouldn't get partial content response if we didn't want it!"
- if self.waiting:
- self.waiting = 0
- try:
- if not self.file:
- self.file = self.openFile(partialContent)
- except IOError:
- #raise
- self.deferred.errback(failure.Failure())
-
- def pagePart(self, data):
- if not self.file:
- return
- try:
- self.file.write(data)
- except IOError:
- #raise
- self.file = None
- self.deferred.errback(failure.Failure())
-
- def pageEnd(self):
- if not self.file:
- return
- try:
- self.file.close()
- except IOError:
- self.deferred.errback(failure.Failure())
- return
- self.deferred.callback(self.value)
-
-
-def _parse(url, defaultPort=None):
- """
- Split the given URL into the scheme, host, port, and path.
-
- @type url: C{str}
- @param url: An URL to parse.
-
- @type defaultPort: C{int} or C{None}
- @param defaultPort: An alternate value to use as the port if the URL does
- not include one.
-
- @return: A four-tuple of the scheme, host, port, and path of the URL. All
- of these are C{str} instances except for port, which is an C{int}.
- """
- url = url.strip()
- parsed = http.urlparse(url)
- scheme = parsed[0]
- path = urlunparse(('','')+parsed[2:])
- if defaultPort is None:
- if scheme == 'https':
- defaultPort = 443
- else:
- defaultPort = 80
- host, port = parsed[1], defaultPort
- if ':' in host:
- host, port = host.split(':')
- port = int(port)
- if path == "":
- path = "/"
- return scheme, host, port, path
-
-
-def getPage(url, contextFactory=None, *args, **kwargs):
- """Download a web page as a string.
-
- Download a page. Return a deferred, which will callback with a
- page (as a string) or errback with a description of the error.
-
- See HTTPClientFactory to see what extra args can be passed.
- """
- scheme, host, port, path = _parse(url)
- factory = HTTPClientFactory(url, *args, **kwargs)
- if scheme == 'https':
- from twisted.internet import ssl
- if contextFactory is None:
- contextFactory = ssl.ClientContextFactory()
- reactor.connectSSL(host, port, factory, contextFactory)
- else:
- reactor.connectTCP(host, port, factory)
- return factory.deferred
-
-
-def downloadPage(url, file, contextFactory=None, *args, **kwargs):
- """Download a web page to a file.
-
- @param file: path to file on filesystem, or file-like object.
-
- See HTTPDownloader to see what extra args can be passed.
- """
- scheme, host, port, path = _parse(url)
- factory = HTTPDownloader(url, file, *args, **kwargs)
- if scheme == 'https':
- from twisted.internet import ssl
- if contextFactory is None:
- contextFactory = ssl.ClientContextFactory()
- reactor.connectSSL(host, port, factory, contextFactory)
- else:
- reactor.connectTCP(host, port, factory)
- return factory.deferred
diff --git a/tools/buildbot/pylibs/twisted/web/demo.py b/tools/buildbot/pylibs/twisted/web/demo.py
deleted file mode 100644
index 57df240..0000000
--- a/tools/buildbot/pylibs/twisted/web/demo.py
+++ /dev/null
@@ -1,29 +0,0 @@
-
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""I am a simple test resource.
-"""
-
-from twisted.python import log
-from twisted.web import static
-
-class Test(static.Data):
- isLeaf = True
- def __init__(self):
- static.Data.__init__(
- self,
- """
- <html>
- <head><title>Temporary Test</title><head>
- <body>
-
- Hello! This is a temporary test until a more sophisticated form
- demo can be put back in using more up-to-date Twisted APIs.
-
- </body>
- </html>
- """,
- "text/html")
-
diff --git a/tools/buildbot/pylibs/twisted/web/distrib.py b/tools/buildbot/pylibs/twisted/web/distrib.py
deleted file mode 100644
index df2141b..0000000
--- a/tools/buildbot/pylibs/twisted/web/distrib.py
+++ /dev/null
@@ -1,303 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_web -*-
-
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""Distributed web servers.
-
-This is going to have to be refactored so that argument parsing is done
-by each subprocess and not by the main web server (i.e. GET, POST etc.).
-"""
-
-# System Imports
-import types, os, copy, string, cStringIO
-if (os.sys.platform != 'win32') and (os.name != 'java'):
- import pwd
-
-# Twisted Imports
-from twisted.spread import pb
-from twisted.web import http
-from twisted.python import log
-from twisted.persisted import styles
-from twisted.web.woven import page
-from twisted.internet import address, reactor
-
-# Sibling Imports
-import resource
-import server
-import error
-import html
-import static
-from server import NOT_DONE_YET
-
-class _ReferenceableProducerWrapper(pb.Referenceable):
- def __init__(self, producer):
- self.producer = producer
-
- def remote_resumeProducing(self):
- self.producer.resumeProducing()
-
- def remote_pauseProducing(self):
- self.producer.pauseProducing()
-
- def remote_stopProducing(self):
- self.producer.stopProducing()
-
-
-class Request(pb.RemoteCopy, server.Request):
- def setCopyableState(self, state):
- for k in 'host', 'client':
- tup = state[k]
- addrdesc = {'INET': 'TCP', 'UNIX': 'UNIX'}[tup[0]]
- addr = {'TCP': lambda: address.IPv4Address(addrdesc,
- tup[1], tup[2],
- _bwHack='INET'),
- 'UNIX': lambda: address.UNIXAddress(tup[1])}[addrdesc]()
- state[k] = addr
- pb.RemoteCopy.setCopyableState(self, state)
- # Emulate the local request interface --
- self.content = cStringIO.StringIO(self.content_data)
- self.write = self.remote.remoteMethod('write')
- self.finish = self.remote.remoteMethod('finish')
- self.setHeader = self.remote.remoteMethod('setHeader')
- self.addCookie = self.remote.remoteMethod('addCookie')
- self.setETag = self.remote.remoteMethod('setETag')
- self.setResponseCode = self.remote.remoteMethod('setResponseCode')
- self.setLastModified = self.remote.remoteMethod('setLastModified')
-
- def registerProducer(self, producer, streaming):
- self.remote.callRemote("registerProducer",
- _ReferenceableProducerWrapper(producer),
- streaming).addErrback(self.fail)
-
- def unregisterProducer(self):
- self.remote.callRemote("unregisterProducer").addErrback(self.fail)
-
- def fail(self, failure):
- log.err(failure)
-
-
-pb.setCopierForClass(server.Request, Request)
-
-class Issue:
- def __init__(self, request):
- self.request = request
-
- def finished(self, result):
- if result != NOT_DONE_YET:
- assert isinstance(result, types.StringType),\
- "return value not a string"
- self.request.write(result)
- self.request.finish()
-
- def failed(self, failure):
- #XXX: Argh. FIXME.
- failure = str(failure)
- self.request.write(
- error.ErrorPage(http.INTERNAL_SERVER_ERROR,
- "Server Connection Lost",
- "Connection to distributed server lost:" +
- html.PRE(failure)).
- render(self.request))
- self.request.finish()
- log.msg(failure)
-
-
-class ResourceSubscription(resource.Resource):
- isLeaf = 1
- waiting = 0
- def __init__(self, host, port):
- resource.Resource.__init__(self)
- self.host = host
- self.port = port
- self.pending = []
- self.publisher = None
-
- def __getstate__(self):
- """Get persistent state for this ResourceSubscription.
- """
- # When I unserialize,
- state = copy.copy(self.__dict__)
- # Publisher won't be connected...
- state['publisher'] = None
- # I won't be making a connection
- state['waiting'] = 0
- # There will be no pending requests.
- state['pending'] = []
- return state
-
- def connected(self, publisher):
- """I've connected to a publisher; I'll now send all my requests.
- """
- log.msg('connected to publisher')
- publisher.broker.notifyOnDisconnect(self.booted)
- self.publisher = publisher
- self.waiting = 0
- for request in self.pending:
- self.render(request)
- self.pending = []
-
- def notConnected(self, msg):
- """I can't connect to a publisher; I'll now reply to all pending
- requests.
- """
- log.msg("could not connect to distributed web service: %s" % msg)
- self.waiting = 0
- self.publisher = None
- for request in self.pending:
- request.write("Unable to connect to distributed server.")
- request.finish()
- self.pending = []
-
- def booted(self):
- self.notConnected("connection dropped")
-
- def render(self, request):
- """Render this request, from my server.
-
- This will always be asynchronous, and therefore return NOT_DONE_YET.
- It spins off a request to the pb client, and either adds it to the list
- of pending issues or requests it immediately, depending on if the
- client is already connected.
- """
- if not self.publisher:
- self.pending.append(request)
- if not self.waiting:
- self.waiting = 1
- bf = pb.PBClientFactory()
- timeout = 10
- if self.host == "unix":
- reactor.connectUNIX(self.port, bf, timeout)
- else:
- reactor.connectTCP(self.host, self.port, bf, timeout)
- d = bf.getRootObject()
- d.addCallbacks(self.connected, self.notConnected)
-
- else:
- i = Issue(request)
- self.publisher.callRemote('request', request).addCallbacks(i.finished, i.failed)
- return NOT_DONE_YET
-
-class ResourcePublisher(pb.Root, styles.Versioned):
- def __init__(self, site):
- self.site = site
-
- persistenceVersion = 2
-
- def upgradeToVersion2(self):
- self.application.authorizer.removeIdentity("web")
- del self.application.services[self.serviceName]
- del self.serviceName
- del self.application
- del self.perspectiveName
-
- def getPerspectiveNamed(self, name):
- return self
-
- def remote_request(self, request):
- res = self.site.getResourceFor(request)
- log.msg( request )
- return res.render(request)
-
-class UserDirectory(page.Page):
- userDirName = 'public_html'
- userSocketName = '.twistd-web-pb'
-
- template = """
-<html>
- <head>
- <title>twisted.web.distrib.UserDirectory</title>
- <style>
-
- a
- {
- font-family: Lucida, Verdana, Helvetica, Arial, sans-serif;
- color: #369;
- text-decoration: none;
- }
-
- th
- {
- font-family: Lucida, Verdana, Helvetica, Arial, sans-serif;
- font-weight: bold;
- text-decoration: none;
- text-align: left;
- }
-
- pre, code
- {
- font-family: "Courier New", Courier, monospace;
- }
-
- p, body, td, ol, ul, menu, blockquote, div
- {
- font-family: Lucida, Verdana, Helvetica, Arial, sans-serif;
- color: #000;
- }
-
- </style>
- <base view="Attributes" model="base" />
- </head>
-
- <body>
- <h1>twisted.web.distrib.UserDirectory</h1>
-
- <ul view="List" model="directory">
- <li pattern="listItem"><a view="Link" /> </li>
- </ul>
-</body>
-</html>
- """
-
- def wmfactory_base(self, request):
- return {'href':request.prePathURL()}
-
- def wmfactory_directory(self, request):
- m = []
- for user in pwd.getpwall():
- pw_name, pw_passwd, pw_uid, pw_gid, pw_gecos, pw_dir, pw_shell \
- = user
- realname = string.split(pw_gecos,',')[0]
- if not realname:
- realname = pw_name
- if os.path.exists(os.path.join(pw_dir, self.userDirName)):
- m.append({
- 'href':'%s/'%pw_name,
- 'text':'%s (file)'%realname
- })
- twistdsock = os.path.join(pw_dir, self.userSocketName)
- if os.path.exists(twistdsock):
- linknm = '%s.twistd' % pw_name
- m.append({
- 'href':'%s/'%linknm,
- 'text':'%s (twistd)'%realname})
- return m
-
- def getChild(self, name, request):
- if name == '':
- return self
-
- td = '.twistd'
-
- if name[-len(td):] == td:
- username = name[:-len(td)]
- sub = 1
- else:
- username = name
- sub = 0
- try:
- pw_name, pw_passwd, pw_uid, pw_gid, pw_gecos, pw_dir, pw_shell \
- = pwd.getpwnam(username)
- except KeyError:
- return error.NoResource()
- if sub:
- twistdsock = os.path.join(pw_dir, self.userSocketName)
- rs = ResourceSubscription('unix',twistdsock)
- self.putChild(name, rs)
- return rs
- else:
- path = os.path.join(pw_dir, self.userDirName)
- if not os.path.exists(path):
- return error.NoResource()
- return static.File(path)
diff --git a/tools/buildbot/pylibs/twisted/web/domhelpers.py b/tools/buildbot/pylibs/twisted/web/domhelpers.py
deleted file mode 100644
index e1322c4..0000000
--- a/tools/buildbot/pylibs/twisted/web/domhelpers.py
+++ /dev/null
@@ -1,260 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_woven -*-
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-#
-
-from __future__ import nested_scopes
-
-from twisted.web import microdom
-from microdom import getElementsByTagName, escape, unescape
-
-try:
- import cStringIO as StringIO
-except ImportError:
- import StringIO
-
-class NodeLookupError(Exception): pass
-
-
-def substitute(request, node, subs):
- """
- Look through the given node's children for strings, and
- attempt to do string substitution with the given parameter.
- """
- for child in node.childNodes:
- if hasattr(child, 'nodeValue') and child.nodeValue:
- child.replaceData(0, len(child.nodeValue), child.nodeValue % subs)
- substitute(request, child, subs)
-
-def _get(node, nodeId, nodeAttrs=('id','class','model','pattern')):
- """
- (internal) Get a node with the specified C{nodeId} as any of the C{class},
- C{id} or C{pattern} attributes.
- """
-
- if hasattr(node, 'hasAttributes') and node.hasAttributes():
- for nodeAttr in nodeAttrs:
- if (str (node.getAttribute(nodeAttr)) == nodeId):
- return node
- if node.hasChildNodes():
- if hasattr(node.childNodes, 'length'):
- length = node.childNodes.length
- else:
- length = len(node.childNodes)
- for childNum in range(length):
- result = _get(node.childNodes[childNum], nodeId)
- if result: return result
-
-def get(node, nodeId):
- """
- Get a node with the specified C{nodeId} as any of the C{class},
- C{id} or C{pattern} attributes. If there is no such node, raise
- L{NodeLookupError}.
- """
- result = _get(node, nodeId)
- if result: return result
- raise NodeLookupError, nodeId
-
-def getIfExists(node, nodeId):
- """
- Get a node with the specified C{nodeId} as any of the C{class},
- C{id} or C{pattern} attributes. If there is no such node, return
- C{None}.
- """
- return _get(node, nodeId)
-
-def getAndClear(node, nodeId):
- """Get a node with the specified C{nodeId} as any of the C{class},
- C{id} or C{pattern} attributes. If there is no such node, raise
- L{NodeLookupError}. Remove all child nodes before returning.
- """
- result = get(node, nodeId)
- if result:
- clearNode(result)
- return result
-
-def clearNode(node):
- """
- Remove all children from the given node.
- """
- node.childNodes[:] = []
-
-def locateNodes(nodeList, key, value, noNesting=1):
- """
- Find subnodes in the given node where the given attribute
- has the given value.
- """
- returnList = []
- if not isinstance(nodeList, type([])):
- return locateNodes(nodeList.childNodes, key, value, noNesting)
- for childNode in nodeList:
- if not hasattr(childNode, 'getAttribute'):
- continue
- if str(childNode.getAttribute(key)) == value:
- returnList.append(childNode)
- if noNesting:
- continue
- returnList.extend(locateNodes(childNode, key, value, noNesting))
- return returnList
-
-def superSetAttribute(node, key, value):
- if not hasattr(node, 'setAttribute'): return
- node.setAttribute(key, value)
- if node.hasChildNodes():
- for child in node.childNodes:
- superSetAttribute(child, key, value)
-
-def superPrependAttribute(node, key, value):
- if not hasattr(node, 'setAttribute'): return
- old = node.getAttribute(key)
- if old:
- node.setAttribute(key, value+'/'+old)
- else:
- node.setAttribute(key, value)
- if node.hasChildNodes():
- for child in node.childNodes:
- superPrependAttribute(child, key, value)
-
-def superAppendAttribute(node, key, value):
- if not hasattr(node, 'setAttribute'): return
- old = node.getAttribute(key)
- if old:
- node.setAttribute(key, old + '/' + value)
- else:
- node.setAttribute(key, value)
- if node.hasChildNodes():
- for child in node.childNodes:
- superAppendAttribute(child, key, value)
-
-def gatherTextNodes(iNode, dounescape=0, joinWith=""):
- """Visit each child node and collect its text data, if any, into a string.
-For example::
- >>> doc=microdom.parseString('<a>1<b>2<c>3</c>4</b></a>')
- >>> gatherTextNodes(doc.documentElement)
- '1234'
-With dounescape=1, also convert entities back into normal characters.
-@return: the gathered nodes as a single string
-@rtype: str
-"""
- gathered=[]
- gathered_append=gathered.append
- slice=[iNode]
- while len(slice)>0:
- c=slice.pop(0)
- if hasattr(c, 'nodeValue') and c.nodeValue is not None:
- if dounescape:
- val=unescape(c.nodeValue)
- else:
- val=c.nodeValue
- gathered_append(val)
- slice[:0]=c.childNodes
- return joinWith.join(gathered)
-
-class RawText(microdom.Text):
- """This is an evil and horrible speed hack. Basically, if you have a big
- chunk of XML that you want to insert into the DOM, but you don't want to
- incur the cost of parsing it, you can construct one of these and insert it
- into the DOM. This will most certainly only work with microdom as the API
- for converting nodes to xml is different in every DOM implementation.
-
- This could be improved by making this class a Lazy parser, so if you
- inserted this into the DOM and then later actually tried to mutate this
- node, it would be parsed then.
- """
-
- def writexml(self, writer, indent="", addindent="", newl="", strip=0, nsprefixes=None, namespace=None):
- writer.write("%s%s%s" % (indent, self.data, newl))
-
-def findNodes(parent, matcher, accum=None):
- if accum is None:
- accum = []
- if not parent.hasChildNodes():
- return accum
- for child in parent.childNodes:
- # print child, child.nodeType, child.nodeName
- if matcher(child):
- accum.append(child)
- findNodes(child, matcher, accum)
- return accum
-
-
-def findNodesShallowOnMatch(parent, matcher, recurseMatcher, accum=None):
- if accum is None:
- accum = []
- if not parent.hasChildNodes():
- return accum
- for child in parent.childNodes:
- # print child, child.nodeType, child.nodeName
- if matcher(child):
- accum.append(child)
- if recurseMatcher(child):
- findNodesShallowOnMatch(child, matcher, recurseMatcher, accum)
- return accum
-
-def findNodesShallow(parent, matcher, accum=None):
- if accum is None:
- accum = []
- if not parent.hasChildNodes():
- return accum
- for child in parent.childNodes:
- if matcher(child):
- accum.append(child)
- else:
- findNodes(child, matcher, accum)
- return accum
-
-
-def findElementsWithAttributeShallow(parent, attribute):
- return findNodesShallow(parent,
- lambda n: isinstance(n, microdom.Element) and
- n.hasAttribute(attribute))
-
-
-def findElements(parent, matcher):
- return findNodes(
- parent,
- lambda n, matcher=matcher: isinstance(n, microdom.Element) and
- matcher(n))
-
-def findElementsWithAttribute(parent, attribute, value=None):
- if value:
- return findElements(
- parent,
- lambda n, attribute=attribute, value=value:
- n.hasAttribute(attribute) and n.getAttribute(attribute) == value)
- else:
- return findElements(
- parent,
- lambda n, attribute=attribute: n.hasAttribute(attribute))
-
-
-def findNodesNamed(parent, name):
- return findNodes(parent, lambda n, name=name: n.nodeName == name)
-
-
-def writeNodeData(node, oldio):
- for subnode in node.childNodes:
- if hasattr(subnode, 'data'):
- oldio.write(str(subnode.data))
- else:
- writeNodeData(subnode, oldio)
-
-
-def getNodeText(node):
- oldio = StringIO.StringIO()
- writeNodeData(node, oldio)
- return oldio.getvalue()
-
-def getParents(node):
- l = []
- while node:
- l.append(node)
- node = node.parentNode
- return l
-
-def namedChildren(parent, nodeName):
- """namedChildren(parent, nodeName) -> children (not descendants) of parent
- that have tagName == nodeName
- """
- return [n for n in parent.childNodes if getattr(n, 'tagName', '')==nodeName]
diff --git a/tools/buildbot/pylibs/twisted/web/error.py b/tools/buildbot/pylibs/twisted/web/error.py
deleted file mode 100644
index 737f1f5..0000000
--- a/tools/buildbot/pylibs/twisted/web/error.py
+++ /dev/null
@@ -1,61 +0,0 @@
-
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""I am the Twisted.Web error resources and exceptions."""
-
-#t.w imports
-import resource
-
-from twisted.web import http
-
-class Error(Exception):
- def __init__(self, code, message = None, response = None):
- message = message or http.responses.get(code)
- Exception.__init__(self, code, message, response)
- self.status = code
- self.response = response
-
- def __str__(self):
- return '%s %s' % (self[0], self[1])
-
-class PageRedirect(Error):
- """A request that resulted in a http redirect """
- def __init__(self, code, message = None, response = None, location = None):
- message = message or ("%s to %s" % (http.responses.get(code), location))
- Error.__init__(self, code, message, response)
- self.location = location
-
-class ErrorPage(resource.Resource):
- def __init__(self, status, brief, detail):
- resource.Resource.__init__(self)
- self.code = status
- self.brief = brief
- self.detail = detail
-
- def render(self, request):
- request.setResponseCode(self.code)
- request.setHeader("content-type", "text/html")
- return ("""<html>
- <head><title>%s - %s</title></head>
- <body><h1>%s</h1>
- <p>%s</p>
- </body></html>\n\n""" %
- (self.code, self.brief, self.brief, self.detail))
-
- def getChild(self, chnam, request):
- return self
-
-
-class NoResource(ErrorPage):
- def __init__(self, message="Sorry. No luck finding that resource."):
- ErrorPage.__init__(self, http.NOT_FOUND,
- "No Such Resource",
- message)
-
-class ForbiddenResource(ErrorPage):
- def __init__(self, message="Sorry, resource is forbidden."):
- ErrorPage.__init__(self, http.FORBIDDEN,
- "Forbidden Resource",
- message)
diff --git a/tools/buildbot/pylibs/twisted/web/google.py b/tools/buildbot/pylibs/twisted/web/google.py
deleted file mode 100644
index a0b8e8f..0000000
--- a/tools/buildbot/pylibs/twisted/web/google.py
+++ /dev/null
@@ -1,75 +0,0 @@
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-#
-"""\"I'm Feeling Lucky\" with U{Google<http://google.com>}.
-"""
-import urllib
-from twisted.internet import protocol, reactor, defer
-from twisted.web import http
-
-class GoogleChecker(http.HTTPClient):
-
- def connectionMade(self):
- self.sendCommand('GET', self.factory.url)
- self.sendHeader('Host', self.factory.host)
- self.sendHeader('User-Agent', self.factory.agent)
- self.endHeaders()
-
- def handleHeader(self, key, value):
- key = key.lower()
- if key == 'location':
- self.factory.gotLocation(value)
-
- def handleStatus(self, version, status, message):
- if status != '302':
- self.factory.noLocation(ValueError("bad status"))
-
- def handleEndHeaders(self):
- self.factory.noLocation(ValueError("no location"))
-
- def handleResponsePart(self, part):
- pass
-
- def handleResponseEnd(self):
- pass
-
- def connectionLost(self, reason):
- self.factory.noLocation(reason)
-
-
-class GoogleCheckerFactory(protocol.ClientFactory):
-
- protocol = GoogleChecker
-
- def __init__(self, words):
- self.url = ('/search?q=%s&btnI=%s' %
- (urllib.quote_plus(' '.join(words)),
- urllib.quote_plus("I'm Feeling Lucky")))
- self.agent="Twisted/GoogleChecker"
- self.host = "www.google.com"
- self.deferred = defer.Deferred()
-
- def clientConnectionFailed(self, _, reason):
- self.noLocation(reason)
-
- def gotLocation(self, location):
- if self.deferred:
- self.deferred.callback(location)
- self.deferred = None
-
- def noLocation(self, error):
- if self.deferred:
- self.deferred.errback(error)
- self.deferred = None
-
-
-def checkGoogle(words):
- """Check google for a match.
-
- @returns: a Deferred which will callback with a URL or errback with a
- Failure.
- """
- factory = GoogleCheckerFactory(words)
- reactor.connectTCP('www.google.com', 80, factory)
- return factory.deferred
diff --git a/tools/buildbot/pylibs/twisted/web/guard.py b/tools/buildbot/pylibs/twisted/web/guard.py
deleted file mode 100644
index 9b5cd3c..0000000
--- a/tools/buildbot/pylibs/twisted/web/guard.py
+++ /dev/null
@@ -1,217 +0,0 @@
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""DEPRECATED.
-
-You probably should be using twisted.web.woven.guard instead.
-"""
-
-# System Imports
-import string, traceback
-from cStringIO import StringIO
-
-from twisted.python import log
-
-# Sibling Imports
-import error
-import html
-import resource
-import widgets
-from server import NOT_DONE_YET
-
-import warnings
-warnings.warn("Please use twisted.web.woven.guard", DeprecationWarning, 2)
-
-
-class _Detacher:
- """Detach a web session from an attached perspective.
-
- This will happen when the session expires.
- """
-
- def __init__(self, session, identity, perspective):
- self.session = session
- self.identity = identity
- self.perspective = perspective
- session.notifyOnExpire(self.detach)
-
- def detach(self):
- self.perspective.detached(self.session, self.identity)
- del self.session
- del self.identity
- del self.perspective
-
-
-class AuthForm(widgets.Form):
- formFields = [
- ['string','Identity','username',''],
- ['password','Password','password',''],
- ['string','Perspective','perspective','']
- ]
-
- formAcceptExtraArgs = 1
-
- def __init__(self, reqauth, sessionIdentity=None, sessionPerspective=None):
- """Initialize, specifying various options.
-
- @param reqauth: a web.resource.Resource instance, indicating which
- resource a user will be logging into with this form; this must
- specify a serviceName attribute which indicates the name of the
- service from which perspectives will be requested.
-
- @param sessionIdentity: if specified, the name of the attribute on
- the user's session to set for the identity they get from logging
- in to this form.
-
- @param sessionPerspective: if specified, the name of the attribute on
- the user's session to set for the perspective they get from
- logging in to this form.
- """
- self.reqauth = reqauth
- self.sessionPerspective = sessionPerspective
- self.sessionIdentity = sessionIdentity
-
- def gotPerspective(self, perspective, request, ident):
- # TODO: fix this...
- resKey = string.join(['AUTH',self.reqauth.service.serviceName], '_')
- sess = request.getSession()
- setattr(sess, resKey, perspective)
- if self.sessionPerspective:
- setattr(sess, self.sessionPerspective, perspective)
- if self.sessionIdentity:
- setattr(sess, self.sessionIdentity, ident)
- p = perspective.attached(sess, ident)
- _Detacher(sess, ident, p)
- return self.reqauth.reallyRender(request)
-
- def didntGetPerspective(self, error, request):
- log.msg('Password not verified! Error: %s' % error)
- io = StringIO()
- io.write(self.formatError("Login incorrect."))
- self.format(self.getFormFields(request), io.write, request)
- return [io.getvalue()]
-
- def gotIdentity(self, ident, password, request, perspectiveName):
- pwrq = ident.verifyPlainPassword(password)
- pwrq.addCallback(self.passwordIsOk, ident, password,
- request, perspectiveName)
- pwrq.addErrback(self.didntGetPerspective, request)
- pwrq.needsHeader = 1
- return [pwrq]
-
- def passwordIsOk(self, msg, ident, password, request, perspectiveName):
- ret = ident.requestPerspectiveForKey(self.reqauth.service.serviceName,
- perspectiveName).addCallbacks(
- self.gotPerspective, self.didntGetPerspective,
- callbackArgs=(request,ident),
- errbackArgs=(request,))
- ret.needsHeader = 1
- return [ret]
-
- def didntGetIdentity(self, unauth, request):
- io = StringIO()
- io.write(self.formatError("Login incorrect."))
- self.format(self.getFormFields(request), io.write, request)
- return io.getvalue()
-
- def process(self, write, request, submit, username, password, perspective):
- """Process the form results.
- """
- # must be done before page is displayed so cookie can get set!
- request.getSession()
- # this site must be tagged with an application.
- idrq = self.reqauth.service.authorizer.getIdentityRequest(username)
- idrq.needsHeader = 1
- idrq.addCallbacks(self.gotIdentity, self.didntGetIdentity,
- callbackArgs=(password,request,perspective or username),
- errbackArgs=(request,))
- return [idrq]
-
-class AuthPage(widgets.Page):
- template = '''
- <html><head><title>Authorization Required</title></head>
- <body>
- <center>
- %%%%authForm%%%%
- </center>
- </body>
- </html>
- '''
- authForm = None
- def __init__(self, reqauth, sessionIdentity=None, sessionPerspective=None):
- widgets.Page.__init__(self)
- self.authForm = AuthForm(reqauth, sessionPerspective, sessionIdentity)
-
-
-class WidgetGuard(widgets.Widget):
-
- def __init__(self, wid, service,
- sessionIdentity=None,
- sessionPerspective=None):
- self.wid = wid
- self.service = service
- self.sessionPerspective = sessionPerspective
- self.sessionIdentity = sessionIdentity
-
- def reallyRender(self, request):
- return widgets.possiblyDeferWidget(self.wid, request)
-
- def display(self, request):
- session = request.getSession()
- resKey = string.join(['AUTH',self.service.serviceName], '_')
- if hasattr(session, resKey):
- return self.wid.display(request)
- else:
- return AuthForm(self).display(request)
-
-
-
-# TODO hiding forms behind a ResourceGuard sucks, because if
-# ResourceGuard needs to authenticate the user, it will 1) complain
-# about the form submitted, 2) throw the data away. This happens if
-# you use "foo?a=b" -style URLs and the user hasn't authenticated yet,
-# or with session expiry.
-
-class ResourceGuard(resource.Resource):
-
- isLeaf = 1
-
- def __init__(self, res, service, sessionIdentity=None, sessionPerspective=None):
- resource.Resource.__init__(self)
- self.res = res
- self.service = service
- self.sessionPerspective = sessionPerspective
- self.sessionIdentity = sessionIdentity
-
- def __getattr__(self, k):
- if not self.__dict__.has_key("res"):
- raise AttributeError, k
- return getattr(self.res, k)
-
- def __getstate__(self):
- return self.__dict__.copy()
-
- def listNames(self):
- return self.res.listNames()
-
- def reallyRender(self, request):
- # it's authenticated already...
- res = resource.getChildForRequest(self.res, request)
- val = res.render(request)
- if val != NOT_DONE_YET:
- request.write(val)
- request.finish()
- return widgets.FORGET_IT
-
- def render(self, request):
- session = request.getSession()
- resKey = string.join(['AUTH',self.service.serviceName], '_')
- if hasattr(session, resKey):
- self.reallyRender(request)
- return NOT_DONE_YET
- else:
- return AuthPage(self,
- self.sessionPerspective,
- self.sessionIdentity).render(request)
-
diff --git a/tools/buildbot/pylibs/twisted/web/html.py b/tools/buildbot/pylibs/twisted/web/html.py
deleted file mode 100644
index fd3ff5f..0000000
--- a/tools/buildbot/pylibs/twisted/web/html.py
+++ /dev/null
@@ -1,49 +0,0 @@
-
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""I hold HTML generation helpers.
-"""
-
-from twisted.python import log
-#t.w imports
-from twisted.web import resource
-
-import traceback, string
-
-from cStringIO import StringIO
-from microdom import escape
-
-def PRE(text):
- "Wrap <pre> tags around some text and HTML-escape it."
- return "<pre>"+escape(text)+"</pre>"
-
-def UL(lst):
- io = StringIO()
- io.write("<ul>\n")
- for el in lst:
- io.write("<li> %s</li>\n" % el)
- io.write("</ul>")
- return io.getvalue()
-
-def linkList(lst):
- io = StringIO()
- io.write("<ul>\n")
- for hr, el in lst:
- io.write('<li> <a href="%s">%s</a></li>\n' % (hr, el))
- io.write("</ul>")
- return io.getvalue()
-
-def output(func, *args, **kw):
- """output(func, *args, **kw) -> html string
- Either return the result of a function (which presumably returns an
- HTML-legal string) or a sparse HTMLized error message and a message
- in the server log.
- """
- try:
- return func(*args, **kw)
- except:
- log.msg("Error calling %r:" % (func,))
- log.err()
- return PRE("An error occurred.")
diff --git a/tools/buildbot/pylibs/twisted/web/http.py b/tools/buildbot/pylibs/twisted/web/http.py
deleted file mode 100644
index 1a68250..0000000
--- a/tools/buildbot/pylibs/twisted/web/http.py
+++ /dev/null
@@ -1,1244 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_http -*-
-
-# Copyright (c) 2001-2007 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""
-HyperText Transfer Protocol implementation.
-
-This is used by twisted.web.
-
-Future Plans:
- - HTTP client support will at some point be refactored to support HTTP/1.1.
- - Accept chunked data from clients in server.
- - Other missing HTTP features from the RFC.
-
-Maintainer: U{Itamar Shtull-Trauring<mailto:twisted@itamarst.org>}
-"""
-
-# system imports
-from cStringIO import StringIO
-import tempfile
-import base64, binascii
-import cgi
-import socket
-import math
-import time
-import calendar
-import warnings
-import os
-from urlparse import urlparse as _urlparse
-
-from zope.interface import implements
-
-# twisted imports
-from twisted.internet import interfaces, reactor, protocol, address
-from twisted.protocols import policies, basic
-from twisted.python import log
-try: # try importing the fast, C version
- from twisted.protocols._c_urlarg import unquote
-except ImportError:
- from urllib import unquote
-
-
-protocol_version = "HTTP/1.1"
-
-_CONTINUE = 100
-SWITCHING = 101
-
-OK = 200
-CREATED = 201
-ACCEPTED = 202
-NON_AUTHORITATIVE_INFORMATION = 203
-NO_CONTENT = 204
-RESET_CONTENT = 205
-PARTIAL_CONTENT = 206
-MULTI_STATUS = 207
-
-MULTIPLE_CHOICE = 300
-MOVED_PERMANENTLY = 301
-FOUND = 302
-SEE_OTHER = 303
-NOT_MODIFIED = 304
-USE_PROXY = 305
-TEMPORARY_REDIRECT = 307
-
-BAD_REQUEST = 400
-UNAUTHORIZED = 401
-PAYMENT_REQUIRED = 402
-FORBIDDEN = 403
-NOT_FOUND = 404
-NOT_ALLOWED = 405
-NOT_ACCEPTABLE = 406
-PROXY_AUTH_REQUIRED = 407
-REQUEST_TIMEOUT = 408
-CONFLICT = 409
-GONE = 410
-LENGTH_REQUIRED = 411
-PRECONDITION_FAILED = 412
-REQUEST_ENTITY_TOO_LARGE = 413
-REQUEST_URI_TOO_LONG = 414
-UNSUPPORTED_MEDIA_TYPE = 415
-REQUESTED_RANGE_NOT_SATISFIABLE = 416
-EXPECTATION_FAILED = 417
-
-INTERNAL_SERVER_ERROR = 500
-NOT_IMPLEMENTED = 501
-BAD_GATEWAY = 502
-SERVICE_UNAVAILABLE = 503
-GATEWAY_TIMEOUT = 504
-HTTP_VERSION_NOT_SUPPORTED = 505
-INSUFFICIENT_STORAGE_SPACE = 507
-NOT_EXTENDED = 510
-
-RESPONSES = {
- # 100
- _CONTINUE: "Continue",
- SWITCHING: "Switching Protocols",
-
- # 200
- OK: "OK",
- CREATED: "Created",
- ACCEPTED: "Accepted",
- NON_AUTHORITATIVE_INFORMATION: "Non-Authoritative Information",
- NO_CONTENT: "No Content",
- RESET_CONTENT: "Reset Content.",
- PARTIAL_CONTENT: "Partial Content",
- MULTI_STATUS: "Multi-Status",
-
- # 300
- MULTIPLE_CHOICE: "Multiple Choices",
- MOVED_PERMANENTLY: "Moved Permanently",
- FOUND: "Found",
- SEE_OTHER: "See Other",
- NOT_MODIFIED: "Not Modified",
- USE_PROXY: "Use Proxy",
- # 306 not defined??
- TEMPORARY_REDIRECT: "Temporary Redirect",
-
- # 400
- BAD_REQUEST: "Bad Request",
- UNAUTHORIZED: "Unauthorized",
- PAYMENT_REQUIRED: "Payment Required",
- FORBIDDEN: "Forbidden",
- NOT_FOUND: "Not Found",
- NOT_ALLOWED: "Method Not Allowed",
- NOT_ACCEPTABLE: "Not Acceptable",
- PROXY_AUTH_REQUIRED: "Proxy Authentication Required",
- REQUEST_TIMEOUT: "Request Time-out",
- CONFLICT: "Conflict",
- GONE: "Gone",
- LENGTH_REQUIRED: "Length Required",
- PRECONDITION_FAILED: "Precondition Failed",
- REQUEST_ENTITY_TOO_LARGE: "Request Entity Too Large",
- REQUEST_URI_TOO_LONG: "Request-URI Too Long",
- UNSUPPORTED_MEDIA_TYPE: "Unsupported Media Type",
- REQUESTED_RANGE_NOT_SATISFIABLE: "Requested Range not satisfiable",
- EXPECTATION_FAILED: "Expectation Failed",
-
- # 500
- INTERNAL_SERVER_ERROR: "Internal Server Error",
- NOT_IMPLEMENTED: "Not Implemented",
- BAD_GATEWAY: "Bad Gateway",
- SERVICE_UNAVAILABLE: "Service Unavailable",
- GATEWAY_TIMEOUT: "Gateway Time-out",
- HTTP_VERSION_NOT_SUPPORTED: "HTTP Version not supported",
- INSUFFICIENT_STORAGE_SPACE: "Insufficient Storage Space",
- NOT_EXTENDED: "Not Extended"
- }
-
-CACHED = """Magic constant returned by http.Request methods to set cache
-validation headers when the request is conditional and the value fails
-the condition."""
-
-# backwards compatability
-responses = RESPONSES
-
-
-# datetime parsing and formatting
-weekdayname = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
-monthname = [None,
- 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
- 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
-weekdayname_lower = [name.lower() for name in weekdayname]
-monthname_lower = [name and name.lower() for name in monthname]
-
-def urlparse(url):
- """
- Parse an URL into six components.
-
- This is similar to L{urlparse.urlparse}, but rejects C{unicode} input
- and always produces C{str} output.
-
- @type url: C{str}
-
- @raise TypeError: The given url was a C{unicode} string instead of a
- C{str}.
-
- @rtype: six-tuple of str
- @return: The scheme, net location, path, params, query string, and fragment
- of the URL.
- """
- if isinstance(url, unicode):
- raise TypeError("url must be str, not unicode")
- scheme, netloc, path, params, query, fragment = _urlparse(url)
- if isinstance(scheme, unicode):
- scheme = scheme.encode('ascii')
- netloc = netloc.encode('ascii')
- path = path.encode('ascii')
- query = query.encode('ascii')
- fragment = fragment.encode('ascii')
- return scheme, netloc, path, params, query, fragment
-
-
-def parse_qs(qs, keep_blank_values=0, strict_parsing=0, unquote=unquote):
- """like cgi.parse_qs, only with custom unquote function"""
- d = {}
- items = [s2 for s1 in qs.split("&") for s2 in s1.split(";")]
- for item in items:
- try:
- k, v = item.split("=", 1)
- except ValueError:
- if strict_parsing:
- raise
- continue
- if v or keep_blank_values:
- k = unquote(k.replace("+", " "))
- v = unquote(v.replace("+", " "))
- if k in d:
- d[k].append(v)
- else:
- d[k] = [v]
- return d
-
-def datetimeToString(msSinceEpoch=None):
- """Convert seconds since epoch to HTTP datetime string."""
- if msSinceEpoch == None:
- msSinceEpoch = time.time()
- year, month, day, hh, mm, ss, wd, y, z = time.gmtime(msSinceEpoch)
- s = "%s, %02d %3s %4d %02d:%02d:%02d GMT" % (
- weekdayname[wd],
- day, monthname[month], year,
- hh, mm, ss)
- return s
-
-def datetimeToLogString(msSinceEpoch=None):
- """Convert seconds since epoch to log datetime string."""
- if msSinceEpoch == None:
- msSinceEpoch = time.time()
- year, month, day, hh, mm, ss, wd, y, z = time.gmtime(msSinceEpoch)
- s = "[%02d/%3s/%4d:%02d:%02d:%02d +0000]" % (
- day, monthname[month], year,
- hh, mm, ss)
- return s
-
-
-# a hack so we don't need to recalculate log datetime every hit,
-# at the price of a small, unimportant, inaccuracy.
-_logDateTime = None
-_logDateTimeUsers = 0
-_resetLogDateTimeID = None
-
-def _resetLogDateTime():
- global _logDateTime
- global _resetLogDateTime
- global _resetLogDateTimeID
- _logDateTime = datetimeToLogString()
- _resetLogDateTimeID = reactor.callLater(1, _resetLogDateTime)
-
-def _logDateTimeStart():
- global _logDateTimeUsers
- if not _logDateTimeUsers:
- _resetLogDateTime()
- _logDateTimeUsers += 1
-
-def _logDateTimeStop():
- global _logDateTimeUsers
- _logDateTimeUsers -= 1;
- if (not _logDateTimeUsers and _resetLogDateTimeID
- and _resetLogDateTimeID.active()):
- _resetLogDateTimeID.cancel()
-
-def timegm(year, month, day, hour, minute, second):
- """Convert time tuple in GMT to seconds since epoch, GMT"""
- EPOCH = 1970
- assert year >= EPOCH
- assert 1 <= month <= 12
- days = 365*(year-EPOCH) + calendar.leapdays(EPOCH, year)
- for i in range(1, month):
- days = days + calendar.mdays[i]
- if month > 2 and calendar.isleap(year):
- days = days + 1
- days = days + day - 1
- hours = days*24 + hour
- minutes = hours*60 + minute
- seconds = minutes*60 + second
- return seconds
-
-def stringToDatetime(dateString):
- """Convert an HTTP date string (one of three formats) to seconds since epoch."""
- parts = dateString.split()
-
- if not parts[0][0:3].lower() in weekdayname_lower:
- # Weekday is stupid. Might have been omitted.
- try:
- return stringToDatetime("Sun, "+dateString)
- except ValueError:
- # Guess not.
- pass
-
- partlen = len(parts)
- if (partlen == 5 or partlen == 6) and parts[1].isdigit():
- # 1st date format: Sun, 06 Nov 1994 08:49:37 GMT
- # (Note: "GMT" is literal, not a variable timezone)
- # (also handles without "GMT")
- # This is the normal format
- day = parts[1]
- month = parts[2]
- year = parts[3]
- time = parts[4]
- elif (partlen == 3 or partlen == 4) and parts[1].find('-') != -1:
- # 2nd date format: Sunday, 06-Nov-94 08:49:37 GMT
- # (Note: "GMT" is literal, not a variable timezone)
- # (also handles without without "GMT")
- # Two digit year, yucko.
- day, month, year = parts[1].split('-')
- time = parts[2]
- year=int(year)
- if year < 69:
- year = year + 2000
- elif year < 100:
- year = year + 1900
- elif len(parts) == 5:
- # 3rd date format: Sun Nov 6 08:49:37 1994
- # ANSI C asctime() format.
- day = parts[2]
- month = parts[1]
- year = parts[4]
- time = parts[3]
- else:
- raise ValueError("Unknown datetime format %r" % dateString)
-
- day = int(day)
- month = int(monthname_lower.index(month.lower()))
- year = int(year)
- hour, min, sec = map(int, time.split(':'))
- return int(timegm(year, month, day, hour, min, sec))
-
-def toChunk(data):
- """Convert string to a chunk.
-
- @returns: a tuple of strings representing the chunked encoding of data"""
- return ("%x\r\n" % len(data), data, "\r\n")
-
-def fromChunk(data):
- """Convert chunk to string.
-
- @returns: tuple (result, remaining), may raise ValueError.
- """
- prefix, rest = data.split('\r\n', 1)
- length = int(prefix, 16)
- if length < 0:
- raise ValueError("Chunk length must be >= 0, not %d" % (length,))
- if not rest[length:length + 2] == '\r\n':
- raise ValueError, "chunk must end with CRLF"
- return rest[:length], rest[length + 2:]
-
-
-def parseContentRange(header):
- """Parse a content-range header into (start, end, realLength).
-
- realLength might be None if real length is not known ('*').
- """
- kind, other = header.strip().split()
- if kind.lower() != "bytes":
- raise ValueError, "a range of type %r is not supported"
- startend, realLength = other.split("/")
- start, end = map(int, startend.split("-"))
- if realLength == "*":
- realLength = None
- else:
- realLength = int(realLength)
- return (start, end, realLength)
-
-
-class StringTransport:
- """
- I am a StringIO wrapper that conforms for the transport API. I support
- the `writeSequence' method.
- """
- def __init__(self):
- self.s = StringIO()
- def writeSequence(self, seq):
- self.s.write(''.join(seq))
- def __getattr__(self, attr):
- return getattr(self.__dict__['s'], attr)
-
-
-class HTTPClient(basic.LineReceiver):
- """A client for HTTP 1.0
-
- Notes:
- You probably want to send a 'Host' header with the name of
- the site you're connecting to, in order to not break name
- based virtual hosting.
- """
- length = None
- firstLine = 1
- __buffer = None
-
- def sendCommand(self, command, path):
- self.transport.write('%s %s HTTP/1.0\r\n' % (command, path))
-
- def sendHeader(self, name, value):
- self.transport.write('%s: %s\r\n' % (name, value))
-
- def endHeaders(self):
- self.transport.write('\r\n')
-
- def lineReceived(self, line):
- if self.firstLine:
- self.firstLine = 0
- l = line.split(None, 2)
- version = l[0]
- status = l[1]
- try:
- message = l[2]
- except IndexError:
- # sometimes there is no message
- message = ""
- self.handleStatus(version, status, message)
- return
- if line:
- key, val = line.split(':', 1)
- val = val.lstrip()
- self.handleHeader(key, val)
- if key.lower() == 'content-length':
- self.length = int(val)
- else:
- self.__buffer = StringIO()
- self.handleEndHeaders()
- self.setRawMode()
-
- def connectionLost(self, reason):
- self.handleResponseEnd()
-
- def handleResponseEnd(self):
- if self.__buffer is not None:
- b = self.__buffer.getvalue()
- self.__buffer = None
- self.handleResponse(b)
-
- def handleResponsePart(self, data):
- self.__buffer.write(data)
-
- def connectionMade(self):
- pass
-
- handleStatus = handleHeader = handleEndHeaders = lambda *args: None
-
- def rawDataReceived(self, data):
- if self.length is not None:
- data, rest = data[:self.length], data[self.length:]
- self.length -= len(data)
- else:
- rest = ''
- self.handleResponsePart(data)
- if self.length == 0:
- self.handleResponseEnd()
- self.setLineMode(rest)
-
-
-# response codes that must have empty bodies
-NO_BODY_CODES = (204, 304)
-
-class Request:
- """A HTTP request.
-
- Subclasses should override the process() method to determine how
- the request will be processed.
-
- @ivar method: The HTTP method that was used.
- @ivar uri: The full URI that was requested (includes arguments).
- @ivar path: The path only (arguments not included).
- @ivar args: All of the arguments, including URL and POST arguments.
- @type args: A mapping of strings (the argument names) to lists of values.
- i.e., ?foo=bar&foo=baz&quux=spam results in
- {'foo': ['bar', 'baz'], 'quux': ['spam']}.
- @ivar received_headers: All received headers
- """
-
- implements(interfaces.IConsumer)
-
- producer = None
- finished = 0
- code = OK
- code_message = RESPONSES[OK]
- method = "(no method yet)"
- clientproto = "(no clientproto yet)"
- uri = "(no uri yet)"
- startedWriting = 0
- chunked = 0
- sentLength = 0 # content-length of response, or total bytes sent via chunking
- etag = None
- lastModified = None
- _forceSSL = 0
-
- def __init__(self, channel, queued):
- """
- @param channel: the channel we're connected to.
- @param queued: are we in the request queue, or can we start writing to
- the transport?
- """
- self.channel = channel
- self.queued = queued
- self.received_headers = {}
- self.received_cookies = {}
- self.headers = {} # outgoing headers
- self.cookies = [] # outgoing cookies
-
- if queued:
- self.transport = StringTransport()
- else:
- self.transport = self.channel.transport
-
- def _cleanup(self):
- """Called when have finished responding and are no longer queued."""
- if self.producer:
- log.err(RuntimeError("Producer was not unregistered for %s" % self.uri))
- self.unregisterProducer()
- self.channel.requestDone(self)
- del self.channel
- try:
- self.content.close()
- except OSError:
- # win32 suckiness, no idea why it does this
- pass
- del self.content
-
- # methods for channel - end users should not use these
-
- def noLongerQueued(self):
- """Notify the object that it is no longer queued.
-
- We start writing whatever data we have to the transport, etc.
-
- This method is not intended for users.
- """
- if not self.queued:
- raise RuntimeError, "noLongerQueued() got called unnecessarily."
-
- self.queued = 0
-
- # set transport to real one and send any buffer data
- data = self.transport.getvalue()
- self.transport = self.channel.transport
- if data:
- self.transport.write(data)
-
- # if we have producer, register it with transport
- if (self.producer is not None) and not self.finished:
- self.transport.registerProducer(self.producer, self.streamingProducer)
-
- # if we're finished, clean up
- if self.finished:
- self._cleanup()
-
- def gotLength(self, length):
- """Called when HTTP channel got length of content in this request.
-
- This method is not intended for users.
- """
- if length < 100000:
- self.content = StringIO()
- else:
- self.content = tempfile.TemporaryFile()
-
- def parseCookies(self):
- """Parse cookie headers.
-
- This method is not intended for users."""
- cookietxt = self.getHeader("cookie")
- if cookietxt:
- for cook in cookietxt.split(';'):
- cook = cook.lstrip()
- try:
- k, v = cook.split('=', 1)
- self.received_cookies[k] = v
- except ValueError:
- pass
-
- def handleContentChunk(self, data):
- """Write a chunk of data.
-
- This method is not intended for users.
- """
- self.content.write(data)
-
- def requestReceived(self, command, path, version):
- """Called by channel when all data has been received.
-
- This method is not intended for users.
- """
- self.content.seek(0,0)
- self.args = {}
- self.stack = []
-
- self.method, self.uri = command, path
- self.clientproto = version
- x = self.uri.split('?', 1)
-
- if len(x) == 1:
- self.path = self.uri
- else:
- self.path, argstring = x
- self.args = parse_qs(argstring, 1)
-
- # cache the client and server information, we'll need this later to be
- # serialized and sent with the request so CGIs will work remotely
- self.client = self.channel.transport.getPeer()
- self.host = self.channel.transport.getHost()
-
- # Argument processing
- args = self.args
- ctype = self.getHeader('content-type')
- if self.method == "POST" and ctype:
- mfd = 'multipart/form-data'
- key, pdict = cgi.parse_header(ctype)
- if key == 'application/x-www-form-urlencoded':
- args.update(parse_qs(self.content.read(), 1))
- elif key == mfd:
- try:
- args.update(cgi.parse_multipart(self.content, pdict))
- except KeyError, e:
- if e.args[0] == 'content-disposition':
- # Parse_multipart can't cope with missing
- # content-dispostion headers in multipart/form-data
- # parts, so we catch the exception and tell the client
- # it was a bad request.
- self.channel.transport.write(
- "HTTP/1.1 400 Bad Request\r\n\r\n")
- self.channel.transport.loseConnection()
- return
- raise
-
- self.process()
-
- def __repr__(self):
- return '<%s %s %s>'% (self.method, self.uri, self.clientproto)
-
- def process(self):
- """Override in subclasses.
-
- This method is not intended for users.
- """
- pass
-
-
- # consumer interface
-
- def registerProducer(self, producer, streaming):
- """Register a producer."""
- if self.producer:
- raise ValueError, "registering producer %s before previous one (%s) was unregistered" % (producer, self.producer)
-
- self.streamingProducer = streaming
- self.producer = producer
-
- if self.queued:
- producer.pauseProducing()
- else:
- self.transport.registerProducer(producer, streaming)
-
- def unregisterProducer(self):
- """Unregister the producer."""
- if not self.queued:
- self.transport.unregisterProducer()
- self.producer = None
-
- # private http response methods
-
- def _sendError(self, code, resp=''):
- self.transport.write('%s %s %s\r\n\r\n' % (self.clientproto, code, resp))
-
-
- # The following is the public interface that people should be
- # writing to.
-
- def getHeader(self, key):
- """Get a header that was sent from the network.
- """
- return self.received_headers.get(key.lower())
-
- def getCookie(self, key):
- """Get a cookie that was sent from the network.
- """
- return self.received_cookies.get(key)
-
- def finish(self):
- """We are finished writing data."""
- if self.finished:
- warnings.warn("Warning! request.finish called twice.", stacklevel=2)
- return
-
- if not self.startedWriting:
- # write headers
- self.write('')
-
- if self.chunked:
- # write last chunk and closing CRLF
- self.transport.write("0\r\n\r\n")
-
- # log request
- if hasattr(self.channel, "factory"):
- self.channel.factory.log(self)
-
- self.finished = 1
- if not self.queued:
- self._cleanup()
-
- def write(self, data):
- """
- Write some data as a result of an HTTP request. The first
- time this is called, it writes out response data.
- """
- if not self.startedWriting:
- self.startedWriting = 1
- version = self.clientproto
- l = []
- l.append('%s %s %s\r\n' % (version, self.code,
- self.code_message))
- # if we don't have a content length, we send data in
- # chunked mode, so that we can support pipelining in
- # persistent connections.
- if ((version == "HTTP/1.1") and
- (self.headers.get('content-length', None) is None) and
- self.method != "HEAD" and self.code not in NO_BODY_CODES):
- l.append("%s: %s\r\n" % ('Transfer-encoding', 'chunked'))
- self.chunked = 1
- if self.lastModified is not None:
- if self.headers.has_key('last-modified'):
- log.msg("Warning: last-modified specified both in"
- " header list and lastModified attribute.")
- else:
- self.setHeader('last-modified',
- datetimeToString(self.lastModified))
- if self.etag is not None:
- self.setHeader('ETag', self.etag)
- for name, value in self.headers.items():
- l.append("%s: %s\r\n" % (name.capitalize(), value))
- for cookie in self.cookies:
- l.append('%s: %s\r\n' % ("Set-Cookie", cookie))
- l.append("\r\n")
-
- self.transport.writeSequence(l)
-
- # if this is a "HEAD" request, we shouldn't return any data
- if self.method == "HEAD":
- self.write = lambda data: None
- return
-
- # for certain result codes, we should never return any data
- if self.code in NO_BODY_CODES:
- self.write = lambda data: None
- return
-
- self.sentLength = self.sentLength + len(data)
- if data:
- if self.chunked:
- self.transport.writeSequence(toChunk(data))
- else:
- self.transport.write(data)
-
- def addCookie(self, k, v, expires=None, domain=None, path=None, max_age=None, comment=None, secure=None):
- """Set an outgoing HTTP cookie.
-
- In general, you should consider using sessions instead of cookies, see
- twisted.web.server.Request.getSession and the
- twisted.web.server.Session class for details.
- """
- cookie = '%s=%s' % (k, v)
- if expires is not None:
- cookie = cookie +"; Expires=%s" % expires
- if domain is not None:
- cookie = cookie +"; Domain=%s" % domain
- if path is not None:
- cookie = cookie +"; Path=%s" % path
- if max_age is not None:
- cookie = cookie +"; Max-Age=%s" % max_age
- if comment is not None:
- cookie = cookie +"; Comment=%s" % comment
- if secure:
- cookie = cookie +"; Secure"
- self.cookies.append(cookie)
-
- def setResponseCode(self, code, message=None):
- """Set the HTTP response code.
- """
- self.code = code
- if message:
- self.code_message = message
- else:
- self.code_message = RESPONSES.get(code, "Unknown Status")
-
- def setHeader(self, k, v):
- """Set an outgoing HTTP header.
- """
- self.headers[k.lower()] = v
-
- def redirect(self, url):
- """Utility function that does a redirect.
-
- The request should have finish() called after this.
- """
- self.setResponseCode(FOUND)
- self.setHeader("location", url)
-
- def setLastModified(self, when):
- """Set the X{Last-Modified} time for the response to this request.
-
- If I am called more than once, I ignore attempts to set
- Last-Modified earlier, only replacing the Last-Modified time
- if it is to a later value.
-
- If I am a conditional request, I may modify my response code
- to L{NOT_MODIFIED} if appropriate for the time given.
-
- @param when: The last time the resource being returned was
- modified, in seconds since the epoch.
- @type when: number
- @return: If I am a X{If-Modified-Since} conditional request and
- the time given is not newer than the condition, I return
- L{http.CACHED<CACHED>} to indicate that you should write no
- body. Otherwise, I return a false value.
- """
- # time.time() may be a float, but the HTTP-date strings are
- # only good for whole seconds.
- when = long(math.ceil(when))
- if (not self.lastModified) or (self.lastModified < when):
- self.lastModified = when
-
- modified_since = self.getHeader('if-modified-since')
- if modified_since:
- modified_since = stringToDatetime(modified_since.split(';', 1)[0])
- if modified_since >= when:
- self.setResponseCode(NOT_MODIFIED)
- return CACHED
- return None
-
- def setETag(self, etag):
- """Set an X{entity tag} for the outgoing response.
-
- That's \"entity tag\" as in the HTTP/1.1 X{ETag} header, \"used
- for comparing two or more entities from the same requested
- resource.\"
-
- If I am a conditional request, I may modify my response code
- to L{NOT_MODIFIED} or L{PRECONDITION_FAILED}, if appropriate
- for the tag given.
-
- @param etag: The entity tag for the resource being returned.
- @type etag: string
- @return: If I am a X{If-None-Match} conditional request and
- the tag matches one in the request, I return
- L{http.CACHED<CACHED>} to indicate that you should write
- no body. Otherwise, I return a false value.
- """
- if etag:
- self.etag = etag
-
- tags = self.getHeader("if-none-match")
- if tags:
- tags = tags.split()
- if (etag in tags) or ('*' in tags):
- self.setResponseCode(((self.method in ("HEAD", "GET"))
- and NOT_MODIFIED)
- or PRECONDITION_FAILED)
- return CACHED
- return None
-
- def getAllHeaders(self):
- """Return dictionary of all headers the request received."""
- return self.received_headers
-
- def getRequestHostname(self):
- """
- Get the hostname that the user passed in to the request.
-
- This will either use the Host: header (if it is available) or the
- host we are listening on if the header is unavailable.
-
- @returns: the requested hostname
- @rtype: C{str}
- """
- return (self.getHeader('host') or
- socket.gethostbyaddr(self.getHost()[1])[0]
- ).split(':')[0]
-
- def getHost(self):
- """Get my originally requesting transport's host.
-
- Don't rely on the 'transport' attribute, since Request objects may be
- copied remotely. For information on this method's return value, see
- twisted.internet.tcp.Port.
- """
- return self.host
-
- def setHost(self, host, port, ssl=0):
- """Change the host and port the request thinks it's using.
-
- This method is useful for working with reverse HTTP proxies (e.g.
- both Squid and Apache's mod_proxy can do this), when the address
- the HTTP client is using is different than the one we're listening on.
-
- For example, Apache may be listening on https://www.example.com, and then
- forwarding requests to http://localhost:8080, but we don't want HTML produced
- by Twisted to say 'http://localhost:8080', they should say 'https://www.example.com',
- so we do::
-
- request.setHost('www.example.com', 443, ssl=1)
-
- This method is experimental.
- """
- self._forceSSL = ssl
- self.received_headers["host"] = host
- self.host = address.IPv4Address("TCP", host, port)
-
- def getClientIP(self):
- """
- Return the IP address of the client who submitted this request.
-
- @returns: the client IP address
- @rtype: C{str}
- """
- if isinstance(self.client, address.IPv4Address):
- return self.client.host
- else:
- return None
-
- def isSecure(self):
- """
- Return True if this request is using a secure transport.
-
- Normally this method returns True if this request's HTTPChannel
- instance is using a transport that implements ISSLTransport.
-
- This will also return True if setHost() has been called
- with ssl=True.
-
- @returns: True if this request is secure
- @rtype: C{bool}
- """
- if self._forceSSL:
- return True
- transport = getattr(getattr(self, 'channel', None), 'transport', None)
- if interfaces.ISSLTransport(transport, None) is not None:
- return True
- return False
-
- def _authorize(self):
- # Authorization, (mostly) per the RFC
- try:
- authh = self.getHeader("Authorization")
- if not authh:
- self.user = self.password = ''
- return
- bas, upw = authh.split()
- if bas.lower() != "basic":
- raise ValueError
- upw = base64.decodestring(upw)
- self.user, self.password = upw.split(':', 1)
- except (binascii.Error, ValueError):
- self.user = self.password = ""
- except:
- log.err()
- self.user = self.password = ""
-
- def getUser(self):
- """
- Return the HTTP user sent with this request, if any.
-
- If no user was supplied, return the empty string.
-
- @returns: the HTTP user, if any
- @rtype: C{str}
- """
- try:
- return self.user
- except:
- pass
- self._authorize()
- return self.user
-
- def getPassword(self):
- """
- Return the HTTP password sent with this request, if any.
-
- If no password was supplied, return the empty string.
-
- @returns: the HTTP password, if any
- @rtype: C{str}
- """
- try:
- return self.password
- except:
- pass
- self._authorize()
- return self.password
-
- def getClient(self):
- if self.client.type != 'TCP':
- return None
- host = self.client.host
- try:
- name, names, addresses = socket.gethostbyaddr(host)
- except socket.error:
- return host
- names.insert(0, name)
- for name in names:
- if '.' in name:
- return name
- return names[0]
-
- def connectionLost(self, reason):
- """connection was lost"""
- pass
-
-class HTTPChannel(basic.LineReceiver, policies.TimeoutMixin):
- """A receiver for HTTP requests."""
-
- maxHeaders = 500 # max number of headers allowed per request
-
- length = 0
- persistent = 1
- __header = ''
- __first_line = 1
- __content = None
-
- # set in instances or subclasses
- requestFactory = Request
-
- _savedTimeOut = None
-
- def __init__(self):
- # the request queue
- self.requests = []
-
- def connectionMade(self):
- self.setTimeout(self.timeOut)
-
- def lineReceived(self, line):
- self.resetTimeout()
-
- if self.__first_line:
- # if this connection is not persistent, drop any data which
- # the client (illegally) sent after the last request.
- if not self.persistent:
- self.dataReceived = self.lineReceived = lambda *args: None
- return
-
- # IE sends an extraneous empty line (\r\n) after a POST request;
- # eat up such a line, but only ONCE
- if not line and self.__first_line == 1:
- self.__first_line = 2
- return
-
- # create a new Request object
- request = self.requestFactory(self, len(self.requests))
- self.requests.append(request)
-
- self.__first_line = 0
- parts = line.split()
- if len(parts) != 3:
- self.transport.write("HTTP/1.1 400 Bad Request\r\n\r\n")
- self.transport.loseConnection()
- return
- command, request, version = parts
- self._command = command
- self._path = request
- self._version = version
- elif line == '':
- if self.__header:
- self.headerReceived(self.__header)
- self.__header = ''
- self.allHeadersReceived()
- if self.length == 0:
- self.allContentReceived()
- else:
- self.setRawMode()
- elif line[0] in ' \t':
- self.__header = self.__header+'\n'+line
- else:
- if self.__header:
- self.headerReceived(self.__header)
- self.__header = line
-
- def headerReceived(self, line):
- """Do pre-processing (for content-length) and store this header away.
- """
- header, data = line.split(':', 1)
- header = header.lower()
- data = data.strip()
- if header == 'content-length':
- self.length = int(data)
- reqHeaders = self.requests[-1].received_headers
- reqHeaders[header] = data
- if len(reqHeaders) > self.maxHeaders:
- self.transport.write("HTTP/1.1 400 Bad Request\r\n\r\n")
- self.transport.loseConnection()
-
- def allContentReceived(self):
- command = self._command
- path = self._path
- version = self._version
-
- # reset ALL state variables, so we don't interfere with next request
- self.length = 0
- self._header = ''
- self.__first_line = 1
- del self._command, self._path, self._version
-
- # Disable the idle timeout, in case this request takes a long
- # time to finish generating output.
- if self.timeOut:
- self._savedTimeOut = self.setTimeout(None)
-
- req = self.requests[-1]
- req.requestReceived(command, path, version)
-
- def rawDataReceived(self, data):
- if len(data) < self.length:
- self.requests[-1].handleContentChunk(data)
- self.length = self.length - len(data)
- else:
- self.requests[-1].handleContentChunk(data[:self.length])
- extraneous = data[self.length:]
- self.allContentReceived()
- self.setLineMode(extraneous)
-
- def allHeadersReceived(self):
- req = self.requests[-1]
- req.parseCookies()
- self.persistent = self.checkPersistence(req, self._version)
- req.gotLength(self.length)
-
- def checkPersistence(self, request, version):
- """Check if the channel should close or not."""
- connection = request.getHeader('connection')
- if connection:
- tokens = map(str.lower, connection.split(' '))
- else:
- tokens = []
-
- # HTTP 1.0 persistent connection support is currently disabled,
- # since we need a way to disable pipelining. HTTP 1.0 can't do
- # pipelining since we can't know in advance if we'll have a
- # content-length header, if we don't have the header we need to close the
- # connection. In HTTP 1.1 this is not an issue since we use chunked
- # encoding if content-length is not available.
-
- #if version == "HTTP/1.0":
- # if 'keep-alive' in tokens:
- # request.setHeader('connection', 'Keep-Alive')
- # return 1
- # else:
- # return 0
- if version == "HTTP/1.1":
- if 'close' in tokens:
- request.setHeader('connection', 'close')
- return 0
- else:
- return 1
- else:
- return 0
-
- def requestDone(self, request):
- """Called by first request in queue when it is done."""
- if request != self.requests[0]: raise TypeError
- del self.requests[0]
-
- if self.persistent:
- # notify next request it can start writing
- if self.requests:
- self.requests[0].noLongerQueued()
- else:
- if self._savedTimeOut:
- self.setTimeout(self._savedTimeOut)
- else:
- self.transport.loseConnection()
-
- def timeoutConnection(self):
- log.msg("Timing out client: %s" % str(self.transport.getPeer()))
- policies.TimeoutMixin.timeoutConnection(self)
-
- def connectionLost(self, reason):
- self.setTimeout(None)
- for request in self.requests:
- request.connectionLost(reason)
-
-
-class HTTPFactory(protocol.ServerFactory):
- """Factory for HTTP server."""
-
- protocol = HTTPChannel
-
- logPath = None
-
- timeOut = 60 * 60 * 12
-
- def __init__(self, logPath=None, timeout=60*60*12):
- if logPath is not None:
- logPath = os.path.abspath(logPath)
- self.logPath = logPath
- self.timeOut = timeout
-
- def buildProtocol(self, addr):
- p = protocol.ServerFactory.buildProtocol(self, addr)
- # timeOut needs to be on the Protocol instance cause
- # TimeoutMixin expects it there
- p.timeOut = self.timeOut
- return p
-
- def startFactory(self):
- _logDateTimeStart()
- if self.logPath:
- self.logFile = self._openLogFile(self.logPath)
- else:
- self.logFile = log.logfile
-
- def stopFactory(self):
- if hasattr(self, "logFile"):
- if self.logFile != log.logfile:
- self.logFile.close()
- del self.logFile
- _logDateTimeStop()
-
- def _openLogFile(self, path):
- """Override in subclasses, e.g. to use twisted.python.logfile."""
- f = open(path, "a", 1)
- return f
-
- def _escape(self, s):
- # pain in the ass. Return a string like python repr, but always
- # escaped as if surrounding quotes were "".
- r = repr(s)
- if r[0] == "'":
- return r[1:-1].replace('"', '\\"').replace("\\'", "'")
- return r[1:-1]
-
- def log(self, request):
- """Log a request's result to the logfile, by default in combined log format."""
- if hasattr(self, "logFile"):
- line = '%s - - %s "%s" %d %s "%s" "%s"\n' % (
- request.getClientIP(),
- # request.getUser() or "-", # the remote user is almost never important
- _logDateTime,
- '%s %s %s' % (self._escape(request.method),
- self._escape(request.uri),
- self._escape(request.clientproto)),
- request.code,
- request.sentLength or "-",
- self._escape(request.getHeader("referer") or "-"),
- self._escape(request.getHeader("user-agent") or "-"))
- self.logFile.write(line)
diff --git a/tools/buildbot/pylibs/twisted/web/microdom.py b/tools/buildbot/pylibs/twisted/web/microdom.py
deleted file mode 100644
index b7b430c..0000000
--- a/tools/buildbot/pylibs/twisted/web/microdom.py
+++ /dev/null
@@ -1,873 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_xml -*-
-#
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-#
-
-"""Micro Document Object Model: a partial DOM implementation with SUX.
-
-This is an implementation of what we consider to be the useful subset of the
-DOM. The chief advantage of this library is that, not being burdened with
-standards compliance, it can remain very stable between versions. We can also
-implement utility 'pythonic' ways to access and mutate the XML tree.
-
-Since this has not subjected to a serious trial by fire, it is not recommended
-to use this outside of Twisted applications. However, it seems to work just
-fine for the documentation generator, which parses a fairly representative
-sample of XML.
-
-Microdom mainly focuses on working with HTML and XHTML.
-"""
-
-from __future__ import nested_scopes
-
-# System Imports
-import re
-from cStringIO import StringIO
-
-# Twisted Imports
-from twisted.web.sux import XMLParser, ParseError
-from twisted.python.util import InsensitiveDict
-
-# create NodeList class
-from types import ListType as NodeList
-from types import StringTypes, UnicodeType
-
-def getElementsByTagName(iNode, name):
- matches = []
- matches_append = matches.append # faster lookup. don't do this at home
- slice=[iNode]
- while len(slice)>0:
- c = slice.pop(0)
- if c.nodeName == name:
- matches_append(c)
- slice[:0] = c.childNodes
- return matches
-
-def getElementsByTagNameNoCase(iNode, name):
- name = name.lower()
- matches = []
- matches_append = matches.append
- slice=[iNode]
- while len(slice)>0:
- c = slice.pop(0)
- if c.nodeName.lower() == name:
- matches_append(c)
- slice[:0] = c.childNodes
- return matches
-
-# order is important
-HTML_ESCAPE_CHARS = (('&', '&amp;'), # don't add any entities before this one
- ('<', '&lt;'),
- ('>', '&gt;'),
- ('"', '&quot;'))
-REV_HTML_ESCAPE_CHARS = list(HTML_ESCAPE_CHARS)
-REV_HTML_ESCAPE_CHARS.reverse()
-
-XML_ESCAPE_CHARS = HTML_ESCAPE_CHARS + (("'", '&apos;'),)
-REV_XML_ESCAPE_CHARS = list(XML_ESCAPE_CHARS)
-REV_XML_ESCAPE_CHARS.reverse()
-
-def unescape(text, chars=REV_HTML_ESCAPE_CHARS):
- "Perform the exact opposite of 'escape'."
- for s, h in chars:
- text = text.replace(h, s)
- return text
-
-def escape(text, chars=HTML_ESCAPE_CHARS):
- "Escape a few XML special chars with XML entities."
- for s, h in chars:
- text = text.replace(s, h)
- return text
-
-
-class MismatchedTags(Exception):
-
- def __init__(self, filename, expect, got, endLine, endCol, begLine, begCol):
- (self.filename, self.expect, self.got, self.begLine, self.begCol, self.endLine,
- self.endCol) = filename, expect, got, begLine, begCol, endLine, endCol
-
- def __str__(self):
- return ("expected </%s>, got </%s> line: %s col: %s, began line: %s col: %s"
- % (self.expect, self.got, self.endLine, self.endCol, self.begLine,
- self.begCol))
-
-
-class Node(object):
- nodeName = "Node"
-
- def __init__(self, parentNode=None):
- self.parentNode = parentNode
- self.childNodes = []
-
- def isEqualToNode(self, n):
- for a, b in zip(self.childNodes, n.childNodes):
- if not a.isEqualToNode(b):
- return 0
- return 1
-
- def writexml(self, stream, indent='', addindent='', newl='', strip=0,
- nsprefixes={}, namespace=''):
- raise NotImplementedError()
-
- def toxml(self, indent='', addindent='', newl='', strip=0, nsprefixes={},
- namespace=''):
- s = StringIO()
- self.writexml(s, indent, addindent, newl, strip, nsprefixes, namespace)
- rv = s.getvalue()
- return rv
-
- def writeprettyxml(self, stream, indent='', addindent=' ', newl='\n', strip=0):
- return self.writexml(stream, indent, addindent, newl, strip)
-
- def toprettyxml(self, indent='', addindent=' ', newl='\n', strip=0):
- return self.toxml(indent, addindent, newl, strip)
-
- def cloneNode(self, deep=0, parent=None):
- raise NotImplementedError()
-
- def hasChildNodes(self):
- if self.childNodes:
- return 1
- else:
- return 0
-
- def appendChild(self, child):
- assert isinstance(child, Node)
- self.childNodes.append(child)
- child.parentNode = self
-
- def insertBefore(self, new, ref):
- i = self.childNodes.index(ref)
- new.parentNode = self
- self.childNodes.insert(i, new)
- return new
-
- def removeChild(self, child):
- if child in self.childNodes:
- self.childNodes.remove(child)
- child.parentNode = None
- return child
-
- def replaceChild(self, newChild, oldChild):
- assert isinstance(newChild, Node)
- #if newChild.parentNode:
- # newChild.parentNode.removeChild(newChild)
- assert (oldChild.parentNode is self,
- ('oldChild (%s): oldChild.parentNode (%s) != self (%s)'
- % (oldChild, oldChild.parentNode, self)))
- self.childNodes[self.childNodes.index(oldChild)] = newChild
- oldChild.parentNode = None
- newChild.parentNode = self
-
- def lastChild(self):
- return self.childNodes[-1]
-
- def firstChild(self):
- if len(self.childNodes):
- return self.childNodes[0]
- return None
-
- #def get_ownerDocument(self):
- # """This doesn't really get the owner document; microdom nodes
- # don't even have one necessarily. This gets the root node,
- # which is usually what you really meant.
- # *NOT DOM COMPLIANT.*
- # """
- # node=self
- # while (node.parentNode): node=node.parentNode
- # return node
- #ownerDocument=node.get_ownerDocument()
- # leaving commented for discussion; see also domhelpers.getParents(node)
-
-class Document(Node):
-
- def __init__(self, documentElement=None):
- Node.__init__(self)
- if documentElement:
- self.appendChild(documentElement)
-
- def cloneNode(self, deep=0, parent=None):
- d = Document()
- d.doctype = self.doctype
- if deep:
- newEl = self.documentElement.cloneNode(1, self)
- else:
- newEl = self.documentElement
- d.appendChild(newEl)
- return d
-
- doctype = None
-
- def isEqualToDocument(self, n):
- return (self.doctype == n.doctype) and self.isEqualToNode(n)
-
- def get_documentElement(self):
- return self.childNodes[0]
- documentElement=property(get_documentElement)
-
- def appendChild(self, c):
- assert not self.childNodes, "Only one element per document."
- Node.appendChild(self, c)
-
- def writexml(self, stream, indent='', addindent='', newl='', strip=0,
- nsprefixes={}, namespace=''):
- stream.write('<?xml version="1.0"?>' + newl)
- if self.doctype:
- stream.write("<!DOCTYPE "+self.doctype+">" + newl)
- self.documentElement.writexml(stream, indent, addindent, newl, strip,
- nsprefixes, namespace)
-
- # of dubious utility (?)
- def createElement(self, name, **kw):
- return Element(name, **kw)
-
- def createTextNode(self, text):
- return Text(text)
-
- def createComment(self, text):
- return Comment(text)
-
- def getElementsByTagName(self, name):
- if self.documentElement.caseInsensitive:
- return getElementsByTagNameNoCase(self, name)
- return getElementsByTagName(self, name)
-
- def getElementById(self, id):
- childNodes = self.childNodes[:]
- while childNodes:
- node = childNodes.pop(0)
- if node.childNodes:
- childNodes.extend(node.childNodes)
- if hasattr(node, 'getAttribute') and node.getAttribute("id") == id:
- return node
-
-
-class EntityReference(Node):
-
- def __init__(self, eref, parentNode=None):
- Node.__init__(self, parentNode)
- self.eref = eref
- self.nodeValue = self.data = "&" + eref + ";"
-
- def isEqualToEntityReference(self, n):
- if not isinstance(n, EntityReference):
- return 0
- return (self.eref == n.eref) and (self.nodeValue == n.nodeValue)
-
- def writexml(self, stream, indent='', addindent='', newl='', strip=0,
- nsprefixes={}, namespace=''):
- stream.write(self.nodeValue)
-
- def cloneNode(self, deep=0, parent=None):
- return EntityReference(self.eref, parent)
-
-
-class CharacterData(Node):
-
- def __init__(self, data, parentNode=None):
- Node.__init__(self, parentNode)
- self.value = self.data = self.nodeValue = data
-
- def isEqualToCharacterData(self, n):
- return self.value == n.value
-
-
-class Comment(CharacterData):
- """A comment node."""
-
- def writexml(self, stream, indent='', addindent='', newl='', strip=0,
- nsprefixes={}, namespace=''):
- val=self.data
- if isinstance(val, UnicodeType):
- val=val.encode('utf8')
- stream.write("<!--%s-->" % val)
-
- def cloneNode(self, deep=0, parent=None):
- return Comment(self.nodeValue, parent)
-
-
-class Text(CharacterData):
-
- def __init__(self, data, parentNode=None, raw=0):
- CharacterData.__init__(self, data, parentNode)
- self.raw = raw
-
- def cloneNode(self, deep=0, parent=None):
- return Text(self.nodeValue, parent, self.raw)
-
- def writexml(self, stream, indent='', addindent='', newl='', strip=0,
- nsprefixes={}, namespace=''):
- if self.raw:
- val = self.nodeValue
- if not isinstance(val, StringTypes):
- val = str(self.nodeValue)
- else:
- v = self.nodeValue
- if not isinstance(v, StringTypes):
- v = str(v)
- if strip:
- v = ' '.join(v.split())
- val = escape(v)
- if isinstance(val, UnicodeType):
- val = val.encode('utf8')
- stream.write(val)
-
- def __repr__(self):
- return "Text(%s" % repr(self.nodeValue) + ')'
-
-
-class CDATASection(CharacterData):
- def cloneNode(self, deep=0, parent=None):
- return CDATASection(self.nodeValue, parent)
-
- def writexml(self, stream, indent='', addindent='', newl='', strip=0,
- nsprefixes={}, namespace=''):
- stream.write("<![CDATA[")
- stream.write(self.nodeValue)
- stream.write("]]>")
-
-def _genprefix():
- i = 0
- while True:
- yield 'p' + str(i)
- i = i + 1
-genprefix = _genprefix().next
-
-class _Attr(CharacterData):
- "Support class for getAttributeNode."
-
-class Element(Node):
-
- preserveCase = 0
- caseInsensitive = 1
- nsprefixes = None
-
- def __init__(self, tagName, attributes=None, parentNode=None,
- filename=None, markpos=None,
- caseInsensitive=1, preserveCase=0,
- namespace=None):
- Node.__init__(self, parentNode)
- self.preserveCase = preserveCase or not caseInsensitive
- self.caseInsensitive = caseInsensitive
- if not preserveCase:
- tagName = tagName.lower()
- if attributes is None:
- self.attributes = {}
- else:
- self.attributes = attributes
- for k, v in self.attributes.items():
- self.attributes[k] = unescape(v)
-
- if caseInsensitive:
- self.attributes = InsensitiveDict(self.attributes,
- preserve=preserveCase)
-
- self.endTagName = self.nodeName = self.tagName = tagName
- self._filename = filename
- self._markpos = markpos
- self.namespace = namespace
-
- def addPrefixes(self, pfxs):
- if self.nsprefixes is None:
- self.nsprefixes = pfxs
- else:
- self.nsprefixes.update(pfxs)
-
- def endTag(self, endTagName):
- if not self.preserveCase:
- endTagName = endTagName.lower()
- self.endTagName = endTagName
-
- def isEqualToElement(self, n):
- if self.caseInsensitive:
- return ((self.attributes == n.attributes)
- and (self.nodeName.lower() == n.nodeName.lower()))
- return (self.attributes == n.attributes) and (self.nodeName == n.nodeName)
-
- def cloneNode(self, deep=0, parent=None):
- clone = Element(
- self.tagName, parentNode=parent, namespace=self.namespace,
- preserveCase=self.preserveCase, caseInsensitive=self.caseInsensitive)
- clone.attributes.update(self.attributes)
- if deep:
- clone.childNodes = [child.cloneNode(1, clone) for child in self.childNodes]
- else:
- clone.childNodes = []
- return clone
-
- def getElementsByTagName(self, name):
- if self.caseInsensitive:
- return getElementsByTagNameNoCase(self, name)
- return getElementsByTagName(self, name)
-
- def hasAttributes(self):
- return 1
-
- def getAttribute(self, name, default=None):
- return self.attributes.get(name, default)
-
- def getAttributeNS(self, ns, name, default=None):
- nsk = (ns, name)
- if self.attributes.has_key(nsk):
- return self.attributes[nsk]
- if ns == self.namespace:
- return self.attributes.get(name, default)
- return default
-
- def getAttributeNode(self, name):
- return _Attr(self.getAttribute(name), self)
-
- def setAttribute(self, name, attr):
- self.attributes[name] = attr
-
- def removeAttribute(self, name):
- if name in self.attributes:
- del self.attributes[name]
-
- def hasAttribute(self, name):
- return name in self.attributes
-
- def writexml(self, stream, indent='', addindent='', newl='', strip=0,
- nsprefixes={}, namespace=''):
- # write beginning
- ALLOWSINGLETON = ('img', 'br', 'hr', 'base', 'meta', 'link', 'param',
- 'area', 'input', 'col', 'basefont', 'isindex',
- 'frame')
- BLOCKELEMENTS = ('html', 'head', 'body', 'noscript', 'ins', 'del',
- 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'script',
- 'ul', 'ol', 'dl', 'pre', 'hr', 'blockquote',
- 'address', 'p', 'div', 'fieldset', 'table', 'tr',
- 'form', 'object', 'fieldset', 'applet', 'map')
- FORMATNICELY = ('tr', 'ul', 'ol', 'head')
-
- # this should never be necessary unless people start
- # changing .tagName on the fly(?)
- if not self.preserveCase:
- self.endTagName = self.tagName
- w = stream.write
- if self.nsprefixes:
- newprefixes = self.nsprefixes.copy()
- for ns in nsprefixes.keys():
- if ns in newprefixes:
- del newprefixes[ns]
- else:
- newprefixes = {}
-
- begin = ['<']
- if self.tagName in BLOCKELEMENTS:
- begin = [newl, indent] + begin
- bext = begin.extend
- writeattr = lambda _atr, _val: bext((' ', _atr, '="', escape(_val), '"'))
- if namespace != self.namespace and self.namespace is not None:
- if nsprefixes.has_key(self.namespace):
- prefix = nsprefixes[self.namespace]
- bext(prefix+':'+self.tagName)
- else:
- bext(self.tagName)
- writeattr("xmlns", self.namespace)
- else:
- bext(self.tagName)
- j = ''.join
- for attr, val in self.attributes.iteritems():
- if isinstance(attr, tuple):
- ns, key = attr
- if nsprefixes.has_key(ns):
- prefix = nsprefixes[ns]
- else:
- prefix = genprefix()
- newprefixes[ns] = prefix
- assert val is not None
- writeattr(prefix+':'+key,val)
- else:
- assert val is not None
- writeattr(attr, val)
- if newprefixes:
- for ns, prefix in newprefixes.iteritems():
- if prefix:
- writeattr('xmlns:'+prefix, ns)
- newprefixes.update(nsprefixes)
- downprefixes = newprefixes
- else:
- downprefixes = nsprefixes
- w(j(begin))
- if self.childNodes:
- w(">")
- newindent = indent + addindent
- for child in self.childNodes:
- if self.tagName in BLOCKELEMENTS and \
- self.tagName in FORMATNICELY:
- w(j((newl, newindent)))
- child.writexml(stream, newindent, addindent, newl, strip,
- downprefixes, self.namespace)
- if self.tagName in BLOCKELEMENTS:
- w(j((newl, indent)))
- w(j(("</", self.endTagName, '>')))
-
- elif self.tagName.lower() not in ALLOWSINGLETON:
- w(j(('></', self.endTagName, '>')))
- else:
- w(" />")
-
- def __repr__(self):
- rep = "Element(%s" % repr(self.nodeName)
- if self.attributes:
- rep += ", attributes=%r" % (self.attributes,)
- if self._filename:
- rep += ", filename=%r" % (self._filename,)
- if self._markpos:
- rep += ", markpos=%r" % (self._markpos,)
- return rep + ')'
-
- def __str__(self):
- rep = "<" + self.nodeName
- if self._filename or self._markpos:
- rep += " ("
- if self._filename:
- rep += repr(self._filename)
- if self._markpos:
- rep += " line %s column %s" % self._markpos
- if self._filename or self._markpos:
- rep += ")"
- for item in self.attributes.items():
- rep += " %s=%r" % item
- if self.hasChildNodes():
- rep += " >...</%s>" % self.nodeName
- else:
- rep += " />"
- return rep
-
-def _unescapeDict(d):
- dd = {}
- for k, v in d.items():
- dd[k] = unescape(v)
- return dd
-
-def _reverseDict(d):
- dd = {}
- for k, v in d.items():
- dd[v]=k
- return dd
-
-class MicroDOMParser(XMLParser):
-
- # <dash> glyph: a quick scan thru the DTD says BODY, AREA, LINK, IMG, HR,
- # P, DT, DD, LI, INPUT, OPTION, THEAD, TFOOT, TBODY, COLGROUP, COL, TR, TH,
- # TD, HEAD, BASE, META, HTML all have optional closing tags
-
- soonClosers = 'area link br img hr input base meta'.split()
- laterClosers = {'p': ['p', 'dt'],
- 'dt': ['dt','dd'],
- 'dd': ['dt', 'dd'],
- 'li': ['li'],
- 'tbody': ['thead', 'tfoot', 'tbody'],
- 'thead': ['thead', 'tfoot', 'tbody'],
- 'tfoot': ['thead', 'tfoot', 'tbody'],
- 'colgroup': ['colgroup'],
- 'col': ['col'],
- 'tr': ['tr'],
- 'td': ['td'],
- 'th': ['th'],
- 'head': ['body'],
- 'title': ['head', 'body'], # this looks wrong...
- 'option': ['option'],
- }
-
-
- def __init__(self, beExtremelyLenient=0, caseInsensitive=1, preserveCase=0,
- soonClosers=soonClosers, laterClosers=laterClosers):
- self.elementstack = []
- d = {'xmlns': 'xmlns', '': None}
- dr = _reverseDict(d)
- self.nsstack = [(d,None,dr)]
- self.documents = []
- self._mddoctype = None
- self.beExtremelyLenient = beExtremelyLenient
- self.caseInsensitive = caseInsensitive
- self.preserveCase = preserveCase or not caseInsensitive
- self.soonClosers = soonClosers
- self.laterClosers = laterClosers
- # self.indentlevel = 0
-
- def shouldPreserveSpace(self):
- for edx in xrange(len(self.elementstack)):
- el = self.elementstack[-edx]
- if el.tagName == 'pre' or el.getAttribute("xml:space", '') == 'preserve':
- return 1
- return 0
-
- def _getparent(self):
- if self.elementstack:
- return self.elementstack[-1]
- else:
- return None
-
- COMMENT = re.compile(r"\s*/[/*]\s*")
-
- def _fixScriptElement(self, el):
- # this deals with case where there is comment or CDATA inside
- # <script> tag and we want to do the right thing with it
- if not self.beExtremelyLenient or not len(el.childNodes) == 1:
- return
- c = el.firstChild()
- if isinstance(c, Text):
- # deal with nasty people who do stuff like:
- # <script> // <!--
- # x = 1;
- # // --></script>
- # tidy does this, for example.
- prefix = ""
- oldvalue = c.value
- match = self.COMMENT.match(oldvalue)
- if match:
- prefix = match.group()
- oldvalue = oldvalue[len(prefix):]
-
- # now see if contents are actual node and comment or CDATA
- try:
- e = parseString("<a>%s</a>" % oldvalue).childNodes[0]
- except (ParseError, MismatchedTags):
- return
- if len(e.childNodes) != 1:
- return
- e = e.firstChild()
- if isinstance(e, (CDATASection, Comment)):
- el.childNodes = []
- if prefix:
- el.childNodes.append(Text(prefix))
- el.childNodes.append(e)
-
- def gotDoctype(self, doctype):
- self._mddoctype = doctype
-
- def gotTagStart(self, name, attributes):
- # print ' '*self.indentlevel, 'start tag',name
- # self.indentlevel += 1
- parent = self._getparent()
- if (self.beExtremelyLenient and isinstance(parent, Element)):
- parentName = parent.tagName
- myName = name
- if self.caseInsensitive:
- parentName = parentName.lower()
- myName = myName.lower()
- if myName in self.laterClosers.get(parentName, []):
- self.gotTagEnd(parent.tagName)
- parent = self._getparent()
- attributes = _unescapeDict(attributes)
- namespaces = self.nsstack[-1][0]
- newspaces = {}
- for k, v in attributes.items():
- if k.startswith('xmlns'):
- spacenames = k.split(':',1)
- if len(spacenames) == 2:
- newspaces[spacenames[1]] = v
- else:
- newspaces[''] = v
- del attributes[k]
- if newspaces:
- namespaces = namespaces.copy()
- namespaces.update(newspaces)
- for k, v in attributes.items():
- ksplit = k.split(':', 1)
- if len(ksplit) == 2:
- pfx, tv = ksplit
- if pfx != 'xml' and namespaces.has_key(pfx):
- attributes[namespaces[pfx], tv] = v
- del attributes[k]
- el = Element(name, attributes, parent,
- self.filename, self.saveMark(),
- caseInsensitive=self.caseInsensitive,
- preserveCase=self.preserveCase,
- namespace=namespaces.get(''))
- revspaces = _reverseDict(newspaces)
- el.addPrefixes(revspaces)
-
- if newspaces:
- rscopy = self.nsstack[-1][2].copy()
- rscopy.update(revspaces)
- self.nsstack.append((namespaces, el, rscopy))
- self.elementstack.append(el)
- if parent:
- parent.appendChild(el)
- if (self.beExtremelyLenient and el.tagName in self.soonClosers):
- self.gotTagEnd(name)
-
- def _gotStandalone(self, factory, data):
- parent = self._getparent()
- te = factory(data, parent)
- if parent:
- parent.appendChild(te)
- elif self.beExtremelyLenient:
- self.documents.append(te)
-
- def gotText(self, data):
- if data.strip() or self.shouldPreserveSpace():
- self._gotStandalone(Text, data)
-
- def gotComment(self, data):
- self._gotStandalone(Comment, data)
-
- def gotEntityReference(self, entityRef):
- self._gotStandalone(EntityReference, entityRef)
-
- def gotCData(self, cdata):
- self._gotStandalone(CDATASection, cdata)
-
- def gotTagEnd(self, name):
- # print ' '*self.indentlevel, 'end tag',name
- # self.indentlevel -= 1
- if not self.elementstack:
- if self.beExtremelyLenient:
- return
- raise MismatchedTags(*((self.filename, "NOTHING", name)
- +self.saveMark()+(0,0)))
- el = self.elementstack.pop()
- pfxdix = self.nsstack[-1][2]
- if self.nsstack[-1][1] is el:
- nstuple = self.nsstack.pop()
- else:
- nstuple = None
- if self.caseInsensitive:
- tn = el.tagName.lower()
- cname = name.lower()
- else:
- tn = el.tagName
- cname = name
-
- nsplit = name.split(':',1)
- if len(nsplit) == 2:
- pfx, newname = nsplit
- ns = pfxdix.get(pfx,None)
- if ns is not None:
- if el.namespace != ns:
- if not self.beExtremelyLenient:
- raise MismatchedTags(*((self.filename, el.tagName, name)
- +self.saveMark()+el._markpos))
- if not (tn == cname):
- if self.beExtremelyLenient:
- if self.elementstack:
- lastEl = self.elementstack[0]
- for idx in xrange(len(self.elementstack)):
- if self.elementstack[-(idx+1)].tagName == cname:
- self.elementstack[-(idx+1)].endTag(name)
- break
- else:
- # this was a garbage close tag; wait for a real one
- self.elementstack.append(el)
- if nstuple is not None:
- self.nsstack.append(nstuple)
- return
- del self.elementstack[-(idx+1):]
- if not self.elementstack:
- self.documents.append(lastEl)
- return
- else:
- raise MismatchedTags(*((self.filename, el.tagName, name)
- +self.saveMark()+el._markpos))
- el.endTag(name)
- if not self.elementstack:
- self.documents.append(el)
- if self.beExtremelyLenient and el.tagName == "script":
- self._fixScriptElement(el)
-
- def connectionLost(self, reason):
- XMLParser.connectionLost(self, reason) # This can cause more events!
- if self.elementstack:
- if self.beExtremelyLenient:
- self.documents.append(self.elementstack[0])
- else:
- raise MismatchedTags(*((self.filename, self.elementstack[-1],
- "END_OF_FILE")
- +self.saveMark()
- +self.elementstack[-1]._markpos))
-
-
-def parse(readable, *args, **kwargs):
- """Parse HTML or XML readable."""
- if not hasattr(readable, "read"):
- readable = open(readable, "rb")
- mdp = MicroDOMParser(*args, **kwargs)
- mdp.filename = getattr(readable, "name", "<xmlfile />")
- mdp.makeConnection(None)
- if hasattr(readable,"getvalue"):
- mdp.dataReceived(readable.getvalue())
- else:
- r = readable.read(1024)
- while r:
- mdp.dataReceived(r)
- r = readable.read(1024)
- mdp.connectionLost(None)
-
- if not mdp.documents:
- raise ParseError(mdp.filename, 0, 0, "No top-level Nodes in document")
-
- if mdp.beExtremelyLenient:
- if len(mdp.documents) == 1:
- d = mdp.documents[0]
- if not isinstance(d, Element):
- el = Element("html")
- el.appendChild(d)
- d = el
- else:
- d = Element("html")
- for child in mdp.documents:
- d.appendChild(child)
- else:
- d = mdp.documents[0]
- doc = Document(d)
- doc.doctype = mdp._mddoctype
- return doc
-
-def parseString(st, *args, **kw):
- if isinstance(st, UnicodeType):
- # this isn't particularly ideal, but it does work.
- return parse(StringIO(st.encode('UTF-16')), *args, **kw)
- return parse(StringIO(st), *args, **kw)
-
-
-def parseXML(readable):
- """Parse an XML readable object."""
- return parse(readable, caseInsensitive=0, preserveCase=1)
-
-
-def parseXMLString(st):
- """Parse an XML readable object."""
- return parseString(st, caseInsensitive=0, preserveCase=1)
-
-
-# Utility
-
-class lmx:
- """Easy creation of XML."""
-
- def __init__(self, node='div'):
- if isinstance(node, StringTypes):
- node = Element(node)
- self.node = node
-
- def __getattr__(self, name):
- if name[0] == '_':
- raise AttributeError("no private attrs")
- return lambda **kw: self.add(name,**kw)
-
- def __setitem__(self, key, val):
- self.node.setAttribute(key, val)
-
- def __getitem__(self, key):
- return self.node.getAttribute(key)
-
- def text(self, txt, raw=0):
- nn = Text(txt, raw=raw)
- self.node.appendChild(nn)
- return self
-
- def add(self, tagName, **kw):
- newNode = Element(tagName, caseInsensitive=0, preserveCase=0)
- self.node.appendChild(newNode)
- xf = lmx(newNode)
- for k, v in kw.items():
- if k[0] == '_':
- k = k[1:]
- xf[k]=v
- return xf
diff --git a/tools/buildbot/pylibs/twisted/web/monitor.py b/tools/buildbot/pylibs/twisted/web/monitor.py
deleted file mode 100644
index 052e94c..0000000
--- a/tools/buildbot/pylibs/twisted/web/monitor.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-#
-from twisted.web import client
-from twisted.internet import reactor
-import md5
-from zope.interface import implements
-
-class IChangeNotified:
- pass
-
-class BaseChangeNotified:
-
- implements(IChangeNotified)
-
- def reportChange(self, old, new):
- pass
-
- def reportNoChange(self):
- pass
-
-class ChangeChecker:
-
- working = 0
- call = None
-
- def __init__(self, notified, url, delay=60):
- self.notified = notified
- self.url = url
- self.md5 = None
- self.delay = delay
-
- def start(self):
- self.working = 1
- self._getPage()
-
- def stop(self):
- if self.call:
- self.call.cancel()
- self.call = None
- self.working = 0
-
- def _getPage(self):
- d = client.getPage(self.url)
- d.addErrback(self.noPage)
- d.addCallback(self.page)
- self.call = None
-
- def noPage(self, e):
- self.gotMD5(None)
-
- def page(self, p):
- if p is None:
- return self.gotMD5(None)
- m = md5.new()
- m.update(p)
- self.gotMD5(m.digest())
-
- def gotMD5(self, md5):
- if not self.working:
- return
- if md5 != self.md5:
- self.notified.reportChange(self.md5, md5)
- self.md5 = md5
- else:
- self.notified.reportNoChange()
- if not self.call:
- self.call = reactor.callLater(self.delay, self._getPage)
-
-
-class ProxyChangeChecker(ChangeChecker):
-
- def __init__(self, proxyHost, proxyPort, notified, url, delay=60):
- self.proxyHost = proxyHost
- self.proxyPort = proxyPort
- ChangeChecker.__init__(self, notified, url, delay)
-
- def _getPage(self):
- factory = client.HTTPClientFactory(self.proxyHost, self.url)
- factory.headers = {'pragma': 'no-cache'}
- reactor.connectTCP(self.proxyHost, self.proxyPort, factory)
- d = factory.deferred
- d.addErrback(self.noPage)
- d.addCallback(self.page)
diff --git a/tools/buildbot/pylibs/twisted/web/proxy.py b/tools/buildbot/pylibs/twisted/web/proxy.py
deleted file mode 100644
index 98e5c41..0000000
--- a/tools/buildbot/pylibs/twisted/web/proxy.py
+++ /dev/null
@@ -1,283 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_proxy -*-
-# Copyright (c) 2001-2007 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-"""
-Simplistic HTTP proxy support.
-
-This comes in two main variants - the Proxy and the ReverseProxy.
-
-When a Proxy is in use, a browser trying to connect to a server (say,
-www.yahoo.com) will be intercepted by the Proxy, and the proxy will covertly
-connect to the server, and return the result.
-
-When a ReverseProxy is in use, the client connects directly to the ReverseProxy
-(say, www.yahoo.com) which farms off the request to one of a pool of servers,
-and returns the result.
-
-Normally, a Proxy is used on the client end of an Internet connection, while a
-ReverseProxy is used on the server end.
-"""
-
-import urlparse
-from urllib import quote as urlquote
-
-from twisted.internet import reactor
-from twisted.internet.protocol import ClientFactory
-from twisted.web.resource import Resource
-from twisted.web.server import NOT_DONE_YET
-from twisted.web.http import HTTPClient, Request, HTTPChannel
-
-
-
-class ProxyClient(HTTPClient):
- """
- Used by ProxyClientFactory to implement a simple web proxy.
- """
-
- def __init__(self, command, rest, version, headers, data, father):
- self.father = father
- self.command = command
- self.rest = rest
- if "proxy-connection" in headers:
- del headers["proxy-connection"]
- headers["connection"] = "close"
- self.headers = headers
- self.data = data
-
-
- def connectionMade(self):
- self.sendCommand(self.command, self.rest)
- for header, value in self.headers.items():
- self.sendHeader(header, value)
- self.endHeaders()
- self.transport.write(self.data)
-
-
- def handleStatus(self, version, code, message):
- if message:
- # Add a whitespace to message, this allows empty messages
- # transparently
- message = " %s" % (message,)
- self.father.transport.write("%s %s%s\r\n" % (version, code, message))
-
-
- def handleHeader(self, key, value):
- self.father.transport.write("%s: %s\r\n" % (key, value))
-
-
- def handleEndHeaders(self):
- self.father.transport.write("\r\n")
-
-
- def handleResponsePart(self, buffer):
- self.father.transport.write(buffer)
-
-
- def handleResponseEnd(self):
- self.transport.loseConnection()
- self.father.channel.transport.loseConnection()
-
-
-
-class ProxyClientFactory(ClientFactory):
- """
- Used by ProxyRequest to implement a simple web proxy.
- """
-
- protocol = ProxyClient
-
-
- def __init__(self, command, rest, version, headers, data, father):
- self.father = father
- self.command = command
- self.rest = rest
- self.headers = headers
- self.data = data
- self.version = version
-
-
- def buildProtocol(self, addr):
- return self.protocol(self.command, self.rest, self.version,
- self.headers, self.data, self.father)
-
-
- def clientConnectionFailed(self, connector, reason):
- self.father.transport.write("HTTP/1.0 501 Gateway error\r\n")
- self.father.transport.write("Content-Type: text/html\r\n")
- self.father.transport.write("\r\n")
- self.father.transport.write('''<H1>Could not connect</H1>''')
- self.father.transport.loseConnection()
-
-
-
-class ProxyRequest(Request):
- """
- Used by Proxy to implement a simple web proxy.
-
- @ivar reactor: the reactor used to create connections.
- @type reactor: object providing L{twisted.internet.interfaces.IReactorTCP}
- """
-
- protocols = {'http': ProxyClientFactory}
- ports = {'http': 80}
-
- def __init__(self, channel, queued, reactor=reactor):
- Request.__init__(self, channel, queued)
- self.reactor = reactor
-
-
- def process(self):
- parsed = urlparse.urlparse(self.uri)
- protocol = parsed[0]
- host = parsed[1]
- port = self.ports[protocol]
- if ':' in host:
- host, port = host.split(':')
- port = int(port)
- rest = urlparse.urlunparse(('', '') + parsed[2:])
- if not rest:
- rest = rest + '/'
- class_ = self.protocols[protocol]
- headers = self.getAllHeaders().copy()
- if 'host' not in headers:
- headers['host'] = host
- self.content.seek(0, 0)
- s = self.content.read()
- clientFactory = class_(self.method, rest, self.clientproto, headers,
- s, self)
- self.reactor.connectTCP(host, port, clientFactory)
-
-
-
-class Proxy(HTTPChannel):
- """
- This class implements a simple web proxy.
-
- Since it inherits from L{twisted.protocols.http.HTTPChannel}, to use it you
- should do something like this::
-
- from twisted.web import http
- f = http.HTTPFactory()
- f.protocol = Proxy
-
- Make the HTTPFactory a listener on a port as per usual, and you have
- a fully-functioning web proxy!
- """
-
- requestFactory = ProxyRequest
-
-
-
-class ReverseProxyRequest(Request):
- """
- Used by ReverseProxy to implement a simple reverse proxy.
-
- @ivar proxyClientFactoryClass: a proxy client factory class, used to create
- new connections.
- @type proxyClientFactoryClass: L{ClientFactory}
-
- @ivar reactor: the reactor used to create connections.
- @type reactor: object providing L{twisted.internet.interfaces.IReactorTCP}
- """
-
- proxyClientFactoryClass = ProxyClientFactory
-
- def __init__(self, channel, queued, reactor=reactor):
- Request.__init__(self, channel, queued)
- self.reactor = reactor
-
-
- def process(self):
- self.received_headers['host'] = self.factory.host
- clientFactory = self.proxyClientFactoryClass(
- self.method, self.uri, self.clientproto, self.getAllHeaders(),
- self.content.read(), self)
- self.reactor.connectTCP(self.factory.host, self.factory.port,
- clientFactory)
-
-
-
-class ReverseProxy(HTTPChannel):
- """
- Implements a simple reverse proxy.
-
- For details of usage, see the file examples/proxy.py.
- """
-
- requestFactory = ReverseProxyRequest
-
-
-
-class ReverseProxyResource(Resource):
- """
- Resource that renders the results gotten from another server
-
- Put this resource in the tree to cause everything below it to be relayed
- to a different server.
-
- @ivar proxyClientFactoryClass: a proxy client factory class, used to create
- new connections.
- @type proxyClientFactoryClass: L{ClientFactory}
-
- @ivar reactor: the reactor used to create connections.
- @type reactor: object providing L{twisted.internet.interfaces.IReactorTCP}
- """
-
- proxyClientFactoryClass = ProxyClientFactory
-
-
- def __init__(self, host, port, path, reactor=reactor):
- """
- @param host: the host of the web server to proxy.
- @type host: C{str}
-
- @param port: the port of the web server to proxy.
- @type port: C{port}
-
- @param path: the base path to fetch data from. Note that you shouldn't
- put any trailing slashes in it, it will be added automatically in
- request. For example, if you put B{/foo}, a request on B{/bar} will
- be proxied to B{/foo/bar}. Any required encoding of special
- characters (such as " " or "/") should have been done already.
-
- @type path: C{str}
- """
- Resource.__init__(self)
- self.host = host
- self.port = port
- self.path = path
- self.reactor = reactor
-
-
- def getChild(self, path, request):
- """
- Create and return a proxy resource with the same proxy configuration
- as this one, except that its path also contains the segment given by
- C{path} at the end.
- """
- return ReverseProxyResource(
- self.host, self.port, self.path + '/' + urlquote(path, safe=""))
-
-
- def render(self, request):
- """
- Render a request by forwarding it to the proxied server.
- """
- # RFC 2616 tells us that we can omit the port if it's the default port,
- # but we have to provide it otherwise
- if self.port == 80:
- request.received_headers['host'] = self.host
- else:
- request.received_headers['host'] = "%s:%d" % (self.host, self.port)
- request.content.seek(0, 0)
- qs = urlparse.urlparse(request.uri)[4]
- if qs:
- rest = self.path + '?' + qs
- else:
- rest = self.path
- clientFactory = self.proxyClientFactoryClass(
- request.method, rest, request.clientproto,
- request.getAllHeaders(), request.content.read(), request)
- self.reactor.connectTCP(self.host, self.port, clientFactory)
- return NOT_DONE_YET
diff --git a/tools/buildbot/pylibs/twisted/web/resource.py b/tools/buildbot/pylibs/twisted/web/resource.py
deleted file mode 100644
index 0becb8d..0000000
--- a/tools/buildbot/pylibs/twisted/web/resource.py
+++ /dev/null
@@ -1,204 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_web -*-
-#
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""I hold the lowest-level Resource class."""
-
-
-# System Imports
-from twisted.internet import defer
-from twisted.python import roots, reflect
-from zope.interface import Attribute, implements, Interface
-
-class IResource(Interface):
- """A web resource."""
-
- isLeaf = Attribute(\
-"""Signal if this IResource implementor is a "leaf node" or not. If True,
-getChildWithDefault will not be called on this Resource.""")
-
- def getChildWithDefault(name, request):
- """Return a child with the given name for the given request.
- This is the external interface used by the Resource publishing
- machinery. If implementing IResource without subclassing
- Resource, it must be provided. However, if subclassing Resource,
- getChild overridden instead.
- """
-
- def putChild(path, child):
- """Put a child IResource implementor at the given path.
- """
-
- def render(request):
- """Render a request. This is called on the leaf resource for
- a request. Render must return either a string, which will
- be sent to the browser as the HTML for the request, or
- server.NOT_DONE_YET. If NOT_DONE_YET is returned,
- at some point later (in a Deferred callback, usually)
- call request.write("<html>") to write data to the request,
- and request.finish() to send the data to the browser.
- """
-
-
-def getChildForRequest(resource, request):
- """Traverse resource tree to find who will handle the request."""
- while request.postpath and not resource.isLeaf:
- pathElement = request.postpath.pop(0)
- request.prepath.append(pathElement)
- resource = resource.getChildWithDefault(pathElement, request)
- return resource
-
-
-class Resource:
- """I define a web-accessible resource.
-
- I serve 2 main purposes; one is to provide a standard representation for
- what HTTP specification calls an 'entity', and the other is to provide an
- abstract directory structure for URL retrieval.
- """
-
- implements(IResource)
-
- entityType = IResource
-
- server = None
-
- def __init__(self):
- """Initialize.
- """
- self.children = {}
-
- isLeaf = 0
-
- ### Abstract Collection Interface
-
- def listStaticNames(self):
- return self.children.keys()
-
- def listStaticEntities(self):
- return self.children.items()
-
- def listNames(self):
- return self.listStaticNames() + self.listDynamicNames()
-
- def listEntities(self):
- return self.listStaticEntities() + self.listDynamicEntities()
-
- def listDynamicNames(self):
- return []
-
- def listDynamicEntities(self, request=None):
- return []
-
- def getStaticEntity(self, name):
- return self.children.get(name)
-
- def getDynamicEntity(self, name, request):
- if not self.children.has_key(name):
- return self.getChild(name, request)
- else:
- return None
-
- def delEntity(self, name):
- del self.children[name]
-
- def reallyPutEntity(self, name, entity):
- self.children[name] = entity
-
- # Concrete HTTP interface
-
- def getChild(self, path, request):
- """Retrieve a 'child' resource from me.
-
- Implement this to create dynamic resource generation -- resources which
- are always available may be registered with self.putChild().
-
- This will not be called if the class-level variable 'isLeaf' is set in
- your subclass; instead, the 'postpath' attribute of the request will be
- left as a list of the remaining path elements.
-
- For example, the URL /foo/bar/baz will normally be::
-
- | site.resource.getChild('foo').getChild('bar').getChild('baz').
-
- However, if the resource returned by 'bar' has isLeaf set to true, then
- the getChild call will never be made on it.
-
- @param path: a string, describing the child
-
- @param request: a twisted.web.server.Request specifying meta-information
- about the request that is being made for this child.
- """
- return error.NoResource("No such child resource.")
-
- def getChildWithDefault(self, path, request):
- """Retrieve a static or dynamically generated child resource from me.
-
- First checks if a resource was added manually by putChild, and then
- call getChild to check for dynamic resources. Only override if you want
- to affect behaviour of all child lookups, rather than just dynamic
- ones.
-
- This will check to see if I have a pre-registered child resource of the
- given name, and call getChild if I do not.
- """
- if self.children.has_key(path):
- return self.children[path]
-
- return self.getChild(path, request)
-
- def getChildForRequest(self, request):
- import warnings
- warnings.warn("Please use module level getChildForRequest.", DeprecationWarning, 2)
- return getChildForRequest(self, request)
-
- def putChild(self, path, child):
- """Register a static child.
-
- You almost certainly don't want '/' in your path. If you
- intended to have the root of a folder, e.g. /foo/, you want
- path to be ''.
- """
- self.children[path] = child
- child.server = self.server
-
- def render(self, request):
- """Render a given resource. See L{IResource}'s render method.
-
- I delegate to methods of self with the form 'render_METHOD'
- where METHOD is the HTTP that was used to make the
- request. Examples: render_GET, render_HEAD, render_POST, and
- so on. Generally you should implement those methods instead of
- overriding this one.
-
- render_METHOD methods are expected to return a string which
- will be the rendered page, unless the return value is
- twisted.web.server.NOT_DONE_YET, in which case it is this
- class's responsibility to write the results to
- request.write(data), then call request.finish().
-
- Old code that overrides render() directly is likewise expected
- to return a string or NOT_DONE_YET.
- """
- m = getattr(self, 'render_' + request.method, None)
- if not m:
- from twisted.web.server import UnsupportedMethod
- raise UnsupportedMethod(getattr(self, 'allowedMethods', ()))
- return m(request)
-
- def render_HEAD(self, request):
- """Default handling of HEAD method.
-
- I just return self.render_GET(request). When method is HEAD,
- the framework will handle this correctly.
- """
- return self.render_GET(request)
-
-
-#t.w imports
-#This is ugly, I know, but since error.py directly access resource.Resource
-#during import-time (it subclasses it), the Resource class must be defined
-#by the time error is imported.
-import error
diff --git a/tools/buildbot/pylibs/twisted/web/rewrite.py b/tools/buildbot/pylibs/twisted/web/rewrite.py
deleted file mode 100644
index b41ca00..0000000
--- a/tools/buildbot/pylibs/twisted/web/rewrite.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-#
-from twisted.web import resource
-
-class RewriterResource(resource.Resource):
-
- def __init__(self, orig, *rewriteRules):
- resource.Resource.__init__(self)
- self.resource = orig
- self.rewriteRules = list(rewriteRules)
-
- def _rewrite(self, request):
- for rewriteRule in self.rewriteRules:
- rewriteRule(request)
-
- def getChild(self, path, request):
- request.postpath.insert(0, path)
- request.prepath.pop()
- self._rewrite(request)
- path = request.postpath.pop(0)
- request.prepath.append(path)
- return self.resource.getChildWithDefault(path, request)
-
- def render(self, request):
- self._rewrite(request)
- return self.resource.render(request)
-
-
-def tildeToUsers(request):
- if request.postpath and request.postpath[0][:1]=='~':
- request.postpath[:1] = ['users', request.postpath[0][1:]]
- request.path = '/'+'/'.join(request.prepath+request.postpath)
-
-def alias(aliasPath, sourcePath):
- """
- I am not a very good aliaser. But I'm the best I can be. If I'm
- aliasing to a Resource that generates links, and it uses any parts
- of request.prepath to do so, the links will not be relative to the
- aliased path, but rather to the aliased-to path. That I can't
- alias static.File directory listings that nicely. However, I can
- still be useful, as many resources will play nice.
- """
- sourcePath = sourcePath.split('/')
- aliasPath = aliasPath.split('/')
- def rewriter(request):
- if request.postpath[:len(aliasPath)] == aliasPath:
- after = request.postpath[len(aliasPath):]
- request.postpath = sourcePath + after
- request.path = '/'+'/'.join(request.prepath+request.postpath)
- return rewriter
diff --git a/tools/buildbot/pylibs/twisted/web/script.py b/tools/buildbot/pylibs/twisted/web/script.py
deleted file mode 100644
index d1fae3f..0000000
--- a/tools/buildbot/pylibs/twisted/web/script.py
+++ /dev/null
@@ -1,163 +0,0 @@
-
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""I contain PythonScript, which is a very simple python script resource.
-"""
-
-import server
-import resource
-import html
-import error
-
-try:
- import cStringIO as StringIO
-except ImportError:
- import StringIO
-
-from twisted.web import http
-from twisted import copyright
-import traceback
-import os
-from twisted.web import resource
-from twisted.web import static
-
-rpyNoResource = """<p>You forgot to assign to the variable "resource" in your script. For example:</p>
-<pre>
-# MyCoolWebApp.rpy
-
-import mygreatresource
-
-resource = mygreatresource.MyGreatResource()
-</pre>
-"""
-
-class AlreadyCached(Exception):
- """This exception is raised when a path has already been cached.
- """
-
-class CacheScanner:
- def __init__(self, path, registry):
- self.path = path
- self.registry = registry
- self.doCache = 0
-
- def cache(self):
- c = self.registry.getCachedPath(self.path)
- if c is not None:
- raise AlreadyCached(c)
- self.recache()
-
- def recache(self):
- self.doCache = 1
-
-noRsrc = error.ErrorPage(500, "Whoops! Internal Error", rpyNoResource)
-
-def ResourceScript(path, registry):
- """
- I am a normal py file which must define a 'resource' global, which should
- be an instance of (a subclass of) web.resource.Resource; it will be
- renderred.
- """
- cs = CacheScanner(path, registry)
- glob = {'__file__': path,
- 'resource': noRsrc,
- 'registry': registry,
- 'cache': cs.cache,
- 'recache': cs.recache}
- try:
- execfile(path, glob, glob)
- except AlreadyCached, ac:
- return ac.args[0]
- rsrc = glob['resource']
- if cs.doCache and rsrc is not noRsrc:
- registry.cachePath(path, rsrc)
- return rsrc
-
-def ResourceTemplate(path, registry):
- from quixote import ptl_compile
-
- glob = {'__file__': path,
- 'resource': error.ErrorPage(500, "Whoops! Internal Error",
- rpyNoResource),
- 'registry': registry}
-
- e = ptl_compile.compile_template(open(path), path)
- exec e in glob
- return glob['resource']
-
-
-class ResourceScriptWrapper(resource.Resource):
-
- def __init__(self, path, registry=None):
- resource.Resource.__init__(self)
- self.path = path
- self.registry = registry or static.Registry()
-
- def render(self, request):
- res = ResourceScript(self.path, self.registry)
- return res.render(request)
-
- def getChildWithDefault(self, path, request):
- res = ResourceScript(self.path, self.registry)
- return res.getChildWithDefault(path, request)
-
-
-
-class ResourceScriptDirectory(resource.Resource):
- def __init__(self, pathname, registry=None):
- resource.Resource.__init__(self)
- self.path = pathname
- self.registry = registry or static.Registry()
-
- def getChild(self, path, request):
- fn = os.path.join(self.path, path)
-
- if os.path.isdir(fn):
- return ResourceScriptDirectory(fn, self.registry)
- if os.path.exists(fn):
- return ResourceScript(fn, self.registry)
- return error.NoResource()
-
- def render(self, request):
- return error.NoResource().render(request)
-
-
-class PythonScript(resource.Resource):
- """I am an extremely simple dynamic resource; an embedded python script.
-
- This will execute a file (usually of the extension '.epy') as Python code,
- internal to the webserver.
- """
- isLeaf = 1
- def __init__(self, filename, registry):
- """Initialize me with a script name.
- """
- self.filename = filename
- self.registry = registry
-
- def render(self, request):
- """Render me to a web client.
-
- Load my file, execute it in a special namespace (with 'request' and
- '__file__' global vars) and finish the request. Output to the web-page
- will NOT be handled with print - standard output goes to the log - but
- with request.write.
- """
- request.setHeader("x-powered-by","Twisted/%s" % copyright.version)
- namespace = {'request': request,
- '__file__': self.filename,
- 'registry': self.registry}
- try:
- execfile(self.filename, namespace, namespace)
- except IOError, e:
- if e.errno == 2: #file not found
- request.setResponseCode(http.NOT_FOUND)
- request.write(error.NoResource("File not found.").render(request))
- except:
- io = StringIO.StringIO()
- traceback.print_exc(file=io)
- request.write(html.PRE(io.getvalue()))
- request.finish()
- return server.NOT_DONE_YET
diff --git a/tools/buildbot/pylibs/twisted/web/server.py b/tools/buildbot/pylibs/twisted/web/server.py
deleted file mode 100644
index 9ee9579..0000000
--- a/tools/buildbot/pylibs/twisted/web/server.py
+++ /dev/null
@@ -1,571 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_web -*-
-
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""This is a web-server which integrates with the twisted.internet
-infrastructure.
-"""
-
-# System Imports
-
-import string
-import types
-import operator
-import copy
-import time
-import os
-from urllib import quote
-try:
- from twisted.protocols._c_urlarg import unquote
-except ImportError:
- from urllib import unquote
-
-#some useful constants
-NOT_DONE_YET = 1
-
-# Twisted Imports
-from twisted.spread import pb
-from twisted.internet import defer, address, task
-from twisted.web import http
-from twisted.python import log, reflect, failure, components
-from twisted import copyright
-
-# Sibling Imports
-import error, resource
-from twisted.web import util as webutil
-
-
-# backwards compatability
-date_time_string = http.datetimeToString
-string_date_time = http.stringToDatetime
-
-# Support for other methods may be implemented on a per-resource basis.
-supportedMethods = ('GET', 'HEAD', 'POST')
-
-
-class UnsupportedMethod(Exception):
- """Raised by a resource when faced with a strange request method.
-
- RFC 2616 (HTTP 1.1) gives us two choices when faced with this situtation:
- If the type of request is known to us, but not allowed for the requested
- resource, respond with NOT_ALLOWED. Otherwise, if the request is something
- we don't know how to deal with in any case, respond with NOT_IMPLEMENTED.
-
- When this exception is raised by a Resource's render method, the server
- will make the appropriate response.
-
- This exception's first argument MUST be a sequence of the methods the
- resource *does* support.
- """
-
- allowedMethods = ()
-
- def __init__(self, allowedMethods, *args):
- Exception.__init__(self, allowedMethods, *args)
- self.allowedMethods = allowedMethods
-
- if not operator.isSequenceType(allowedMethods):
- why = "but my first argument is not a sequence."
- s = ("First argument must be a sequence of"
- " supported methods, %s" % (why,))
- raise TypeError, s
-
-def _addressToTuple(addr):
- if isinstance(addr, address.IPv4Address):
- return ('INET', addr.host, addr.port)
- elif isinstance(addr, address.UNIXAddress):
- return ('UNIX', addr.name)
- else:
- return tuple(addr)
-
-class Request(pb.Copyable, http.Request, components.Componentized):
-
- site = None
- appRootURL = None
- __pychecker__ = 'unusednames=issuer'
-
- def __init__(self, *args, **kw):
- http.Request.__init__(self, *args, **kw)
- components.Componentized.__init__(self)
- self.notifications = []
-
- def getStateToCopyFor(self, issuer):
- x = self.__dict__.copy()
- del x['transport']
- # XXX refactor this attribute out; it's from protocol
- # del x['server']
- del x['channel']
- del x['content']
- del x['site']
- self.content.seek(0, 0)
- x['content_data'] = self.content.read()
- x['remote'] = pb.ViewPoint(issuer, self)
-
- # Address objects aren't jellyable
- x['host'] = _addressToTuple(x['host'])
- x['client'] = _addressToTuple(x['client'])
-
- return x
-
- # HTML generation helpers
-
- def sibLink(self, name):
- "Return the text that links to a sibling of the requested resource."
- if self.postpath:
- return (len(self.postpath)*"../") + name
- else:
- return name
-
- def childLink(self, name):
- "Return the text that links to a child of the requested resource."
- lpp = len(self.postpath)
- if lpp > 1:
- return ((lpp-1)*"../") + name
- elif lpp == 1:
- return name
- else: # lpp == 0
- if len(self.prepath) and self.prepath[-1]:
- return self.prepath[-1] + '/' + name
- else:
- return name
-
- def process(self):
- "Process a request."
-
- # get site from channel
- self.site = self.channel.site
-
- # set various default headers
- self.setHeader('server', version)
- self.setHeader('date', http.datetimeToString())
- self.setHeader('content-type', "text/html")
-
- # Resource Identification
- self.prepath = []
- self.postpath = map(unquote, string.split(self.path[1:], '/'))
- try:
- resrc = self.site.getResourceFor(self)
- self.render(resrc)
- except:
- self.processingFailed(failure.Failure())
-
-
- def render(self, resrc):
- try:
- body = resrc.render(self)
- except UnsupportedMethod, e:
- allowedMethods = e.allowedMethods
- if (self.method == "HEAD") and ("GET" in allowedMethods):
- # We must support HEAD (RFC 2616, 5.1.1). If the
- # resource doesn't, fake it by giving the resource
- # a 'GET' request and then return only the headers,
- # not the body.
- log.msg("Using GET to fake a HEAD request for %s" %
- (resrc,))
- self.method = "GET"
- body = resrc.render(self)
-
- if body is NOT_DONE_YET:
- log.msg("Tried to fake a HEAD request for %s, but "
- "it got away from me." % resrc)
- # Oh well, I guess we won't include the content length.
- else:
- self.setHeader('content-length', str(len(body)))
-
- self.write('')
- self.finish()
- return
-
- if self.method in (supportedMethods):
- # We MUST include an Allow header
- # (RFC 2616, 10.4.6 and 14.7)
- self.setHeader('Allow', allowedMethods)
- s = ('''Your browser approached me (at %(URI)s) with'''
- ''' the method "%(method)s". I only allow'''
- ''' the method%(plural)s %(allowed)s here.''' % {
- 'URI': self.uri,
- 'method': self.method,
- 'plural': ((len(allowedMethods) > 1) and 's') or '',
- 'allowed': string.join(allowedMethods, ', ')
- })
- epage = error.ErrorPage(http.NOT_ALLOWED,
- "Method Not Allowed", s)
- body = epage.render(self)
- else:
- epage = error.ErrorPage(http.NOT_IMPLEMENTED, "Huh?",
- """I don't know how to treat a"""
- """ %s request."""
- % (self.method))
- body = epage.render(self)
- # end except UnsupportedMethod
-
- if body == NOT_DONE_YET:
- return
- if type(body) is not types.StringType:
- body = error.ErrorPage(http.INTERNAL_SERVER_ERROR,
- "Request did not return a string",
- "Request: "+html.PRE(reflect.safe_repr(self))+"<br />"+
- "Resource: "+html.PRE(reflect.safe_repr(resrc))+"<br />"+
- "Value: "+html.PRE(reflect.safe_repr(body))).render(self)
-
- if self.method == "HEAD":
- if len(body) > 0:
- # This is a Bad Thing (RFC 2616, 9.4)
- log.msg("Warning: HEAD request %s for resource %s is"
- " returning a message body."
- " I think I'll eat it."
- % (self, resrc))
- self.setHeader('content-length', str(len(body)))
- self.write('')
- else:
- self.setHeader('content-length', str(len(body)))
- self.write(body)
- self.finish()
-
- def processingFailed(self, reason):
- log.err(reason)
- if self.site.displayTracebacks:
- body = ("<html><head><title>web.Server Traceback (most recent call last)</title></head>"
- "<body><b>web.Server Traceback (most recent call last):</b>\n\n"
- "%s\n\n</body></html>\n"
- % webutil.formatFailure(reason))
- else:
- body = ("<html><head><title>Processing Failed</title></head><body>"
- "<b>Processing Failed</b></body></html>")
-
- self.setResponseCode(http.INTERNAL_SERVER_ERROR)
- self.setHeader('content-type',"text/html")
- self.setHeader('content-length', str(len(body)))
- self.write(body)
- self.finish()
- return reason
-
- def notifyFinish(self):
- """Notify when finishing the request
-
- @return: A deferred. The deferred will be triggered when the
- request is finished -- with a C{None} value if the request
- finishes successfully or with an error if the request is stopped
- by the client.
- """
- self.notifications.append(defer.Deferred())
- return self.notifications[-1]
-
- def connectionLost(self, reason):
- for d in self.notifications:
- d.errback(reason)
- self.notifications = []
-
- def finish(self):
- http.Request.finish(self)
- for d in self.notifications:
- d.callback(None)
- self.notifications = []
-
- def view_write(self, issuer, data):
- """Remote version of write; same interface.
- """
- self.write(data)
-
- def view_finish(self, issuer):
- """Remote version of finish; same interface.
- """
- self.finish()
-
- def view_addCookie(self, issuer, k, v, **kwargs):
- """Remote version of addCookie; same interface.
- """
- self.addCookie(k, v, **kwargs)
-
- def view_setHeader(self, issuer, k, v):
- """Remote version of setHeader; same interface.
- """
- self.setHeader(k, v)
-
- def view_setLastModified(self, issuer, when):
- """Remote version of setLastModified; same interface.
- """
- self.setLastModified(when)
-
- def view_setETag(self, issuer, tag):
- """Remote version of setETag; same interface.
- """
- self.setETag(tag)
-
- def view_setResponseCode(self, issuer, code):
- """Remote version of setResponseCode; same interface.
- """
- self.setResponseCode(code)
-
- def view_registerProducer(self, issuer, producer, streaming):
- """Remote version of registerProducer; same interface.
- (requires a remote producer.)
- """
- self.registerProducer(_RemoteProducerWrapper(producer), streaming)
-
- def view_unregisterProducer(self, issuer):
- self.unregisterProducer()
-
- ### these calls remain local
-
- session = None
-
- def getSession(self, sessionInterface = None):
- # Session management
- if not self.session:
- cookiename = string.join(['TWISTED_SESSION'] + self.sitepath, "_")
- sessionCookie = self.getCookie(cookiename)
- if sessionCookie:
- try:
- self.session = self.site.getSession(sessionCookie)
- except KeyError:
- pass
- # if it still hasn't been set, fix it up.
- if not self.session:
- self.session = self.site.makeSession()
- self.addCookie(cookiename, self.session.uid, path='/')
- self.session.touch()
- if sessionInterface:
- return self.session.getComponent(sessionInterface)
- return self.session
-
- def _prePathURL(self, prepath):
- port = self.getHost().port
- if self.isSecure():
- default = 443
- else:
- default = 80
- if port == default:
- hostport = ''
- else:
- hostport = ':%d' % port
- return 'http%s://%s%s/%s' % (
- self.isSecure() and 's' or '',
- self.getRequestHostname(),
- hostport,
- '/'.join([quote(segment, safe='') for segment in prepath]))
-
- def prePathURL(self):
- return self._prePathURL(self.prepath)
-
- def URLPath(self):
- from twisted.python import urlpath
- return urlpath.URLPath.fromRequest(self)
-
- def rememberRootURL(self):
- """
- Remember the currently-processed part of the URL for later
- recalling.
- """
- url = self._prePathURL(self.prepath[:-1])
- self.appRootURL = url
-
- def getRootURL(self):
- """
- Get a previously-remembered URL.
- """
- return self.appRootURL
-
-
-class _RemoteProducerWrapper:
- def __init__(self, remote):
- self.resumeProducing = remote.remoteMethod("resumeProducing")
- self.pauseProducing = remote.remoteMethod("pauseProducing")
- self.stopProducing = remote.remoteMethod("stopProducing")
-
-
-class Session(components.Componentized):
- """
- A user's session with a system.
-
- This utility class contains no functionality, but is used to
- represent a session.
-
- @ivar sessionTimeout: timeout of a session, in seconds.
- @ivar loopFactory: factory for creating L{task.LoopingCall}. Mainly for
- testing.
- """
- sessionTimeout = 900
- loopFactory = task.LoopingCall
-
- def __init__(self, site, uid):
- """
- Initialize a session with a unique ID for that session.
- """
- components.Componentized.__init__(self)
- self.site = site
- self.uid = uid
- self.expireCallbacks = []
- self.checkExpiredLoop = None
- self.touch()
- self.sessionNamespaces = {}
-
-
- def startCheckingExpiration(self, lifetime):
- """
- Start expiration tracking.
-
- @type lifetime: C{int} or C{float}
- @param lifetime: The number of seconds this session is allowed to be
- idle before it expires.
-
- @return: C{None}
- """
- self.checkExpiredLoop = self.loopFactory(self.checkExpired)
- self.checkExpiredLoop.start(lifetime, now=False)
-
-
- def notifyOnExpire(self, callback):
- """
- Call this callback when the session expires or logs out.
- """
- self.expireCallbacks.append(callback)
-
-
- def expire(self):
- """
- Expire/logout of the session.
- """
- del self.site.sessions[self.uid]
- for c in self.expireCallbacks:
- c()
- self.expireCallbacks = []
- if self.checkExpiredLoop is not None:
- self.checkExpiredLoop.stop()
- # Break reference cycle.
- self.checkExpiredLoop = None
-
-
- def _getTime(self):
- """
- Return current time used for session validity.
- """
- return time.time()
-
-
- def touch(self):
- """
- Notify session modification.
- """
- self.lastModified = self._getTime()
-
-
- def checkExpired(self):
- """
- Is it time for me to expire?
-
- If I haven't been touched in fifteen minutes, I will call my
- expire method.
- """
- # If I haven't been touched in 15 minutes:
- if self._getTime() - self.lastModified > self.sessionTimeout:
- if self.uid in self.site.sessions:
- self.expire()
-
-
-version = "TwistedWeb/%s" % copyright.version
-
-
-class Site(http.HTTPFactory):
- """
- A web site: manage log, sessions, and resources.
-
- @ivar counter: increment value used for generating unique sessions ID.
- @ivar requestFactory: factory creating requests objects. Default to
- L{Request}.
- @ivar displayTracebacks: if set, Twisted internal errors are displayed on
- rendered pages. Default to C{True}.
- @ivar sessionFactory: factory for sessions objects. Default to L{Session}.
- @ivar sessionCheckTime: interval between each check of session expiration.
- """
- counter = 0
- requestFactory = Request
- displayTracebacks = True
- sessionFactory = Session
- sessionCheckTime = 1800
-
- def __init__(self, resource, logPath=None, timeout=60*60*12):
- """
- Initialize.
- """
- http.HTTPFactory.__init__(self, logPath=logPath, timeout=timeout)
- self.sessions = {}
- self.resource = resource
-
- def _openLogFile(self, path):
- from twisted.python import logfile
- return logfile.LogFile(os.path.basename(path), os.path.dirname(path))
-
- def __getstate__(self):
- d = self.__dict__.copy()
- d['sessions'] = {}
- return d
-
- def _mkuid(self):
- """
- (internal) Generate an opaque, unique ID for a user's session.
- """
- import md5, random
- self.counter = self.counter + 1
- return md5.new("%s_%s" % (str(random.random()) , str(self.counter))).hexdigest()
-
- def makeSession(self):
- """
- Generate a new Session instance, and store it for future reference.
- """
- uid = self._mkuid()
- session = self.sessions[uid] = self.sessionFactory(self, uid)
- session.startCheckingExpiration(self.sessionCheckTime)
- return session
-
- def getSession(self, uid):
- """
- Get a previously generated session, by its unique ID.
- This raises a KeyError if the session is not found.
- """
- return self.sessions[uid]
-
- def buildProtocol(self, addr):
- """
- Generate a channel attached to this site.
- """
- channel = http.HTTPFactory.buildProtocol(self, addr)
- channel.requestFactory = self.requestFactory
- channel.site = self
- return channel
-
- isLeaf = 0
-
- def render(self, request):
- """
- Redirect because a Site is always a directory.
- """
- request.redirect(request.prePathURL() + '/')
- request.finish()
-
- def getChildWithDefault(self, pathEl, request):
- """
- Emulate a resource's getChild method.
- """
- request.site = self
- return self.resource.getChildWithDefault(pathEl, request)
-
- def getResourceFor(self, request):
- """
- Get a resource for a request.
-
- This iterates through the resource heirarchy, calling
- getChildWithDefault on each resource it finds for a path element,
- stopping when it hits an element where isLeaf is true.
- """
- request.site = self
- # Sitepath is used to determine cookie names between distributed
- # servers and disconnected sites.
- request.sitepath = copy.copy(request.prepath)
- return resource.getChildForRequest(self.resource, request)
-
-
-import html
-
diff --git a/tools/buildbot/pylibs/twisted/web/soap.py b/tools/buildbot/pylibs/twisted/web/soap.py
deleted file mode 100644
index 00b0473..0000000
--- a/tools/buildbot/pylibs/twisted/web/soap.py
+++ /dev/null
@@ -1,154 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_soap -*-
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""
-SOAP support for twisted.web.
-
-Requires SOAPpy 0.10.1 or later.
-
-Maintainer: U{Itamar Shtull-Trauring<mailto:twisted@itamarst.org>}
-
-Future plans:
-SOAPContext support of some kind.
-Pluggable method lookup policies.
-"""
-
-# SOAPpy
-import SOAPpy
-
-# twisted imports
-from twisted.web import server, resource, client
-from twisted.internet import defer
-
-
-class SOAPPublisher(resource.Resource):
- """Publish SOAP methods.
-
- By default, publish methods beginning with 'soap_'. If the method
- has an attribute 'useKeywords', it well get the arguments passed
- as keyword args.
- """
-
- isLeaf = 1
-
- # override to change the encoding used for responses
- encoding = "UTF-8"
-
- def lookupFunction(self, functionName):
- """Lookup published SOAP function.
-
- Override in subclasses. Default behaviour - publish methods
- starting with soap_.
-
- @return: callable or None if not found.
- """
- return getattr(self, "soap_%s" % functionName, None)
-
- def render(self, request):
- """Handle a SOAP command."""
- data = request.content.read()
-
- p, header, body, attrs = SOAPpy.parseSOAPRPC(data, 1, 1, 1)
-
- methodName, args, kwargs, ns = p._name, p._aslist, p._asdict, p._ns
-
- # deal with changes in SOAPpy 0.11
- if callable(args):
- args = args()
- if callable(kwargs):
- kwargs = kwargs()
-
- function = self.lookupFunction(methodName)
-
- if not function:
- self._methodNotFound(request, methodName)
- return server.NOT_DONE_YET
- else:
- if hasattr(function, "useKeywords"):
- keywords = {}
- for k, v in kwargs.items():
- keywords[str(k)] = v
- d = defer.maybeDeferred(function, **keywords)
- else:
- d = defer.maybeDeferred(function, *args)
-
- d.addCallback(self._gotResult, request, methodName)
- d.addErrback(self._gotError, request, methodName)
- return server.NOT_DONE_YET
-
- def _methodNotFound(self, request, methodName):
- response = SOAPpy.buildSOAP(SOAPpy.faultType("%s:Client" %
- SOAPpy.NS.ENV_T, "Method %s not found" % methodName),
- encoding=self.encoding)
- self._sendResponse(request, response, status=500)
-
- def _gotResult(self, result, request, methodName):
- if not isinstance(result, SOAPpy.voidType):
- result = {"Result": result}
- response = SOAPpy.buildSOAP(kw={'%sResponse' % methodName: result},
- encoding=self.encoding)
- self._sendResponse(request, response)
-
- def _gotError(self, failure, request, methodName):
- e = failure.value
- if isinstance(e, SOAPpy.faultType):
- fault = e
- else:
- fault = SOAPpy.faultType("%s:Server" % SOAPpy.NS.ENV_T,
- "Method %s failed." % methodName)
- response = SOAPpy.buildSOAP(fault, encoding=self.encoding)
- self._sendResponse(request, response, status=500)
-
- def _sendResponse(self, request, response, status=200):
- request.setResponseCode(status)
-
- if self.encoding is not None:
- mimeType = 'text/xml; charset="%s"' % self.encoding
- else:
- mimeType = "text/xml"
- request.setHeader("Content-type", mimeType)
- request.setHeader("Content-length", str(len(response)))
- request.write(response)
- request.finish()
-
-
-class Proxy:
- """A Proxy for making remote SOAP calls.
-
- Pass the URL of the remote SOAP server to the constructor.
-
- Use proxy.callRemote('foobar', 1, 2) to call remote method
- 'foobar' with args 1 and 2, proxy.callRemote('foobar', x=1)
- will call foobar with named argument 'x'.
- """
-
- # at some point this should have encoding etc. kwargs
- def __init__(self, url, namespace=None, header=None):
- self.url = url
- self.namespace = namespace
- self.header = header
-
- def _cbGotResult(self, result):
- result = SOAPpy.parseSOAPRPC(result)
- if hasattr(result, 'Result'):
- return result.Result
- elif len(result) == 1:
- ## SOAPpy 0.11.6 wraps the return results in a containing structure.
- ## This check added to make Proxy behaviour emulate SOAPProxy, which
- ## flattens the structure by default.
- ## This behaviour is OK because even singleton lists are wrapped in
- ## another singleton structType, which is almost always useless.
- return result[0]
- else:
- return result
-
- def callRemote(self, method, *args, **kwargs):
- payload = SOAPpy.buildSOAP(args=args, kw=kwargs, method=method,
- header=self.header, namespace=self.namespace)
- return client.getPage(self.url, postdata=payload, method="POST",
- headers={'content-type': 'text/xml',
- 'SOAPAction': method}
- ).addCallback(self._cbGotResult)
-
diff --git a/tools/buildbot/pylibs/twisted/web/static.py b/tools/buildbot/pylibs/twisted/web/static.py
deleted file mode 100644
index 9d5dd56..0000000
--- a/tools/buildbot/pylibs/twisted/web/static.py
+++ /dev/null
@@ -1,466 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_web -*-
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""I deal with static resources.
-"""
-
-from __future__ import nested_scopes
-
-# System Imports
-import os, stat, string
-import cStringIO
-import traceback
-import warnings
-import types
-StringIO = cStringIO
-del cStringIO
-import urllib
-
-# Sibling Imports
-from twisted.web import server
-from twisted.web import error
-from twisted.web import resource
-from twisted.web.util import redirectTo
-
-# Twisted Imports
-from twisted.web import http
-from twisted.python import threadable, log, components, failure, filepath
-from twisted.internet import abstract, interfaces, defer
-from twisted.spread import pb
-from twisted.persisted import styles
-from twisted.python.util import InsensitiveDict
-from twisted.python.runtime import platformType
-
-
-dangerousPathError = error.NoResource("Invalid request URL.")
-
-def isDangerous(path):
- return path == '..' or '/' in path or os.sep in path
-
-
-class Data(resource.Resource):
- """
- This is a static, in-memory resource.
- """
-
- def __init__(self, data, type):
- resource.Resource.__init__(self)
- self.data = data
- self.type = type
-
- def render(self, request):
- request.setHeader("content-type", self.type)
- request.setHeader("content-length", str(len(self.data)))
- if request.method == "HEAD":
- return ''
- return self.data
-
-def addSlash(request):
- qs = ''
- qindex = string.find(request.uri, '?')
- if qindex != -1:
- qs = request.uri[qindex:]
-
- return "http%s://%s%s/%s" % (
- request.isSecure() and 's' or '',
- request.getHeader("host"),
- (string.split(request.uri,'?')[0]),
- qs)
-
-class Redirect(resource.Resource):
- def __init__(self, request):
- resource.Resource.__init__(self)
- self.url = addSlash(request)
-
- def render(self, request):
- return redirectTo(self.url, request)
-
-
-class Registry(components.Componentized, styles.Versioned):
- """
- I am a Componentized object that will be made available to internal Twisted
- file-based dynamic web content such as .rpy and .epy scripts.
- """
-
- def __init__(self):
- components.Componentized.__init__(self)
- self._pathCache = {}
-
- persistenceVersion = 1
-
- def upgradeToVersion1(self):
- self._pathCache = {}
-
- def cachePath(self, path, rsrc):
- self._pathCache[path] = rsrc
-
- def getCachedPath(self, path):
- return self._pathCache.get(path)
-
-
-def loadMimeTypes(mimetype_locations=['/etc/mime.types']):
- """
- Multiple file locations containing mime-types can be passed as a list.
- The files will be sourced in that order, overriding mime-types from the
- files sourced beforehand, but only if a new entry explicitly overrides
- the current entry.
- """
- import mimetypes
- # Grab Python's built-in mimetypes dictionary.
- contentTypes = mimetypes.types_map
- # Update Python's semi-erroneous dictionary with a few of the
- # usual suspects.
- contentTypes.update(
- {
- '.conf': 'text/plain',
- '.diff': 'text/plain',
- '.exe': 'application/x-executable',
- '.flac': 'audio/x-flac',
- '.java': 'text/plain',
- '.ogg': 'application/ogg',
- '.oz': 'text/x-oz',
- '.swf': 'application/x-shockwave-flash',
- '.tgz': 'application/x-gtar',
- '.wml': 'text/vnd.wap.wml',
- '.xul': 'application/vnd.mozilla.xul+xml',
- '.py': 'text/plain',
- '.patch': 'text/plain',
- }
- )
- # Users can override these mime-types by loading them out configuration
- # files (this defaults to ['/etc/mime.types']).
- for location in mimetype_locations:
- if os.path.exists(location):
- more = mimetypes.read_mime_types(location)
- if more is not None:
- contentTypes.update(more)
-
- return contentTypes
-
-def getTypeAndEncoding(filename, types, encodings, defaultType):
- p, ext = os.path.splitext(filename)
- ext = ext.lower()
- if encodings.has_key(ext):
- enc = encodings[ext]
- ext = os.path.splitext(p)[1].lower()
- else:
- enc = None
- type = types.get(ext, defaultType)
- return type, enc
-
-class File(resource.Resource, styles.Versioned, filepath.FilePath):
- """
- File is a resource that represents a plain non-interpreted file
- (although it can look for an extension like .rpy or .cgi and hand the
- file to a processor for interpretation if you wish). Its constructor
- takes a file path.
-
- Alternatively, you can give a directory path to the constructor. In this
- case the resource will represent that directory, and its children will
- be files underneath that directory. This provides access to an entire
- filesystem tree with a single Resource.
-
- If you map the URL 'http://server/FILE' to a resource created as
- File('/tmp'), then http://server/FILE/ will return an HTML-formatted
- listing of the /tmp/ directory, and http://server/FILE/foo/bar.html will
- return the contents of /tmp/foo/bar.html .
-
- @cvar childNotFound: L{Resource} used to render 404 Not Found error pages.
- """
-
- contentTypes = loadMimeTypes()
-
- contentEncodings = {
- ".gz" : "gzip",
- ".bz2": "bzip2"
- }
-
- processors = {}
-
- indexNames = ["index", "index.html", "index.htm", "index.trp", "index.rpy"]
-
- type = None
-
- ### Versioning
-
- persistenceVersion = 6
-
- def upgradeToVersion6(self):
- self.ignoredExts = []
- if self.allowExt:
- self.ignoreExt("*")
- del self.allowExt
-
- def upgradeToVersion5(self):
- if not isinstance(self.registry, Registry):
- self.registry = Registry()
-
- def upgradeToVersion4(self):
- if not hasattr(self, 'registry'):
- self.registry = {}
-
- def upgradeToVersion3(self):
- if not hasattr(self, 'allowExt'):
- self.allowExt = 0
-
- def upgradeToVersion2(self):
- self.defaultType = "text/html"
-
- def upgradeToVersion1(self):
- if hasattr(self, 'indexName'):
- self.indexNames = [self.indexName]
- del self.indexName
-
- def __init__(self, path, defaultType="text/html", ignoredExts=(), registry=None, allowExt=0):
- """Create a file with the given path.
- """
- resource.Resource.__init__(self)
- filepath.FilePath.__init__(self, path)
- # Remove the dots from the path to split
- self.defaultType = defaultType
- if ignoredExts in (0, 1) or allowExt:
- warnings.warn("ignoredExts should receive a list, not a boolean")
- if ignoredExts or allowExt:
- self.ignoredExts = ['*']
- else:
- self.ignoredExts = []
- else:
- self.ignoredExts = list(ignoredExts)
- self.registry = registry or Registry()
-
- def ignoreExt(self, ext):
- """Ignore the given extension.
-
- Serve file.ext if file is requested
- """
- self.ignoredExts.append(ext)
-
- childNotFound = error.NoResource("File not found.")
-
- def directoryListing(self):
- from twisted.web.woven import dirlist
- return dirlist.DirectoryLister(self.path,
- self.listNames(),
- self.contentTypes,
- self.contentEncodings,
- self.defaultType)
-
- def getChild(self, path, request):
- """See twisted.web.Resource.getChild.
- """
- self.restat()
-
- if not self.isdir():
- return self.childNotFound
-
- if path:
- fpath = self.child(path)
- else:
- fpath = self.childSearchPreauth(*self.indexNames)
- if fpath is None:
- return self.directoryListing()
-
- if not fpath.exists():
- fpath = fpath.siblingExtensionSearch(*self.ignoredExts)
- if fpath is None:
- return self.childNotFound
-
- if platformType == "win32":
- # don't want .RPY to be different than .rpy, since that would allow
- # source disclosure.
- processor = InsensitiveDict(self.processors).get(fpath.splitext()[1])
- else:
- processor = self.processors.get(fpath.splitext()[1])
- if processor:
- return resource.IResource(processor(fpath.path, self.registry))
- return self.createSimilarFile(fpath.path)
-
- # methods to allow subclasses to e.g. decrypt files on the fly:
- def openForReading(self):
- """Open a file and return it."""
- return self.open()
-
- def getFileSize(self):
- """Return file size."""
- return self.getsize()
-
-
- def render(self, request):
- """You know what you doing."""
- self.restat()
-
- if self.type is None:
- self.type, self.encoding = getTypeAndEncoding(self.basename(),
- self.contentTypes,
- self.contentEncodings,
- self.defaultType)
-
- if not self.exists():
- return self.childNotFound.render(request)
-
- if self.isdir():
- return self.redirect(request)
-
- #for content-length
- fsize = size = self.getFileSize()
-
-# request.setHeader('accept-ranges','bytes')
-
- if self.type:
- request.setHeader('content-type', self.type)
- if self.encoding:
- request.setHeader('content-encoding', self.encoding)
-
- try:
- f = self.openForReading()
- except IOError, e:
- import errno
- if e[0] == errno.EACCES:
- return error.ForbiddenResource().render(request)
- else:
- raise
-
- if request.setLastModified(self.getmtime()) is http.CACHED:
- return ''
-
-# Commented out because it's totally broken. --jknight 11/29/04
-# try:
-# range = request.getHeader('range')
-#
-# if range is not None:
-# # This is a request for partial data...
-# bytesrange = string.split(range, '=')
-# assert bytesrange[0] == 'bytes',\
-# "Syntactically invalid http range header!"
-# start, end = string.split(bytesrange[1],'-')
-# if start:
-# f.seek(int(start))
-# if end:
-# end = int(end)
-# size = end
-# else:
-# end = size
-# request.setResponseCode(http.PARTIAL_CONTENT)
-# request.setHeader('content-range',"bytes %s-%s/%s " % (
-# str(start), str(end), str(size)))
-# #content-length should be the actual size of the stuff we're
-# #sending, not the full size of the on-server entity.
-# fsize = end - int(start)
-#
-# request.setHeader('content-length', str(fsize))
-# except:
-# traceback.print_exc(file=log.logfile)
-
- request.setHeader('content-length', str(fsize))
- if request.method == 'HEAD':
- return ''
-
- # return data
- FileTransfer(f, size, request)
- # and make sure the connection doesn't get closed
- return server.NOT_DONE_YET
-
- def redirect(self, request):
- return redirectTo(addSlash(request), request)
-
- def listNames(self):
- if not self.isdir():
- return []
- directory = self.listdir()
- directory.sort()
- return directory
-
- def listEntities(self):
- return map(lambda fileName, self=self: self.createSimilarFile(os.path.join(self.path, fileName)), self.listNames())
-
- def createPickleChild(self, name, child):
- if not os.path.isdir(self.path):
- resource.Resource.putChild(self, name, child)
- # xxx use a file-extension-to-save-function dictionary instead
- if type(child) == type(""):
- fl = open(os.path.join(self.path, name), 'wb')
- fl.write(child)
- else:
- if '.' not in name:
- name = name + '.trp'
- fl = open(os.path.join(self.path, name), 'wb')
- from pickle import Pickler
- pk = Pickler(fl)
- pk.dump(child)
- fl.close()
-
- def createSimilarFile(self, path):
- f = self.__class__(path, self.defaultType, self.ignoredExts, self.registry)
- # refactoring by steps, here - constructor should almost certainly take these
- f.processors = self.processors
- f.indexNames = self.indexNames[:]
- f.childNotFound = self.childNotFound
- return f
-
-class FileTransfer(pb.Viewable):
- """
- A class to represent the transfer of a file over the network.
- """
- request = None
-
- def __init__(self, file, size, request):
- self.file = file
- self.size = size
- self.request = request
- self.written = self.file.tell()
- request.registerProducer(self, 0)
-
- def resumeProducing(self):
- if not self.request:
- return
- data = self.file.read(min(abstract.FileDescriptor.bufferSize, self.size - self.written))
- if data:
- self.written += len(data)
- # this .write will spin the reactor, calling .doWrite and then
- # .resumeProducing again, so be prepared for a re-entrant call
- self.request.write(data)
- if self.request and self.file.tell() == self.size:
- self.request.unregisterProducer()
- self.request.finish()
- self.request = None
-
- def pauseProducing(self):
- pass
-
- def stopProducing(self):
- self.file.close()
- self.request = None
-
- # Remotely relay producer interface.
-
- def view_resumeProducing(self, issuer):
- self.resumeProducing()
-
- def view_pauseProducing(self, issuer):
- self.pauseProducing()
-
- def view_stopProducing(self, issuer):
- self.stopProducing()
-
-
- synchronized = ['resumeProducing', 'stopProducing']
-
-threadable.synchronize(FileTransfer)
-
-"""I contain AsIsProcessor, which serves files 'As Is'
- Inspired by Apache's mod_asis
-"""
-
-class ASISProcessor(resource.Resource):
-
- def __init__(self, path, registry=None):
- resource.Resource.__init__(self)
- self.path = path
- self.registry = registry or Registry()
-
- def render(self, request):
- request.startedWriting = 1
- res = File(self.path, registry=self.registry)
- return res.render(request)
diff --git a/tools/buildbot/pylibs/twisted/web/sux.py b/tools/buildbot/pylibs/twisted/web/sux.py
deleted file mode 100644
index 6f8fea1..0000000
--- a/tools/buildbot/pylibs/twisted/web/sux.py
+++ /dev/null
@@ -1,657 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_xml -*-
-#
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""
-*S*mall, *U*ncomplicated *X*ML.
-
-This is a very simple implementation of XML/HTML as a network
-protocol. It is not at all clever. Its main features are that it
-does not:
-
- - support namespaces
- - mung mnemonic entity references
- - validate
- - perform *any* external actions (such as fetching URLs or writing files)
- under *any* circumstances
- - has lots and lots of horrible hacks for supporting broken HTML (as an
- option, they're not on by default).
-"""
-
-from twisted.internet.protocol import Protocol, FileWrapper
-from twisted.python.reflect import prefixedMethodNames
-
-
-
-# Elements of the three-tuples in the state table.
-BEGIN_HANDLER = 0
-DO_HANDLER = 1
-END_HANDLER = 2
-
-identChars = '.-_:'
-lenientIdentChars = identChars + ';+#/%~'
-
-def nop(*args, **kw):
- "Do nothing."
-
-
-def unionlist(*args):
- l = []
- for x in args:
- l.extend(x)
- d = dict([(x, 1) for x in l])
- return d.keys()
-
-
-def zipfndict(*args, **kw):
- default = kw.get('default', nop)
- d = {}
- for key in unionlist(*[fndict.keys() for fndict in args]):
- d[key] = tuple([x.get(key, default) for x in args])
- return d
-
-
-def prefixedMethodClassDict(clazz, prefix):
- return dict([(name, getattr(clazz, prefix + name)) for name in prefixedMethodNames(clazz, prefix)])
-
-
-def prefixedMethodObjDict(obj, prefix):
- return dict([(name, getattr(obj, prefix + name)) for name in prefixedMethodNames(obj.__class__, prefix)])
-
-
-class ParseError(Exception):
-
- def __init__(self, filename, line, col, message):
- self.filename = filename
- self.line = line
- self.col = col
- self.message = message
-
- def __str__(self):
- return "%s:%s:%s: %s" % (self.filename, self.line, self.col,
- self.message)
-
-class XMLParser(Protocol):
-
- state = None
- encodings = None
- filename = "<xml />"
- beExtremelyLenient = 0
- _prepend = None
-
- # _leadingBodyData will sometimes be set before switching to the
- # 'bodydata' state, when we "accidentally" read a byte of bodydata
- # in a different state.
- _leadingBodyData = None
-
- def connectionMade(self):
- self.lineno = 1
- self.colno = 0
- self.encodings = []
-
- def saveMark(self):
- '''Get the line number and column of the last character parsed'''
- # This gets replaced during dataReceived, restored afterwards
- return (self.lineno, self.colno)
-
- def _parseError(self, message):
- raise ParseError(*((self.filename,)+self.saveMark()+(message,)))
-
- def _buildStateTable(self):
- '''Return a dictionary of begin, do, end state function tuples'''
- # _buildStateTable leaves something to be desired but it does what it
- # does.. probably slowly, so I'm doing some evil caching so it doesn't
- # get called more than once per class.
- stateTable = getattr(self.__class__, '__stateTable', None)
- if stateTable is None:
- stateTable = self.__class__.__stateTable = zipfndict(
- *[prefixedMethodObjDict(self, prefix)
- for prefix in ('begin_', 'do_', 'end_')])
- return stateTable
-
- def _decode(self, data):
- if 'UTF-16' in self.encodings or 'UCS-2' in self.encodings:
- assert not len(data) & 1, 'UTF-16 must come in pairs for now'
- if self._prepend:
- data = self._prepend + data
- for encoding in self.encodings:
- data = unicode(data, encoding)
- return data
-
- def maybeBodyData(self):
- if self.endtag:
- return 'bodydata'
-
- # Get ready for fun! We're going to allow
- # <script>if (foo < bar)</script> to work!
- # We do this by making everything between <script> and
- # </script> a Text
- # BUT <script src="foo"> will be special-cased to do regular,
- # lenient behavior, because those may not have </script>
- # -radix
-
- if (self.tagName == 'script'
- and not self.tagAttributes.has_key('src')):
- # we do this ourselves rather than having begin_waitforendscript
- # becuase that can get called multiple times and we don't want
- # bodydata to get reset other than the first time.
- self.begin_bodydata(None)
- return 'waitforendscript'
- return 'bodydata'
-
-
-
- def dataReceived(self, data):
- stateTable = self._buildStateTable()
- if not self.state:
- # all UTF-16 starts with this string
- if data.startswith('\xff\xfe'):
- self._prepend = '\xff\xfe'
- self.encodings.append('UTF-16')
- data = data[2:]
- elif data.startswith('\xfe\xff'):
- self._prepend = '\xfe\xff'
- self.encodings.append('UTF-16')
- data = data[2:]
- self.state = 'begin'
- if self.encodings:
- data = self._decode(data)
- # bring state, lineno, colno into local scope
- lineno, colno = self.lineno, self.colno
- curState = self.state
- # replace saveMark with a nested scope function
- _saveMark = self.saveMark
- def saveMark():
- return (lineno, colno)
- self.saveMark = saveMark
- # fetch functions from the stateTable
- beginFn, doFn, endFn = stateTable[curState]
- try:
- for byte in data:
- # do newline stuff
- if byte == '\n':
- lineno += 1
- colno = 0
- else:
- colno += 1
- newState = doFn(byte)
- if newState is not None and newState != curState:
- # this is the endFn from the previous state
- endFn()
- curState = newState
- beginFn, doFn, endFn = stateTable[curState]
- beginFn(byte)
- finally:
- self.saveMark = _saveMark
- self.lineno, self.colno = lineno, colno
- # state doesn't make sense if there's an exception..
- self.state = curState
-
-
- def connectionLost(self, reason):
- """
- End the last state we were in.
- """
- stateTable = self._buildStateTable()
- stateTable[self.state][END_HANDLER]()
-
-
- # state methods
-
- def do_begin(self, byte):
- if byte.isspace():
- return
- if byte != '<':
- if self.beExtremelyLenient:
- self._leadingBodyData = byte
- return 'bodydata'
- self._parseError("First char of document [%r] wasn't <" % (byte,))
- return 'tagstart'
-
- def begin_comment(self, byte):
- self.commentbuf = ''
-
- def do_comment(self, byte):
- self.commentbuf += byte
- if self.commentbuf.endswith('-->'):
- self.gotComment(self.commentbuf[:-3])
- return 'bodydata'
-
- def begin_tagstart(self, byte):
- self.tagName = '' # name of the tag
- self.tagAttributes = {} # attributes of the tag
- self.termtag = 0 # is the tag self-terminating
- self.endtag = 0
-
- def do_tagstart(self, byte):
- if byte.isalnum() or byte in identChars:
- self.tagName += byte
- if self.tagName == '!--':
- return 'comment'
- elif byte.isspace():
- if self.tagName:
- if self.endtag:
- # properly strict thing to do here is probably to only
- # accept whitespace
- return 'waitforgt'
- return 'attrs'
- else:
- self._parseError("Whitespace before tag-name")
- elif byte == '>':
- if self.endtag:
- self.gotTagEnd(self.tagName)
- return 'bodydata'
- else:
- self.gotTagStart(self.tagName, {})
- return (not self.beExtremelyLenient) and 'bodydata' or self.maybeBodyData()
- elif byte == '/':
- if self.tagName:
- return 'afterslash'
- else:
- self.endtag = 1
- elif byte in '!?':
- if self.tagName:
- if not self.beExtremelyLenient:
- self._parseError("Invalid character in tag-name")
- else:
- self.tagName += byte
- self.termtag = 1
- elif byte == '[':
- if self.tagName == '!':
- return 'expectcdata'
- else:
- self._parseError("Invalid '[' in tag-name")
- else:
- if self.beExtremelyLenient:
- self.bodydata = '<'
- return 'unentity'
- self._parseError('Invalid tag character: %r'% byte)
-
- def begin_unentity(self, byte):
- self.bodydata += byte
-
- def do_unentity(self, byte):
- self.bodydata += byte
- return 'bodydata'
-
- def end_unentity(self):
- self.gotText(self.bodydata)
-
- def begin_expectcdata(self, byte):
- self.cdatabuf = byte
-
- def do_expectcdata(self, byte):
- self.cdatabuf += byte
- cdb = self.cdatabuf
- cd = '[CDATA['
- if len(cd) > len(cdb):
- if cd.startswith(cdb):
- return
- elif self.beExtremelyLenient:
- ## WHAT THE CRAP!? MSWord9 generates HTML that includes these
- ## bizarre <![if !foo]> <![endif]> chunks, so I've gotta ignore
- ## 'em as best I can. this should really be a separate parse
- ## state but I don't even have any idea what these _are_.
- return 'waitforgt'
- else:
- self._parseError("Mal-formed CDATA header")
- if cd == cdb:
- self.cdatabuf = ''
- return 'cdata'
- self._parseError("Mal-formed CDATA header")
-
- def do_cdata(self, byte):
- self.cdatabuf += byte
- if self.cdatabuf.endswith("]]>"):
- self.cdatabuf = self.cdatabuf[:-3]
- return 'bodydata'
-
- def end_cdata(self):
- self.gotCData(self.cdatabuf)
- self.cdatabuf = ''
-
- def do_attrs(self, byte):
- if byte.isalnum() or byte in identChars:
- # XXX FIXME really handle !DOCTYPE at some point
- if self.tagName == '!DOCTYPE':
- return 'doctype'
- if self.tagName[0] in '!?':
- return 'waitforgt'
- return 'attrname'
- elif byte.isspace():
- return
- elif byte == '>':
- self.gotTagStart(self.tagName, self.tagAttributes)
- return (not self.beExtremelyLenient) and 'bodydata' or self.maybeBodyData()
- elif byte == '/':
- return 'afterslash'
- elif self.beExtremelyLenient:
- # discard and move on? Only case I've seen of this so far was:
- # <foo bar="baz"">
- return
- self._parseError("Unexpected character: %r" % byte)
-
- def begin_doctype(self, byte):
- self.doctype = byte
-
- def do_doctype(self, byte):
- if byte == '>':
- return 'bodydata'
- self.doctype += byte
-
- def end_doctype(self):
- self.gotDoctype(self.doctype)
- self.doctype = None
-
- def do_waitforgt(self, byte):
- if byte == '>':
- if self.endtag or not self.beExtremelyLenient:
- return 'bodydata'
- return self.maybeBodyData()
-
- def begin_attrname(self, byte):
- self.attrname = byte
- self._attrname_termtag = 0
-
- def do_attrname(self, byte):
- if byte.isalnum() or byte in identChars:
- self.attrname += byte
- return
- elif byte == '=':
- return 'beforeattrval'
- elif byte.isspace():
- return 'beforeeq'
- elif self.beExtremelyLenient:
- if byte in '"\'':
- return 'attrval'
- if byte in lenientIdentChars or byte.isalnum():
- self.attrname += byte
- return
- if byte == '/':
- self._attrname_termtag = 1
- return
- if byte == '>':
- self.attrval = 'True'
- self.tagAttributes[self.attrname] = self.attrval
- self.gotTagStart(self.tagName, self.tagAttributes)
- if self._attrname_termtag:
- self.gotTagEnd(self.tagName)
- return 'bodydata'
- return self.maybeBodyData()
- # something is really broken. let's leave this attribute where it
- # is and move on to the next thing
- return
- self._parseError("Invalid attribute name: %r %r" % (self.attrname, byte))
-
- def do_beforeattrval(self, byte):
- if byte in '"\'':
- return 'attrval'
- elif byte.isspace():
- return
- elif self.beExtremelyLenient:
- if byte in lenientIdentChars or byte.isalnum():
- return 'messyattr'
- if byte == '>':
- self.attrval = 'True'
- self.tagAttributes[self.attrname] = self.attrval
- self.gotTagStart(self.tagName, self.tagAttributes)
- return self.maybeBodyData()
- if byte == '\\':
- # I saw this in actual HTML once:
- # <font size=\"3\"><sup>SM</sup></font>
- return
- self._parseError("Invalid initial attribute value: %r; Attribute values must be quoted." % byte)
-
- attrname = ''
- attrval = ''
-
- def begin_beforeeq(self,byte):
- self._beforeeq_termtag = 0
-
- def do_beforeeq(self, byte):
- if byte == '=':
- return 'beforeattrval'
- elif byte.isspace():
- return
- elif self.beExtremelyLenient:
- if byte.isalnum() or byte in identChars:
- self.attrval = 'True'
- self.tagAttributes[self.attrname] = self.attrval
- return 'attrname'
- elif byte == '>':
- self.attrval = 'True'
- self.tagAttributes[self.attrname] = self.attrval
- self.gotTagStart(self.tagName, self.tagAttributes)
- if self._beforeeq_termtag:
- self.gotTagEnd(self.tagName)
- return 'bodydata'
- return self.maybeBodyData()
- elif byte == '/':
- self._beforeeq_termtag = 1
- return
- self._parseError("Invalid attribute")
-
- def begin_attrval(self, byte):
- self.quotetype = byte
- self.attrval = ''
-
- def do_attrval(self, byte):
- if byte == self.quotetype:
- return 'attrs'
- self.attrval += byte
-
- def end_attrval(self):
- self.tagAttributes[self.attrname] = self.attrval
- self.attrname = self.attrval = ''
-
- def begin_messyattr(self, byte):
- self.attrval = byte
-
- def do_messyattr(self, byte):
- if byte.isspace():
- return 'attrs'
- elif byte == '>':
- endTag = 0
- if self.attrval.endswith('/'):
- endTag = 1
- self.attrval = self.attrval[:-1]
- self.tagAttributes[self.attrname] = self.attrval
- self.gotTagStart(self.tagName, self.tagAttributes)
- if endTag:
- self.gotTagEnd(self.tagName)
- return 'bodydata'
- return self.maybeBodyData()
- else:
- self.attrval += byte
-
- def end_messyattr(self):
- if self.attrval:
- self.tagAttributes[self.attrname] = self.attrval
-
- def begin_afterslash(self, byte):
- self._after_slash_closed = 0
-
- def do_afterslash(self, byte):
- # this state is only after a self-terminating slash, e.g. <foo/>
- if self._after_slash_closed:
- self._parseError("Mal-formed")#XXX When does this happen??
- if byte != '>':
- if self.beExtremelyLenient:
- return
- else:
- self._parseError("No data allowed after '/'")
- self._after_slash_closed = 1
- self.gotTagStart(self.tagName, self.tagAttributes)
- self.gotTagEnd(self.tagName)
- # don't need maybeBodyData here because there better not be
- # any javascript code after a <script/>... we'll see :(
- return 'bodydata'
-
- def begin_bodydata(self, byte):
- if self._leadingBodyData:
- self.bodydata = self._leadingBodyData
- del self._leadingBodyData
- else:
- self.bodydata = ''
-
- def do_bodydata(self, byte):
- if byte == '<':
- return 'tagstart'
- if byte == '&':
- return 'entityref'
- self.bodydata += byte
-
- def end_bodydata(self):
- self.gotText(self.bodydata)
- self.bodydata = ''
-
- def do_waitforendscript(self, byte):
- if byte == '<':
- return 'waitscriptendtag'
- self.bodydata += byte
-
- def begin_waitscriptendtag(self, byte):
- self.temptagdata = ''
- self.tagName = ''
- self.endtag = 0
-
- def do_waitscriptendtag(self, byte):
- # 1 enforce / as first byte read
- # 2 enforce following bytes to be subset of "script" until
- # tagName == "script"
- # 2a when that happens, gotText(self.bodydata) and gotTagEnd(self.tagName)
- # 3 spaces can happen anywhere, they're ignored
- # e.g. < / script >
- # 4 anything else causes all data I've read to be moved to the
- # bodydata, and switch back to waitforendscript state
-
- # If it turns out this _isn't_ a </script>, we need to
- # remember all the data we've been through so we can append it
- # to bodydata
- self.temptagdata += byte
-
- # 1
- if byte == '/':
- self.endtag = True
- elif not self.endtag:
- self.bodydata += "<" + self.temptagdata
- return 'waitforendscript'
- # 2
- elif byte.isalnum() or byte in identChars:
- self.tagName += byte
- if not 'script'.startswith(self.tagName):
- self.bodydata += "<" + self.temptagdata
- return 'waitforendscript'
- elif self.tagName == 'script':
- self.gotText(self.bodydata)
- self.gotTagEnd(self.tagName)
- return 'waitforgt'
- # 3
- elif byte.isspace():
- return 'waitscriptendtag'
- # 4
- else:
- self.bodydata += "<" + self.temptagdata
- return 'waitforendscript'
-
-
- def begin_entityref(self, byte):
- self.erefbuf = ''
- self.erefextra = '' # extra bit for lenient mode
-
- def do_entityref(self, byte):
- if byte.isspace() or byte == "<":
- if self.beExtremelyLenient:
- # '&foo' probably was '&amp;foo'
- if self.erefbuf and self.erefbuf != "amp":
- self.erefextra = self.erefbuf
- self.erefbuf = "amp"
- if byte == "<":
- return "tagstart"
- else:
- self.erefextra += byte
- return 'spacebodydata'
- self._parseError("Bad entity reference")
- elif byte != ';':
- self.erefbuf += byte
- else:
- return 'bodydata'
-
- def end_entityref(self):
- self.gotEntityReference(self.erefbuf)
-
- # hacky support for space after & in entityref in beExtremelyLenient
- # state should only happen in that case
- def begin_spacebodydata(self, byte):
- self.bodydata = self.erefextra
- self.erefextra = None
- do_spacebodydata = do_bodydata
- end_spacebodydata = end_bodydata
-
- # Sorta SAX-ish API
-
- def gotTagStart(self, name, attributes):
- '''Encountered an opening tag.
-
- Default behaviour is to print.'''
- print 'begin', name, attributes
-
- def gotText(self, data):
- '''Encountered text
-
- Default behaviour is to print.'''
- print 'text:', repr(data)
-
- def gotEntityReference(self, entityRef):
- '''Encountered mnemonic entity reference
-
- Default behaviour is to print.'''
- print 'entityRef: &%s;' % entityRef
-
- def gotComment(self, comment):
- '''Encountered comment.
-
- Default behaviour is to ignore.'''
- pass
-
- def gotCData(self, cdata):
- '''Encountered CDATA
-
- Default behaviour is to call the gotText method'''
- self.gotText(cdata)
-
- def gotDoctype(self, doctype):
- """Encountered DOCTYPE
-
- This is really grotty: it basically just gives you everything between
- '<!DOCTYPE' and '>' as an argument.
- """
- print '!DOCTYPE', repr(doctype)
-
- def gotTagEnd(self, name):
- '''Encountered closing tag
-
- Default behaviour is to print.'''
- print 'end', name
-
-if __name__ == '__main__':
- from cStringIO import StringIO
- testDocument = '''
-
- <!DOCTYPE ignore all this shit, hah its malformed!!!!@$>
- <?xml version="suck it"?>
- <foo>
- &#65;
- <bar />
- <baz boz="buz">boz &zop;</baz>
- <![CDATA[ foo bar baz ]]>
- </foo>
- '''
- x = XMLParser()
- x.makeConnection(FileWrapper(StringIO()))
- # fn = "/home/glyph/Projects/Twisted/doc/howto/ipc10paper.html"
- fn = "/home/glyph/gruesome.xml"
- # testDocument = open(fn).read()
- x.dataReceived(testDocument)
diff --git a/tools/buildbot/pylibs/twisted/web/tap.py b/tools/buildbot/pylibs/twisted/web/tap.py
deleted file mode 100644
index 559b801..0000000
--- a/tools/buildbot/pylibs/twisted/web/tap.py
+++ /dev/null
@@ -1,201 +0,0 @@
-# Copyright (c) 2001-2008 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-"""
-Support for creating a service which runs a web server.
-"""
-
-import os
-
-# Twisted Imports
-from twisted.web import server, static, twcgi, script, demo, distrib, trp
-from twisted.internet import interfaces
-from twisted.python import usage, reflect
-from twisted.spread import pb
-from twisted.application import internet, service, strports
-
-
-class Options(usage.Options):
- synopsis = "Usage: mktap web [options]"
- optParameters = [["port", "p", "8080","Port to start the server on."],
- ["logfile", "l", None, "Path to web CLF (Combined Log Format) log file."],
- ["https", None, None, "Port to listen on for Secure HTTP."],
- ["certificate", "c", "server.pem", "SSL certificate to use for HTTPS. "],
- ["privkey", "k", "server.pem", "SSL certificate to use for HTTPS."],
- ]
- optFlags = [["personal", "",
- "Instead of generating a webserver, generate a "
- "ResourcePublisher which listens on "
- "~/%s" % distrib.UserDirectory.userSocketName],
- ["notracebacks", "n", "Display tracebacks in broken web pages. " +
- "Displaying tracebacks to users may be security risk!"],
-]
- zsh_actions = {"logfile" : "_files -g '*.log'", "certificate" : "_files -g '*.pem'",
- "privkey" : "_files -g '*.pem'"}
-
-
- longdesc = """\
-This creates a web.tap file that can be used by twistd. If you specify
-no arguments, it will be a demo webserver that has the Test class from
-twisted.web.demo in it."""
-
- def __init__(self):
- usage.Options.__init__(self)
- self['indexes'] = []
- self['root'] = None
-
- def opt_index(self, indexName):
- """Add the name of a file used to check for directory indexes.
- [default: index, index.html]
- """
- self['indexes'].append(indexName)
-
- opt_i = opt_index
-
- def opt_user(self):
- """Makes a server with ~/public_html and ~/.twistd-web-pb support for
- users.
- """
- self['root'] = distrib.UserDirectory()
-
- opt_u = opt_user
-
- def opt_path(self, path):
- """<path> is either a specific file or a directory to
- be set as the root of the web server. Use this if you
- have a directory full of HTML, cgi, php3, epy, or rpy files or
- any other files that you want to be served up raw.
- """
-
- self['root'] = static.File(os.path.abspath(path))
- self['root'].processors = {
- '.cgi': twcgi.CGIScript,
- '.php3': twcgi.PHP3Script,
- '.php': twcgi.PHPScript,
- '.epy': script.PythonScript,
- '.rpy': script.ResourceScript,
- '.trp': trp.ResourceUnpickler,
- }
-
- def opt_processor(self, proc):
- """`ext=class' where `class' is added as a Processor for files ending
- with `ext'.
- """
- if not isinstance(self['root'], static.File):
- raise usage.UsageError("You can only use --processor after --path.")
- ext, klass = proc.split('=', 1)
- self['root'].processors[ext] = reflect.namedClass(klass)
-
- def opt_static(self, path):
- """Same as --path, this is deprecated and will be removed in a
- future release."""
- print ("WARNING: --static is deprecated and will be removed in"
- "a future release. Please use --path.")
- self.opt_path(path)
- opt_s = opt_static
-
- def opt_class(self, className):
- """Create a Resource subclass with a zero-argument constructor.
- """
- classObj = reflect.namedClass(className)
- self['root'] = classObj()
-
-
- def opt_resource_script(self, name):
- """An .rpy file to be used as the root resource of the webserver."""
- self['root'] = script.ResourceScriptWrapper(name)
-
-
- def opt_mime_type(self, defaultType):
- """Specify the default mime-type for static files."""
- if not isinstance(self['root'], static.File):
- raise usage.UsageError("You can only use --mime_type after --path.")
- self['root'].defaultType = defaultType
- opt_m = opt_mime_type
-
-
- def opt_allow_ignore_ext(self):
- """Specify whether or not a request for 'foo' should return 'foo.ext'"""
- if not isinstance(self['root'], static.File):
- raise usage.UsageError("You can only use --allow_ignore_ext "
- "after --path.")
- self['root'].ignoreExt('*')
-
- def opt_ignore_ext(self, ext):
- """Specify an extension to ignore. These will be processed in order.
- """
- if not isinstance(self['root'], static.File):
- raise usage.UsageError("You can only use --ignore_ext "
- "after --path.")
- self['root'].ignoreExt(ext)
-
- def opt_flashconduit(self, port=None):
- """Start a flashconduit on the specified port.
- """
- if not port:
- port = "4321"
- self['flashconduit'] = port
-
- def postOptions(self):
- if self['https']:
- try:
- from twisted.internet.ssl import DefaultOpenSSLContextFactory
- except ImportError:
- raise usage.UsageError("SSL support not installed")
-
-
-
-def makePersonalServerFactory(site):
- """
- Create and return a factory which will respond to I{distrib} requests
- against the given site.
-
- @type site: L{twisted.web.server.Site}
- @rtype: L{twisted.internet.protocol.Factory}
- """
- return pb.PBServerFactory(distrib.ResourcePublisher(site))
-
-
-
-def makeService(config):
- s = service.MultiService()
- if config['root']:
- root = config['root']
- if config['indexes']:
- config['root'].indexNames = config['indexes']
- else:
- # This really ought to be web.Admin or something
- root = demo.Test()
-
- if isinstance(root, static.File):
- root.registry.setComponent(interfaces.IServiceCollection, s)
-
- if config['logfile']:
- site = server.Site(root, logPath=config['logfile'])
- else:
- site = server.Site(root)
-
- site.displayTracebacks = not config["notracebacks"]
-
- if config['personal']:
- import pwd
- name, passwd, uid, gid, gecos, dir, shell = pwd.getpwuid(os.getuid())
- personal = internet.UNIXServer(
- os.path.join(dir, distrib.UserDirectory.userSocketName),
- makePersonalServerFactory(site))
- personal.setServiceParent(s)
- else:
- if config['https']:
- from twisted.internet.ssl import DefaultOpenSSLContextFactory
- i = internet.SSLServer(int(config['https']), site,
- DefaultOpenSSLContextFactory(config['privkey'],
- config['certificate']))
- i.setServiceParent(s)
- strports.service(config['port'], site).setServiceParent(s)
-
- flashport = config.get('flashconduit', None)
- if flashport:
- from twisted.web.woven.flashconduit import FlashConduitFactory
- i = internet.TCPServer(int(flashport), FlashConduitFactory(site))
- i.setServiceParent(s)
- return s
diff --git a/tools/buildbot/pylibs/twisted/web/test/__init__.py b/tools/buildbot/pylibs/twisted/web/test/__init__.py
deleted file mode 100644
index 1ca3db1..0000000
--- a/tools/buildbot/pylibs/twisted/web/test/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-'web tests'
diff --git a/tools/buildbot/pylibs/twisted/web/test/test_cgi.py b/tools/buildbot/pylibs/twisted/web/test/test_cgi.py
deleted file mode 100644
index 528c4d1..0000000
--- a/tools/buildbot/pylibs/twisted/web/test/test_cgi.py
+++ /dev/null
@@ -1,121 +0,0 @@
-import sys, os
-
-from twisted.trial import unittest
-from twisted.internet import reactor, interfaces
-from twisted.python import util
-from twisted.web import static, twcgi, server, resource
-from twisted.web import client
-
-DUMMY_CGI = '''\
-print "Header: OK"
-print
-print "cgi output"
-'''
-
-READINPUT_CGI = '''\
-# this is an example of a correctly-written CGI script which reads a body
-# from stdin, which only reads env['CONTENT_LENGTH'] bytes.
-
-import os, sys
-
-body_length = int(os.environ.get('CONTENT_LENGTH',0))
-indata = sys.stdin.read(body_length)
-print "Header: OK"
-print
-print "readinput ok"
-'''
-
-READALLINPUT_CGI = '''\
-# this is an example of the typical (incorrect) CGI script which expects
-# the server to close stdin when the body of the request is complete.
-# A correct CGI should only read env['CONTENT_LENGTH'] bytes.
-
-import sys
-
-indata = sys.stdin.read()
-print "Header: OK"
-print
-print "readallinput ok"
-'''
-
-class PythonScript(twcgi.FilteredScript):
- filter = sys.executable
- filters = sys.executable, # web2's version
-
-class CGI(unittest.TestCase):
- def startServer(self, cgi):
- root = resource.Resource()
- cgipath = util.sibpath(__file__, cgi)
- root.putChild("cgi", PythonScript(cgipath))
- site = server.Site(root)
- self.p = reactor.listenTCP(0, site)
- return self.p.getHost().port
-
- def tearDown(self):
- if self.p:
- return self.p.stopListening()
-
-
- def testCGI(self):
- cgiFilename = os.path.abspath(self.mktemp())
- cgiFile = file(cgiFilename, 'wt')
- cgiFile.write(DUMMY_CGI)
- cgiFile.close()
-
- portnum = self.startServer(cgiFilename)
- d = client.getPage("http://localhost:%d/cgi" % portnum)
- d.addCallback(self._testCGI_1)
- return d
- def _testCGI_1(self, res):
- self.failUnlessEqual(res, "cgi output" + os.linesep)
-
-
- def testReadEmptyInput(self):
- cgiFilename = os.path.abspath(self.mktemp())
- cgiFile = file(cgiFilename, 'wt')
- cgiFile.write(READINPUT_CGI)
- cgiFile.close()
-
- portnum = self.startServer(cgiFilename)
- d = client.getPage("http://localhost:%d/cgi" % portnum)
- d.addCallback(self._testReadEmptyInput_1)
- return d
- testReadEmptyInput.timeout = 5
- def _testReadEmptyInput_1(self, res):
- self.failUnlessEqual(res, "readinput ok%s" % os.linesep)
-
- def testReadInput(self):
- cgiFilename = os.path.abspath(self.mktemp())
- cgiFile = file(cgiFilename, 'wt')
- cgiFile.write(READINPUT_CGI)
- cgiFile.close()
-
- portnum = self.startServer(cgiFilename)
- d = client.getPage("http://localhost:%d/cgi" % portnum,
- method="POST",
- postdata="Here is your stdin")
- d.addCallback(self._testReadInput_1)
- return d
- testReadInput.timeout = 5
- def _testReadInput_1(self, res):
- self.failUnlessEqual(res, "readinput ok%s" % os.linesep)
-
-
- def testReadAllInput(self):
- cgiFilename = os.path.abspath(self.mktemp())
- cgiFile = file(cgiFilename, 'wt')
- cgiFile.write(READALLINPUT_CGI)
- cgiFile.close()
-
- portnum = self.startServer(cgiFilename)
- d = client.getPage("http://localhost:%d/cgi" % portnum,
- method="POST",
- postdata="Here is your stdin")
- d.addCallback(self._testReadAllInput_1)
- return d
- testReadAllInput.timeout = 5
- def _testReadAllInput_1(self, res):
- self.failUnlessEqual(res, "readallinput ok%s" % os.linesep)
-
-if not interfaces.IReactorProcess.providedBy(reactor):
- CGI.skip = "CGI tests require a functional reactor.spawnProcess()"
diff --git a/tools/buildbot/pylibs/twisted/web/test/test_distrib.py b/tools/buildbot/pylibs/twisted/web/test/test_distrib.py
deleted file mode 100644
index 152b3f3..0000000
--- a/tools/buildbot/pylibs/twisted/web/test/test_distrib.py
+++ /dev/null
@@ -1,64 +0,0 @@
-# Copyright (c) 2008 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-"""
-Tests for L{twisted.web.distrib}.
-"""
-
-from twisted.trial import unittest
-from twisted.web import http, distrib, client, resource, static, server
-from twisted.internet import reactor, defer
-from twisted.spread import pb
-from twisted.python import log
-
-class MySite(server.Site):
- def stopFactory(self):
- if hasattr(self, "logFile"):
- if self.logFile != log.logfile:
- self.logFile.close()
- del self.logFile
-
-
-class PBServerFactory(pb.PBServerFactory):
- def buildProtocol(self, addr):
- self.proto = pb.PBServerFactory.buildProtocol(self, addr)
- return self.proto
-
-
-class DistribTest(unittest.TestCase):
- port1 = None
- port2 = None
- sub = None
-
- def tearDown(self):
- dl = [defer.Deferred(), defer.Deferred()]
- self.f1.proto.notifyOnDisconnect(lambda: dl[0].callback(None))
- if self.sub is not None:
- self.sub.publisher.broker.notifyOnDisconnect(
- lambda: dl[1].callback(None))
- self.sub.publisher.broker.transport.loseConnection()
- http._logDateTimeStop()
- if self.port1 is not None:
- dl.append(self.port1.stopListening())
- if self.port2 is not None:
- dl.append(self.port2.stopListening())
- return defer.gatherResults(dl)
-
- def testDistrib(self):
- # site1 is the publisher
- r1 = resource.Resource()
- r1.putChild("there", static.Data("root", "text/plain"))
- site1 = server.Site(r1)
- self.f1 = PBServerFactory(distrib.ResourcePublisher(site1))
- self.port1 = reactor.listenTCP(0, self.f1)
- self.sub = distrib.ResourceSubscription("127.0.0.1",
- self.port1.getHost().port)
- r2 = resource.Resource()
- r2.putChild("here", self.sub)
- f2 = MySite(r2)
- self.port2 = reactor.listenTCP(0, f2)
- d = client.getPage("http://127.0.0.1:%d/here/there" % \
- self.port2.getHost().port)
- d.addCallback(self.failUnlessEqual, 'root')
- return d
-
diff --git a/tools/buildbot/pylibs/twisted/web/test/test_domhelpers.py b/tools/buildbot/pylibs/twisted/web/test/test_domhelpers.py
deleted file mode 100644
index 6d52fc2..0000000
--- a/tools/buildbot/pylibs/twisted/web/test/test_domhelpers.py
+++ /dev/null
@@ -1,234 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_domhelpers -*-
-#
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-#
-
-"""Specific tests for (some of) the methods in t.web.domhelpers"""
-
-from twisted.trial.unittest import TestCase
-
-from twisted.web import microdom
-
-from twisted.web import domhelpers
-
-class DomHelpersTest(TestCase):
- def test_getElementsByTagName(self):
- doc1=microdom.parseString('<foo/>')
- actual=domhelpers.getElementsByTagName(doc1, 'foo')[0].nodeName
- expected='foo'
- self.assertEquals(actual, expected)
- el1=doc1.documentElement
- actual=domhelpers.getElementsByTagName(el1, 'foo')[0].nodeName
- self.assertEqual(actual, expected)
-
- doc2_xml='<a><foo in="a"/><b><foo in="b"/></b><c><foo in="c"/></c><foo in="d"/><foo in="ef"/><g><foo in="g"/><h><foo in="h"/></h></g></a>'
- doc2=microdom.parseString(doc2_xml)
- tag_list=domhelpers.getElementsByTagName(doc2, 'foo')
- actual=''.join([node.getAttribute('in') for node in tag_list])
- expected='abcdefgh'
- self.assertEquals(actual, expected)
- el2=doc2.documentElement
- tag_list=domhelpers.getElementsByTagName(el2, 'foo')
- actual=''.join([node.getAttribute('in') for node in tag_list])
- self.assertEqual(actual, expected)
-
- doc3_xml='''
-<a><foo in="a"/>
- <b><foo in="b"/>
- <d><foo in="d"/>
- <g><foo in="g"/></g>
- <h><foo in="h"/></h>
- </d>
- <e><foo in="e"/>
- <i><foo in="i"/></i>
- </e>
- </b>
- <c><foo in="c"/>
- <f><foo in="f"/>
- <j><foo in="j"/></j>
- </f>
- </c>
-</a>'''
- doc3=microdom.parseString(doc3_xml)
- tag_list=domhelpers.getElementsByTagName(doc3, 'foo')
- actual=''.join([node.getAttribute('in') for node in tag_list])
- expected='abdgheicfj'
- self.assertEquals(actual, expected)
- el3=doc3.documentElement
- tag_list=domhelpers.getElementsByTagName(el3, 'foo')
- actual=''.join([node.getAttribute('in') for node in tag_list])
- self.assertEqual(actual, expected)
-
- doc4_xml='<foo><bar></bar><baz><foo/></baz></foo>'
- doc4=microdom.parseString(doc4_xml)
- actual=domhelpers.getElementsByTagName(doc4, 'foo')
- root=doc4.documentElement
- expected=[root, root.lastChild().firstChild()]
- self.assertEquals(actual, expected)
- actual=domhelpers.getElementsByTagName(root, 'foo')
- self.assertEqual(actual, expected)
-
-
- def test_gatherTextNodes(self):
- doc1=microdom.parseString('<a>foo</a>')
- actual=domhelpers.gatherTextNodes(doc1)
- expected='foo'
- self.assertEqual(actual, expected)
- actual=domhelpers.gatherTextNodes(doc1.documentElement)
- self.assertEqual(actual, expected)
-
- doc2_xml='<a>a<b>b</b><c>c</c>def<g>g<h>h</h></g></a>'
- doc2=microdom.parseString(doc2_xml)
- actual=domhelpers.gatherTextNodes(doc2)
- expected='abcdefgh'
- self.assertEqual(actual, expected)
- actual=domhelpers.gatherTextNodes(doc2.documentElement)
- self.assertEqual(actual, expected)
-
- doc3_xml=('<a>a<b>b<d>d<g>g</g><h>h</h></d><e>e<i>i</i></e></b>' +
- '<c>c<f>f<j>j</j></f></c></a>')
- doc3=microdom.parseString(doc3_xml)
- actual=domhelpers.gatherTextNodes(doc3)
- expected='abdgheicfj'
- self.assertEqual(actual, expected)
- actual=domhelpers.gatherTextNodes(doc3.documentElement)
- self.assertEqual(actual, expected)
-
- doc4_xml='''<html>
- <head>
- </head>
- <body>
- stuff
- </body>
-</html>
-'''
- doc4=microdom.parseString(doc4_xml)
- actual=domhelpers.gatherTextNodes(doc4)
- expected='\n stuff\n '
- assert actual==expected, 'expected %s, got %s' % (expected, actual)
- actual=domhelpers.gatherTextNodes(doc4.documentElement)
- self.assertEqual(actual, expected)
-
- doc5_xml='<x>Souffl&eacute;</x>'
- doc5=microdom.parseString(doc5_xml)
- actual=domhelpers.gatherTextNodes(doc5)
- expected='Souffl&eacute;'
- self.assertEqual(actual, expected)
- actual=domhelpers.gatherTextNodes(doc5.documentElement)
- self.assertEqual(actual, expected)
-
- def test_clearNode(self):
- doc1=microdom.parseString('<a><b><c><d/></c></b></a>')
- a_node=doc1.documentElement
- domhelpers.clearNode(a_node)
- actual=doc1.documentElement.toxml()
- expected='<a></a>'
- assert actual==expected, 'expected %s, got %s' % (expected, actual)
-
- doc2=microdom.parseString('<a><b><c><d/></c></b></a>')
- b_node=doc2.documentElement.childNodes[0]
- domhelpers.clearNode(b_node)
- actual=doc2.documentElement.toxml()
- expected='<a><b></b></a>'
- assert actual==expected, 'expected %s, got %s' % (expected, actual)
-
- doc3=microdom.parseString('<a><b><c><d/></c></b></a>')
- c_node=doc3.documentElement.childNodes[0].childNodes[0]
- domhelpers.clearNode(c_node)
- actual=doc3.documentElement.toxml()
- expected='<a><b><c></c></b></a>'
- assert actual==expected, 'expected %s, got %s' % (expected, actual)
-
- def test_get(self):
- doc1=microdom.parseString('<a><b id="bar"/><c class="foo"/></a>')
- node=domhelpers.get(doc1, "foo")
- actual=node.toxml()
- expected='<c class="foo"></c>'
- assert actual==expected, 'expected %s, got %s' % (expected, actual)
-
- node=domhelpers.get(doc1, "bar")
- actual=node.toxml()
- expected='<b id="bar"></b>'
- assert actual==expected, 'expected %s, got %s' % (expected, actual)
-
- self.assertRaises(domhelpers.NodeLookupError,
- domhelpers.get,
- doc1,
- "pzork")
-
- def test_getIfExists(self):
- doc1=microdom.parseString('<a><b id="bar"/><c class="foo"/></a>')
- node=domhelpers.getIfExists(doc1, "foo")
- actual=node.toxml()
- expected='<c class="foo"></c>'
- assert actual==expected, 'expected %s, got %s' % (expected, actual)
-
- node=domhelpers.getIfExists(doc1, "pzork")
- assert node==None, 'expected None, didn\'t get None'
-
- def test_getAndClear(self):
- doc1=microdom.parseString('<a><b id="foo"><c></c></b></a>')
- node=domhelpers.getAndClear(doc1, "foo")
- actual=node.toxml()
- expected='<b id="foo"></b>'
- assert actual==expected, 'expected %s, got %s' % (expected, actual)
-
- def test_locateNodes(self):
- doc1=microdom.parseString('<a><b foo="olive"><c foo="olive"/></b><d foo="poopy"/></a>')
- node_list=domhelpers.locateNodes(doc1.childNodes, 'foo', 'olive',
- noNesting=1)
- actual=''.join([node.toxml() for node in node_list])
- expected='<b foo="olive"><c foo="olive"></c></b>'
- assert actual==expected, 'expected %s, got %s' % (expected, actual)
-
- node_list=domhelpers.locateNodes(doc1.childNodes, 'foo', 'olive',
- noNesting=0)
- actual=''.join([node.toxml() for node in node_list])
- expected='<b foo="olive"><c foo="olive"></c></b><c foo="olive"></c>'
- assert actual==expected, 'expected %s, got %s' % (expected, actual)
-
- def test_getParents(self):
- doc1=microdom.parseString('<a><b><c><d/></c><e/></b><f/></a>')
- node_list=domhelpers.getParents(doc1.childNodes[0].childNodes[0].childNodes[0])
- actual=''.join([node.tagName for node in node_list
- if hasattr(node, 'tagName')])
- expected='cba'
- assert actual==expected, 'expected %s, got %s' % (expected, actual)
-
- def test_findElementsWithAttribute(self):
- doc1=microdom.parseString('<a foo="1"><b foo="2"/><c foo="1"/><d/></a>')
- node_list=domhelpers.findElementsWithAttribute(doc1, 'foo')
- actual=''.join([node.tagName for node in node_list])
- expected='abc'
- assert actual==expected, 'expected %s, got %s' % (expected, actual)
-
- node_list=domhelpers.findElementsWithAttribute(doc1, 'foo', '1')
- actual=''.join([node.tagName for node in node_list])
- expected='ac'
- assert actual==expected, 'expected %s, got %s' % (expected, actual)
-
- def test_findNodesNamed(self):
- doc1=microdom.parseString('<doc><foo/><bar/><foo>a</foo></doc>')
- node_list=domhelpers.findNodesNamed(doc1, 'foo')
- actual=len(node_list)
- expected=2
- assert actual==expected, 'expected %d, got %d' % (expected, actual)
-
- # NOT SURE WHAT THESE ARE SUPPOSED TO DO..
- # def test_RawText FIXME
- # def test_superSetAttribute FIXME
- # def test_superPrependAttribute FIXME
- # def test_superAppendAttribute FIXME
- # def test_substitute FIXME
-
- def test_escape(self):
- j='this string " contains many & characters> xml< won\'t like'
- expected='this string &quot; contains many &amp; characters&gt; xml&lt; won\'t like'
- self.assertEqual(domhelpers.escape(j), expected)
-
- def test_unescape(self):
- j='this string &quot; has &&amp; entities &gt; &lt; and some characters xml won\'t like<'
- expected='this string " has && entities > < and some characters xml won\'t like<'
- self.assertEqual(domhelpers.unescape(j), expected)
diff --git a/tools/buildbot/pylibs/twisted/web/test/test_http.py b/tools/buildbot/pylibs/twisted/web/test/test_http.py
deleted file mode 100644
index 97caba5..0000000
--- a/tools/buildbot/pylibs/twisted/web/test/test_http.py
+++ /dev/null
@@ -1,548 +0,0 @@
-# Copyright (c) 2001-2007 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""
-Test HTTP support.
-"""
-
-from urlparse import urlparse, urlunsplit, clear_cache
-import string, random, urllib, cgi
-
-from twisted.trial import unittest
-from twisted.web import http
-from twisted.protocols import loopback
-from twisted.internet import protocol
-from twisted.test.test_protocols import StringIOWithoutClosing
-
-
-class DateTimeTest(unittest.TestCase):
- """Test date parsing functions."""
-
- def testRoundtrip(self):
- for i in range(10000):
- time = random.randint(0, 2000000000)
- timestr = http.datetimeToString(time)
- time2 = http.stringToDatetime(timestr)
- self.assertEquals(time, time2)
-
-
-class OrderedDict:
-
- def __init__(self, dict):
- self.dict = dict
- self.l = dict.keys()
-
- def __setitem__(self, k, v):
- self.l.append(k)
- self.dict[k] = v
-
- def __getitem__(self, k):
- return self.dict[k]
-
- def items(self):
- result = []
- for i in self.l:
- result.append((i, self.dict[i]))
- return result
-
- def __getattr__(self, attr):
- return getattr(self.dict, attr)
-
-
-class DummyHTTPHandler(http.Request):
-
- def process(self):
- self.headers = OrderedDict(self.headers)
- self.content.seek(0, 0)
- data = self.content.read()
- length = self.getHeader('content-length')
- request = "'''\n"+str(length)+"\n"+data+"'''\n"
- self.setResponseCode(200)
- self.setHeader("Request", self.uri)
- self.setHeader("Command", self.method)
- self.setHeader("Version", self.clientproto)
- self.setHeader("Content-Length", len(request))
- self.write(request)
- self.finish()
-
-
-class LoopbackHTTPClient(http.HTTPClient):
-
- def connectionMade(self):
- self.sendCommand("GET", "/foo/bar")
- self.sendHeader("Content-Length", 10)
- self.endHeaders()
- self.transport.write("0123456789")
-
-
-class HTTP1_0TestCase(unittest.TestCase):
-
- requests = '''\
-GET / HTTP/1.0
-
-GET / HTTP/1.1
-Accept: text/html
-
-'''
- requests = string.replace(requests, '\n', '\r\n')
-
- expected_response = "HTTP/1.0 200 OK\015\012Request: /\015\012Command: GET\015\012Version: HTTP/1.0\015\012Content-length: 13\015\012\015\012'''\012None\012'''\012"
-
- def test_buffer(self):
- """
- Send requests over a channel and check responses match what is expected.
- """
- b = StringIOWithoutClosing()
- a = http.HTTPChannel()
- a.requestFactory = DummyHTTPHandler
- a.makeConnection(protocol.FileWrapper(b))
- # one byte at a time, to stress it.
- for byte in self.requests:
- a.dataReceived(byte)
- a.connectionLost(IOError("all one"))
- value = b.getvalue()
- self.assertEquals(value, self.expected_response)
-
-
-class HTTP1_1TestCase(HTTP1_0TestCase):
-
- requests = '''\
-GET / HTTP/1.1
-Accept: text/html
-
-POST / HTTP/1.1
-Content-Length: 10
-
-0123456789POST / HTTP/1.1
-Content-Length: 10
-
-0123456789HEAD / HTTP/1.1
-
-'''
- requests = string.replace(requests, '\n', '\r\n')
-
- expected_response = "HTTP/1.1 200 OK\015\012Request: /\015\012Command: GET\015\012Version: HTTP/1.1\015\012Content-length: 13\015\012\015\012'''\012None\012'''\012HTTP/1.1 200 OK\015\012Request: /\015\012Command: POST\015\012Version: HTTP/1.1\015\012Content-length: 21\015\012\015\012'''\01210\0120123456789'''\012HTTP/1.1 200 OK\015\012Request: /\015\012Command: POST\015\012Version: HTTP/1.1\015\012Content-length: 21\015\012\015\012'''\01210\0120123456789'''\012HTTP/1.1 200 OK\015\012Request: /\015\012Command: HEAD\015\012Version: HTTP/1.1\015\012Content-length: 13\015\012\015\012"
-
-class HTTP1_1_close_TestCase(HTTP1_0TestCase):
-
- requests = '''\
-GET / HTTP/1.1
-Accept: text/html
-Connection: close
-
-GET / HTTP/1.0
-
-'''
-
- requests = string.replace(requests, '\n', '\r\n')
-
- expected_response = "HTTP/1.1 200 OK\015\012Connection: close\015\012Request: /\015\012Command: GET\015\012Version: HTTP/1.1\015\012Content-length: 13\015\012\015\012'''\012None\012'''\012"
-
-
-class HTTP0_9TestCase(HTTP1_0TestCase):
-
- requests = '''\
-GET /
-'''
- requests = string.replace(requests, '\n', '\r\n')
-
- expected_response = "HTTP/1.1 400 Bad Request\r\n\r\n"
-
-
-class HTTPLoopbackTestCase(unittest.TestCase):
-
- expectedHeaders = {'request' : '/foo/bar',
- 'command' : 'GET',
- 'version' : 'HTTP/1.0',
- 'content-length' : '21'}
- numHeaders = 0
- gotStatus = 0
- gotResponse = 0
- gotEndHeaders = 0
-
- def _handleStatus(self, version, status, message):
- self.gotStatus = 1
- self.assertEquals(version, "HTTP/1.0")
- self.assertEquals(status, "200")
-
- def _handleResponse(self, data):
- self.gotResponse = 1
- self.assertEquals(data, "'''\n10\n0123456789'''\n")
-
- def _handleHeader(self, key, value):
- self.numHeaders = self.numHeaders + 1
- self.assertEquals(self.expectedHeaders[string.lower(key)], value)
-
- def _handleEndHeaders(self):
- self.gotEndHeaders = 1
- self.assertEquals(self.numHeaders, 4)
-
- def testLoopback(self):
- server = http.HTTPChannel()
- server.requestFactory = DummyHTTPHandler
- client = LoopbackHTTPClient()
- client.handleResponse = self._handleResponse
- client.handleHeader = self._handleHeader
- client.handleEndHeaders = self._handleEndHeaders
- client.handleStatus = self._handleStatus
- d = loopback.loopbackAsync(server, client)
- d.addCallback(self._cbTestLoopback)
- return d
-
- def _cbTestLoopback(self, ignored):
- if not (self.gotStatus and self.gotResponse and self.gotEndHeaders):
- raise RuntimeError(
- "didn't got all callbacks %s"
- % [self.gotStatus, self.gotResponse, self.gotEndHeaders])
- del self.gotEndHeaders
- del self.gotResponse
- del self.gotStatus
- del self.numHeaders
-
-
-class PRequest:
- """Dummy request for persistence tests."""
-
- def __init__(self, **headers):
- self.received_headers = headers
- self.headers = {}
-
- def getHeader(self, k):
- return self.received_headers.get(k, '')
-
- def setHeader(self, k, v):
- self.headers[k] = v
-
-
-class PersistenceTestCase(unittest.TestCase):
- """Tests for persistent HTTP connections."""
-
- ptests = [#(PRequest(connection="Keep-Alive"), "HTTP/1.0", 1, {'connection' : 'Keep-Alive'}),
- (PRequest(), "HTTP/1.0", 0, {'connection': None}),
- (PRequest(connection="close"), "HTTP/1.1", 0, {'connection' : 'close'}),
- (PRequest(), "HTTP/1.1", 1, {'connection': None}),
- (PRequest(), "HTTP/0.9", 0, {'connection': None}),
- ]
-
-
- def testAlgorithm(self):
- c = http.HTTPChannel()
- for req, version, correctResult, resultHeaders in self.ptests:
- result = c.checkPersistence(req, version)
- self.assertEquals(result, correctResult)
- for header in resultHeaders.keys():
- self.assertEquals(req.headers.get(header, None), resultHeaders[header])
-
-
-class ChunkingTestCase(unittest.TestCase):
-
- strings = ["abcv", "", "fdfsd423", "Ffasfas\r\n",
- "523523\n\rfsdf", "4234"]
-
- def testChunks(self):
- for s in self.strings:
- self.assertEquals((s, ''), http.fromChunk(''.join(http.toChunk(s))))
- self.assertRaises(ValueError, http.fromChunk, '-5\r\nmalformed!\r\n')
-
- def testConcatenatedChunks(self):
- chunked = ''.join([''.join(http.toChunk(t)) for t in self.strings])
- result = []
- buffer = ""
- for c in chunked:
- buffer = buffer + c
- try:
- data, buffer = http.fromChunk(buffer)
- result.append(data)
- except ValueError:
- pass
- self.assertEquals(result, self.strings)
-
-
-
-class ParsingTestCase(unittest.TestCase):
-
- def runRequest(self, httpRequest, requestClass, success=1):
- httpRequest = httpRequest.replace("\n", "\r\n")
- b = StringIOWithoutClosing()
- a = http.HTTPChannel()
- a.requestFactory = requestClass
- a.makeConnection(protocol.FileWrapper(b))
- # one byte at a time, to stress it.
- for byte in httpRequest:
- if a.transport.closed:
- break
- a.dataReceived(byte)
- a.connectionLost(IOError("all done"))
- if success:
- self.assertEquals(self.didRequest, 1)
- del self.didRequest
- else:
- self.assert_(not hasattr(self, "didRequest"))
-
- def testBasicAuth(self):
- testcase = self
- class Request(http.Request):
- l = []
- def process(self):
- testcase.assertEquals(self.getUser(), self.l[0])
- testcase.assertEquals(self.getPassword(), self.l[1])
- for u, p in [("foo", "bar"), ("hello", "there:z")]:
- Request.l[:] = [u, p]
- s = "%s:%s" % (u, p)
- f = "GET / HTTP/1.0\nAuthorization: Basic %s\n\n" % (s.encode("base64").strip(), )
- self.runRequest(f, Request, 0)
-
- def testTooManyHeaders(self):
- httpRequest = "GET / HTTP/1.0\n"
- for i in range(502):
- httpRequest += "%s: foo\n" % i
- httpRequest += "\n"
- class MyRequest(http.Request):
- def process(self):
- raise RuntimeError, "should not get called"
- self.runRequest(httpRequest, MyRequest, 0)
-
- def testHeaders(self):
- httpRequest = """\
-GET / HTTP/1.0
-Foo: bar
-baz: 1 2 3
-
-"""
- testcase = self
-
- class MyRequest(http.Request):
- def process(self):
- testcase.assertEquals(self.getHeader('foo'), 'bar')
- testcase.assertEquals(self.getHeader('Foo'), 'bar')
- testcase.assertEquals(self.getHeader('bAz'), '1 2 3')
- testcase.didRequest = 1
- self.finish()
-
- self.runRequest(httpRequest, MyRequest)
-
- def testCookies(self):
- """
- Test cookies parsing and reading.
- """
- httpRequest = '''\
-GET / HTTP/1.0
-Cookie: rabbit="eat carrot"; ninja=secret; spam="hey 1=1!"
-
-'''
- testcase = self
-
- class MyRequest(http.Request):
- def process(self):
- testcase.assertEquals(self.getCookie('rabbit'), '"eat carrot"')
- testcase.assertEquals(self.getCookie('ninja'), 'secret')
- testcase.assertEquals(self.getCookie('spam'), '"hey 1=1!"')
- testcase.didRequest = 1
- self.finish()
-
- self.runRequest(httpRequest, MyRequest)
-
- def testGET(self):
- httpRequest = '''\
-GET /?key=value&multiple=two+words&multiple=more%20words&empty= HTTP/1.0
-
-'''
- testcase = self
- class MyRequest(http.Request):
- def process(self):
- testcase.assertEquals(self.method, "GET")
- testcase.assertEquals(self.args["key"], ["value"])
- testcase.assertEquals(self.args["empty"], [""])
- testcase.assertEquals(self.args["multiple"], ["two words", "more words"])
- testcase.didRequest = 1
- self.finish()
-
- self.runRequest(httpRequest, MyRequest)
-
-
- def test_extraQuestionMark(self):
- """
- While only a single '?' is allowed in an URL, several other servers
- allow several and pass all after the first through as part of the
- query arguments. Test that we emulate this behavior.
- """
- httpRequest = 'GET /foo?bar=?&baz=quux HTTP/1.0\n\n'
-
- testcase = self
- class MyRequest(http.Request):
- def process(self):
- testcase.assertEqual(self.method, 'GET')
- testcase.assertEqual(self.path, '/foo')
- testcase.assertEqual(self.args['bar'], ['?'])
- testcase.assertEqual(self.args['baz'], ['quux'])
- testcase.didRequest = 1
- self.finish()
-
- self.runRequest(httpRequest, MyRequest)
-
-
- def testPOST(self):
- query = 'key=value&multiple=two+words&multiple=more%20words&empty='
- httpRequest = '''\
-POST / HTTP/1.0
-Content-Length: %d
-Content-Type: application/x-www-form-urlencoded
-
-%s''' % (len(query), query)
-
- testcase = self
- class MyRequest(http.Request):
- def process(self):
- testcase.assertEquals(self.method, "POST")
- testcase.assertEquals(self.args["key"], ["value"])
- testcase.assertEquals(self.args["empty"], [""])
- testcase.assertEquals(self.args["multiple"], ["two words", "more words"])
- testcase.didRequest = 1
- self.finish()
-
- self.runRequest(httpRequest, MyRequest)
-
- def testMissingContentDisposition(self):
- req = '''\
-POST / HTTP/1.0
-Content-Type: multipart/form-data; boundary=AaB03x
-Content-Length: 103
-
---AaB03x
-Content-Type: text/plain
-Content-Transfer-Encoding: quoted-printable
-
-abasdfg
---AaB03x--
-'''
- self.runRequest(req, http.Request, success=False)
-
-class QueryArgumentsTestCase(unittest.TestCase):
- def testUnquote(self):
- try:
- from twisted.protocols import _c_urlarg
- except ImportError:
- raise unittest.SkipTest("_c_urlarg module is not available")
- # work exactly like urllib.unquote, including stupid things
- # % followed by a non-hexdigit in the middle and in the end
- self.failUnlessEqual(urllib.unquote("%notreally%n"),
- _c_urlarg.unquote("%notreally%n"))
- # % followed by hexdigit, followed by non-hexdigit
- self.failUnlessEqual(urllib.unquote("%1quite%1"),
- _c_urlarg.unquote("%1quite%1"))
- # unquoted text, followed by some quoted chars, ends in a trailing %
- self.failUnlessEqual(urllib.unquote("blah%21%40%23blah%"),
- _c_urlarg.unquote("blah%21%40%23blah%"))
- # Empty string
- self.failUnlessEqual(urllib.unquote(""), _c_urlarg.unquote(""))
-
- def testParseqs(self):
- self.failUnlessEqual(cgi.parse_qs("a=b&d=c;+=f"),
- http.parse_qs("a=b&d=c;+=f"))
- self.failUnlessRaises(ValueError, http.parse_qs, "blah",
- strict_parsing = 1)
- self.failUnlessEqual(cgi.parse_qs("a=&b=c", keep_blank_values = 1),
- http.parse_qs("a=&b=c", keep_blank_values = 1))
- self.failUnlessEqual(cgi.parse_qs("a=&b=c"),
- http.parse_qs("a=&b=c"))
-
-
- def test_urlparse(self):
- """
- For a given URL, L{http.urlparse} should behave the same as
- L{urlparse}, except it should always return C{str}, never C{unicode}.
- """
- def urls():
- for scheme in ('http', 'https'):
- for host in ('example.com',):
- for port in (None, 100):
- for path in ('', 'path'):
- if port is not None:
- host = host + ':' + str(port)
- yield urlunsplit((scheme, host, path, '', ''))
-
-
- def assertSameParsing(url, decode):
- """
- Verify that C{url} is parsed into the same objects by both
- L{http.urlparse} and L{urlparse}.
- """
- urlToStandardImplementation = url
- if decode:
- urlToStandardImplementation = url.decode('ascii')
- standardResult = urlparse(urlToStandardImplementation)
- scheme, netloc, path, params, query, fragment = http.urlparse(url)
- self.assertEqual(
- (scheme, netloc, path, params, query, fragment),
- standardResult)
- self.assertTrue(isinstance(scheme, str))
- self.assertTrue(isinstance(netloc, str))
- self.assertTrue(isinstance(path, str))
- self.assertTrue(isinstance(params, str))
- self.assertTrue(isinstance(query, str))
- self.assertTrue(isinstance(fragment, str))
-
- # With caching, unicode then str
- clear_cache()
- for url in urls():
- assertSameParsing(url, True)
- assertSameParsing(url, False)
-
- # With caching, str then unicode
- clear_cache()
- for url in urls():
- assertSameParsing(url, False)
- assertSameParsing(url, True)
-
- # Without caching
- for url in urls():
- clear_cache()
- assertSameParsing(url, True)
- clear_cache()
- assertSameParsing(url, False)
-
-
- def test_urlparseRejectsUnicode(self):
- """
- L{http.urlparse} should reject unicode input early.
- """
- self.assertRaises(TypeError, http.urlparse, u'http://example.org/path')
-
-
- def testEscchar(self):
- try:
- from twisted.protocols import _c_urlarg
- except ImportError:
- raise unittest.SkipTest("_c_urlarg module is not available")
- self.failUnlessEqual("!@#+b",
- _c_urlarg.unquote("+21+40+23+b", "+"))
-
-class ClientDriver(http.HTTPClient):
- def handleStatus(self, version, status, message):
- self.version = version
- self.status = status
- self.message = message
-
-class ClientStatusParsing(unittest.TestCase):
- def testBaseline(self):
- c = ClientDriver()
- c.lineReceived('HTTP/1.0 201 foo')
- self.failUnlessEqual(c.version, 'HTTP/1.0')
- self.failUnlessEqual(c.status, '201')
- self.failUnlessEqual(c.message, 'foo')
-
- def testNoMessage(self):
- c = ClientDriver()
- c.lineReceived('HTTP/1.0 201')
- self.failUnlessEqual(c.version, 'HTTP/1.0')
- self.failUnlessEqual(c.status, '201')
- self.failUnlessEqual(c.message, '')
-
- def testNoMessage_trailingSpace(self):
- c = ClientDriver()
- c.lineReceived('HTTP/1.0 201 ')
- self.failUnlessEqual(c.version, 'HTTP/1.0')
- self.failUnlessEqual(c.status, '201')
- self.failUnlessEqual(c.message, '')
-
diff --git a/tools/buildbot/pylibs/twisted/web/test/test_mvc.py b/tools/buildbot/pylibs/twisted/web/test/test_mvc.py
deleted file mode 100644
index 312eaf9..0000000
--- a/tools/buildbot/pylibs/twisted/web/test/test_mvc.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""Test cases for Twisted Model-View-Controller architecture."""
-
-import random
-
-try:
- import cPickle as pickle
-except ImportError:
- import pickle
-
-from twisted.trial import unittest
-
-from twisted.web.woven import model, view, controller, interfaces
-from twisted.python import components
-
-# simple pickled string storage to test persistence
-persisted_model = ""
-
-class MyModel(model.Model):
- def __init__(self, foo, random=None):
- # I hate having to explicitly initialize the super
- model.Model.__init__(self)
- self.foo=foo
- self.random=random
-
-class MyView(view.View):
- def __init__(self, model, *args, **kwargs):
- view.View.__init__(self, model, *args, **kwargs)
- self.model.addView(self)
- # pretend self.foo is what the user now sees on their screen
- self.foo = self.model.foo
- self.random = self.model.random
- self.controller = interfaces.IController(self.model, None)
-
- def modelChanged(self, changed):
- if changed.has_key('foo'):
- self.foo = changed['foo']
- if changed.has_key('random'):
- self.random = changed['random']
-
- def twiddleControl(self, newValue):
- """
- The user twiddled a control onscreen, causing this event
- """
- self.controller.setFoo(newValue)
-
- def pushButton(self):
- """
- The user hit a button onscreen, causing this event
- """
- return self.controller.doRandom()
-
-# Register MyView as the view for instances of type MyModel
-components.registerAdapter(MyView, MyModel, interfaces.IView)
-
-class MyController(controller.Controller):
- def setFoo(self, newValue):
- self.model.foo = newValue
- self.model.notify({'foo': newValue})
- self.persist()
-
- def doRandom(self):
- rnd = random.choice(range(100))
- self.model.random = rnd
- self.model.notify({'random': rnd})
- self.persist()
- return rnd
-
- def persist(self):
- """
- Save the model object to persistent storage
- """
- global persisted_model
-
- persisted_model = pickle.dumps(self.model)
-
-# Register MyController as the controller for instances of type MyModel
-components.registerAdapter(MyController, MyModel, interfaces.IController)
-
-class MVCTestCase(unittest.TestCase):
- """Test MVC."""
- def setUp(self):
- self.model = MyModel("foo")
-
- def getView(self):
- return interfaces.IView(self.model, None)
-
- def testViewConstruction(self):
- view = self.getView()
- self.assert_(isinstance(view, MyView))
-
- def testControllerConstruction(self):
- view = self.getView()
- self.assert_(isinstance(view.controller, MyController))
-
- def testModelManipulation(self):
- view = self.getView()
- view.twiddleControl("bar")
- self.assertEquals("bar", self.model.foo)
-
- def testMoreModelManipulation(self):
- view = self.getView()
- value = view.pushButton()
- self.assertEquals(value, self.model.random)
-
- def testViewManipulation(self):
- """When the model updates the view should too"""
- view = self.getView()
- view.twiddleControl("bar")
- self.assertEquals("bar", view.foo)
-
- def testMoreViewManipulation(self):
- """When the model updates the view should too"""
- view = self.getView()
- value = view.pushButton()
- self.assertEquals(value, view.random)
-
-
-testCases = [MVCTestCase]
diff --git a/tools/buildbot/pylibs/twisted/web/test/test_proxy.py b/tools/buildbot/pylibs/twisted/web/test/test_proxy.py
deleted file mode 100644
index 4b0194b..0000000
--- a/tools/buildbot/pylibs/twisted/web/test/test_proxy.py
+++ /dev/null
@@ -1,407 +0,0 @@
-# Copyright (c) 2007 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-"""
-Test for L{twisted.web.proxy}.
-"""
-
-from twisted.trial.unittest import TestCase
-from twisted.test.proto_helpers import StringTransportWithDisconnection
-from twisted.internet.error import ConnectionDone
-
-from twisted.web.resource import Resource
-from twisted.web.server import Site
-from twisted.web.proxy import ReverseProxyResource, ProxyClientFactory
-from twisted.web.proxy import ProxyClient, ProxyRequest, ReverseProxyRequest
-
-
-
-class FakeReactor(object):
- """
- A fake reactor to be used in tests.
-
- @ivar connect: a list that keeps track of connection attempts (ie, calls
- to C{connectTCP}).
- @type connect: C{list}
- """
-
- def __init__(self):
- """
- Initialize the C{connect} list.
- """
- self.connect = []
-
-
- def connectTCP(self, host, port, factory):
- """
- Fake L{reactor.connectTCP}, that does nothing but log the call.
- """
- self.connect.append([host, port, factory])
-
-
-
-class ReverseProxyResourceTestCase(TestCase):
- """
- Tests for L{ReverseProxyResource}.
- """
-
- def _testRender(self, uri, expectedURI):
- """
- Check that a request pointing at C{uri} produce a new proxy connection,
- with the path of this request pointing at C{expectedURI}.
- """
- root = Resource()
- reactor = FakeReactor()
- resource = ReverseProxyResource("127.0.0.1", 1234, "/path", reactor)
- root.putChild('index', resource)
- site = Site(root)
-
- transport = StringTransportWithDisconnection()
- channel = site.buildProtocol(None)
- channel.makeConnection(transport)
- # Clear the timeout if the tests failed
- self.addCleanup(channel.connectionLost, None)
-
- channel.dataReceived("GET %s HTTP/1.1\r\nAccept: text/html\r\n\r\n" %
- (uri,))
-
- # Check that one connection has been created, to the good host/port
- self.assertEquals(len(reactor.connect), 1)
- self.assertEquals(reactor.connect[0][0], "127.0.0.1")
- self.assertEquals(reactor.connect[0][1], 1234)
-
- # Check the factory passed to the connect, and its given path
- factory = reactor.connect[0][2]
- self.assertIsInstance(factory, ProxyClientFactory)
- self.assertEquals(factory.rest, expectedURI)
- self.assertEquals(factory.headers["host"], "127.0.0.1:1234")
-
-
- def test_render(self):
- """
- Test that L{ReverseProxyResource.render} initiates a connection to the
- given server with a L{ProxyClientFactory} as parameter.
- """
- return self._testRender("/index", "/path")
-
-
- def test_renderWithQuery(self):
- """
- Test that L{ReverseProxyResource.render} passes query parameters to the
- created factory.
- """
- return self._testRender("/index?foo=bar", "/path?foo=bar")
-
-
- def test_getChild(self):
- """
- The L{ReverseProxyResource.getChild} method should return a resource
- instance with the same class as the originating resource, forward port
- and host values, and update the path value with the value passed.
- """
- resource = ReverseProxyResource("127.0.0.1", 1234, "/path")
- child = resource.getChild('foo', None)
- # The child should keep the same class
- self.assertIsInstance(child, ReverseProxyResource)
- self.assertEquals(child.path, "/path/foo")
- self.assertEquals(child.port, 1234)
- self.assertEquals(child.host, "127.0.0.1")
-
-
- def test_getChildWithSpecial(self):
- """
- The L{ReverseProxyResource} return by C{getChild} has a path which has
- already been quoted.
- """
- resource = ReverseProxyResource("127.0.0.1", 1234, "/path")
- child = resource.getChild(' /%', None)
- self.assertEqual(child.path, "/path/%20%2F%25")
-
-
-
-class DummyParent(object):
- """
- A dummy parent request that holds a channel and its transport.
-
- @ivar channel: the request channel.
- @ivar transport: the transport of the channel.
- """
-
- def __init__(self, channel):
- """
- Hold a reference to the channel and its transport.
- """
- self.channel = channel
- self.transport = channel.transport
-
-
-
-class DummyChannel(object):
- """
- A dummy HTTP channel, that does nothing but holds a transport and saves
- connection lost.
-
- @ivar transport: the transport used by the client.
- @ivar lostReason: the reason saved at connection lost.
- """
-
- def __init__(self, transport):
- """
- Hold a reference to the transport.
- """
- self.transport = transport
- self.lostReason = None
-
-
- def connectionLost(self, reason):
- """
- Keep track of the connection lost reason.
- """
- self.lostReason = reason
-
-
-
-class ProxyClientTestCase(TestCase):
- """
- Tests for L{ProxyClient}.
- """
-
- def _testDataForward(self, data, method="GET", body=""):
- """
- Build a fake proxy connection, and send C{data} over it, checking that
- it's forwarded to the originating request.
- """
- # Connect everything
- clientTransport = StringTransportWithDisconnection()
- serverTransport = StringTransportWithDisconnection()
- channel = DummyChannel(serverTransport)
- parent = DummyParent(channel)
- serverTransport.protocol = channel
-
- client = ProxyClient(method, '/foo', 'HTTP/1.0',
- {"accept": "text/html"}, body, parent)
- clientTransport.protocol = client
- client.makeConnection(clientTransport)
-
- # Check data sent
- self.assertEquals(clientTransport.value(),
- "%s /foo HTTP/1.0\r\n"
- "connection: close\r\n"
- "accept: text/html\r\n\r\n%s" % (method, body))
-
- # Fake an answer
- client.dataReceived(data)
-
- # Check that the data has been forwarded
- self.assertEquals(serverTransport.value(), data)
-
- clientTransport.loseConnection()
- self.assertIsInstance(channel.lostReason, ConnectionDone)
-
-
- def test_forward(self):
- """
- When connected to the server, L{ProxyClient} should send the saved
- request, with modifications of the headers, and then forward the result
- to the parent request.
- """
- return self._testDataForward("200 OK\r\nFoo: bar\r\n\r\nSome data\r\n")
-
-
- def test_postData(self):
- """
- Try to post content in the request, and check that the proxy client
- forward the body of the request.
- """
- return self._testDataForward(
- "200 OK\r\nFoo: bar\r\n\r\nSome data\r\n", "POST", "Some content")
-
-
- def test_statusWithMessage(self):
- """
- If the response contains a status with a message, it should be
- forwarded to the parent request with all the information.
- """
- return self._testDataForward("404 Not Found\r\n")
-
-
- def test_headersCleanups(self):
- """
- The headers given at initialization should be modified:
- B{proxy-connection} should be removed if present, and B{connection}
- should be added.
- """
- client = ProxyClient('GET', '/foo', 'HTTP/1.0',
- {"accept": "text/html", "proxy-connection": "foo"}, '', None)
- self.assertEquals(client.headers,
- {"accept": "text/html", "connection": "close"})
-
-
-
-class ProxyClientFactoryTestCase(TestCase):
- """
- Tests for L{ProxyClientFactory}.
- """
-
- def test_connectionFailed(self):
- """
- Check that L{ProxyClientFactory.clientConnectionFailed} produces
- a B{501} response to the parent request.
- """
- serverTransport = StringTransportWithDisconnection()
- channel = DummyChannel(serverTransport)
- parent = DummyParent(channel)
- serverTransport.protocol = channel
- factory = ProxyClientFactory('GET', '/foo', 'HTTP/1.0',
- {"accept": "text/html"}, '', parent)
-
- factory.clientConnectionFailed(None, None)
- self.assertEquals(serverTransport.value(),
- "HTTP/1.0 501 Gateway error\r\n"
- "Content-Type: text/html\r\n\r\n"
- "<H1>Could not connect</H1>")
- self.assertIsInstance(channel.lostReason, ConnectionDone)
-
-
- def test_buildProtocol(self):
- """
- L{ProxyClientFactory.buildProtocol} should produce a L{ProxyClient}
- with the same values of attributes (with updates on the headers).
- """
- factory = ProxyClientFactory('GET', '/foo', 'HTTP/1.0',
- {"accept": "text/html"}, 'Some data',
- None)
- proto = factory.buildProtocol(None)
- self.assertIsInstance(proto, ProxyClient)
- self.assertEquals(proto.command, 'GET')
- self.assertEquals(proto.rest, '/foo')
- self.assertEquals(proto.data, 'Some data')
- self.assertEquals(proto.headers,
- {"accept": "text/html", "connection": "close"})
-
-
-
-class ProxyRequestTestCase(TestCase):
- """
- Tests for L{ProxyRequest}.
- """
-
- def _testProcess(self, uri, expectedURI, method="GET", data=""):
- """
- Build a request pointing at C{uri}, and check that a proxied request
- is created, pointing a C{expectedURI}.
- """
- transport = StringTransportWithDisconnection()
- channel = DummyChannel(transport)
- reactor = FakeReactor()
- request = ProxyRequest(channel, False, reactor)
- request.gotLength(len(data))
- request.handleContentChunk(data)
- request.requestReceived(method, 'http://example.com%s' % (uri,),
- 'HTTP/1.0')
-
- self.assertEquals(len(reactor.connect), 1)
- self.assertEquals(reactor.connect[0][0], "example.com")
- self.assertEquals(reactor.connect[0][1], 80)
-
- factory = reactor.connect[0][2]
- self.assertIsInstance(factory, ProxyClientFactory)
- self.assertEquals(factory.command, method)
- self.assertEquals(factory.version, 'HTTP/1.0')
- self.assertEquals(factory.headers, {'host': 'example.com'})
- self.assertEquals(factory.data, data)
- self.assertEquals(factory.rest, expectedURI)
- self.assertEquals(factory.father, request)
-
-
- def test_process(self):
- """
- L{ProxyRequest.process} should create a connection to the given server,
- with a L{ProxyClientFactory} as connection factory, with the correct
- parameters:
- - forward comment, version and data values
- - update headers with the B{host} value
- - remove the host from the URL
- - pass the request as parent request
- """
- return self._testProcess("/foo/bar", "/foo/bar")
-
-
- def test_processWithoutTrailingSlash(self):
- """
- If the incoming request doesn't contain a slash,
- L{ProxyRequest.process} should add one when instantiating
- L{ProxyClientFactory}.
- """
- return self._testProcess("", "/")
-
-
- def test_processWithData(self):
- """
- L{ProxyRequest.process} should be able to retrieve request body and
- to forward it.
- """
- return self._testProcess(
- "/foo/bar", "/foo/bar", "POST", "Some content")
-
-
- def test_processWithPort(self):
- """
- Check that L{ProxyRequest.process} correctly parse port in the incoming
- URL, and create a outgoing connection with this port.
- """
- transport = StringTransportWithDisconnection()
- channel = DummyChannel(transport)
- reactor = FakeReactor()
- request = ProxyRequest(channel, False, reactor)
- request.gotLength(0)
- request.requestReceived('GET', 'http://example.com:1234/foo/bar',
- 'HTTP/1.0')
-
- # That should create one connection, with the port parsed from the URL
- self.assertEquals(len(reactor.connect), 1)
- self.assertEquals(reactor.connect[0][0], "example.com")
- self.assertEquals(reactor.connect[0][1], 1234)
-
-
-
-class DummyFactory(object):
- """
- A simple holder for C{host} and C{port} information.
- """
-
- def __init__(self, host, port):
- self.host = host
- self.port = port
-
-
-
-class ReverseProxyRequestTestCase(TestCase):
- """
- Tests for L{ReverseProxyRequest}.
- """
-
- def test_process(self):
- """
- L{ReverseProxyRequest.process} should create a connection to its
- factory host/port, using a L{ProxyClientFactory} instantiated with the
- correct parameters, and particulary set the B{host} header to the
- factory host.
- """
- transport = StringTransportWithDisconnection()
- channel = DummyChannel(transport)
- reactor = FakeReactor()
- request = ReverseProxyRequest(channel, False, reactor)
- request.factory = DummyFactory("example.com", 1234)
- request.gotLength(0)
- request.requestReceived('GET', '/foo/bar', 'HTTP/1.0')
-
- # Check that one connection has been created, to the good host/port
- self.assertEquals(len(reactor.connect), 1)
- self.assertEquals(reactor.connect[0][0], "example.com")
- self.assertEquals(reactor.connect[0][1], 1234)
-
- # Check the factory passed to the connect, and its headers
- factory = reactor.connect[0][2]
- self.assertIsInstance(factory, ProxyClientFactory)
- self.assertEquals(factory.headers, {'host': 'example.com'})
diff --git a/tools/buildbot/pylibs/twisted/web/test/test_soap.py b/tools/buildbot/pylibs/twisted/web/test/test_soap.py
deleted file mode 100644
index 54e990e..0000000
--- a/tools/buildbot/pylibs/twisted/web/test/test_soap.py
+++ /dev/null
@@ -1,114 +0,0 @@
-#
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-#
-
-"""Test SOAP support."""
-
-try:
- import SOAPpy
-except ImportError:
- SOAPpy = None
- class SOAPPublisher: pass
-else:
- from twisted.web import soap
- SOAPPublisher = soap.SOAPPublisher
-
-from twisted.trial import unittest
-from twisted.web import server, error
-from twisted.internet import reactor, defer
-
-
-class Test(SOAPPublisher):
-
- def soap_add(self, a, b):
- return a + b
-
- def soap_kwargs(self, a=1, b=2):
- return a + b
- soap_kwargs.useKeywords=True
-
- def soap_triple(self, string, num):
- return [string, num, None]
-
- def soap_struct(self):
- return SOAPpy.structType({"a": "c"})
-
- def soap_defer(self, x):
- return defer.succeed(x)
-
- def soap_deferFail(self):
- return defer.fail(ValueError())
-
- def soap_fail(self):
- raise RuntimeError
-
- def soap_deferFault(self):
- return defer.fail(ValueError())
-
- def soap_complex(self):
- return {"a": ["b", "c", 12, []], "D": "foo"}
-
- def soap_dict(self, map, key):
- return map[key]
-
-
-class SOAPTestCase(unittest.TestCase):
-
- def setUp(self):
- self.publisher = Test()
- self.p = reactor.listenTCP(0, server.Site(self.publisher),
- interface="127.0.0.1")
- self.port = self.p.getHost().port
-
- def tearDown(self):
- return self.p.stopListening()
-
- def proxy(self):
- return soap.Proxy("http://127.0.0.1:%d/" % self.port)
-
- def testResults(self):
- inputOutput = [
- ("add", (2, 3), 5),
- ("defer", ("a",), "a"),
- ("dict", ({"a": 1}, "a"), 1),
- ("triple", ("a", 1), ["a", 1, None])]
-
- dl = []
- for meth, args, outp in inputOutput:
- d = self.proxy().callRemote(meth, *args)
- d.addCallback(self.assertEquals, outp)
- dl.append(d)
-
- # SOAPpy kinda blows.
- d = self.proxy().callRemote('complex')
- d.addCallback(lambda result: result._asdict())
- d.addCallback(self.assertEquals, {"a": ["b", "c", 12, []], "D": "foo"})
- dl.append(d)
-
- # We now return to our regularly scheduled program, already in progress.
- return defer.DeferredList(dl, fireOnOneErrback=True)
-
- def testMethodNotFound(self):
- """
- Check that a non existing method return error 500.
- """
- d = self.proxy().callRemote('doesntexist')
- self.assertFailure(d, error.Error)
- def cb(err):
- self.assertEquals(int(err.status), 500)
- d.addCallback(cb)
- return d
-
- def testLookupFunction(self):
- """
- Test lookupFunction method on publisher, to see available remote
- methods.
- """
- self.assertTrue(self.publisher.lookupFunction("add"))
- self.assertTrue(self.publisher.lookupFunction("fail"))
- self.assertFalse(self.publisher.lookupFunction("foobar"))
-
-if not SOAPpy:
- SOAPTestCase.skip = "SOAPpy not installed"
-
diff --git a/tools/buildbot/pylibs/twisted/web/test/test_static.py b/tools/buildbot/pylibs/twisted/web/test/test_static.py
deleted file mode 100644
index eb0463a..0000000
--- a/tools/buildbot/pylibs/twisted/web/test/test_static.py
+++ /dev/null
@@ -1,64 +0,0 @@
-from twisted.trial import unittest
-import os
-from twisted.web import static
-
-class FakeRequest:
- method = 'GET'
-
- _headers = None
- _setHeaders = None
- _written = ''
-
- def __init__(self):
- self._headers = {}
- self._setHeaders = {}
-
- def getHeader(self, k):
- if self._headers is None:
- return None
- return self._headers.get(k)
-
- def setHeader(self, k, v):
- self._setHeaders.setdefault(k, []).append(v)
-
- def setLastModified(self, x):
- pass
- def registerProducer(self, producer, x):
- producer.resumeProducing()
- def unregisterProducer(self):
- pass
- def finish(self):
- pass
-
- def write(self, data):
- self._written = self._written + data
-
-class Range(unittest.TestCase):
- todo = (unittest.FailTest, 'No range support yet.')
-
- def setUp(self):
- self.tmpdir = self.mktemp()
- os.mkdir(self.tmpdir)
- name = os.path.join(self.tmpdir, 'junk')
- f = file(name, 'w')
- f.write(8000 * 'x')
- f.close()
- self.file = static.File(name)
- self.request = FakeRequest()
-
- def testBodyLength(self):
- self.request._headers['range'] = 'bytes=0-1999'
- self.file.render(self.request)
- self.assertEquals(len(self.request._written), 2000)
-
- def testContentLength(self):
- """Content-Length of a request is correct."""
- self.request._headers['range'] = 'bytes=0-1999'
- self.file.render(self.request)
- self.assertEquals(self.request._setHeaders['content-length'], ['2000'])
-
- def testContentRange(self):
- """Content-Range of a request is correct."""
- self.request._headers['range'] = 'bytes=0-1999'
- self.file.render(self.request)
- self.assertEquals(self.request._setHeaders.get('content-range'), ['bytes 0-1999/8000'])
diff --git a/tools/buildbot/pylibs/twisted/web/test/test_tap.py b/tools/buildbot/pylibs/twisted/web/test/test_tap.py
deleted file mode 100644
index 553f9ca..0000000
--- a/tools/buildbot/pylibs/twisted/web/test/test_tap.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (c) 2008 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-"""
-Tests for L{twisted.web.tap}.
-"""
-
-from twisted.trial.unittest import TestCase
-
-from twisted.web.server import Site
-from twisted.web.static import Data
-from twisted.web.distrib import ResourcePublisher
-from twisted.web.tap import makePersonalServerFactory
-
-from twisted.spread.pb import PBServerFactory
-
-
-class ServiceTests(TestCase):
- """
- Tests for the service creation APIs in L{twisted.web.tap}.
- """
- def test_makePersonalServerFactory(self):
- """
- L{makePersonalServerFactory} returns a PB server factory which has
- as its root object a L{ResourcePublisher}.
- """
- # The fact that this pile of objects can actually be used somehow is
- # verified by twisted.web.test.test_distrib.
- site = Site(Data("foo bar", "text/plain"))
- serverFactory = makePersonalServerFactory(site)
- self.assertIsInstance(serverFactory, PBServerFactory)
- self.assertIsInstance(serverFactory.root, ResourcePublisher)
- self.assertIdentical(serverFactory.root.site, site)
diff --git a/tools/buildbot/pylibs/twisted/web/test/test_web.py b/tools/buildbot/pylibs/twisted/web/test/test_web.py
deleted file mode 100644
index 2bbb390..0000000
--- a/tools/buildbot/pylibs/twisted/web/test/test_web.py
+++ /dev/null
@@ -1,611 +0,0 @@
-# Copyright (c) 2001-2007 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-from twisted.trial import unittest
-from cStringIO import StringIO
-
-from twisted.web import server, resource, util
-from twisted.internet import defer, interfaces, error, task
-from twisted.web import http
-from twisted.python import log
-from twisted.internet.address import IPv4Address
-from zope.interface import implements
-
-class DummyRequest:
- uri='http://dummy/'
- method = 'GET'
-
- def getHeader(self, h):
- return None
-
- def registerProducer(self, prod,s):
- self.go = 1
- while self.go:
- prod.resumeProducing()
-
- def unregisterProducer(self):
- self.go = 0
-
- def __init__(self, postpath, session=None):
- self.sitepath = []
- self.written = []
- self.finished = 0
- self.postpath = postpath
- self.prepath = []
- self.session = None
- self.protoSession = session or server.Session(0, self)
- self.args = {}
- self.outgoingHeaders = {}
-
- def setHeader(self, name, value):
- """TODO: make this assert on write() if the header is content-length
- """
- self.outgoingHeaders[name.lower()] = value
-
- def getSession(self):
- if self.session:
- return self.session
- assert not self.written, "Session cannot be requested after data has been written."
- self.session = self.protoSession
- return self.session
- def write(self, data):
- self.written.append(data)
- def finish(self):
- self.finished = self.finished + 1
- def addArg(self, name, value):
- self.args[name] = [value]
- def setResponseCode(self, code):
- assert not self.written, "Response code cannot be set after data has been written: %s." % "@@@@".join(self.written)
- def setLastModified(self, when):
- assert not self.written, "Last-Modified cannot be set after data has been written: %s." % "@@@@".join(self.written)
- def setETag(self, tag):
- assert not self.written, "ETag cannot be set after data has been written: %s." % "@@@@".join(self.written)
-
-class ResourceTestCase(unittest.TestCase):
- def testListEntities(self):
- r = resource.Resource()
- self.failUnlessEqual([], r.listEntities())
-
-
-class SimpleResource(resource.Resource):
- def render(self, request):
- if http.CACHED in (request.setLastModified(10),
- request.setETag('MatchingTag')):
- return ''
- else:
- return "correct"
-
-class SiteTest(unittest.TestCase):
- def testSimplestSite(self):
- sres1 = SimpleResource()
- sres2 = SimpleResource()
- sres1.putChild("",sres2)
- site = server.Site(sres1)
- assert site.getResourceFor(DummyRequest([''])) is sres2, "Got the wrong resource."
-
-
-
-class SessionTest(unittest.TestCase):
-
- def setUp(self):
- """
- Set up a session using a simulated scheduler. Creates a
- C{times} attribute which specifies the return values of the
- session's C{_getTime} method.
- """
- clock = self.clock = task.Clock()
- times = self.times = []
-
- class MockSession(server.Session):
- """
- A mock L{server.Session} object which fakes out scheduling
- with the C{clock} attribute and fakes out the current time
- to be the elements of L{SessionTest}'s C{times} attribute.
- """
- def loopFactory(self, *a, **kw):
- """
- Create a L{task.LoopingCall} which uses
- L{SessionTest}'s C{clock} attribute.
- """
- call = task.LoopingCall(*a, **kw)
- call.clock = clock
- return call
-
- def _getTime(self):
- return times.pop(0)
-
- self.site = server.Site(SimpleResource())
- self.site.sessionFactory = MockSession
-
-
- def test_basicExpiration(self):
- """
- Test session expiration: setup a session, and simulate an expiration
- time.
- """
- self.times.extend([0, server.Session.sessionTimeout + 1])
- session = self.site.makeSession()
- hasExpired = [False]
- def cbExpire():
- hasExpired[0] = True
- session.notifyOnExpire(cbExpire)
- self.clock.advance(server.Site.sessionCheckTime - 1)
- # Looping call should not have been executed
- self.failIf(hasExpired[0])
-
- self.clock.advance(1)
-
- self.failUnless(hasExpired[0])
-
-
- def test_delayedCallCleanup(self):
- """
- Checking to make sure Sessions do not leave extra DelayedCalls.
- """
- self.times.extend([0, 100])
-
- session = self.site.makeSession()
- loop = session.checkExpiredLoop
- session.touch()
- self.failUnless(loop.running)
-
- session.expire()
-
- self.failIf(self.clock.calls)
- self.failIf(loop.running)
-
-
-
-# Conditional requests:
-# If-None-Match, If-Modified-Since
-
-# make conditional request:
-# normal response if condition succeeds
-# if condition fails:
-# response code
-# no body
-
-def httpBody(whole):
- return whole.split('\r\n\r\n', 1)[1]
-
-def httpHeader(whole, key):
- key = key.lower()
- headers = whole.split('\r\n\r\n', 1)[0]
- for header in headers.split('\r\n'):
- if header.lower().startswith(key):
- return header.split(':', 1)[1].strip()
- return None
-
-def httpCode(whole):
- l1 = whole.split('\r\n', 1)[0]
- return int(l1.split()[1])
-
-class ConditionalTest(unittest.TestCase):
- """web.server's handling of conditional requests for cache validation."""
-
- # XXX: test web.distrib.
-
- def setUp(self):
- self.resrc = SimpleResource()
- self.resrc.putChild('', self.resrc)
- self.site = server.Site(self.resrc)
- self.site = server.Site(self.resrc)
- self.site.logFile = log.logfile
-
- # HELLLLLLLLLLP! This harness is Very Ugly.
- self.channel = self.site.buildProtocol(None)
- self.transport = http.StringTransport()
- self.transport.close = lambda *a, **kw: None
- self.transport.disconnecting = lambda *a, **kw: 0
- self.transport.getPeer = lambda *a, **kw: "peer"
- self.transport.getHost = lambda *a, **kw: "host"
- self.channel.makeConnection(self.transport)
- for l in ["GET / HTTP/1.1",
- "Accept: text/html"]:
- self.channel.lineReceived(l)
-
- def tearDown(self):
- self.channel.connectionLost(None)
-
- def test_modified(self):
- """If-Modified-Since cache validator (positive)"""
- self.channel.lineReceived("If-Modified-Since: %s"
- % http.datetimeToString(1))
- self.channel.lineReceived('')
- result = self.transport.getvalue()
- self.failUnlessEqual(httpCode(result), http.OK)
- self.failUnlessEqual(httpBody(result), "correct")
-
- def test_unmodified(self):
- """If-Modified-Since cache validator (negative)"""
- self.channel.lineReceived("If-Modified-Since: %s"
- % http.datetimeToString(100))
- self.channel.lineReceived('')
- result = self.transport.getvalue()
- self.failUnlessEqual(httpCode(result), http.NOT_MODIFIED)
- self.failUnlessEqual(httpBody(result), "")
-
- def test_etagMatchedNot(self):
- """If-None-Match ETag cache validator (positive)"""
- self.channel.lineReceived("If-None-Match: unmatchedTag")
- self.channel.lineReceived('')
- result = self.transport.getvalue()
- self.failUnlessEqual(httpCode(result), http.OK)
- self.failUnlessEqual(httpBody(result), "correct")
-
- def test_etagMatched(self):
- """If-None-Match ETag cache validator (negative)"""
- self.channel.lineReceived("If-None-Match: MatchingTag")
- self.channel.lineReceived('')
- result = self.transport.getvalue()
- self.failUnlessEqual(httpHeader(result, "ETag"), "MatchingTag")
- self.failUnlessEqual(httpCode(result), http.NOT_MODIFIED)
- self.failUnlessEqual(httpBody(result), "")
-
-from twisted.web import google
-class GoogleTestCase(unittest.TestCase):
- def testCheckGoogle(self):
- raise unittest.SkipTest("no violation of google ToS")
- d = google.checkGoogle('site:www.twistedmatrix.com twisted')
- d.addCallback(self.assertEquals, 'http://twistedmatrix.com/')
- return d
-
-from twisted.web import static
-from twisted.web import script
-
-class StaticFileTest(unittest.TestCase):
-
- def testStaticPaths(self):
- import os
- dp = os.path.join(self.mktemp(),"hello")
- ddp = os.path.join(dp, "goodbye")
- tp = os.path.abspath(os.path.join(dp,"world.txt"))
- tpy = os.path.join(dp,"wyrld.rpy")
- os.makedirs(dp)
- f = open(tp,"wb")
- f.write("hello world")
- f = open(tpy, "wb")
- f.write("""
-from twisted.web.static import Data
-resource = Data('dynamic world','text/plain')
-""")
- f = static.File(dp)
- f.processors = {
- '.rpy': script.ResourceScript,
- }
-
- f.indexNames = f.indexNames + ['world.txt']
- self.assertEquals(f.getChild('', DummyRequest([''])).path,
- tp)
- self.assertEquals(f.getChild('wyrld.rpy', DummyRequest(['wyrld.rpy'])
- ).__class__,
- static.Data)
- f = static.File(dp)
- wtextr = DummyRequest(['world.txt'])
- wtext = f.getChild('world.txt', wtextr)
- self.assertEquals(wtext.path, tp)
- wtext.render(wtextr)
- self.assertEquals(wtextr.outgoingHeaders.get('content-length'),
- str(len('hello world')))
- self.assertNotEquals(f.getChild('', DummyRequest([''])).__class__,
- static.File)
-
- def testIgnoreExt(self):
- f = static.File(".")
- f.ignoreExt(".foo")
- self.assertEquals(f.ignoredExts, [".foo"])
- f = static.File(".")
- self.assertEquals(f.ignoredExts, [])
- f = static.File(".", ignoredExts=(".bar", ".baz"))
- self.assertEquals(f.ignoredExts, [".bar", ".baz"])
-
- def testIgnoredExts(self):
- import os
- dp = os.path.join(self.mktemp(), 'allYourBase')
- fp = os.path.join(dp, 'AreBelong.ToUs')
- os.makedirs(dp)
- open(fp, 'wb').write("Take off every 'Zig'!!")
- f = static.File(dp)
- f.ignoreExt('.ToUs')
- dreq = DummyRequest([''])
- child_without_ext = f.getChild('AreBelong', dreq)
- self.assertNotEquals(child_without_ext, f.childNotFound)
-
-class DummyChannel:
- class TCP:
- port = 80
- def getPeer(self):
- return IPv4Address("TCP", 'client.example.com', 12344)
- def getHost(self):
- return IPv4Address("TCP", 'example.com', self.port)
- class SSL(TCP):
- implements(interfaces.ISSLTransport)
- transport = TCP()
- site = server.Site(resource.Resource())
-
-class TestRequest(unittest.TestCase):
-
- def testChildLink(self):
- request = server.Request(DummyChannel(), 1)
- request.gotLength(0)
- request.requestReceived('GET', '/foo/bar', 'HTTP/1.0')
- self.assertEqual(request.childLink('baz'), 'bar/baz')
- request = server.Request(DummyChannel(), 1)
- request.gotLength(0)
- request.requestReceived('GET', '/foo/bar/', 'HTTP/1.0')
- self.assertEqual(request.childLink('baz'), 'baz')
-
- def testPrePathURLSimple(self):
- request = server.Request(DummyChannel(), 1)
- request.gotLength(0)
- request.requestReceived('GET', '/foo/bar', 'HTTP/1.0')
- request.setHost('example.com', 80)
- self.assertEqual(request.prePathURL(), 'http://example.com/foo/bar')
-
- def testPrePathURLNonDefault(self):
- d = DummyChannel()
- d.transport = DummyChannel.TCP()
- d.transport.port = 81
- request = server.Request(d, 1)
- request.setHost('example.com', 81)
- request.gotLength(0)
- request.requestReceived('GET', '/foo/bar', 'HTTP/1.0')
- self.assertEqual(request.prePathURL(), 'http://example.com:81/foo/bar')
-
- def testPrePathURLSSLPort(self):
- d = DummyChannel()
- d.transport = DummyChannel.TCP()
- d.transport.port = 443
- request = server.Request(d, 1)
- request.setHost('example.com', 443)
- request.gotLength(0)
- request.requestReceived('GET', '/foo/bar', 'HTTP/1.0')
- self.assertEqual(request.prePathURL(), 'http://example.com:443/foo/bar')
-
- def testPrePathURLSSLPortAndSSL(self):
- d = DummyChannel()
- d.transport = DummyChannel.SSL()
- d.transport.port = 443
- request = server.Request(d, 1)
- request.setHost('example.com', 443)
- request.gotLength(0)
- request.requestReceived('GET', '/foo/bar', 'HTTP/1.0')
- self.assertEqual(request.prePathURL(), 'https://example.com/foo/bar')
-
- def testPrePathURLHTTPPortAndSSL(self):
- d = DummyChannel()
- d.transport = DummyChannel.SSL()
- d.transport.port = 80
- request = server.Request(d, 1)
- request.setHost('example.com', 80)
- request.gotLength(0)
- request.requestReceived('GET', '/foo/bar', 'HTTP/1.0')
- self.assertEqual(request.prePathURL(), 'https://example.com:80/foo/bar')
-
- def testPrePathURLSSLNonDefault(self):
- d = DummyChannel()
- d.transport = DummyChannel.SSL()
- d.transport.port = 81
- request = server.Request(d, 1)
- request.setHost('example.com', 81)
- request.gotLength(0)
- request.requestReceived('GET', '/foo/bar', 'HTTP/1.0')
- self.assertEqual(request.prePathURL(), 'https://example.com:81/foo/bar')
-
- def testPrePathURLSetSSLHost(self):
- d = DummyChannel()
- d.transport = DummyChannel.TCP()
- d.transport.port = 81
- request = server.Request(d, 1)
- request.setHost('foo.com', 81, 1)
- request.gotLength(0)
- request.requestReceived('GET', '/foo/bar', 'HTTP/1.0')
- self.assertEqual(request.prePathURL(), 'https://foo.com:81/foo/bar')
-
-
- def test_prePathURLQuoting(self):
- """
- L{Request.prePathURL} quotes special characters in the URL segments to
- preserve the original meaning.
- """
- d = DummyChannel()
- request = server.Request(d, 1)
- request.setHost('example.com', 80)
- request.gotLength(0)
- request.requestReceived('GET', '/foo%2Fbar', 'HTTP/1.0')
- self.assertEqual(request.prePathURL(), 'http://example.com/foo%2Fbar')
-
-
- def testNotifyFinishConnectionLost(self):
- d = DummyChannel()
- d.transport = DummyChannel.TCP()
- request = server.Request(d, 1)
- finished = request.notifyFinish()
- request.connectionLost(error.ConnectionDone("Connection done"))
- return self.assertFailure(finished, error.ConnectionDone)
-
-
-class RootResource(resource.Resource):
- isLeaf=0
- def getChildWithDefault(self, name, request):
- request.rememberRootURL()
- return resource.Resource.getChildWithDefault(self, name, request)
- def render(self, request):
- return ''
-
-class RememberURLTest(unittest.TestCase):
- def createServer(self, r):
- chan = DummyChannel()
- chan.transport = DummyChannel.TCP()
- chan.site = server.Site(r)
- return chan
-
- def testSimple(self):
- r = resource.Resource()
- r.isLeaf=0
- rr = RootResource()
- r.putChild('foo', rr)
- rr.putChild('', rr)
- rr.putChild('bar', resource.Resource())
- chan = self.createServer(r)
- for url in ['/foo/', '/foo/bar', '/foo/bar/baz', '/foo/bar/']:
- request = server.Request(chan, 1)
- request.setHost('example.com', 81)
- request.gotLength(0)
- request.requestReceived('GET', url, 'HTTP/1.0')
- self.assertEqual(request.getRootURL(), "http://example.com/foo")
-
- def testRoot(self):
- rr = RootResource()
- rr.putChild('', rr)
- rr.putChild('bar', resource.Resource())
- chan = self.createServer(rr)
- for url in ['/', '/bar', '/bar/baz', '/bar/']:
- request = server.Request(chan, 1)
- request.setHost('example.com', 81)
- request.gotLength(0)
- request.requestReceived('GET', url, 'HTTP/1.0')
- self.assertEqual(request.getRootURL(), "http://example.com/")
-
-
-class NewRenderResource(resource.Resource):
- def render_GET(self, request):
- return "hi hi"
-
- def render_HEH(self, request):
- return "ho ho"
-
-
-class NewRenderTestCase(unittest.TestCase):
- def _getReq(self):
- d = DummyChannel()
- d.site.resource.putChild('newrender', NewRenderResource())
- d.transport = DummyChannel.TCP()
- d.transport.port = 81
- request = server.Request(d, 1)
- request.setHost('example.com', 81)
- request.gotLength(0)
- return request
-
- def testGoodMethods(self):
- req = self._getReq()
- req.requestReceived('GET', '/newrender', 'HTTP/1.0')
- self.assertEquals(req.transport.getvalue().splitlines()[-1], 'hi hi')
-
- req = self._getReq()
- req.requestReceived('HEH', '/newrender', 'HTTP/1.0')
- self.assertEquals(req.transport.getvalue().splitlines()[-1], 'ho ho')
-
- def testBadMethods(self):
- req = self._getReq()
- req.requestReceived('CONNECT', '/newrender', 'HTTP/1.0')
- self.assertEquals(req.code, 501)
-
- req = self._getReq()
- req.requestReceived('hlalauguG', '/newrender', 'HTTP/1.0')
- self.assertEquals(req.code, 501)
-
- def testImplicitHead(self):
- req = self._getReq()
- req.requestReceived('HEAD', '/newrender', 'HTTP/1.0')
- self.assertEquals(req.code, 200)
- self.assertEquals(-1, req.transport.getvalue().find('hi hi'))
-
-
-class SDResource(resource.Resource):
- def __init__(self,default): self.default=default
- def getChildWithDefault(self,name,request):
- d=defer.succeed(self.default)
- return util.DeferredResource(d).getChildWithDefault(name, request)
-
-class SDTest(unittest.TestCase):
-
- def testDeferredResource(self):
- r = resource.Resource()
- r.isLeaf = 1
- s = SDResource(r)
- d = DummyRequest(['foo', 'bar', 'baz'])
- resource.getChildForRequest(s, d)
- self.assertEqual(d.postpath, ['bar', 'baz'])
-
-class DummyRequestForLogTest(DummyRequest):
- uri='/dummy' # parent class uri has "http://", which doesn't really happen
- code = 123
- client = '1.2.3.4'
- clientproto = 'HTTP/1.0'
- sentLength = None
-
- def __init__(self, *a, **kw):
- DummyRequest.__init__(self, *a, **kw)
- self.headers = {}
-
- def getHeader(self, h):
- return self.headers.get(h.lower(), None)
-
- def getClientIP(self):
- return self.client
-
-class TestLogEscaping(unittest.TestCase):
- def setUp(self):
- self.site = http.HTTPFactory()
- self.site.logFile = StringIO()
- self.request = DummyRequestForLogTest(self.site, False)
-
- def testSimple(self):
- http._logDateTime = "[%02d/%3s/%4d:%02d:%02d:%02d +0000]" % (
- 25, 'Oct', 2004, 12, 31, 59)
- self.site.log(self.request)
- self.site.logFile.seek(0)
- self.assertEqual(
- self.site.logFile.read(),
- '1.2.3.4 - - [25/Oct/2004:12:31:59 +0000] "GET /dummy HTTP/1.0" 123 - "-" "-"\n')
-
- def testMethodQuote(self):
- http._logDateTime = "[%02d/%3s/%4d:%02d:%02d:%02d +0000]" % (
- 25, 'Oct', 2004, 12, 31, 59)
- self.request.method = 'G"T'
- self.site.log(self.request)
- self.site.logFile.seek(0)
- self.assertEqual(
- self.site.logFile.read(),
- '1.2.3.4 - - [25/Oct/2004:12:31:59 +0000] "G\\"T /dummy HTTP/1.0" 123 - "-" "-"\n')
-
- def testRequestQuote(self):
- http._logDateTime = "[%02d/%3s/%4d:%02d:%02d:%02d +0000]" % (
- 25, 'Oct', 2004, 12, 31, 59)
- self.request.uri='/dummy"withquote'
- self.site.log(self.request)
- self.site.logFile.seek(0)
- self.assertEqual(
- self.site.logFile.read(),
- '1.2.3.4 - - [25/Oct/2004:12:31:59 +0000] "GET /dummy\\"withquote HTTP/1.0" 123 - "-" "-"\n')
-
- def testProtoQuote(self):
- http._logDateTime = "[%02d/%3s/%4d:%02d:%02d:%02d +0000]" % (
- 25, 'Oct', 2004, 12, 31, 59)
- self.request.clientproto='HT"P/1.0'
- self.site.log(self.request)
- self.site.logFile.seek(0)
- self.assertEqual(
- self.site.logFile.read(),
- '1.2.3.4 - - [25/Oct/2004:12:31:59 +0000] "GET /dummy HT\\"P/1.0" 123 - "-" "-"\n')
-
- def testRefererQuote(self):
- http._logDateTime = "[%02d/%3s/%4d:%02d:%02d:%02d +0000]" % (
- 25, 'Oct', 2004, 12, 31, 59)
- self.request.headers['referer'] = 'http://malicious" ".website.invalid'
- self.site.log(self.request)
- self.site.logFile.seek(0)
- self.assertEqual(
- self.site.logFile.read(),
- '1.2.3.4 - - [25/Oct/2004:12:31:59 +0000] "GET /dummy HTTP/1.0" 123 - "http://malicious\\" \\".website.invalid" "-"\n')
-
- def testUserAgentQuote(self):
- http._logDateTime = "[%02d/%3s/%4d:%02d:%02d:%02d +0000]" % (
- 25, 'Oct', 2004, 12, 31, 59)
- self.request.headers['user-agent'] = 'Malicious Web" Evil'
- self.site.log(self.request)
- self.site.logFile.seek(0)
- self.assertEqual(
- self.site.logFile.read(),
- '1.2.3.4 - - [25/Oct/2004:12:31:59 +0000] "GET /dummy HTTP/1.0" 123 - "-" "Malicious Web\\" Evil"\n')
diff --git a/tools/buildbot/pylibs/twisted/web/test/test_webclient.py b/tools/buildbot/pylibs/twisted/web/test/test_webclient.py
deleted file mode 100644
index a1bab78..0000000
--- a/tools/buildbot/pylibs/twisted/web/test/test_webclient.py
+++ /dev/null
@@ -1,475 +0,0 @@
-# Copyright (c) 2001-2008 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-"""
-Tests for L{twisted.web.client}.
-"""
-
-import os
-
-from urlparse import urlparse
-
-from twisted.trial import unittest
-from twisted.web import server, static, client, error, util, resource
-from twisted.internet import reactor, defer, interfaces
-from twisted.python.filepath import FilePath
-
-try:
- from twisted.internet import ssl
-except:
- ssl = None
-
-serverCallID = None
-
-class LongTimeTakingResource(resource.Resource):
- def render(self, request):
- global serverCallID
- serverCallID = reactor.callLater(1, self.writeIt, request)
- return server.NOT_DONE_YET
-
- def writeIt(self, request):
- request.write("hello!!!")
- request.finish()
-
-class CookieMirrorResource(resource.Resource):
- def render(self, request):
- l = []
- for k,v in request.received_cookies.items():
- l.append((k, v))
- l.sort()
- return repr(l)
-
-class RawCookieMirrorResource(resource.Resource):
- def render(self, request):
- return repr(request.getHeader('cookie'))
-
-class ErrorResource(resource.Resource):
-
- def render(self, request):
- request.setResponseCode(401)
- if request.args.get("showlength"):
- request.setHeader("content-length", "0")
- return ""
-
-class NoLengthResource(resource.Resource):
-
- def render(self, request):
- return "nolength"
-
-class HostHeaderResource(resource.Resource):
-
- def render(self, request):
- return request.received_headers["host"]
-
-class PayloadResource(resource.Resource):
-
- def render(self, request):
- data = request.content.read()
- if len(data) != 100 or int(request.received_headers["content-length"]) != 100:
- return "ERROR"
- return data
-
-class BrokenDownloadResource(resource.Resource):
-
- def render(self, request):
- # only sends 3 bytes even though it claims to send 5
- request.setHeader("content-length", "5")
- request.write('abc')
- return ''
-
-
-
-class ParseUrlTestCase(unittest.TestCase):
- """
- Test URL parsing facility and defaults values.
- """
-
- def testParse(self):
- scheme, host, port, path = client._parse("http://127.0.0.1/")
- self.assertEquals(path, "/")
- self.assertEquals(port, 80)
- scheme, host, port, path = client._parse("https://127.0.0.1/")
- self.assertEquals(path, "/")
- self.assertEquals(port, 443)
- scheme, host, port, path = client._parse("http://spam:12345/")
- self.assertEquals(port, 12345)
- scheme, host, port, path = client._parse("http://foo ")
- self.assertEquals(host, "foo")
- self.assertEquals(path, "/")
- scheme, host, port, path = client._parse("http://egg:7890")
- self.assertEquals(port, 7890)
- self.assertEquals(host, "egg")
- self.assertEquals(path, "/")
-
-
- def test_externalUnicodeInterference(self):
- """
- L{client._parse} should return C{str} for the scheme, host, and path
- elements of its return tuple, even when passed an URL which has
- previously been passed to L{urlparse} as a C{unicode} string.
- """
- badInput = u'http://example.com/path'
- goodInput = badInput.encode('ascii')
- urlparse(badInput)
- scheme, host, port, path = client._parse(goodInput)
- self.assertTrue(isinstance(scheme, str))
- self.assertTrue(isinstance(host, str))
- self.assertTrue(isinstance(path, str))
-
-
-
-class WebClientTestCase(unittest.TestCase):
- def _listen(self, site):
- return reactor.listenTCP(0, site, interface="127.0.0.1")
-
- def setUp(self):
- name = self.mktemp()
- os.mkdir(name)
- FilePath(name).child("file").setContent("0123456789")
- r = static.File(name)
- r.putChild("redirect", util.Redirect("/file"))
- r.putChild("wait", LongTimeTakingResource())
- r.putChild("error", ErrorResource())
- r.putChild("nolength", NoLengthResource())
- r.putChild("host", HostHeaderResource())
- r.putChild("payload", PayloadResource())
- r.putChild("broken", BrokenDownloadResource())
- site = server.Site(r, timeout=None)
- self.port = self._listen(site)
- self.portno = self.port.getHost().port
-
- def tearDown(self):
- if serverCallID and serverCallID.active():
- serverCallID.cancel()
- return self.port.stopListening()
-
- def getURL(self, path):
- return "http://127.0.0.1:%d/%s" % (self.portno, path)
-
- def testPayload(self):
- s = "0123456789" * 10
- return client.getPage(self.getURL("payload"), postdata=s
- ).addCallback(self.assertEquals, s
- )
-
- def testBrokenDownload(self):
- # test what happens when download gets disconnected in the middle
- d = client.getPage(self.getURL("broken"))
- d = self.assertFailure(d, client.PartialDownloadError)
- d.addCallback(lambda exc: self.assertEquals(exc.response, "abc"))
- return d
-
- def testHostHeader(self):
- # if we pass Host header explicitly, it should be used, otherwise
- # it should extract from url
- return defer.gatherResults([
- client.getPage(self.getURL("host")).addCallback(self.assertEquals, "127.0.0.1"),
- client.getPage(self.getURL("host"), headers={"Host": "www.example.com"}).addCallback(self.assertEquals, "www.example.com")])
-
-
- def test_getPage(self):
- """
- L{client.getPage} returns a L{Deferred} which is called back with
- the body of the response if the default method B{GET} is used.
- """
- d = client.getPage(self.getURL("file"))
- d.addCallback(self.assertEquals, "0123456789")
- return d
-
-
- def test_getPageHead(self):
- """
- L{client.getPage} returns a L{Deferred} which is called back with
- the empty string if the method is C{HEAD} and there is a successful
- response code.
- """
- def getPage(method):
- return client.getPage(self.getURL("file"), method=method)
- return defer.gatherResults([
- getPage("head").addCallback(self.assertEqual, ""),
- getPage("HEAD").addCallback(self.assertEqual, "")])
-
-
- def testTimeoutNotTriggering(self):
- # Test that when the timeout doesn't trigger, things work as expected.
- d = client.getPage(self.getURL("wait"), timeout=100)
- d.addCallback(self.assertEquals, "hello!!!")
- return d
-
- def testTimeoutTriggering(self):
- # Test that when the timeout does trigger, we get a defer.TimeoutError.
- return self.assertFailure(
- client.getPage(self.getURL("wait"), timeout=0.5),
- defer.TimeoutError)
-
- def testDownloadPage(self):
- downloads = []
- downloadData = [("file", self.mktemp(), "0123456789"),
- ("nolength", self.mktemp(), "nolength")]
-
- for (url, name, data) in downloadData:
- d = client.downloadPage(self.getURL(url), name)
- d.addCallback(self._cbDownloadPageTest, data, name)
- downloads.append(d)
- return defer.gatherResults(downloads)
-
- def _cbDownloadPageTest(self, ignored, data, name):
- bytes = file(name, "rb").read()
- self.assertEquals(bytes, data)
-
- def testDownloadPageError1(self):
- class errorfile:
- def write(self, data):
- raise IOError, "badness happened during write"
- def close(self):
- pass
- ef = errorfile()
- return self.assertFailure(
- client.downloadPage(self.getURL("file"), ef),
- IOError)
-
- def testDownloadPageError2(self):
- class errorfile:
- def write(self, data):
- pass
- def close(self):
- raise IOError, "badness happened during close"
- ef = errorfile()
- return self.assertFailure(
- client.downloadPage(self.getURL("file"), ef),
- IOError)
-
- def testDownloadPageError3(self):
- # make sure failures in open() are caught too. This is tricky.
- # Might only work on posix.
- tmpfile = open("unwritable", "wb")
- tmpfile.close()
- os.chmod("unwritable", 0) # make it unwritable (to us)
- d = self.assertFailure(
- client.downloadPage(self.getURL("file"), "unwritable"),
- IOError)
- d.addBoth(self._cleanupDownloadPageError3)
- return d
-
- def _cleanupDownloadPageError3(self, ignored):
- os.chmod("unwritable", 0700)
- os.unlink("unwritable")
- return ignored
-
- def _downloadTest(self, method):
- dl = []
- for (url, code) in [("nosuchfile", "404"), ("error", "401"),
- ("error?showlength=1", "401")]:
- d = method(url)
- d = self.assertFailure(d, error.Error)
- d.addCallback(lambda exc, code=code: self.assertEquals(exc.args[0], code))
- dl.append(d)
- return defer.DeferredList(dl, fireOnOneErrback=True)
-
- def testServerError(self):
- return self._downloadTest(lambda url: client.getPage(self.getURL(url)))
-
- def testDownloadServerError(self):
- return self._downloadTest(lambda url: client.downloadPage(self.getURL(url), url.split('?')[0]))
-
- def testFactoryInfo(self):
- url = self.getURL('file')
- scheme, host, port, path = client._parse(url)
- factory = client.HTTPClientFactory(url)
- reactor.connectTCP(host, port, factory)
- return factory.deferred.addCallback(self._cbFactoryInfo, factory)
-
- def _cbFactoryInfo(self, ignoredResult, factory):
- self.assertEquals(factory.status, '200')
- self.assert_(factory.version.startswith('HTTP/'))
- self.assertEquals(factory.message, 'OK')
- self.assertEquals(factory.response_headers['content-length'][0], '10')
-
-
- def testRedirect(self):
- return client.getPage(self.getURL("redirect")).addCallback(self._cbRedirect)
-
- def _cbRedirect(self, pageData):
- self.assertEquals(pageData, "0123456789")
- d = self.assertFailure(
- client.getPage(self.getURL("redirect"), followRedirect=0),
- error.PageRedirect)
- d.addCallback(self._cbCheckLocation)
- return d
-
- def _cbCheckLocation(self, exc):
- self.assertEquals(exc.location, "/file")
-
- def testPartial(self):
- name = self.mktemp()
- f = open(name, "wb")
- f.write("abcd")
- f.close()
-
- downloads = []
- partialDownload = [(True, "abcd456789"),
- (True, "abcd456789"),
- (False, "0123456789")]
-
- d = defer.succeed(None)
- for (partial, expectedData) in partialDownload:
- d.addCallback(self._cbRunPartial, name, partial)
- d.addCallback(self._cbPartialTest, expectedData, name)
-
- return d
-
- testPartial.skip = "Cannot test until webserver can serve partial data properly"
-
- def _cbRunPartial(self, ignored, name, partial):
- return client.downloadPage(self.getURL("file"), name, supportPartial=partial)
-
- def _cbPartialTest(self, ignored, expectedData, filename):
- bytes = file(filename, "rb").read()
- self.assertEquals(bytes, expectedData)
-
-class WebClientSSLTestCase(WebClientTestCase):
- def _listen(self, site):
- from twisted import test
- return reactor.listenSSL(0, site,
- contextFactory=ssl.DefaultOpenSSLContextFactory(
- FilePath(test.__file__).sibling('server.pem').path,
- FilePath(test.__file__).sibling('server.pem').path,
- ),
- interface="127.0.0.1")
-
- def getURL(self, path):
- return "https://127.0.0.1:%d/%s" % (self.portno, path)
-
- def testFactoryInfo(self):
- url = self.getURL('file')
- scheme, host, port, path = client._parse(url)
- factory = client.HTTPClientFactory(url)
- reactor.connectSSL(host, port, factory, ssl.ClientContextFactory())
- # The base class defines _cbFactoryInfo correctly for this
- return factory.deferred.addCallback(self._cbFactoryInfo, factory)
-
-class WebClientRedirectBetweenSSLandPlainText(unittest.TestCase):
- def getHTTPS(self, path):
- return "https://127.0.0.1:%d/%s" % (self.tlsPortno, path)
-
- def getHTTP(self, path):
- return "http://127.0.0.1:%d/%s" % (self.plainPortno, path)
-
- def setUp(self):
- plainRoot = static.Data('not me', 'text/plain')
- tlsRoot = static.Data('me neither', 'text/plain')
-
- plainSite = server.Site(plainRoot, timeout=None)
- tlsSite = server.Site(tlsRoot, timeout=None)
-
- from twisted import test
- self.tlsPort = reactor.listenSSL(0, tlsSite,
- contextFactory=ssl.DefaultOpenSSLContextFactory(
- FilePath(test.__file__).sibling('server.pem').path,
- FilePath(test.__file__).sibling('server.pem').path,
- ),
- interface="127.0.0.1")
- self.plainPort = reactor.listenTCP(0, plainSite, interface="127.0.0.1")
-
- self.plainPortno = self.plainPort.getHost().port
- self.tlsPortno = self.tlsPort.getHost().port
-
- plainRoot.putChild('one', util.Redirect(self.getHTTPS('two')))
- tlsRoot.putChild('two', util.Redirect(self.getHTTP('three')))
- plainRoot.putChild('three', util.Redirect(self.getHTTPS('four')))
- tlsRoot.putChild('four', static.Data('FOUND IT!', 'text/plain'))
-
- def tearDown(self):
- ds = map(defer.maybeDeferred,
- [self.plainPort.stopListening, self.tlsPort.stopListening])
- return defer.gatherResults(ds)
-
- def testHoppingAround(self):
- return client.getPage(self.getHTTP("one")
- ).addCallback(self.assertEquals, "FOUND IT!"
- )
-
-class FakeTransport:
- disconnecting = False
- def __init__(self):
- self.data = []
- def write(self, stuff):
- self.data.append(stuff)
-
-class CookieTestCase(unittest.TestCase):
- def _listen(self, site):
- return reactor.listenTCP(0, site, interface="127.0.0.1")
-
- def setUp(self):
- root = static.Data('El toro!', 'text/plain')
- root.putChild("cookiemirror", CookieMirrorResource())
- root.putChild("rawcookiemirror", RawCookieMirrorResource())
- site = server.Site(root, timeout=None)
- self.port = self._listen(site)
- self.portno = self.port.getHost().port
-
- def tearDown(self):
- return self.port.stopListening()
-
- def getHTTP(self, path):
- return "http://127.0.0.1:%d/%s" % (self.portno, path)
-
- def testNoCookies(self):
- return client.getPage(self.getHTTP("cookiemirror")
- ).addCallback(self.assertEquals, "[]"
- )
-
- def testSomeCookies(self):
- cookies = {'foo': 'bar', 'baz': 'quux'}
- return client.getPage(self.getHTTP("cookiemirror"), cookies=cookies
- ).addCallback(self.assertEquals, "[('baz', 'quux'), ('foo', 'bar')]"
- )
-
- def testRawNoCookies(self):
- return client.getPage(self.getHTTP("rawcookiemirror")
- ).addCallback(self.assertEquals, "None"
- )
-
- def testRawSomeCookies(self):
- cookies = {'foo': 'bar', 'baz': 'quux'}
- return client.getPage(self.getHTTP("rawcookiemirror"), cookies=cookies
- ).addCallback(self.assertEquals, "'foo=bar; baz=quux'"
- )
-
- def testCookieHeaderParsing(self):
- d = defer.Deferred()
- factory = client.HTTPClientFactory('http://foo.example.com/')
- proto = factory.buildProtocol('127.42.42.42')
- proto.transport = FakeTransport()
- proto.connectionMade()
- for line in [
- '200 Ok',
- 'Squash: yes',
- 'Hands: stolen',
- 'Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT',
- 'Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/',
- 'Set-Cookie: SHIPPING=FEDEX; path=/foo',
- '',
- 'body',
- 'more body',
- ]:
- proto.dataReceived(line + '\r\n')
- self.assertEquals(proto.transport.data,
- ['GET / HTTP/1.0\r\n',
- 'Host: foo.example.com\r\n',
- 'User-Agent: Twisted PageGetter\r\n',
- '\r\n'])
- self.assertEquals(factory.cookies,
- {
- 'CUSTOMER': 'WILE_E_COYOTE',
- 'PART_NUMBER': 'ROCKET_LAUNCHER_0001',
- 'SHIPPING': 'FEDEX',
- })
-
-if ssl is None or not hasattr(ssl, 'DefaultOpenSSLContextFactory'):
- for case in [WebClientSSLTestCase, WebClientRedirectBetweenSSLandPlainText]:
- case.skip = "OpenSSL not present"
-
-if not interfaces.IReactorSSL(reactor, None):
- for case in [WebClientSSLTestCase, WebClientRedirectBetweenSSLandPlainText]:
- case.skip = "Reactor doesn't support SSL"
diff --git a/tools/buildbot/pylibs/twisted/web/test/test_woven.py b/tools/buildbot/pylibs/twisted/web/test/test_woven.py
deleted file mode 100644
index 29dd17f..0000000
--- a/tools/buildbot/pylibs/twisted/web/test/test_woven.py
+++ /dev/null
@@ -1,570 +0,0 @@
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-from twisted.trial import unittest
-from twisted.web import server, resource, microdom, domhelpers
-from twisted.web import http
-from twisted.web.test import test_web
-from twisted.internet import reactor, defer, address
-
-from twisted.web.woven import template, model, view, controller, widgets, input, page, guard
-
-outputNum = 0
-
-# Reusable test harness
-
-class WovenTC(unittest.TestCase):
- modelFactory = lambda self: None
- resourceFactory = None
- def setUp(self):
- self.m = self.modelFactory()
- self.t = self.resourceFactory(self.m)
- self.r = test_web.DummyRequest([''])
- self.r.prepath = ['']
- self.prerender()
- self.t.render(self.r)
-
- self.channel = "a fake channel"
- self.output = ''.join(self.r.written)
- assert self.output, "No output was generated by the test."
- global outputNum
- open("wovenTestOutput%s.html" % (outputNum + 1), 'w').write(self.output)
- outputNum += 1
- self.d = microdom.parseString(self.output)
-
- def prerender(self):
- pass
-
-# Test 1
-# Test that replacing nodes with a string works properly
-
-
-class SimpleTemplate(template.DOMTemplate):
- template = """<http>
- <head>
- <title id="title"><span view="getTitle">Hello</span></title>
- </head>
- <body>
- <h3 id="hello"><span view="getHello">Hi</span></h3>
- </body>
-</http>"""
-
- def factory_getTitle(self, request, node):
- return "Title"
-
- def factory_getHello(self, request, node):
- return "Hello"
-
-
-class DOMTemplateTest(WovenTC):
- resourceFactory = SimpleTemplate
- def testSimpleRender(self):
- titleNode = self.d.getElementById("title")
- helloNode = self.d.getElementById("hello")
-
- self.assert_(domhelpers.gatherTextNodes(titleNode) == 'Title')
- self.assert_(domhelpers.gatherTextNodes(helloNode) == 'Hello')
-
-
-# Test 2
-# Test just like the first, but with Text widgets
-
-class TemplateWithWidgets(SimpleTemplate):
- def wcfactory_getTitle(self, request, node):
- return widgets.Text("Title")
-
- def wcfactory_getHello(self, request, node):
- return widgets.Text("Hello")
-
-
-class TWWTest(DOMTemplateTest):
- resourceFactory = TemplateWithWidgets
-
-
-# Test 3
-# Test a fancier widget, and controllers handling submitted input
-
-
-class MDemo(model.AttributeModel):
- foo = "Hello world"
- color = 'blue'
-
-
-class FancyBox(widgets.Widget):
- def setUp(self, request, node, data):
- self['style'] = 'margin: 1em; padding: 1em; background-color: %s' % data
-
-
-class VDemo(view.View):
- template = """<html>
-
-<div id="box" model="color" view="FancyBox"></div>
-
-<form action="">
-Type a color and hit submit:
-<input type="text" controller="change" model="color" name="color" />
-<input type="submit" />
-</form>
-
-</html>
-"""
- def wvfactory_FancyBox(self, request, node, model):
- return FancyBox(model)
-
- def renderFailure(self, failure, request):
- return failure
-
-
-class ChangeColor(input.Anything):
- def commit(self, request, node, data):
- session = request.getSession()
- session.color = data
- self.model.setData(request, data)
- self.model.notify({'request': request})
-
-
-class CDemo(controller.Controller):
- def setUp(self, request):
- session = request.getSession()
- self.model.color = getattr(session, 'color', self.model.color)
-
- def wcfactory_change(self, request, node, model):
- return ChangeColor(model)
-
-
-view.registerViewForModel(VDemo, MDemo)
-controller.registerControllerForModel(CDemo, MDemo)
-
-
-class ControllerTest(WovenTC):
- modelFactory = MDemo
- resourceFactory = CDemo
-
- def prerender(self):
- self.r.addArg('color', 'red')
-
- def testControllerOutput(self):
- boxNode = self.d.getElementById("box")
- assert boxNode, "Test %s failed" % outputNum
- style = boxNode.getAttribute("style")
- styles = style.split(";")
- sDict = {}
- for item in styles:
- key, value = item.split(":")
- key = key.strip()
- value = value.strip()
- sDict[key] = value
-
-# print sDict
- assert sDict['background-color'] == 'red'
-
-
-# Test 4
-# Test a list, a list widget, and Deferred data handling
-
-identityList = ['asdf', 'foo', 'fredf', 'bob']
-
-class MIdentityList(model.AttributeModel):
- def __init__(self):
- model.Model.__init__(self)
- self.identityList = defer.Deferred()
- self.identityList.callback(identityList)
-
-
-class VIdentityList(view.View):
- template = """<html>
- <ul id="list" view="identityList" model="identityList">
- <li listItemOf="identityList" view="text">
- Stuff.
- </li>
- </ul>
-</html>"""
-
- def wvfactory_identityList(self, request, node, model):
- return widgets.List(model)
-
- def wvfactory_text(self, request, node, model):
- return widgets.Text(model)
-
- def renderFailure(self, failure, request):
- return failure
-
-
-class CIdentityList(controller.Controller):
- pass
-
-
-view.registerViewForModel(VIdentityList, MIdentityList)
-controller.registerControllerForModel(CIdentityList, MIdentityList)
-
-
-class ListDeferredTest(WovenTC):
- modelFactory = MIdentityList
- resourceFactory = CIdentityList
-
- def testOutput(self):
- listNode = self.d.getElementById("list")
- assert listNode, "Test %s failed; there was no element with the id 'list' in the output" % outputNum
- liNodes = domhelpers.getElementsByTagName(listNode, 'li')
- assert len(liNodes) == len(identityList), "Test %s failed; the number of 'li' nodes did not match the list size" % outputNum
-
-
-# Test 5
-# Test nested lists
-
-class LLModel(model.AttributeModel):
- data = [['foo', 'bar', 'baz'],
- ['gum', 'shoe'],
- ['ggg', 'hhh', 'iii']
- ]
-
-
-class LLView(view.View):
- template = """<html>
- <ul id="first" view="List" model="data">
- <li pattern="listItem" view="DefaultWidget">
- <ol view="List">
- <li pattern="listItem" view="Text" />
- </ol>
- </li>
- </ul>
-</html>"""
-
- def wvfactory_List(self, request, node, model):
- return widgets.List(model)
-
-
-class NestedListTest(WovenTC):
- modelFactory = LLModel
- resourceFactory = LLView
-
- def testOutput(self):
- listNode = self.d.getElementById("first")
- assert listNode, "Test %s failed" % outputNum
- liNodes = filter(lambda x: hasattr(x, 'tagName') and x.tagName == 'li', listNode.childNodes)
-# print len(liNodes), len(self.m.data), liNodes, self.m.data
- assert len(liNodes) == len(self.m.data), "Test %s failed" % outputNum
- for i in range(len(liNodes)):
- sublistNode = domhelpers.getElementsByTagName(liNodes[i], 'ol')[0]
- subLiNodes = domhelpers.getElementsByTagName(sublistNode, 'li')
- assert len(self.m.data[i]) == len(subLiNodes)
-
-# Test 6
-# Test notification when a model is a dict or a list
-
-class MNotifyTest(model.AttributeModel):
- def initialize(self, *args, **kwargs):
- self.root = {"inventory": [], 'log': ""}
-
-
-class VNotifyTest(view.View):
- template = """<html>
- <body>
- <ol id="theList" model="root/inventory" view="List">
- <li view="someText" pattern="listItem" />
- </ol>
-
- <form action="">
- <input model="root" view="DefaultWidget" controller="updateInventory" name="root" />
- <input type="submit" />
- </form>
- </body>
-</html>"""
-
- def wvfactory_someText(self, request, node, m):
- return widgets.Text(m)
-
-class InventoryUpdater(input.Anything):
- def commit(self, request, node, data):
- invmodel = self.model.getSubmodel(request, "inventory")
- log = self.model.getSubmodel(request, "log")
- inv = invmodel.getData(request)
- inv.append(data) # just add a string to the list
- log.setData(request, log.getData(request) + ("%s added to servers\n" % data))
- invmodel.setData(request, inv)
- invmodel.notify({'request': request})
-
-
-class CNotifyTest(controller.Controller):
- def wcfactory_updateInventory(self, request, node, model):
- return InventoryUpdater(model)
-
-
-view.registerViewForModel(VNotifyTest, MNotifyTest)
-controller.registerControllerForModel(CNotifyTest, MNotifyTest)
-
-class NotifyTest(WovenTC):
- modelFactory = MNotifyTest
- resourceFactory = CNotifyTest
-
- def prerender(self):
- self.r.addArg('root', 'test')
-
- def testComplexNotification(self):
- listNode = self.d.getElementById("theList")
- self.assert_(listNode, "Test %s failed" % outputNum)
- liNodes = domhelpers.getElementsByTagName(listNode, 'li')
- self.assert_(liNodes,
- "DOM was not updated by notifying Widgets. Test %s" % outputNum)
- text = domhelpers.gatherTextNodes(liNodes[0])
- self.assert_(text.strip() == "test",
- "Wrong output: %s. Test %s" % (text, outputNum))
-
-view.registerViewForModel(LLView, LLModel)
-
-#### Test 7
-# Test model path syntax
-# model="/" should get you the root object
-# model="." should get you the current object
-# model=".." should get you the parent model object
-
-
-# xxx sanity check for now; just make sure it doesn't raise anything
-
-class ModelPathTest(WovenTC):
- modelFactory = lambda self: ['hello', ['hi', 'there'],
- 'hi', ['asdf', ['qwer', 'asdf']]]
- resourceFactory = page.Page
-
- def prerender(self):
- self.t.template = """<html>
- <div model="0" view="None">
- <div model=".." view="Text" />
- </div>
-
- <div model="0" view="None">
- <div model="../1/../2/../3" view="Text" />
- </div>
-
- <div model="0" view="None">
- <div model="../3/1/./1" view="Text" />
- </div>
-
- <div model="3/1/0" view="None">
- <div model="/" view="Text" />
- </div>
-
- <div model="3/1/0" view="None">
- <div model="/3" view="Text" />
- </div>
-
-</html>"""
-
-#### Test 8
-# Test a large number of widgets
-
-class HugeTest(WovenTC):
- modelFactory = lambda self: ['hello' for x in range(100)]
- resourceFactory = page.Page
-
- def prerender(self):
- self.t.template = """<html>
- <div model="." view="List">
- <div pattern="listItem" view="Text" />
- </div>
-</html>"""
-
- def testHugeTest(self):
- pass
-
-
-class ListOfDeferredsTest(WovenTC):
- """Test rendering a model which is a list of Deferreds."""
-
- modelFactory = lambda self: [defer.succeed("hello"), defer.succeed("world")]
- resourceFactory = page.Page
-
- def prerender(self):
- t = '''<div model="." view="List">
- <b pattern="listItem" view="Text" />
- </div>'''
- self.t.template = t
-
- def testResult(self):
- n = self.d.firstChild()
- self.assertEquals(len(n.childNodes), 2)
- for c in n.childNodes:
- self.assertEquals(c.nodeName, "b")
- self.assertEquals(n.firstChild().firstChild().toxml().strip(), "hello")
- self.assertEquals(n.lastChild().firstChild().toxml().strip(), "world")
-
-
-class FakeHTTPChannel:
- # TODO: this should be an interface in twisted.protocols.http... lots of
- # things want to fake out HTTP
- def __init__(self):
- self.transport = self
- self.factory = self
- self.received_cookies = {}
-
- # 'factory' attribute needs this
- def log(self, req):
- pass
-
- # 'channel' of request needs this
- def requestDone(self, req):
- self.req = req
-
- # 'transport' attribute needs this
- def getPeer(self):
- return address.IPv4Address("TCP", "fake", "fake")
- def getHost(self):
- return address.IPv4Address("TCP", "fake", 80)
-
- def write(self, data):
- # print data
- pass
- def writeSequence(self, datas):
- for data in datas:
- self.write(data)
-
- # Utility for testing.
-
- def makeFakeRequest(self, path, **vars):
- req = FakeHTTPRequest(self, queued=0)
- req.received_cookies.update(self.received_cookies)
- req.requestReceived("GET", path, "1.0")
- return req
-
-class FakeHTTPRequest(server.Request):
- def __init__(self, *args, **kw):
- server.Request.__init__(self, *args, **kw)
- self._cookieCache = {}
- from cStringIO import StringIO
- self.content = StringIO()
- self.received_headers['host'] = 'fake.com'
- self.written = StringIO()
-
- def write(self, data):
- self.written.write(data)
- server.Request.write(self, data)
-
- def addCookie(self, k, v, *args,**kw):
- server.Request.addCookie(self,k,v,*args,**kw)
- assert not self._cookieCache.has_key(k), "Should not be setting duplicate cookies!"
- self._cookieCache[k] = v
- self.channel.received_cookies[k] = v
-
- def processingFailed(self, fail):
- raise fail
-
-class FakeSite(server.Site):
- def getResourceFor(self, req):
- res = server.Site.getResourceFor(self,req)
- self.caughtRes = res
- return res
-
-from twisted.web import static
-
-class GuardTest(unittest.TestCase):
- def testSessionInit(self):
- sessWrapped = static.Data("you should never see this", "text/plain")
- swChild = static.Data("NO", "text/plain")
- sessWrapped.putChild("yyy",swChild)
- swrap = guard.SessionWrapper(sessWrapped)
- da = static.Data("b","text/plain")
- da.putChild("xxx", swrap)
- st = FakeSite(da)
- chan = FakeHTTPChannel()
- chan.site = st
-
- # first we're going to make sure that the session doesn't get set by
- # accident when browsing without first explicitly initializing the
- # session
- req = FakeHTTPRequest(chan, queued=0)
- req.requestReceived("GET", "/xxx/yyy", "1.0")
- assert len(req._cookieCache.values()) == 0, req._cookieCache.values()
- self.assertEquals(req.getSession(),None)
-
- # now we're going to make sure that the redirect and cookie are properly set
- req = FakeHTTPRequest(chan, queued=0)
- req.requestReceived("GET", "/xxx/"+guard.INIT_SESSION, "1.0")
- ccv = req._cookieCache.values()
- self.assertEquals(len(ccv),1)
- cookie = ccv[0]
- # redirect set?
- self.failUnless(req.headers.has_key('location'))
- # redirect matches cookie?
- self.assertEquals(req.headers['location'].split('/')[-1], guard.SESSION_KEY+cookie)
- # URL is correct?
- self.assertEquals(req.headers['location'],
- 'http://fake.com/xxx/'+guard.SESSION_KEY+cookie)
- oldreq = req
-
- # now let's try with a request for the session-cookie URL that has a cookie set
- url = "/"+(oldreq.headers['location'].split('http://fake.com/',1))[1]
- req = chan.makeFakeRequest(url)
- self.assertEquals(req.headers['location'].split('?')[0],
- 'http://fake.com/xxx/')
- for sz in swrap.sessions.values():
- sz.expire()
-
-
-
-class _TestPage(page.Page):
- template = """
- <html><body>
-
- <div>First: <span model="title" view="Text"/></div>
- <div>Second: <span model="title" view="Text"/></div>
- <div>Third: <span model="title" view="Text"/></div>
-
- </body></html>
- """
-
- def wmfactory_title(self, request):
- d = defer.Deferred()
- reactor.callLater(0, d.callback, 'The Result')
- return d
-
-class DeferredModelTestCase(unittest.TestCase):
- def testDeferredModel(self):
- # Test that multiple uses of a deferred model work correctly.
- channel = FakeHTTPChannel()
- channel.site = FakeSite(_TestPage())
- request = channel.makeFakeRequest('/')
-
- d = request.notifyFinish()
- def check(_):
- dom = microdom.parseXMLString(request.written.getvalue())
- spanElems = domhelpers.findNodesNamed(dom, 'span')
- for spanElem in spanElems:
- self.failUnlessEqual('The Result', spanElem.childNodes[0].data)
-
- return d.addCallback(check)
-
-
-class MyMacroPage(page.Page):
- template = """\
-<html macro='foo'>
-<head fill-slot='head'>
-<script>
-<![CDATA[
- <>'"&
-]]>
-</script>
-</head>
-</html>
-"""
- def wvfactory_foo(self, request, node, model):
- return widgets.ExpandMacro(model, macroFile = 'cdataxtester.html',
- macroFileDirectory = '.',
- macroName = 'foo'
- )
-
-class ExpandMacroTestCase(WovenTC):
- resourceFactory = MyMacroPage
- def setUp(self, *args, **kwargs):
- thepage = """\
-<html>
-<head slot='head' />
-</html>
-"""
- file('cdatatester.html', 'wb').write(thepage)
- WovenTC.setUp(self, *args, **kwargs)
- def testCDATANotQuoted(self):
- self.failUnless(self.output.find('<>\'"&')>=0)
-
-
-
diff --git a/tools/buildbot/pylibs/twisted/web/test/test_xml.py b/tools/buildbot/pylibs/twisted/web/test/test_xml.py
deleted file mode 100644
index a2e235c..0000000
--- a/tools/buildbot/pylibs/twisted/web/test/test_xml.py
+++ /dev/null
@@ -1,760 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_xml -*-
-#
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""Some fairly inadequate testcases for Twisted XML support."""
-
-from __future__ import nested_scopes
-
-from twisted.trial.unittest import TestCase
-
-from twisted.web import sux
-
-from twisted.web import microdom
-
-from twisted.web import domhelpers
-
-class Sux0r(sux.XMLParser):
- def __init__(self):
- self.tokens = []
-
- def getTagStarts(self):
- return [token for token in self.tokens if token[0] == 'start']
-
- def gotTagStart(self, name, attrs):
- self.tokens.append(("start", name, attrs))
-
- def gotText(self, text):
- self.tokens.append(("text", text))
-
-class SUXTest(TestCase):
-
- def testBork(self):
- s = "<bork><bork><bork>"
- ms = Sux0r()
- ms.connectionMade()
- ms.dataReceived(s)
- self.failUnlessEqual(len(ms.getTagStarts()),3)
-
-
-class MicroDOMTest(TestCase):
-
- def test_leadingTextDropping(self):
- """
- Make sure that if there's no top-level node lenient-mode won't
- drop leading text that's outside of any elements.
- """
- s = "Hi orders! <br>Well. <br>"
- d = microdom.parseString(s, beExtremelyLenient=True)
- self.assertEquals(d.firstChild().toxml(),
- '<html>Hi orders! <br />Well. <br /></html>')
-
- def test_trailingTextDropping(self):
- """
- Ensure that no *trailing* text in a mal-formed
- no-top-level-element document(s) will not be dropped.
- """
- s = "<br>Hi orders!"
- d = microdom.parseString(s, beExtremelyLenient=True)
- self.assertEquals(d.firstChild().toxml(),
- '<html><br />Hi orders!</html>')
-
-
- def test_noTags(self):
- """
- A string with nothing that looks like a tag at all should just
- be parsed as body text.
- """
- s = "Hi orders!"
- d = microdom.parseString(s, beExtremelyLenient=True)
- self.assertEquals(d.firstChild().toxml(),
- "<html>Hi orders!</html>")
-
-
- def test_surroundingCrap(self):
- """
- If a document is surrounded by non-xml text, the text should
- be remain in the XML.
- """
- s = "Hi<br> orders!"
- d = microdom.parseString(s, beExtremelyLenient=True)
- self.assertEquals(d.firstChild().toxml(),
- "<html>Hi<br /> orders!</html>")
-
-
- def testCaseSensitiveSoonCloser(self):
- s = """
- <HTML><BODY>
- <P ALIGN="CENTER">
- <A HREF="http://www.apache.org/"><IMG SRC="/icons/apache_pb.gif"></A>
- </P>
-
- <P>
- This is an insane set of text nodes that should NOT be gathered under
- the A tag above.
- </P>
- </BODY></HTML>
- """
- d = microdom.parseString(s, beExtremelyLenient=1)
- l = domhelpers.findNodesNamed(d.documentElement, 'a')
- n = domhelpers.gatherTextNodes(l[0],1).replace('&nbsp;',' ')
- self.assertEquals(n.find('insane'), -1)
-
-
- def test_lenientParenting(self):
- """
- Test that C{parentNode} attributes are set to meaningful values when
- we are parsing HTML that lacks a root node.
- """
- # Spare the rod, ruin the child.
- s = "<br/><br/>"
- d = microdom.parseString(s, beExtremelyLenient=1)
- self.assertIdentical(d.documentElement,
- d.documentElement.firstChild().parentNode)
-
-
- def test_lenientParentSingle(self):
- """
- Test that the C{parentNode} attribute is set to a meaningful value
- when we parse an HTML document that has a non-Element root node.
- """
- s = "Hello"
- d = microdom.parseString(s, beExtremelyLenient=1)
- self.assertIdentical(d.documentElement,
- d.documentElement.firstChild().parentNode)
-
-
- def testUnEntities(self):
- s = """
- <HTML>
- This HTML goes between Stupid <=CrAzY!=> Dumb.
- </HTML>
- """
- d = microdom.parseString(s, beExtremelyLenient=1)
- n = domhelpers.gatherTextNodes(d)
- self.assertNotEquals(n.find('>'), -1)
-
- def testEmptyError(self):
- self.assertRaises(sux.ParseError, microdom.parseString, "")
-
- def testTameDocument(self):
- s = """
- <test>
- <it>
- <is>
- <a>
- test
- </a>
- </is>
- </it>
- </test>
- """
- d = microdom.parseString(s)
- self.assertEquals(
- domhelpers.gatherTextNodes(d.documentElement).strip() ,'test')
-
- def testAwfulTagSoup(self):
- s = """
- <html>
- <head><title> I send you this message to have your advice!!!!</titl e
- </headd>
-
- <body bgcolor alink hlink vlink>
-
- <h1><BLINK>SALE</blINK> TWENTY MILLION EMAILS & FUR COAT NOW
- FREE WITH `ENLARGER'</h1>
-
- YES THIS WONDERFUL AWFER IS NOW HERER!!!
-
- <script LANGUAGE="javascript">
-function give_answers() {
-if (score < 70) {
-alert("I hate you");
-}}
- </script><a href=/foo.com/lalal name=foo>lalal</a>
- </body>
- </HTML>
- """
- d = microdom.parseString(s, beExtremelyLenient=1)
- l = domhelpers.findNodesNamed(d.documentElement, 'blink')
- self.assertEquals(len(l), 1)
-
- def testScriptLeniency(self):
- s = """
- <script>(foo < bar) and (bar > foo)</script>
- <script language="javascript">foo </scrip bar </script>
- <script src="foo">
- <script src="foo">baz</script>
- <script /><script></script>
- """
- d = microdom.parseString(s, beExtremelyLenient=1)
- self.assertEquals(d.firstChild().firstChild().firstChild().data,
- "(foo < bar) and (bar > foo)")
- self.assertEquals(
- d.firstChild().getElementsByTagName("script")[1].firstChild().data,
- "foo </scrip bar ")
-
- def testScriptLeniencyIntelligence(self):
- # if there is comment or CDATA in script, the autoquoting in bEL mode
- # should not happen
- s = """<script><!-- lalal --></script>"""
- self.assertEquals(
- microdom.parseString(s, beExtremelyLenient=1).firstChild().toxml(), s)
- s = """<script><![CDATA[lalal]]></script>"""
- self.assertEquals(
- microdom.parseString(s, beExtremelyLenient=1).firstChild().toxml(), s)
- s = """<script> // <![CDATA[
- lalal
- //]]></script>"""
- self.assertEquals(
- microdom.parseString(s, beExtremelyLenient=1).firstChild().toxml(), s)
-
- def testPreserveCase(self):
- s = '<eNcApSuLaTe><sUxor></sUxor><bOrk><w00T>TeXt</W00t></BoRk></EnCaPsUlAtE>'
- s2 = s.lower().replace('text', 'TeXt')
- # these are the only two option permutations that *can* parse the above
- d = microdom.parseString(s, caseInsensitive=1, preserveCase=1)
- d2 = microdom.parseString(s, caseInsensitive=1, preserveCase=0)
- # caseInsensitive=0 preserveCase=0 is not valid, it's converted to
- # caseInsensitive=0 preserveCase=1
- d3 = microdom.parseString(s2, caseInsensitive=0, preserveCase=1)
- d4 = microdom.parseString(s2, caseInsensitive=1, preserveCase=0)
- d5 = microdom.parseString(s2, caseInsensitive=1, preserveCase=1)
- # this is slightly contrived, toxml() doesn't need to be identical
- # for the documents to be equivalent (i.e. <b></b> to <b/>),
- # however this assertion tests preserving case for start and
- # end tags while still matching stuff like <bOrk></BoRk>
- self.assertEquals(d.documentElement.toxml(), s)
- self.assert_(d.isEqualToDocument(d2), "%r != %r" % (d.toxml(), d2.toxml()))
- self.assert_(d2.isEqualToDocument(d3), "%r != %r" % (d2.toxml(), d3.toxml()))
- # caseInsensitive=0 on the left, NOT perserveCase=1 on the right
- ## XXX THIS TEST IS TURNED OFF UNTIL SOMEONE WHO CARES ABOUT FIXING IT DOES
- #self.failIf(d3.isEqualToDocument(d2), "%r == %r" % (d3.toxml(), d2.toxml()))
- self.assert_(d3.isEqualToDocument(d4), "%r != %r" % (d3.toxml(), d4.toxml()))
- self.assert_(d4.isEqualToDocument(d5), "%r != %r" % (d4.toxml(), d5.toxml()))
-
- def testDifferentQuotes(self):
- s = '<test a="a" b=\'b\' />'
- d = microdom.parseString(s)
- e = d.documentElement
- self.assertEquals(e.getAttribute('a'), 'a')
- self.assertEquals(e.getAttribute('b'), 'b')
-
- def testLinebreaks(self):
- s = '<test \na="a"\n\tb="#b" />'
- d = microdom.parseString(s)
- e = d.documentElement
- self.assertEquals(e.getAttribute('a'), 'a')
- self.assertEquals(e.getAttribute('b'), '#b')
-
- def testMismatchedTags(self):
- for s in '<test>', '<test> </tset>', '</test>':
- self.assertRaises(microdom.MismatchedTags, microdom.parseString, s)
-
- def testComment(self):
- s = "<bar><!--<foo />--></bar>"
- d = microdom.parseString(s)
- e = d.documentElement
- self.assertEquals(e.nodeName, "bar")
- c = e.childNodes[0]
- self.assert_(isinstance(c, microdom.Comment))
- self.assertEquals(c.value, "<foo />")
- c2 = c.cloneNode()
- self.assert_(c is not c2)
- self.assertEquals(c2.toxml(), "<!--<foo />-->")
-
- def testText(self):
- d = microdom.parseString("<bar>xxxx</bar>").documentElement
- text = d.childNodes[0]
- self.assert_(isinstance(text, microdom.Text))
- self.assertEquals(text.value, "xxxx")
- clone = text.cloneNode()
- self.assert_(clone is not text)
- self.assertEquals(clone.toxml(), "xxxx")
-
- def testEntities(self):
- nodes = microdom.parseString("<b>&amp;&#12AB;</b>").documentElement.childNodes
- self.assertEquals(len(nodes), 2)
- self.assertEquals(nodes[0].data, "&amp;")
- self.assertEquals(nodes[1].data, "&#12AB;")
- self.assertEquals(nodes[0].cloneNode().toxml(), "&amp;")
- for n in nodes:
- self.assert_(isinstance(n, microdom.EntityReference))
-
- def testCData(self):
- s = '<x><![CDATA[</x>\r\n & foo]]></x>'
- cdata = microdom.parseString(s).documentElement.childNodes[0]
- self.assert_(isinstance(cdata, microdom.CDATASection))
- self.assertEquals(cdata.data, "</x>\r\n & foo")
- self.assertEquals(cdata.cloneNode().toxml(), "<![CDATA[</x>\r\n & foo]]>")
-
- def testSingletons(self):
- s = "<foo><b/><b /><b\n/></foo>"
- s2 = "<foo><b/><b/><b/></foo>"
- nodes = microdom.parseString(s).documentElement.childNodes
- nodes2 = microdom.parseString(s2).documentElement.childNodes
- self.assertEquals(len(nodes), 3)
- for (n, n2) in zip(nodes, nodes2):
- self.assert_(isinstance(n, microdom.Element))
- self.assertEquals(n.nodeName, "b")
- self.assert_(n.isEqualToNode(n2))
-
- def testAttributes(self):
- s = '<foo a="b" />'
- node = microdom.parseString(s).documentElement
-
- self.assertEquals(node.getAttribute("a"), "b")
- self.assertEquals(node.getAttribute("c"), None)
- self.assert_(node.hasAttribute("a"))
- self.assert_(not node.hasAttribute("c"))
- a = node.getAttributeNode("a")
- self.assertEquals(a.value, "b")
-
- node.setAttribute("foo", "bar")
- self.assertEquals(node.getAttribute("foo"), "bar")
-
- def testChildren(self):
- s = "<foo><bar /><baz /><bax>foo</bax></foo>"
- d = microdom.parseString(s).documentElement
- self.assertEquals([n.nodeName for n in d.childNodes], ["bar", "baz", "bax"])
- self.assertEquals(d.lastChild().nodeName, "bax")
- self.assertEquals(d.firstChild().nodeName, "bar")
- self.assert_(d.hasChildNodes())
- self.assert_(not d.firstChild().hasChildNodes())
-
- def testMutate(self):
- s = "<foo />"
- s1 = '<foo a="b"><bar/><foo/></foo>'
- s2 = '<foo a="b">foo</foo>'
- d = microdom.parseString(s).documentElement
- d1 = microdom.parseString(s1).documentElement
- d2 = microdom.parseString(s2).documentElement
-
- d.appendChild(d.cloneNode())
- d.setAttribute("a", "b")
- child = d.childNodes[0]
- self.assertEquals(child.getAttribute("a"), None)
- self.assertEquals(child.nodeName, "foo")
-
- d.insertBefore(microdom.Element("bar"), child)
- self.assertEquals(d.childNodes[0].nodeName, "bar")
- self.assertEquals(d.childNodes[1], child)
- for n in d.childNodes:
- self.assertEquals(n.parentNode, d)
- self.assert_(d.isEqualToNode(d1))
-
- d.removeChild(child)
- self.assertEquals(len(d.childNodes), 1)
- self.assertEquals(d.childNodes[0].nodeName, "bar")
-
- t = microdom.Text("foo")
- d.replaceChild(t, d.firstChild())
- self.assertEquals(d.firstChild(), t)
- self.assert_(d.isEqualToNode(d2))
-
- def testSearch(self):
- s = "<foo><bar id='me' /><baz><foo /></baz></foo>"
- s2 = "<fOo><bAr id='me' /><bAz><fOO /></bAz></fOo>"
- d = microdom.parseString(s)
- d2 = microdom.parseString(s2, caseInsensitive=0, preserveCase=1)
- d3 = microdom.parseString(s2, caseInsensitive=1, preserveCase=1)
-
- root = d.documentElement
- self.assertEquals(root.firstChild(), d.getElementById('me'))
- self.assertEquals(d.getElementsByTagName("foo"),
- [root, root.lastChild().firstChild()])
-
- root = d2.documentElement
- self.assertEquals(root.firstChild(), d2.getElementById('me'))
- self.assertEquals(d2.getElementsByTagName('fOo'), [root])
- self.assertEquals(d2.getElementsByTagName('fOO'),
- [root.lastChild().firstChild()])
- self.assertEquals(d2.getElementsByTagName('foo'), [])
-
- root = d3.documentElement
- self.assertEquals(root.firstChild(), d3.getElementById('me'))
- self.assertEquals(d3.getElementsByTagName('FOO'),
- [root, root.lastChild().firstChild()])
- self.assertEquals(d3.getElementsByTagName('fOo'),
- [root, root.lastChild().firstChild()])
-
- def testDoctype(self):
- s = ('<?xml version="1.0"?>'
- '<!DOCTYPE foo PUBLIC "baz" "http://www.example.com/example.dtd">'
- '<foo></foo>')
- s2 = '<foo/>'
- d = microdom.parseString(s)
- d2 = microdom.parseString(s2)
- self.assertEquals(d.doctype,
- 'foo PUBLIC "baz" "http://www.example.com/example.dtd"')
- self.assertEquals(d.toxml(), s)
- self.failIf(d.isEqualToDocument(d2))
- self.failUnless(d.documentElement.isEqualToNode(d2.documentElement))
-
- samples = [("<img/>", "<img />"),
- ("<foo A='b'>x</foo>", '<foo A="b">x</foo>'),
- ("<foo><BAR /></foo>", "<foo><BAR></BAR></foo>"),
- ("<foo>hello there &amp; yoyoy</foo>",
- "<foo>hello there &amp; yoyoy</foo>"),
- ]
-
- def testOutput(self):
- for s, out in self.samples:
- d = microdom.parseString(s, caseInsensitive=0)
- d2 = microdom.parseString(out, caseInsensitive=0)
- testOut = d.documentElement.toxml()
- self.assertEquals(out, testOut)
- self.assert_(d.isEqualToDocument(d2))
-
- def testErrors(self):
- for s in ["<foo>&am</foo>", "<foo", "<f>&</f>", "<() />"]:
- self.assertRaises(Exception, microdom.parseString, s)
-
- def testCaseInsensitive(self):
- s = "<foo a='b'><BAx>x</bax></FOO>"
- s2 = '<foo a="b"><bax>x</bax></foo>'
- s3 = "<FOO a='b'><BAx>x</BAx></FOO>"
- s4 = "<foo A='b'>x</foo>"
- d = microdom.parseString(s)
- d2 = microdom.parseString(s2)
- d3 = microdom.parseString(s3, caseInsensitive=1)
- d4 = microdom.parseString(s4, caseInsensitive=1, preserveCase=1)
- d5 = microdom.parseString(s4, caseInsensitive=1, preserveCase=0)
- d6 = microdom.parseString(s4, caseInsensitive=0, preserveCase=0)
- out = microdom.parseString(s).documentElement.toxml()
- self.assertRaises(microdom.MismatchedTags, microdom.parseString,
- s, caseInsensitive=0)
- self.assertEquals(out, s2)
- self.failUnless(d.isEqualToDocument(d2))
- self.failUnless(d.isEqualToDocument(d3))
- self.failUnless(d4.documentElement.hasAttribute('a'))
- self.failIf(d6.documentElement.hasAttribute('a'))
- self.assertEquals(d4.documentElement.toxml(), '<foo A="b">x</foo>')
- self.assertEquals(d5.documentElement.toxml(), '<foo a="b">x</foo>')
- def testEatingWhitespace(self):
- s = """<hello>
- </hello>"""
- d = microdom.parseString(s)
- self.failUnless(not d.documentElement.hasChildNodes(),
- d.documentElement.childNodes)
- self.failUnless(d.isEqualToDocument(microdom.parseString('<hello></hello>')))
-
- def testLenientAmpersand(self):
- prefix = "<?xml version='1.0'?>"
- # we use <pre> so space will be preserved
- for i, o in [("&", "&amp;"),
- ("& ", "&amp; "),
- ("&amp;", "&amp;"),
- ("&hello monkey", "&amp;hello monkey")]:
- d = microdom.parseString("%s<pre>%s</pre>"
- % (prefix, i), beExtremelyLenient=1)
- self.assertEquals(d.documentElement.toxml(), "<pre>%s</pre>" % o)
- # non-space preserving
- d = microdom.parseString("<t>hello & there</t>", beExtremelyLenient=1)
- self.assertEquals(d.documentElement.toxml(), "<t>hello &amp; there</t>")
-
- def testInsensitiveLenient(self):
- # testing issue #537
- d = microdom.parseString(
- "<?xml version='1.0'?><bar><xA><y>c</Xa> <foo></bar>",
- beExtremelyLenient=1)
- self.assertEquals(d.documentElement.firstChild().toxml(), "<xa><y>c</y></xa>")
-
- def testSpacing(self):
- # testing issue #414
- s = "<?xml version='1.0'?><p><q>smart</q> <code>HairDryer</code></p>"
- d = microdom.parseString(s, beExtremelyLenient=1)
- expected = "<p><q>smart</q> <code>HairDryer</code></p>"
- actual = d.documentElement.toxml()
- self.assertEquals(expected, actual)
-
- testSpacing.todo = "AAARGH white space swallowing screws this up"
-
- def testLaterCloserSimple(self):
- s = "<ul><li>foo<li>bar<li>baz</ul>"
- d = microdom.parseString(s, beExtremelyLenient=1)
- expected = "<ul><li>foo</li><li>bar</li><li>baz</li></ul>"
- actual = d.documentElement.toxml()
- self.assertEquals(expected, actual)
-
- def testLaterCloserCaseInsensitive(self):
- s = "<DL><p><DT>foo<DD>bar</DL>"
- d = microdom.parseString(s, beExtremelyLenient=1)
- expected = "<dl><p></p><dt>foo</dt><dd>bar</dd></dl>"
- actual = d.documentElement.toxml()
- self.assertEquals(expected, actual)
-
- def testLaterCloserTable(self):
- s = ("<table>"
- "<tr><th>name<th>value<th>comment"
- "<tr><th>this<td>tag<td>soup"
- "<tr><th>must<td>be<td>handled"
- "</table>")
- expected = ("<table>"
- "<tr><th>name</th><th>value</th><th>comment</th></tr>"
- "<tr><th>this</th><td>tag</td><td>soup</td></tr>"
- "<tr><th>must</th><td>be</td><td>handled</td></tr>"
- "</table>")
- d = microdom.parseString(s, beExtremelyLenient=1)
- actual = d.documentElement.toxml()
- self.assertEquals(expected, actual)
- testLaterCloserTable.todo = "Table parsing needs to be fixed."
-
- def testLaterCloserDL(self):
- s = ("<dl>"
- "<dt>word<dd>definition"
- "<dt>word<dt>word<dd>definition<dd>definition"
- "</dl>")
- expected = ("<dl>"
- "<dt>word</dt><dd>definition</dd>"
- "<dt>word</dt><dt>word</dt><dd>definition</dd><dd>definition</dd>"
- "</dl>")
- d = microdom.parseString(s, beExtremelyLenient=1)
- actual = d.documentElement.toxml()
- self.assertEquals(expected, actual)
-
- def testLaterCloserDL2(self):
- s = ("<dl>"
- "<dt>word<dd>definition<p>more definition"
- "<dt>word"
- "</dl>")
- expected = ("<dl>"
- "<dt>word</dt><dd>definition<p>more definition</p></dd>"
- "<dt>word</dt>"
- "</dl>")
- d = microdom.parseString(s, beExtremelyLenient=1)
- actual = d.documentElement.toxml()
- self.assertEquals(expected, actual)
-
- testLaterCloserDL2.todo = "unclosed <p> messes it up."
-
- def testUnicodeTolerance(self):
- import struct
- s = '<foo><bar><baz /></bar></foo>'
- j =(u'<?xml version="1.0" encoding="UCS-2" ?>\r\n<JAPANESE>\r\n'
- u'<TITLE>\u5c02\u9580\u5bb6\u30ea\u30b9\u30c8 </TITLE></JAPANESE>')
- j2=('\xff\xfe<\x00?\x00x\x00m\x00l\x00 \x00v\x00e\x00r\x00s\x00i\x00o'
- '\x00n\x00=\x00"\x001\x00.\x000\x00"\x00 \x00e\x00n\x00c\x00o\x00d'
- '\x00i\x00n\x00g\x00=\x00"\x00U\x00C\x00S\x00-\x002\x00"\x00 \x00?'
- '\x00>\x00\r\x00\n\x00<\x00J\x00A\x00P\x00A\x00N\x00E\x00S\x00E'
- '\x00>\x00\r\x00\n\x00<\x00T\x00I\x00T\x00L\x00E\x00>\x00\x02\\'
- '\x80\x95\xb6[\xea0\xb90\xc80 \x00<\x00/\x00T\x00I\x00T\x00L\x00E'
- '\x00>\x00<\x00/\x00J\x00A\x00P\x00A\x00N\x00E\x00S\x00E\x00>\x00')
- def reverseBytes(s):
- fmt = str(len(s) / 2) + 'H'
- return struct.pack('<' + fmt, *struct.unpack('>' + fmt, s))
- urd = microdom.parseString(reverseBytes(s.encode('UTF-16')))
- ud = microdom.parseString(s.encode('UTF-16'))
- sd = microdom.parseString(s)
- self.assert_(ud.isEqualToDocument(sd))
- self.assert_(ud.isEqualToDocument(urd))
- ud = microdom.parseString(j)
- urd = microdom.parseString(reverseBytes(j2))
- sd = microdom.parseString(j2)
- self.assert_(ud.isEqualToDocument(sd))
- self.assert_(ud.isEqualToDocument(urd))
-
- # test that raw text still gets encoded
- # test that comments get encoded
- j3=microdom.parseString(u'<foo/>')
- hdr='<?xml version="1.0"?>'
- div=microdom.lmx().text(u'\u221a', raw=1).node
- de=j3.documentElement
- de.appendChild(div)
- de.appendChild(j3.createComment(u'\u221a'))
- self.assertEquals(j3.toxml(), hdr+
- u'<foo><div>\u221a</div><!--\u221a--></foo>'.encode('utf8'))
-
- def testNamedChildren(self):
- tests = {"<foo><bar /><bar unf='1' /><bar>asdfadsf</bar>"
- "<bam/></foo>" : 3,
- '<foo>asdf</foo>' : 0,
- '<foo><bar><bar></bar></bar></foo>' : 1,
- }
- for t in tests.keys():
- node = microdom.parseString(t).documentElement
- result = domhelpers.namedChildren(node, 'bar')
- self.assertEquals(len(result), tests[t])
- if result:
- self.assert_(hasattr(result[0], 'tagName'))
-
- def testCloneNode(self):
- s = '<foo a="b"><bax>x</bax></foo>'
- node = microdom.parseString(s).documentElement
- clone = node.cloneNode(deep=1)
- self.failIfEquals(node, clone)
- self.assertEquals(len(node.childNodes), len(clone.childNodes))
- c1, c2 = node.firstChild(), clone.firstChild()
- self.failIfEquals(c1, c2)
- self.assertEquals(len(c1.childNodes), len(c2.childNodes))
- self.failIfEquals(c1.firstChild(), c2.firstChild())
- self.assertEquals(s, clone.toxml())
- self.assertEquals(node.namespace, clone.namespace)
-
- def testCloneDocument(self):
- s = ('<?xml version="1.0"?>'
- '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'
- '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><foo></foo>')
-
- node = microdom.parseString(s)
- clone = node.cloneNode(deep=1)
- self.failIfEquals(node, clone)
- self.assertEquals(len(node.childNodes), len(clone.childNodes))
- self.assertEquals(s, clone.toxml())
-
- self.failUnless(clone.isEqualToDocument(node))
- self.failUnless(node.isEqualToDocument(clone))
-
-
- def testLMX(self):
- n = microdom.Element("p")
- lmx = microdom.lmx(n)
- lmx.text("foo")
- b = lmx.b(a="c")
- b.foo()["z"] = "foo"
- b.foo()
- b.add("bar", c="y")
-
- s = '<p>foo<b a="c"><foo z="foo"></foo><foo></foo><bar c="y"></bar></b></p>'
- self.assertEquals(s, n.toxml())
-
- def testDict(self):
- n = microdom.Element("p")
- d = {n : 1} # will fail if Element is unhashable
-
- def testEscaping(self):
- # issue 590
- raw = "&'some \"stuff\"', <what up?>"
- cooked = "&amp;'some &quot;stuff&quot;', &lt;what up?&gt;"
- esc1 = microdom.escape(raw)
- self.assertEquals(esc1, cooked)
- self.assertEquals(microdom.unescape(esc1), raw)
-
- def testNamespaces(self):
- s = '''
- <x xmlns="base">
- <y />
- <y q="1" x:q="2" y:q="3" />
- <y:y xml:space="1">here is some space </y:y>
- <y:y />
- <x:y />
- </x>
- '''
- d = microdom.parseString(s)
- # at least make sure it doesn't traceback
- s2 = d.toprettyxml()
- self.assertEquals(d.documentElement.namespace,
- "base")
- self.assertEquals(d.documentElement.getElementsByTagName("y")[0].namespace,
- "base")
- self.assertEquals(
- d.documentElement.getElementsByTagName("y")[1].getAttributeNS('base','q'),
- '1')
-
- d2 = microdom.parseString(s2)
- self.assertEquals(d2.documentElement.namespace,
- "base")
- self.assertEquals(d2.documentElement.getElementsByTagName("y")[0].namespace,
- "base")
- self.assertEquals(
- d2.documentElement.getElementsByTagName("y")[1].getAttributeNS('base','q'),
- '1')
-
- def testNamespaceDelete(self):
- """
- Test that C{toxml} can support xml structures that remove namespaces.
- """
- s1 = ('<?xml version="1.0"?><html xmlns="http://www.w3.org/TR/REC-html40">'
- '<body xmlns=""></body></html>')
- s2 = microdom.parseString(s1).toxml()
- self.assertEquals(s1, s2)
-
- def testNamespaceInheritance(self):
- """
- Check that unspecified namespace is a thing separate from undefined
- namespace. This test added after discovering some weirdness in Lore.
- """
- # will only work if childNodes is mutated. not sure why.
- child = microdom.Element('ol')
- parent = microdom.Element('div', namespace='http://www.w3.org/1999/xhtml')
- parent.childNodes = [child]
- self.assertEquals(parent.toxml(),
- '<div xmlns="http://www.w3.org/1999/xhtml"><ol></ol></div>')
-
-
-class TestBrokenHTML(TestCase):
- """
- Tests for when microdom encounters very bad HTML and C{beExtremelyLenient}
- is enabled. These tests are inspired by some HTML generated in by a mailer,
- which breaks up very long lines by splitting them with '!\n '. The expected
- behaviour is loosely modelled on the way Firefox treats very bad HTML.
- """
-
- def checkParsed(self, input, expected, beExtremelyLenient=1):
- """
- Check that C{input}, when parsed, produces a DOM where the XML
- of the document element is equal to C{expected}.
- """
- output = microdom.parseString(input,
- beExtremelyLenient=beExtremelyLenient)
- self.assertEquals(output.documentElement.toxml(), expected)
-
-
- def test_brokenAttributeName(self):
- """
- Check that microdom does its best to handle broken attribute names.
- The important thing is that it doesn't raise an exception.
- """
- input = '<body><h1><div al!\n ign="center">Foo</div></h1></body>'
- expected = ('<body><h1><div ign="center" al="True">'
- 'Foo</div></h1></body>')
- self.checkParsed(input, expected)
-
-
- def test_brokenAttributeValue(self):
- """
- Check that microdom encompasses broken attribute values.
- """
- input = '<body><h1><div align="cen!\n ter">Foo</div></h1></body>'
- expected = '<body><h1><div align="cen!\n ter">Foo</div></h1></body>'
- self.checkParsed(input, expected)
-
-
- def test_brokenOpeningTag(self):
- """
- Check that microdom does its best to handle broken opening tags.
- The important thing is that it doesn't raise an exception.
- """
- input = '<body><h1><sp!\n an>Hello World!</span></h1></body>'
- expected = '<body><h1><sp an="True">Hello World!</sp></h1></body>'
- self.checkParsed(input, expected)
-
-
- def test_brokenSelfClosingTag(self):
- """
- Check that microdom does its best to handle broken self-closing tags
- The important thing is that it doesn't raise an exception.
- """
- self.checkParsed('<body><span /!\n></body>',
- '<body><span></span></body>')
- self.checkParsed('<span!\n />', '<span></span>')
-
-
- def test_brokenClosingTag(self):
- """
- Check that microdom does its best to handle broken closing tags.
- The important thing is that it doesn't raise an exception.
- """
- input = '<body><h1><span>Hello World!</sp!\nan></h1></body>'
- expected = '<body><h1><span>Hello World!</span></h1></body>'
- self.checkParsed(input, expected)
- input = '<body><h1><span>Hello World!</!\nspan></h1></body>'
- self.checkParsed(input, expected)
- input = '<body><h1><span>Hello World!</span!\n></h1></body>'
- self.checkParsed(input, expected)
- input = '<body><h1><span>Hello World!<!\n/span></h1></body>'
- expected = '<body><h1><span>Hello World!<!></!></span></h1></body>'
- self.checkParsed(input, expected)
-
diff --git a/tools/buildbot/pylibs/twisted/web/test/test_xmlrpc.py b/tools/buildbot/pylibs/twisted/web/test/test_xmlrpc.py
deleted file mode 100644
index c34430a..0000000
--- a/tools/buildbot/pylibs/twisted/web/test/test_xmlrpc.py
+++ /dev/null
@@ -1,452 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_xmlrpc -*-
-#
-# Copyright (c) 2001-2007 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-"""
-Test XML-RPC support.
-"""
-
-try:
- import xmlrpclib
-except ImportError:
- xmlrpclib = None
- class XMLRPC: pass
-else:
- from twisted.web import xmlrpc
- from twisted.web.xmlrpc import XMLRPC, addIntrospection, _QueryFactory
-
-from twisted.trial import unittest
-from twisted.web import server, static, client, error, http
-from twisted.internet import reactor, defer
-from twisted.internet.error import ConnectionDone
-from twisted.python import failure
-
-
-class TestRuntimeError(RuntimeError):
- pass
-
-class TestValueError(ValueError):
- pass
-
-
-
-class Test(XMLRPC):
-
- FAILURE = 666
- NOT_FOUND = 23
- SESSION_EXPIRED = 42
-
- # the doc string is part of the test
- def xmlrpc_add(self, a, b):
- """
- This function add two numbers.
- """
- return a + b
-
- xmlrpc_add.signature = [['int', 'int', 'int'],
- ['double', 'double', 'double']]
-
- # the doc string is part of the test
- def xmlrpc_pair(self, string, num):
- """
- This function puts the two arguments in an array.
- """
- return [string, num]
-
- xmlrpc_pair.signature = [['array', 'string', 'int']]
-
- # the doc string is part of the test
- def xmlrpc_defer(self, x):
- """Help for defer."""
- return defer.succeed(x)
-
- def xmlrpc_deferFail(self):
- return defer.fail(TestValueError())
-
- # don't add a doc string, it's part of the test
- def xmlrpc_fail(self):
- raise TestRuntimeError
-
- def xmlrpc_fault(self):
- return xmlrpc.Fault(12, "hello")
-
- def xmlrpc_deferFault(self):
- return defer.fail(xmlrpc.Fault(17, "hi"))
-
- def xmlrpc_complex(self):
- return {"a": ["b", "c", 12, []], "D": "foo"}
-
- def xmlrpc_dict(self, map, key):
- return map[key]
-
- def _getFunction(self, functionPath):
- try:
- return XMLRPC._getFunction(self, functionPath)
- except xmlrpc.NoSuchFunction:
- if functionPath.startswith("SESSION"):
- raise xmlrpc.Fault(self.SESSION_EXPIRED,
- "Session non-existant/expired.")
- else:
- raise
-
- xmlrpc_dict.help = 'Help for dict.'
-
-class TestAuthHeader(Test):
- """
- This is used to get the header info so that we can test
- authentication.
- """
- def __init__(self):
- Test.__init__(self)
- self.request = None
-
- def render(self, request):
- self.request = request
- return Test.render(self, request)
-
- def xmlrpc_authinfo(self):
- return self.request.getUser(), self.request.getPassword()
-
-
-class TestQueryProtocol(xmlrpc.QueryProtocol):
- """
- QueryProtocol for tests that saves headers received inside the factory.
- """
- def handleHeader(self, key, val):
- self.factory.headers[key.lower()] = val
-
-
-class TestQueryFactory(xmlrpc._QueryFactory):
- """
- QueryFactory using L{TestQueryProtocol} for saving headers.
- """
- protocol = TestQueryProtocol
-
- def __init__(self, *args, **kwargs):
- self.headers = {}
- xmlrpc._QueryFactory.__init__(self, *args, **kwargs)
-
-
-class XMLRPCTestCase(unittest.TestCase):
-
- def setUp(self):
- self.p = reactor.listenTCP(0, server.Site(Test()),
- interface="127.0.0.1")
- self.port = self.p.getHost().port
- self.factories = []
-
- def tearDown(self):
- self.factories = []
- return self.p.stopListening()
-
- def queryFactory(self, *args, **kwargs):
- """
- Specific queryFactory for proxy that uses our custom
- L{TestQueryFactory}, and save factories.
- """
- factory = TestQueryFactory(*args, **kwargs)
- self.factories.append(factory)
- return factory
-
- def proxy(self):
- p = xmlrpc.Proxy("http://127.0.0.1:%d/" % self.port)
- p.queryFactory = self.queryFactory
- return p
-
- def test_results(self):
- inputOutput = [
- ("add", (2, 3), 5),
- ("defer", ("a",), "a"),
- ("dict", ({"a": 1}, "a"), 1),
- ("pair", ("a", 1), ["a", 1]),
- ("complex", (), {"a": ["b", "c", 12, []], "D": "foo"})]
-
- dl = []
- for meth, args, outp in inputOutput:
- d = self.proxy().callRemote(meth, *args)
- d.addCallback(self.assertEquals, outp)
- dl.append(d)
- return defer.DeferredList(dl, fireOnOneErrback=True)
-
- def test_errors(self):
- """
- Verify that for each way a method exposed via XML-RPC can fail, the
- correct 'Content-type' header is set in the response and that the
- client-side Deferred is errbacked with an appropriate C{Fault}
- instance.
- """
- dl = []
- for code, methodName in [(666, "fail"), (666, "deferFail"),
- (12, "fault"), (23, "noSuchMethod"),
- (17, "deferFault"), (42, "SESSION_TEST")]:
- d = self.proxy().callRemote(methodName)
- d = self.assertFailure(d, xmlrpc.Fault)
- d.addCallback(lambda exc, code=code:
- self.assertEquals(exc.faultCode, code))
- dl.append(d)
- d = defer.DeferredList(dl, fireOnOneErrback=True)
- def cb(ign):
- for factory in self.factories:
- self.assertEquals(factory.headers['content-type'],
- 'text/xml')
- self.flushLoggedErrors(TestRuntimeError, TestValueError)
- d.addCallback(cb)
- return d
-
- def test_errorGet(self):
- """
- A classic GET on the xml server should return a NOT_ALLOWED.
- """
- d = client.getPage("http://127.0.0.1:%d/" % (self.port,))
- d = self.assertFailure(d, error.Error)
- d.addCallback(
- lambda exc: self.assertEquals(int(exc.args[0]), http.NOT_ALLOWED))
- return d
-
- def test_errorXMLContent(self):
- """
- Test that an invalid XML input returns an L{xmlrpc.Fault}.
- """
- d = client.getPage("http://127.0.0.1:%d/" % (self.port,),
- method="POST", postdata="foo")
- def cb(result):
- self.assertRaises(xmlrpc.Fault, xmlrpclib.loads, result)
- d.addCallback(cb)
- return d
-
-
-class XMLRPCTestCase2(XMLRPCTestCase):
- """
- Test with proxy that doesn't add a slash.
- """
-
- def proxy(self):
- p = xmlrpc.Proxy("http://127.0.0.1:%d" % self.port)
- p.queryFactory = self.queryFactory
- return p
-
-
-
-class XMLRPCAllowNoneTestCase(unittest.TestCase):
- """
- Test with allowNone set to True.
-
- These are not meant to be exhaustive serialization tests, since
- L{xmlrpclib} does all of the actual serialization work. They are just
- meant to exercise a few codepaths to make sure we are calling into
- xmlrpclib correctly.
- """
-
- def setUp(self):
- self.p = reactor.listenTCP(
- 0, server.Site(Test(allowNone=True)), interface="127.0.0.1")
- self.port = self.p.getHost().port
-
-
- def tearDown(self):
- return self.p.stopListening()
-
-
- def proxy(self):
- return xmlrpc.Proxy("http://127.0.0.1:%d" % (self.port,),
- allowNone=True)
-
-
- def test_deferredNone(self):
- """
- Test that passing a C{None} as an argument to a remote method and
- returning a L{Deferred} which fires with C{None} properly passes
- </nil> over the network if allowNone is set to True.
- """
- d = self.proxy().callRemote('defer', None)
- d.addCallback(self.assertEquals, None)
- return d
-
-
- def test_dictWithNoneValue(self):
- """
- Test that return a C{dict} with C{None} as a value works properly.
- """
- d = self.proxy().callRemote('defer', {'a': None})
- d.addCallback(self.assertEquals, {'a': None})
- return d
-
-
-
-class XMLRPCTestAuthenticated(XMLRPCTestCase):
- """
- Test with authenticated proxy. We run this with the same inout/ouput as
- above.
- """
- user = "username"
- password = "asecret"
-
- def setUp(self):
- self.p = reactor.listenTCP(0, server.Site(TestAuthHeader()),
- interface="127.0.0.1")
- self.port = self.p.getHost().port
- self.factories = []
-
-
- def test_authInfoInURL(self):
- p = xmlrpc.Proxy("http://%s:%s@127.0.0.1:%d/" % (
- self.user, self.password, self.port))
- d = p.callRemote("authinfo")
- d.addCallback(self.assertEquals, [self.user, self.password])
- return d
-
-
- def test_explicitAuthInfo(self):
- p = xmlrpc.Proxy("http://127.0.0.1:%d/" % (
- self.port,), self.user, self.password)
- d = p.callRemote("authinfo")
- d.addCallback(self.assertEquals, [self.user, self.password])
- return d
-
-
- def test_explicitAuthInfoOverride(self):
- p = xmlrpc.Proxy("http://wrong:info@127.0.0.1:%d/" % (
- self.port,), self.user, self.password)
- d = p.callRemote("authinfo")
- d.addCallback(self.assertEquals, [self.user, self.password])
- return d
-
-
-class XMLRPCTestIntrospection(XMLRPCTestCase):
-
- def setUp(self):
- xmlrpc = Test()
- addIntrospection(xmlrpc)
- self.p = reactor.listenTCP(0, server.Site(xmlrpc),interface="127.0.0.1")
- self.port = self.p.getHost().port
- self.factories = []
-
- def test_listMethods(self):
-
- def cbMethods(meths):
- meths.sort()
- self.failUnlessEqual(
- meths,
- ['add', 'complex', 'defer', 'deferFail',
- 'deferFault', 'dict', 'fail', 'fault',
- 'pair', 'system.listMethods',
- 'system.methodHelp',
- 'system.methodSignature'])
-
- d = self.proxy().callRemote("system.listMethods")
- d.addCallback(cbMethods)
- return d
-
- def test_methodHelp(self):
- inputOutputs = [
- ("defer", "Help for defer."),
- ("fail", ""),
- ("dict", "Help for dict.")]
-
- dl = []
- for meth, expected in inputOutputs:
- d = self.proxy().callRemote("system.methodHelp", meth)
- d.addCallback(self.assertEquals, expected)
- dl.append(d)
- return defer.DeferredList(dl, fireOnOneErrback=True)
-
- def test_methodSignature(self):
- inputOutputs = [
- ("defer", ""),
- ("add", [['int', 'int', 'int'],
- ['double', 'double', 'double']]),
- ("pair", [['array', 'string', 'int']])]
-
- dl = []
- for meth, expected in inputOutputs:
- d = self.proxy().callRemote("system.methodSignature", meth)
- d.addCallback(self.assertEquals, expected)
- dl.append(d)
- return defer.DeferredList(dl, fireOnOneErrback=True)
-
-
-class XMLRPCClientErrorHandling(unittest.TestCase):
- """
- Test error handling on the xmlrpc client.
- """
- def setUp(self):
- self.resource = static.File(__file__)
- self.resource.isLeaf = True
- self.port = reactor.listenTCP(0, server.Site(self.resource),
- interface='127.0.0.1')
-
- def tearDown(self):
- return self.port.stopListening()
-
- def test_erroneousResponse(self):
- """
- Test that calling the xmlrpc client on a static http server raises
- an exception.
- """
- proxy = xmlrpc.Proxy("http://127.0.0.1:%d/" %
- (self.port.getHost().port,))
- return self.assertFailure(proxy.callRemote("someMethod"), Exception)
-
-
-
-class TestQueryFactoryParseResponse(unittest.TestCase):
- """
- Test the behaviour of L{_QueryFactory.parseResponse}.
- """
-
- def setUp(self):
- # The _QueryFactory that we are testing. We don't care about any
- # of the constructor parameters.
- self.queryFactory = _QueryFactory(
- path=None, host=None, method='POST', user=None, password=None,
- allowNone=False, args=())
- # An XML-RPC response that will parse without raising an error.
- self.goodContents = xmlrpclib.dumps(('',))
- # An 'XML-RPC response' that will raise a parsing error.
- self.badContents = 'invalid xml'
- # A dummy 'reason' to pass to clientConnectionLost. We don't care
- # what it is.
- self.reason = failure.Failure(ConnectionDone())
-
-
- def test_parseResponseCallbackSafety(self):
- """
- We can safely call L{_QueryFactory.clientConnectionLost} as a callback
- of L{_QueryFactory.parseResponse}.
- """
- d = self.queryFactory.deferred
- # The failure mode is that this callback raises an AlreadyCalled
- # error. We have to add it now so that it gets called synchronously
- # and triggers the race condition.
- d.addCallback(self.queryFactory.clientConnectionLost, self.reason)
- self.queryFactory.parseResponse(self.goodContents)
- return d
-
-
- def test_parseResponseErrbackSafety(self):
- """
- We can safely call L{_QueryFactory.clientConnectionLost} as an errback
- of L{_QueryFactory.parseResponse}.
- """
- d = self.queryFactory.deferred
- # The failure mode is that this callback raises an AlreadyCalled
- # error. We have to add it now so that it gets called synchronously
- # and triggers the race condition.
- d.addErrback(self.queryFactory.clientConnectionLost, self.reason)
- self.queryFactory.parseResponse(self.badContents)
- return d
-
-
- def test_badStatusErrbackSafety(self):
- """
- We can safely call L{_QueryFactory.clientConnectionLost} as an errback
- of L{_QueryFactory.badStatus}.
- """
- d = self.queryFactory.deferred
- # The failure mode is that this callback raises an AlreadyCalled
- # error. We have to add it now so that it gets called synchronously
- # and triggers the race condition.
- d.addErrback(self.queryFactory.clientConnectionLost, self.reason)
- self.queryFactory.badStatus('status', 'message')
- return d
diff --git a/tools/buildbot/pylibs/twisted/web/topfiles/NEWS b/tools/buildbot/pylibs/twisted/web/topfiles/NEWS
deleted file mode 100644
index 5168065a..0000000
--- a/tools/buildbot/pylibs/twisted/web/topfiles/NEWS
+++ /dev/null
@@ -1,107 +0,0 @@
-8.1.0 (2008-05-18)
-==================
-
-Fixes
------
-
- - Fixed an XMLRPC bug whereby sometimes a callRemote Deferred would
- accidentally be fired twice when a connection was lost during the handling of
- a response (#3152)
- - Fixed a bug in the "Using Twisted Web" document which prevented an example
- resource from being renderable (#3147)
- - The deprecated mktap API is no longer used (#3127)
-
-
-8.0.0 (2008-03-17)
-==================
-
-Features
---------
- - Add support to twisted.web.client.getPage for the HTTP HEAD method. (#2750)
-
-Fixes
------
- - Set content-type in xmlrpc responses to "text/xml" (#2430)
- - Add more error checking in the xmlrpc.XMLRPC render method, and enforce
- POST requests. (#2505)
- - Reject unicode input to twisted.web.client._parse to reject invalid
- unicode URLs early. (#2628)
- - Correctly re-quote URL path segments when generating an URL string to
- return from Request.prePathURL. (#2934)
- - Make twisted.web.proxy.ProxyClientFactory close the connection when
- reporting a 501 error. (#1089)
- - Fix twisted.web.proxy.ReverseProxyResource to specify the port in the
- host header if different from 80. (#1117)
- - Change twisted.web.proxy.ReverseProxyResource so that it correctly encodes
- the request URI it sends on to the server for which it is a proxy. (#3013)
- - Make "twistd web --personal" use PBServerFactory (#2681)
-
-Misc
-----
- - #1996, #2382, #2211, #2633, #2634, #2640, #2752, #238, #2905
-
-
-0.7.0 (2007-01-02)
-==================
-
-Features
---------
- - Python 2.5 is now supported (#1867)
- - twisted.web.xmlrpc now supports the <nil/> xml-rpc extension type
- in both the server and the client (#469)
-
-Fixes
------
- - Microdom and SUX now manages certain malformed XML more resiliently
- (#1984, #2225, #2298)
- - twisted.web.client.getPage can now deal with an URL of the form
- "http://example.com" (no trailing slash) (#1080)
- - The HTTP server now allows (invalid) URLs with multiple question
- marks (#1550)
- - '=' can now be in the value of a cookie (#1051)
- - Microdom now correctly handles xmlns="" (#2184)
-
-Deprecations and Removals
--------------------------
- - websetroot was removed, because it wasn't working anyway (#945)
- - woven.guard no longer supports the old twisted.cred API (#1440)
-
-Other
------
-The following changes are minor or closely related to other changes.
-
- - #1636, #1637, #1638, #1936, #1883, #447
-
-
-0.6.0 (2006-05-21)
-==================
-
-Features
---------
- - Basic auth support for the XMLRPC client (#1474).
-
-Fixes
------
- - More correct datetime parsing.
- - Efficiency improvements (#974)
- - Handle popular non-RFC compliant formats for If-Modified-Since
- headers (#976).
- - Improve support for certain buggy CGI scripts.
- - CONTENT_LENGTH is now available to CGI scripts.
- - Support for even worse HTML in microdom (#1358).
- - Trying to view a user's home page when the user doesn't have a
- ~/public_html no longer displays a traceback (#551).
- - Misc: #543, #1011, #1005, #1287, #1337, #1383, #1079, #1492, #1189,
- #737, #872.
-
-
-0.5.0
-=====
- - Client properly reports timeouts as error
- - "Socially deprecate" woven
- - Fix memory leak in _c_urlarg library
- - Stop using _c_urlarg library
- - Fix 'gzip' and 'bzip2' content-encodings
- - Escape log entries so remote user cannot corrupt the log
- - Commented out range support because it's broken
- - Fix HEAD responses without content-length
diff --git a/tools/buildbot/pylibs/twisted/web/topfiles/README b/tools/buildbot/pylibs/twisted/web/topfiles/README
deleted file mode 100644
index fb8ecc1..0000000
--- a/tools/buildbot/pylibs/twisted/web/topfiles/README
+++ /dev/null
@@ -1 +0,0 @@
-Twisted Web 8.1.0
diff --git a/tools/buildbot/pylibs/twisted/web/topfiles/setup.py b/tools/buildbot/pylibs/twisted/web/topfiles/setup.py
deleted file mode 100644
index f1450bf..0000000
--- a/tools/buildbot/pylibs/twisted/web/topfiles/setup.py
+++ /dev/null
@@ -1,28 +0,0 @@
-import sys
-
-try:
- from twisted.python import dist
-except ImportError:
- raise SystemExit("twisted.python.dist module not found. Make sure you "
- "have installed the Twisted core package before "
- "attempting to install any other Twisted projects.")
-
-if __name__ == '__main__':
- dist.setup(
- twisted_subproject="web",
- scripts=dist.getScripts("web"),
- # metadata
- name="Twisted Web",
- description="Twisted web server, programmable in Python.",
- author="Twisted Matrix Laboratories",
- author_email="twisted-python@twistedmatrix.com",
- maintainer="James Knight",
- maintainer_email="foom@fuhm.net",
- url="http://twistedmatrix.com/trac/wiki/TwistedWeb",
- license="MIT",
- long_description="""\
-Twisted Web is a complete web server, aimed at hosting web
-applications using Twisted and Python, but fully able to serve static
-pages, also.
-""",
- )
diff --git a/tools/buildbot/pylibs/twisted/web/trp.py b/tools/buildbot/pylibs/twisted/web/trp.py
deleted file mode 100644
index e2be8d6..0000000
--- a/tools/buildbot/pylibs/twisted/web/trp.py
+++ /dev/null
@@ -1,15 +0,0 @@
-
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""
-I contain ResourceUnpickler, which will unpickle any python object
-named with the file extension .trp.
-"""
-from pickle import Unpickler
-
-def ResourceUnpickler(path, registry = None):
- fl = open(path)
- result = Unpickler(fl).load()
- return result
diff --git a/tools/buildbot/pylibs/twisted/web/twcgi.py b/tools/buildbot/pylibs/twisted/web/twcgi.py
deleted file mode 100644
index 187df92..0000000
--- a/tools/buildbot/pylibs/twisted/web/twcgi.py
+++ /dev/null
@@ -1,256 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_cgi -*-
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""I hold resource classes and helper classes that deal with CGI scripts.
-"""
-
-# System Imports
-import string
-import os
-import sys
-import urllib
-
-# Twisted Imports
-from twisted.web import http
-from twisted.internet import reactor, protocol
-from twisted.spread import pb
-from twisted.python import log, filepath
-
-# Sibling Imports
-import server
-import error
-import html
-import resource
-import static
-from server import NOT_DONE_YET
-
-class CGIDirectory(resource.Resource, filepath.FilePath):
- def __init__(self, pathname):
- resource.Resource.__init__(self)
- filepath.FilePath.__init__(self, pathname)
-
- def getChild(self, path, request):
- fnp = self.child(path)
- if not fnp.exists():
- return static.File.childNotFound
- elif fnp.isdir():
- return CGIDirectory(fnp.path)
- else:
- return CGIScript(fnp.path)
- return error.NoResource()
-
- def render(self, request):
- return error.NoResource("CGI directories do not support directory listing.").render(request)
-
-class CGIScript(resource.Resource):
- """I represent a CGI script.
-
- My implementation is complex due to the fact that it requires asynchronous
- IPC with an external process with an unpleasant protocol.
- """
- isLeaf = 1
- def __init__(self, filename, registry=None):
- """Initialize, with the name of a CGI script file.
- """
- self.filename = filename
-
- def render(self, request):
- """Do various things to conform to the CGI specification.
-
- I will set up the usual slew of environment variables, then spin off a
- process.
- """
- script_name = "/"+string.join(request.prepath, '/')
- python_path = string.join(sys.path, os.pathsep)
- serverName = string.split(request.getRequestHostname(), ':')[0]
- env = {"SERVER_SOFTWARE": server.version,
- "SERVER_NAME": serverName,
- "GATEWAY_INTERFACE": "CGI/1.1",
- "SERVER_PROTOCOL": request.clientproto,
- "SERVER_PORT": str(request.getHost().port),
- "REQUEST_METHOD": request.method,
- "SCRIPT_NAME": script_name, # XXX
- "SCRIPT_FILENAME": self.filename,
- "REQUEST_URI": request.uri,
- }
-
- client = request.getClient()
- if client is not None:
- env['REMOTE_HOST'] = client
- ip = request.getClientIP()
- if ip is not None:
- env['REMOTE_ADDR'] = ip
- pp = request.postpath
- if pp:
- env["PATH_INFO"] = "/"+string.join(pp, '/')
-
- if hasattr(request, "content"):
- # request.content is either a StringIO or a TemporaryFile, and
- # the file pointer is sitting at the beginning (seek(0,0))
- request.content.seek(0,2)
- length = request.content.tell()
- request.content.seek(0,0)
- env['CONTENT_LENGTH'] = str(length)
-
- qindex = string.find(request.uri, '?')
- if qindex != -1:
- qs = env['QUERY_STRING'] = request.uri[qindex+1:]
- if '=' in qs:
- qargs = []
- else:
- qargs = [urllib.unquote(x) for x in qs.split('+')]
- else:
- env['QUERY_STRING'] = ''
- qargs = []
-
- # Propogate HTTP headers
- for title, header in request.getAllHeaders().items():
- envname = string.upper(string.replace(title, '-', '_'))
- if title not in ('content-type', 'content-length'):
- envname = "HTTP_" + envname
- env[envname] = header
- # Propogate our environment
- for key, value in os.environ.items():
- if not env.has_key(key):
- env[key] = value
- # And they're off!
- self.runProcess(env, request, qargs)
- return NOT_DONE_YET
-
- def runProcess(self, env, request, qargs=[]):
- p = CGIProcessProtocol(request)
- reactor.spawnProcess(p, self.filename, [self.filename]+qargs, env, os.path.dirname(self.filename))
-
-
-class FilteredScript(CGIScript):
- """I am a special version of a CGI script, that uses a specific executable.
-
- This is useful for interfacing with other scripting languages that adhere
- to the CGI standard (cf. PHPScript). My 'filter' attribute specifies what
- executable to run, and my 'filename' init parameter describes which script
- to pass to the first argument of that script.
- """
-
- filter = '/usr/bin/cat'
-
- def runProcess(self, env, request, qargs=[]):
- p = CGIProcessProtocol(request)
- reactor.spawnProcess(p, self.filter, [self.filter, self.filename]+qargs, env, os.path.dirname(self.filename))
-
-
-class PHP3Script(FilteredScript):
- """I am a FilteredScript that uses the default PHP3 command on most systems.
- """
-
- filter = '/usr/bin/php3'
-
-
-class PHPScript(FilteredScript):
- """I am a FilteredScript that uses the PHP command on most systems.
- Sometimes, php wants the path to itself as argv[0]. This is that time.
- """
-
- filter = '/usr/bin/php4'
-
-
-class CGIProcessProtocol(protocol.ProcessProtocol, pb.Viewable):
- handling_headers = 1
- headers_written = 0
- headertext = ''
- errortext = ''
-
- # Remotely relay producer interface.
-
- def view_resumeProducing(self, issuer):
- self.resumeProducing()
-
- def view_pauseProducing(self, issuer):
- self.pauseProducing()
-
- def view_stopProducing(self, issuer):
- self.stopProducing()
-
- def resumeProducing(self):
- self.transport.resumeProducing()
-
- def pauseProducing(self):
- self.transport.pauseProducing()
-
- def stopProducing(self):
- self.transport.loseConnection()
-
- def __init__(self, request):
- self.request = request
-
- def connectionMade(self):
- self.request.registerProducer(self, 1)
- self.request.content.seek(0, 0)
- content = self.request.content.read()
- if content:
- self.transport.write(content)
- self.transport.closeStdin()
-
- def errReceived(self, error):
- self.errortext = self.errortext + error
-
- def outReceived(self, output):
- """
- Handle a chunk of input
- """
- # First, make sure that the headers from the script are sorted
- # out (we'll want to do some parsing on these later.)
- if self.handling_headers:
- text = self.headertext + output
- headerEnds = []
- for delimiter in '\n\n','\r\n\r\n','\r\r', '\n\r\n':
- headerend = string.find(text,delimiter)
- if headerend != -1:
- headerEnds.append((headerend, delimiter))
- if headerEnds:
- headerEnds.sort()
- headerend, delimiter = headerEnds[0]
- self.headertext = text[:headerend]
- # This is a final version of the header text.
- linebreak = delimiter[:len(delimiter)/2]
- headers = string.split(self.headertext, linebreak)
- for header in headers:
- br = string.find(header,': ')
- if br == -1:
- log.msg( 'ignoring malformed CGI header: %s' % header )
- else:
- headerName = string.lower(header[:br])
- headerText = header[br+2:]
- if headerName == 'location':
- self.request.setResponseCode(http.FOUND)
- if headerName == 'status':
- try:
- statusNum = int(headerText[:3]) #"XXX <description>" sometimes happens.
- except:
- log.msg( "malformed status header" )
- else:
- self.request.setResponseCode(statusNum)
- else:
- self.request.setHeader(headerName,headerText)
- output = text[headerend+len(delimiter):]
- self.handling_headers = 0
- if self.handling_headers:
- self.headertext = text
- if not self.handling_headers:
- self.request.write(output)
-
- def processEnded(self, reason):
- if reason.value.exitCode != 0:
- log.msg("CGI %s exited with exit code %s" %
- (self.request.uri, reason.value.exitCode))
- if self.errortext:
- log.msg("Errors from CGI %s: %s" % (self.request.uri, self.errortext))
- if self.handling_headers:
- log.msg("Premature end of headers in %s: %s" % (self.request.uri, self.headertext))
- self.request.write(
- error.ErrorPage(http.INTERNAL_SERVER_ERROR,
- "CGI Script Error",
- "Premature end of script headers.").render(self.request))
- self.request.unregisterProducer()
- self.request.finish()
diff --git a/tools/buildbot/pylibs/twisted/web/util.py b/tools/buildbot/pylibs/twisted/web/util.py
deleted file mode 100644
index 0a50de6..0000000
--- a/tools/buildbot/pylibs/twisted/web/util.py
+++ /dev/null
@@ -1,390 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_web -*-
-
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-from cStringIO import StringIO
-
-from twisted.python import failure
-
-import html
-import resource
-
-
-import linecache
-import string, re
-import types
-
-
-def redirectTo(URL, request):
- request.redirect(URL)
- return """
-<html>
- <head>
- <meta http-equiv=\"refresh\" content=\"0;URL=%(url)s\">
- </head>
- <body bgcolor=\"#FFFFFF\" text=\"#000000\">
- <a href=\"%(url)s\">click here</a>
- </body>
-</html>
-""" % {'url': URL}
-
-class Redirect(resource.Resource):
-
- isLeaf = 1
-
- def __init__(self, url):
- resource.Resource.__init__(self)
- self.url = url
-
- def render(self, request):
- return redirectTo(self.url, request)
-
- def getChild(self, name, request):
- return self
-
-class ChildRedirector(Redirect):
- isLeaf = 0
- def __init__(self, url):
- # XXX is this enough?
- if ((url.find('://') == -1)
- and (not url.startswith('..'))
- and (not url.startswith('/'))):
- raise ValueError("It seems you've given me a redirect (%s) that is a child of myself! That's not good, it'll cause an infinite redirect." % url)
- Redirect.__init__(self, url)
-
- def getChild(self, name, request):
- newUrl = self.url
- if not newUrl.endswith('/'):
- newUrl += '/'
- newUrl += name
- return ChildRedirector(newUrl)
-
-
-from twisted.python import urlpath
-
-class ParentRedirect(resource.Resource):
- """
- I redirect to URLPath.here().
- """
- isLeaf = 1
- def render(self, request):
- return redirectTo(urlpath.URLPath.fromRequest(request).here(), request)
-
- def getChild(self, request):
- return self
-
-
-class DeferredResource(resource.Resource):
- """
- I wrap up a Deferred that will eventually result in a Resource
- object.
- """
- isLeaf = 1
-
- def __init__(self, d):
- resource.Resource.__init__(self)
- self.d = d
-
- def getChild(self, name, request):
- return self
-
- def render(self, request):
- self.d.addCallback(self._cbChild, request).addErrback(
- self._ebChild,request)
- from twisted.web.server import NOT_DONE_YET
- return NOT_DONE_YET
-
- def _cbChild(self, child, request):
- result = resource.getChildForRequest(child, request).render(request)
- from twisted.web.server import NOT_DONE_YET
- if result == NOT_DONE_YET:
- return
- else:
- request.write(result)
- request.finish()
-
- def _ebChild(self, reason, request):
- request.processingFailed(reason)
- return reason
-
-
-stylesheet = """
-<style type="text/css">
- p.error {
- color: red;
- font-family: Verdana, Arial, helvetica, sans-serif;
- font-weight: bold;
- }
-
- div {
- font-family: Verdana, Arial, helvetica, sans-serif;
- }
-
- div.stackTrace {
- }
-
- div.frame {
- padding: 1em;
- background: white;
- border-bottom: thin black dashed;
- }
-
- div.firstFrame {
- padding: 1em;
- background: white;
- border-top: thin black dashed;
- border-bottom: thin black dashed;
- }
-
- div.location {
- }
-
- div.snippet {
- margin-bottom: 0.5em;
- margin-left: 1em;
- background: #FFFFDD;
- }
-
- div.snippetHighlightLine {
- color: red;
- }
-
- span.code {
- font-family: "Courier New", courier, monotype;
- }
-
- span.function {
- font-weight: bold;
- font-family: "Courier New", courier, monotype;
- }
-
- table.variables {
- border-collapse: collapse;
- margin-left: 1em;
- }
-
- td.varName {
- vertical-align: top;
- font-weight: bold;
- padding-left: 0.5em;
- padding-right: 0.5em;
- }
-
- td.varValue {
- padding-left: 0.5em;
- padding-right: 0.5em;
- }
-
- div.variables {
- margin-bottom: 0.5em;
- }
-
- span.heading {
- font-weight: bold;
- }
-
- div.dict {
- background: #cccc99;
- padding: 2px;
- float: left;
- }
-
- td.dictKey {
- background: #ffff99;
- font-weight: bold;
- }
-
- td.dictValue {
- background: #ffff99;
- }
-
- div.list {
- background: #7777cc;
- padding: 2px;
- float: left;
- }
-
- div.listItem {
- background: #9999ff;
- }
-
- div.instance {
- background: #cc7777;
- padding: 2px;
- float: left;
- }
-
- span.instanceName {
- font-weight: bold;
- display: block;
- }
-
- span.instanceRepr {
- background: #ff9999;
- font-family: "Courier New", courier, monotype;
- }
-
- div.function {
- background: orange;
- font-weight: bold;
- float: left;
- }
-</style>
-"""
-
-
-def htmlrepr(x):
- return htmlReprTypes.get(type(x), htmlUnknown)(x)
-
-def saferepr(x):
- try:
- rx = repr(x)
- except:
- rx = "<repr failed! %s instance at %s>" % (x.__class__, id(x))
- return rx
-
-def htmlUnknown(x):
- return '<code>'+html.escape(saferepr(x))+'</code>'
-
-def htmlDict(d):
- io = StringIO()
- w = io.write
- w('<div class="dict"><span class="heading">Dictionary instance @ %s</span>' % hex(id(d)))
- w('<table class="dict">')
- for k, v in d.items():
-
- if k == '__builtins__':
- v = 'builtin dictionary'
- w('<tr><td class="dictKey">%s</td><td class="dictValue">%s</td></tr>' % (htmlrepr(k), htmlrepr(v)))
- w('</table></div>')
- return io.getvalue()
-
-def htmlList(l):
- io = StringIO()
- w = io.write
- w('<div class="list"><span class="heading">List instance @ %s</span>' % hex(id(l)))
- for i in l:
- w('<div class="listItem">%s</div>' % htmlrepr(i))
- w('</div>')
- return io.getvalue()
-
-def htmlInst(i):
- if hasattr(i, "__html__"):
- s = i.__html__()
- else:
- s = html.escape(saferepr(i))
- return '''<div class="instance"><span class="instanceName">%s instance @ %s</span>
- <span class="instanceRepr">%s</span></div>
- ''' % (i.__class__, hex(id(i)), s)
-
-def htmlString(s):
- return html.escape(saferepr(s))
-
-def htmlFunc(f):
- return ('<div class="function">' +
- html.escape("function %s in file %s at line %s" %
- (f.__name__, f.func_code.co_filename,
- f.func_code.co_firstlineno))+
- '</div>')
-
-htmlReprTypes = {types.DictType: htmlDict,
- types.ListType: htmlList,
- types.InstanceType: htmlInst,
- types.StringType: htmlString,
- types.FunctionType: htmlFunc}
-
-
-
-def htmlIndent(snippetLine):
- ret = string.replace(string.replace(html.escape(string.rstrip(snippetLine)),
- ' ', '&nbsp;'),
- '\t', '&nbsp; &nbsp; &nbsp; &nbsp; ')
- return ret
-
-def formatFailure(myFailure):
-
- exceptionHTML = """
-<p class="error">%s: %s</p>
-"""
-
- frameHTML = """
-<div class="location">%s, line %s in <span class="function">%s</span></div>
-"""
-
- snippetLineHTML = """
-<div class="snippetLine"><span class="lineno">%s</span><span class="code">%s</span></div>
-"""
-
- snippetHighlightLineHTML = """
-<div class="snippetHighlightLine"><span class="lineno">%s</span><span class="code">%s</span></div>
-"""
-
- variableHTML = """
-<tr class="varRow"><td class="varName">%s</td><td class="varValue">%s</td></tr>
-"""
-
- if not isinstance(myFailure, failure.Failure):
- return html.PRE(str(myFailure))
- io = StringIO()
- w = io.write
- w(stylesheet)
- w('<a href="#tbend">')
- w(exceptionHTML % (html.escape(str(myFailure.type)),
- html.escape(str(myFailure.value))))
- w('</a>')
- w('<div class="stackTrace">')
- first = 1
- for method, filename, lineno, localVars, globalVars in myFailure.frames:
- if filename == '<string>':
- continue
- if first:
- w('<div class="firstFrame">')
- first = 0
- else:
- w('<div class="frame">')
- w(frameHTML % (filename, lineno, method))
-
- w('<div class="snippet">')
- textSnippet = ''
- for snipLineNo in range(lineno-2, lineno+2):
- snipLine = linecache.getline(filename, snipLineNo)
- textSnippet += snipLine
- snipLine = htmlIndent(snipLine)
- if snipLineNo == lineno:
- w(snippetHighlightLineHTML % (snipLineNo, snipLine))
- else:
- w(snippetLineHTML % (snipLineNo, snipLine))
- w('</div>')
-
- # Instance variables
- for name, var in localVars:
- if name == 'self' and hasattr(var, '__dict__'):
- usedVars = [ (key, value) for (key, value) in var.__dict__.items()
- if re.search(r'\W'+'self.'+key+r'\W', textSnippet) ]
- if usedVars:
- w('<div class="variables"><b>Self</b>')
- w('<table class="variables">')
- for key, value in usedVars:
- w(variableHTML % (key, htmlrepr(value)))
- w('</table></div>')
- break
-
- # Local and global vars
- for nm, varList in ('Locals', localVars), ('Globals', globalVars):
- usedVars = [ (name, var) for (name, var) in varList
- if re.search(r'\W'+name+r'\W', textSnippet) ]
- if usedVars:
- w('<div class="variables"><b>%s</b><table class="variables">' % nm)
- for name, var in usedVars:
- w(variableHTML % (name, htmlrepr(var)))
- w('</table></div>')
-
- w('</div>') # frame
- w('</div>') # stacktrace
- w('<a name="tbend"> </a>')
- w(exceptionHTML % (html.escape(str(myFailure.type)),
- html.escape(str(myFailure.value))))
-
- return io.getvalue()
diff --git a/tools/buildbot/pylibs/twisted/web/vhost.py b/tools/buildbot/pylibs/twisted/web/vhost.py
deleted file mode 100644
index 433c4b3..0000000
--- a/tools/buildbot/pylibs/twisted/web/vhost.py
+++ /dev/null
@@ -1,141 +0,0 @@
-
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""I am a virtual hosts implementation.
-"""
-
-# System Imports
-import string
-
-# Twisted Imports
-from twisted.python import roots
-
-# Sibling Imports
-import resource
-import error
-
-class VirtualHostCollection(roots.Homogenous):
- """Wrapper for virtual hosts collection.
-
- This exists for configuration purposes.
- """
- entityType = resource.Resource
-
- def __init__(self, nvh):
- self.nvh = nvh
-
- def listStaticEntities(self):
- return self.nvh.hosts.items()
-
- def getStaticEntity(self, name):
- return self.nvh.hosts.get(self)
-
- def reallyPutEntity(self, name, entity):
- self.nvh.addHost(name, entity)
-
- def delEntity(self, name):
- self.nvh.removeHost(name)
-
-
-class NameVirtualHost(resource.Resource):
- """I am a resource which represents named virtual hosts.
- """
-
- default = None
-
- def __init__(self):
- """Initialize.
- """
- resource.Resource.__init__(self)
- self.hosts = {}
-
- def listStaticEntities(self):
- return resource.Resource.listStaticEntities(self) + [("Virtual Hosts", VirtualHostCollection(self))]
-
- def getStaticEntity(self, name):
- if name == "Virtual Hosts":
- return VirtualHostCollection(self)
- else:
- return resource.Resource.getStaticEntity(self, name)
-
- def addHost(self, name, resrc):
- """Add a host to this virtual host.
-
- This will take a host named `name', and map it to a resource
- `resrc'. For example, a setup for our virtual hosts would be::
-
- nvh.addHost('divunal.com', divunalDirectory)
- nvh.addHost('www.divunal.com', divunalDirectory)
- nvh.addHost('twistedmatrix.com', twistedMatrixDirectory)
- nvh.addHost('www.twistedmatrix.com', twistedMatrixDirectory)
- """
- self.hosts[name] = resrc
-
- def removeHost(self, name):
- """Remove a host."""
- del self.hosts[name]
-
- def _getResourceForRequest(self, request):
- """(Internal) Get the appropriate resource for the given host.
- """
- hostHeader = request.getHeader('host')
- if hostHeader == None:
- return self.default or error.NoResource()
- else:
- host = string.split(string.lower(hostHeader),':')[0]
- return (self.hosts.get(host, self.default)
- or error.NoResource("host %s not in vhost map" % repr(host)))
-
- def render(self, request):
- """Implementation of resource.Resource's render method.
- """
- resrc = self._getResourceForRequest(request)
- return resrc.render(request)
-
- def getChild(self, path, request):
- """Implementation of resource.Resource's getChild method.
- """
- resrc = self._getResourceForRequest(request)
- if resrc.isLeaf:
- request.postpath.insert(0,request.prepath.pop(-1))
- return resrc
- else:
- return resrc.getChildWithDefault(path, request)
-
-class _HostResource(resource.Resource):
-
- def getChild(self, path, request):
- if ':' in path:
- host, port = path.split(':', 1)
- port = int(port)
- else:
- host, port = path, 80
- request.setHost(host, port)
- prefixLen = 3+request.isSecure()+4+len(path)+len(request.prepath[-3])
- request.path = '/'+'/'.join(request.postpath)
- request.uri = request.uri[prefixLen:]
- del request.prepath[:3]
- return request.site.getResourceFor(request)
-
-
-class VHostMonsterResource(resource.Resource):
-
- """
- Use this to be able to record the hostname and method (http vs. https)
- in the URL without disturbing your web site. If you put this resource
- in a URL http://foo.com/bar then requests to
- http://foo.com/bar/http/baz.com/something will be equivalent to
- http://foo.com/something, except that the hostname the request will
- appear to be accessing will be "baz.com". So if "baz.com" is redirecting
- all requests for to foo.com, while foo.com is inaccessible from the outside,
- then redirect and url generation will work correctly
- """
- def getChild(self, path, request):
- if path == 'http':
- request.isSecure = lambda: 0
- elif path == 'https':
- request.isSecure = lambda: 1
- return _HostResource()
-
diff --git a/tools/buildbot/pylibs/twisted/web/widgets.py b/tools/buildbot/pylibs/twisted/web/widgets.py
deleted file mode 100644
index de2af70..0000000
--- a/tools/buildbot/pylibs/twisted/web/widgets.py
+++ /dev/null
@@ -1,1050 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_web -*-
-#
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""A twisted web component framework.
-
-This module is DEPRECATED.
-"""
-
-import warnings
-warnings.warn("This module is deprecated, please use Woven instead.", DeprecationWarning)
-
-# System Imports
-import string, time, types, traceback, pprint, sys, os
-import linecache
-import re
-from cStringIO import StringIO
-
-# Twisted Imports
-from twisted.python import failure, log, rebuild, reflect, util
-from twisted.internet import defer
-from twisted.web import http
-
-# Sibling Imports
-import html, resource, error
-import util as webutil
-
-#backwards compatibility
-from util import formatFailure, htmlrepr, htmlUnknown, htmlDict, htmlList,\
- htmlInst, htmlString, htmlReprTypes
-
-
-
-from server import NOT_DONE_YET
-
-True = (1==1)
-False = not True
-
-
-# magic value that sez a widget needs to take over the whole page.
-
-FORGET_IT = 99
-
-def listify(x):
- return [x]
-def _ellipsize(x):
- y = repr(x)
- if len(y) > 1024:
- return y[:1024]+"..."
- return y
-
-
-class Widget:
- """A component of a web page.
- """
- title = None
- def getTitle(self, request):
- return self.title or reflect.qual(self.__class__)
-
- def display(self, request):
- """Implement me to represent your widget.
-
- I must return a list of strings and twisted.internet.defer.Deferred
- instances.
- """
- raise NotImplementedError("%s.display" % reflect.qual(self.__class__))
-
-class StreamWidget(Widget):
- """A 'streamable' component of a webpage.
- """
-
- def stream(self, write, request):
- """Call 'write' multiple times with a string argument to represent this widget.
- """
- raise NotImplementedError("%s.stream" % reflect.qual(self.__class__))
-
- def display(self, request):
- """Produce a list containing a single string.
- """
- l = []
- try:
- result = self.stream(l.append, request)
- if result is not None:
- return result
- return l
- except:
- return [webutil.formatFailure(failure.Failure())]
-
-class WidgetMixin(Widget):
- """A mix-in wrapper for a Widget.
-
- This mixin can be used to wrap functionality in any other widget with a
- method of your choosing. It is designed to be used for mix-in classes that
- can be mixed in to Form, StreamWidget, Presentation, etc, to augment the
- data available to the 'display' methods of those classes, usually by adding
- it to a Session.
- """
-
- def display(self):
- raise NotImplementedError("%s.display" % self.__class__)
-
- def displayMixedWidget(self, request):
- for base in reflect.allYourBase(self.__class__):
- if issubclass(base, Widget) and not issubclass(base, WidgetMixin):
- return base.display(self, request)
-
-class Presentation(Widget):
- """I am a widget which formats a template with interspersed python expressions.
- """
- template = '''
- Hello, %%%%world%%%%.
- '''
- world = "you didn't assign to the 'template' attribute"
- def __init__(self, template=None, filename=None):
- if filename:
- self.template = open(filename).read()
- elif template:
- self.template = template
- self.variables = {}
- self.tmpl = string.split(self.template, "%%%%")
-
- def addClassVars(self, namespace, Class):
- for base in Class.__bases__:
- # Traverse only superclasses that know about Presentation.
- if issubclass(base, Presentation) and base is not Presentation:
- self.addClassVars(namespace, base)
- # 'lower' classes in the class heirarchy take precedence.
- for k in Class.__dict__.keys():
- namespace[k] = getattr(self, k)
-
- def addVariables(self, namespace, request):
- self.addClassVars(namespace, self.__class__)
-
- def prePresent(self, request):
- """Perform any tasks which must be done before presenting the page.
- """
-
- def formatTraceback(self, tb):
- return [html.PRE(tb)]
-
- def streamCall(self, call, *args, **kw):
- """Utility: Call a method like StreamWidget's 'stream'.
- """
- io = StringIO()
- apply(call, (io.write,) + args, kw)
- return io.getvalue()
-
- def display(self, request):
- tm = []
- flip = 0
- namespace = {}
- self.prePresent(request)
- self.addVariables(namespace, request)
- # This variable may not be obscured...
- namespace['request'] = request
- namespace['self'] = self
- for elem in self.tmpl:
- flip = not flip
- if flip:
- if elem:
- tm.append(elem)
- else:
- try:
- x = eval(elem, namespace, namespace)
- except:
- log.deferr()
- tm.append(webutil.formatFailure(failure.Failure()))
- else:
- if isinstance(x, types.ListType):
- tm.extend(x)
- elif isinstance(x, Widget):
- val = x.display(request)
- if not isinstance(val, types.ListType):
- raise Exception("%s.display did not return a list, it returned %s!" % (x.__class__, repr(val)))
- tm.extend(val)
- else:
- # Only two allowed types here should be deferred and
- # string.
- tm.append(x)
- return tm
-
-
-def htmlFor_hidden(write, name, value):
- write('<INPUT TYPE="hidden" NAME="%s" VALUE="%s" />' % (name, value))
-
-def htmlFor_file(write, name, value):
- write('<INPUT SIZE="60" TYPE="file" NAME="%s" />' % name)
-
-def htmlFor_string(write, name, value):
- write('<INPUT SIZE="60" TYPE="text" NAME="%s" VALUE="%s" />' % (name, value))
-
-def htmlFor_password(write, name, value):
- write('<INPUT SIZE="60" TYPE="password" NAME="%s" />' % name)
-
-def htmlFor_text(write, name, value):
- write('<textarea COLS="60" ROWS="10" NAME="%s" WRAP="virtual">%s</textarea>' % (name, value))
-
-def htmlFor_menu(write, name, value, allowMultiple=False):
- "Value of the format [(optionName, displayName[, selected]), ...]"
-
- write(' <select NAME="%s"%s>\n' %
- (name, (allowMultiple and " multiple") or ''))
-
- for v in value:
- optionName, displayName, selected = util.padTo(3, v)
- selected = (selected and " selected") or ''
- write(' <option VALUE="%s"%s>%s</option>\n' %
- (optionName, selected, displayName))
- if not value:
- write(' <option VALUE=""></option>\n')
- write(" </select>\n")
-
-def htmlFor_multimenu(write, name, value):
- "Value of the format [(optionName, displayName[, selected]), ...]"
- return htmlFor_menu(write, name, value, True)
-
-def htmlFor_checkbox(write, name, value):
- "A checkbox."
- if value:
- value = 'checked = "1"'
- else:
- value = ''
- write('<INPUT TYPE="checkbox" NAME="__checkboxes__" VALUE="%s" %s />\n' % (name, value))
-
-def htmlFor_checkgroup(write, name, value):
- "A check-group."
- for optionName, displayName, checked in value:
- checked = (checked and 'checked = "1"') or ''
- write('<INPUT TYPE="checkbox" NAME="%s" VALUE="%s" %s />%s<br />\n' % (name, optionName, checked, displayName))
-
-def htmlFor_radio(write, name, value):
- "A radio button group."
- for optionName, displayName, checked in value:
- checked = (checked and 'checked = "1"') or ''
- write('<INPUT TYPE="radio" NAME="%s" VALUE="%s" %s />%s<br />\n' % (name, optionName, checked, displayName))
-
-class FormInputError(Exception):
- pass
-
-class Form(Widget):
- """I am a web form.
-
- In order to use me, you probably want to set self.formFields (or override
- 'getFormFields') and override 'process'. In order to demonstrate how this
- is done, here is a small sample Form subclass::
-
- | from twisted.web import widgets
- | class HelloForm(widgets.Form):
- | formFields = [
- | ['string', 'Who to greet?', 'whoToGreet', 'World',
- | 'This is for choosing who to greet.'],
- | ['menu', 'How to greet?', 'how', [('cheerfully', 'with a smile'),
- | ('sullenly', 'without enthusiasm'),
- | ('spontaneously', 'on the spur of the moment')]]
- | 'This is for choosing how to greet them.']
- | def process(self, write, request, submit, whoToGreet, how):
- | write('The web wakes up and %s says, \"Hello, %s!\"' % (how, whoToGreet))
-
- If you load this widget, you will see that it displays a form with 2 inputs
- derived from data in formFields. Note the argument names to 'process':
- after 'write' and 'request', they are the same as the 3rd elements ('Input
- Name' parameters) of the formFields list.
- """
-
- formGen = {
- 'hidden': htmlFor_hidden,
- 'file': htmlFor_file,
- 'string': htmlFor_string,
- 'int': htmlFor_string,
- 'float': htmlFor_string,
- 'text': htmlFor_text,
- 'menu': htmlFor_menu,
- 'multimenu': htmlFor_multimenu,
- 'password': htmlFor_password,
- 'checkbox': htmlFor_checkbox,
- 'checkgroup': htmlFor_checkgroup,
- 'radio': htmlFor_radio,
- }
-
- formParse = {
- 'int': int,
- 'float': float,
- }
-
- formFields = [
- ]
-
- # do we raise an error when we get extra args or not?
- formAcceptExtraArgs = 0
-
- def getFormFields(self, request, fieldSet = None):
- """I return a list of lists describing this form, or a Deferred.
-
- This information is used both to display the form and to process it.
- The list is in the following format::
-
- | [['Input Type', 'Display Name', 'Input Name', 'Input Value', 'Description'],
- | ['Input Type 2', 'Display Name 2', 'Input Name 2', 'Input Value 2', 'Description 2']
- | ...]
-
- Valid values for 'Input Type' are:
-
- - 'hidden': a hidden field that contains a string that the user won't change
-
- - 'string': a short string
-
- - 'int': an integer, e.g. 1, 0, 25 or -23
-
- - 'float': a float, e.g. 1.0, 2, -3.45, or 28.4324231
-
- - 'text': a longer text field, suitable for entering paragraphs
-
- - 'menu': an HTML SELECT input, a list of choices
-
- - 'multimenu': an HTML SELECT input allowing multiple choices
-
- - 'checkgroup': a group of checkboxes
-
- - 'radio': a group of radio buttons
-
- - 'password': a 'string' field where the contents are not visible as the user types
-
- - 'file': a file-upload form (EXPERIMENTAL)
-
- 'Display Name' is a descriptive string that will be used to
- identify the field to the user.
-
- The 'Input Name' must be a legal Python identifier that describes both
- the value's name on the HTML form and the name of an argument to
- 'self.process()'.
-
- The 'Input Value' is usually a string, but its value can depend on the
- 'Input Type'. 'int' it is an integer, 'menu' it is a list of pairs of
- strings, representing (value, name) pairs for the menu options. Input
- value for 'checkgroup' and 'radio' should be a list of ('inputName',
- 'Display Name', 'checked') triplets.
-
- The 'Description' field is an (optional) string which describes the form
- item to the user.
-
- If this result is statically determined for your Form subclass, you can
- assign it to FormSubclass.formFields; if you need to determine it
- dynamically, you can override this method.
-
- Note: In many cases it is desirable to use user input for defaults in
- the form rather than those supplied by your calculations, which is what
- this method will do to self.formFields. If this is the case for you,
- but you still need to dynamically calculate some fields, pass your
- results back through this method by doing::
-
- | def getFormFields(self, request):
- | myFormFields = [self.myFieldCalculator()]
- | return widgets.Form.getFormFields(self, request, myFormFields)
-
- """
- fields = []
- if fieldSet is None:
- fieldSet = self.formFields
- if not self.shouldProcess(request):
- return fieldSet
-
- for field in fieldSet:
- if len(field)==5:
- inputType, displayName, inputName, inputValue, description = field
- else:
- inputType, displayName, inputName, inputValue = field
- description = ""
-
- if inputType == 'checkbox':
- if request.args.has_key('__checkboxes__'):
- if inputName in request.args['__checkboxes__']:
- inputValue = 1
- else:
- inputValue = 0
- else:
- inputValue = 0
- elif inputType in ('checkgroup', 'radio'):
- if request.args.has_key(inputName):
- keys = request.args[inputName]
- else:
- keys = []
- iv = inputValue
- inputValue = []
- for optionName, optionDisplayName, checked in iv:
- checked = optionName in keys
- inputValue.append([optionName, optionDisplayName, checked])
- elif request.args.has_key(inputName):
- iv = request.args[inputName][0]
- if inputType in ['menu', 'multimenu']:
- if iv in inputValue:
- inputValue.remove(iv)
- inputValue.insert(0, iv)
- else:
- inputValue = iv
- fields.append([inputType, displayName, inputName, inputValue, description])
- return fields
-
- submitNames = ['Submit']
- actionURI = ''
-
- def format(self, form, write, request):
- """I display an HTML FORM according to the result of self.getFormFields.
- """
- write('<form ENCTYPE="multipart/form-data" METHOD="post" ACTION="%s">\n'
- '<table BORDER="0">\n' % (self.actionURI or request.uri))
-
- for field in form:
- if len(field) == 5:
- inputType, displayName, inputName, inputValue, description = field
- else:
- inputType, displayName, inputName, inputValue = field
- description = ""
- write('<tr>\n<td ALIGN="right" VALIGN="top"><B>%s</B></td>\n'
- '<td VALIGN="%s">\n' %
- (displayName, ((inputType == 'text') and 'top') or 'middle'))
- self.formGen[inputType](write, inputName, inputValue)
- write('\n<br />\n<font size="-1">%s</font></td>\n</tr>\n' % description)
-
-
- write('<tr><td></td><td ALIGN="left"><hr />\n')
- for submitName in self.submitNames:
- write('<INPUT TYPE="submit" NAME="submit" VALUE="%s" />\n' % submitName)
- write('</td></tr>\n</table>\n'
- '<INPUT TYPE="hidden" NAME="__formtype__" VALUE="%s" />\n'
- % (reflect.qual(self.__class__)))
- fid = self.getFormID()
- if fid:
- write('<INPUT TYPE="hidden" NAME="__formid__" VALUE="%s" />\n' % fid)
- write("</form>\n")
-
- def getFormID(self):
- """Override me: I disambiguate between multiple forms of the same type.
-
- In order to determine which form an HTTP POST request is for, you must
- have some unique identifier which distinguishes your form from other
- forms of the same class. An example of such a unique identifier would
- be: on a page with multiple FrobConf forms, each FrobConf form refers
- to a particular Frobnitz instance, which has a unique id(). The
- FrobConf form's getFormID would probably look like this::
-
- | def getFormID(self):
- | return str(id(self.frobnitz))
-
- By default, this method will return None, since distinct Form instances
- may be identical as far as the application is concerned.
- """
-
- def process(self, write, request, submit, **kw):
- """Override me: I process a form.
-
- I will only be called when the correct form input data to process this
- form has been received.
-
- I take a variable number of arguments, beginning with 'write',
- 'request', and 'submit'. 'write' is a callable object that will append
- a string to the response, 'request' is a twisted.web.request.Request
- instance, and 'submit' is the name of the submit action taken.
-
- The remainder of my arguments must be correctly named. They will each be named after one of the
-
- """
- write("<pre>Submit: %s <br /> %s</pre>" % (submit, html.PRE(pprint.PrettyPrinter().pformat(kw))))
-
- def _doProcess(self, form, write, request):
- """(internal) Prepare arguments for self.process.
- """
- args = request.args.copy()
- kw = {}
- for field in form:
- inputType, displayName, inputName, inputValue = field[:4]
- if inputType == 'checkbox':
- if request.args.has_key('__checkboxes__'):
- if inputName in request.args['__checkboxes__']:
- formData = 1
- else:
- formData = 0
- else:
- formData = 0
- elif inputType in ['checkgroup', 'radio', 'multimenu']:
- if args.has_key(inputName):
- formData = args[inputName]
- del args[inputName]
- else:
- formData = []
- else:
- if not args.has_key(inputName):
- raise FormInputError("missing field %s." % repr(inputName))
- formData = args[inputName]
- del args[inputName]
- if not len(formData) == 1:
- raise FormInputError("multiple values for field %s." %repr(inputName))
- formData = formData[0]
- method = self.formParse.get(inputType)
- if method:
- try:
- formData = method(formData)
- except:
- raise FormInputError("%s: %s" % (displayName, "error"))
- kw[inputName] = formData
- submitAction = args.get('submit')
- if submitAction:
- submitAction = submitAction[0]
- for field in ['submit', '__formtype__', '__checkboxes__']:
- if args.has_key(field):
- del args[field]
- if args and not self.formAcceptExtraArgs:
- raise FormInputError("unknown fields: %s" % repr(args))
- return apply(self.process, (write, request, submitAction), kw)
-
- def formatError(self,error):
- """Format an error message.
-
- By default, this will make the message appear in red, bold italics.
- """
- return '<font color="#f00"><b><i>%s</i></b></font><br />\n' % error
-
- def shouldProcess(self, request):
- args = request.args
- fid = self.getFormID()
- return (args and # there are arguments to the request
- args.has_key('__formtype__') and # this is a widgets.Form request
- args['__formtype__'][0] == reflect.qual(self.__class__) and # it is for a form of my type
- ((not fid) or # I am only allowed one form per page
- (args.has_key('__formid__') and # if I distinguish myself from others, the request must too
- args['__formid__'][0] == fid))) # I am in fact the same
-
- def tryAgain(self, err, req):
- """Utility method for re-drawing the form with an error message.
-
- This is handy in forms that process Deferred results. Normally you can
- just raise a FormInputError() and this will happen by default.
-
- """
- l = []
- w = l.append
- w(self.formatError(err))
- self.format(self.getFormFields(req), w, req)
- return l
-
- def display(self, request):
- """Display the form."""
- form = self.getFormFields(request)
- if isinstance(form, defer.Deferred):
- if self.shouldProcess(request):
- form.addCallback(lambda form, f=self._displayProcess, r=request: f(r, form))
- else:
- form.addCallback(lambda form, f=self._displayFormat, r=request: f(r, form))
- return [form]
- else:
- if self.shouldProcess(request):
- return self._displayProcess(request, form)
- else:
- return self._displayFormat(request, form)
-
- def _displayProcess(self, request, form):
- l = []
- write = l.append
- try:
- val = self._doProcess(form, write, request)
- if val:
- l.extend(val)
- except FormInputError, fie:
- write(self.formatError(str(fie)))
- return l
-
- def _displayFormat(self, request, form):
- l = []
- self.format(form, l.append, request)
- return l
-
-
-
-class DataWidget(Widget):
- def __init__(self, data):
- self.data = data
- def display(self, request):
- return [self.data]
-
-class Time(Widget):
- def display(self, request):
- return [time.ctime(time.time())]
-
-class Container(Widget):
- def __init__(self, *widgets):
- self.widgets = widgets
-
- def display(self, request):
- value = []
- for widget in self.widgets:
- d = widget.display(request)
- value.extend(d)
- return value
-
-class _RequestDeferral:
- def __init__(self):
- self.deferred = defer.Deferred()
- self.io = StringIO()
- self.write = self.io.write
-
- def finish(self):
- self.deferred.callback([self.io.getvalue()])
-
-def possiblyDeferWidget(widget, request):
- # web in my head get it out get it out
- try:
- disp = widget.display(request)
- # if this widget wants to defer anything -- well, I guess we've got to
- # defer it.
- for elem in disp:
- if isinstance(elem, defer.Deferred):
- req = _RequestDeferral()
- RenderSession(disp, req)
- return req.deferred
- return string.join(disp, '')
- except:
- io = StringIO()
- traceback.print_exc(file=io)
- return html.PRE(io.getvalue())
-
-class RenderSession:
- """I handle rendering of a list of deferreds, outputting their
- results in correct order."""
-
- class Sentinel:
- pass
-
- def __init__(self, lst, request):
- self.lst = lst
- self.request = request
- self.needsHeaders = 0
- self.beforeBody = 1
- self.forgotten = 0
- self.pauseList = []
- for i in range(len(self.lst)):
- item = self.lst[i]
- if isinstance(item, defer.Deferred):
- self._addDeferred(item, self.lst, i)
- self.keepRendering()
-
- def _addDeferred(self, deferred, lst, idx):
- sentinel = self.Sentinel()
- if hasattr(deferred, 'needsHeader'):
- # You might want to set a header from a deferred, in which
- # case you have to set an attribute -- needsHeader.
- self.needsHeaders = self.needsHeaders + 1
- args = (sentinel, 1)
- else:
- args = (sentinel, 0)
- lst[idx] = sentinel, deferred
- deferred.pause()
- self.pauseList.append(deferred)
- deferred.addCallbacks(self.callback, self.callback,
- callbackArgs=args, errbackArgs=args)
-
-
- def callback(self, result, sentinel, decNeedsHeaders):
- if self.forgotten:
- return
- if result != FORGET_IT:
- self.needsHeaders = self.needsHeaders - decNeedsHeaders
- else:
- result = [FORGET_IT]
-
- # Make sure result is a sequence,
- if not type(result) in (types.ListType, types.TupleType):
- result = [result]
-
- # If the deferred does not wish to produce its result all at
- # once, it can give us a partial result as
- # (NOT_DONE_YET, partial_result)
- ## XXX: How would a deferred go about producing the result in multiple
- ## stages?? --glyph
- if result[0] is NOT_DONE_YET:
- done = 0
- result = result[1]
- if not type(result) in (types.ListType, types.TupleType):
- result = [result]
- else:
- done = 1
-
- for i in xrange(len(result)):
- item = result[i]
- if isinstance(item, defer.Deferred):
- self._addDeferred(item, result, i)
-
- for position in range(len(self.lst)):
- item = self.lst[position]
- if type(item) is types.TupleType and len(item) > 0:
- if item[0] is sentinel:
- break
- else:
- raise AssertionError('Sentinel for Deferred not found!')
-
- if done:
- self.lst[position:position+1] = result
- else:
- self.lst[position:position] = result
-
- self.keepRendering()
-
-
- def keepRendering(self):
- while self.pauseList:
- pl = self.pauseList
- self.pauseList = []
- for deferred in pl:
- deferred.unpause()
- return
-
- if self.needsHeaders:
- # short circuit actual rendering process until we're sure no
- # more deferreds need to set headers...
- return
-
- assert self.lst is not None, "This shouldn't happen."
- while 1:
- item = self.lst[0]
- if self.beforeBody and FORGET_IT in self.lst:
- # If I haven't moved yet, and the widget wants to take
- # over the page, let it do so!
- self.forgotten = 1
- return
-
- if isinstance(item, types.StringType):
- self.beforeBody = 0
- self.request.write(item)
- elif type(item) is types.TupleType and len(item) > 0:
- if isinstance(item[0], self.Sentinel):
- return
- elif isinstance(item, failure.Failure):
- self.request.write(webutil.formatFailure(item))
- else:
- self.beforeBody = 0
- unknown = html.PRE(repr(item))
- self.request.write("RENDERING UNKNOWN: %s" % unknown)
-
- del self.lst[0]
- if len(self.lst) == 0:
- self.lst = None
- self.request.finish()
- return
-
-
-## XXX: is this needed?
-class WidgetResource(resource.Resource):
- def __init__(self, widget):
- self.widget = widget
- resource.Resource.__init__(self)
-
- def render(self, request):
- RenderSession(self.widget.display(request), request)
- return NOT_DONE_YET
-
-
-class Page(resource.Resource, Presentation):
-
- def __init__(self):
- resource.Resource.__init__(self)
- Presentation.__init__(self)
-
- def render(self, request):
- displayed = self.display(request)
- RenderSession(displayed, request)
- return NOT_DONE_YET
-
-
-class WidgetPage(Page):
- """
- I am a Page that takes a Widget in its constructor, and displays that
- Widget wrapped up in a simple HTML template.
- """
- stylesheet = '''
- a
- {
- font-family: Lucida, Verdana, Helvetica, Arial, sans-serif;
- color: #369;
- text-decoration: none;
- }
-
- th
- {
- font-family: Lucida, Verdana, Helvetica, Arial, sans-serif;
- font-weight: bold;
- text-decoration: none;
- text-align: left;
- }
-
- pre, code
- {
- font-family: "Courier New", Courier, monospace;
- }
-
- p, body, td, ol, ul, menu, blockquote, div
- {
- font-family: Lucida, Verdana, Helvetica, Arial, sans-serif;
- color: #000;
- }
- '''
-
- template = '''<html>
- <head>
- <title>%%%%self.title%%%%</title>
- <style>
- %%%%self.stylesheet%%%%
- </style>
- <base href="%%%%request.prePathURL()%%%%">
- </head>
-
- <body>
- <h1>%%%%self.title%%%%</h1>
- %%%%self.widget%%%%
- </body>
- </html>
- '''
-
- title = 'No Title'
- widget = 'No Widget'
-
- def __init__(self, widget):
- Page.__init__(self)
- self.widget = widget
- if hasattr(widget, 'stylesheet'):
- self.stylesheet = widget.stylesheet
-
- def prePresent(self, request):
- self.title = self.widget.getTitle(request)
-
- def render(self, request):
- displayed = self.display(request)
- RenderSession(displayed, request)
- return NOT_DONE_YET
-
-class Gadget(resource.Resource):
- """I am a collection of Widgets, to be rendered through a Page Factory.
- self.pageFactory should be a Resource that takes a Widget in its
- constructor. The default is twisted.web.widgets.WidgetPage.
- """
-
- isLeaf = 0
-
- def __init__(self):
- resource.Resource.__init__(self)
- self.widgets = {}
- self.files = []
- self.modules = []
- self.paths = {}
-
- def render(self, request):
- #Redirect to view this entity as a collection.
- request.setResponseCode(http.FOUND)
- # TODO who says it's not https?
- request.setHeader("location","http%s://%s%s/" % (
- request.isSecure() and 's' or '',
- request.getHeader("host"),
- (string.split(request.uri,'?')[0])))
- return "NO DICE!"
-
- def putWidget(self, path, widget):
- """
- Gadget.putWidget(path, widget)
- Add a Widget to this Gadget. It will be rendered through the
- pageFactory associated with this Gadget, whenever 'path' is requested.
- """
- self.widgets[path] = widget
-
- #this is an obsolete function
- def addFile(self, path):
- """
- Gadget.addFile(path)
- Add a static path to this Gadget. This method is obsolete, use
- Gadget.putPath instead.
- """
-
- log.msg("Gadget.addFile() is deprecated.")
- self.paths[path] = path
-
- def putPath(self, path, pathname):
- """
- Gadget.putPath(path, pathname)
- Add a static path to this Gadget. Whenever 'path' is requested,
- twisted.web.static.File(pathname) is sent.
- """
- self.paths[path] = pathname
-
- def getWidget(self, path, request):
- return self.widgets.get(path)
-
- def pageFactory(self, *args, **kwargs):
- """
- Gadget.pageFactory(*args, **kwargs) -> Resource
- By default, this method returns self.page(*args, **kwargs). It
- is only for backwards-compatibility -- you should set the 'pageFactory'
- attribute on your Gadget inside of its __init__ method.
- """
- #XXX: delete this after a while.
- if hasattr(self, "page"):
- log.msg("Gadget.page is deprecated, use Gadget.pageFactory instead")
- return apply(self.page, args, kwargs)
- else:
- return apply(WidgetPage, args, kwargs)
-
- def getChild(self, path, request):
- if path == '':
- # ZOOP!
- if isinstance(self, Widget):
- return self.pageFactory(self)
- widget = self.getWidget(path, request)
- if widget:
- if isinstance(widget, resource.Resource):
- return widget
- else:
- p = self.pageFactory(widget)
- p.isLeaf = getattr(widget,'isLeaf',0)
- return p
- elif self.paths.has_key(path):
- prefix = getattr(sys.modules[self.__module__], '__file__', '')
- if prefix:
- prefix = os.path.abspath(os.path.dirname(prefix))
- return static.File(os.path.join(prefix, self.paths[path]))
-
- elif path == '__reload__':
- return self.pageFactory(Reloader(map(reflect.namedModule, [self.__module__] + self.modules)))
- else:
- return error.NoResource("No such child resource in gadget.")
-
-
-class TitleBox(Presentation):
-
- template = '''\
-<table %%%%self.widthOption%%%% cellpadding="1" cellspacing="0" border="0"><tr>\
-<td bgcolor="%%%%self.borderColor%%%%"><center><font color="%%%%self.titleTextColor%%%%">%%%%self.title%%%%</font></center>\
-<table width="100%" cellpadding="3" cellspacing="0" border="0"><tr>\
-<td bgcolor="%%%%self.boxColor%%%%"><font color="%%%%self.boxTextColor%%%%">%%%%self.widget%%%%</font></td>\
-</tr></table></td></tr></table>\
-'''
-
- borderColor = '#000000'
- titleTextColor = '#ffffff'
- boxTextColor = '#000000'
- boxColor = '#ffffff'
- widthOption = 'width="100%"'
-
- title = 'No Title'
- widget = 'No Widget'
-
- def __init__(self, title, widget):
- """Wrap a widget with a given title.
- """
- self.widget = widget
- self.title = title
- Presentation.__init__(self)
-
-
-class Reloader(Presentation):
- template = '''
- Reloading...
- <ul>
- %%%%reload(request)%%%%
- </ul> ... reloaded!
- '''
- def __init__(self, modules):
- Presentation.__init__(self)
- self.modules = modules
-
- def reload(self, request):
- request.redirect("..")
- x = []
- write = x.append
- for module in self.modules:
- rebuild.rebuild(module)
- write('<li>reloaded %s<br />' % module.__name__)
- return x
-
-class Sidebar(StreamWidget):
- bar = [
- ['Twisted',
- ['mirror', 'http://coopweb.org/ssd/twisted/'],
- ['mailing list', 'cgi-bin/mailman/listinfo/twisted-python']
- ]
- ]
-
- headingColor = 'ffffff'
- headingTextColor = '000000'
- activeHeadingColor = '000000'
- activeHeadingTextColor = 'ffffff'
- sectionColor = '000088'
- sectionTextColor = '008888'
- activeSectionColor = '0000ff'
- activeSectionTextColor = '00ffff'
-
- def __init__(self, highlightHeading, highlightSection):
- self.highlightHeading = highlightHeading
- self.highlightSection = highlightSection
-
- def getList(self):
- return self.bar
-
- def stream(self, write, request):
- write("<table width=120 cellspacing=1 cellpadding=1 border=0>")
- for each in self.getList():
- if each[0] == self.highlightHeading:
- headingColor = self.activeHeadingColor
- headingTextColor = self.activeHeadingTextColor
- canHighlight = 1
- else:
- headingColor = self.headingColor
- headingTextColor = self.headingTextColor
- canHighlight = 0
- write('<tr><td colspan=2 bgcolor="#%s"><font color="%s">'
- '<strong>%s</strong>'
- '</font></td></td></tr>\n' % (headingColor, headingTextColor, each[0]))
- for name, link in each[1:]:
- if canHighlight and (name == self.highlightSection):
- sectionColor = self.activeSectionColor
- sectionTextColor = self.activeSectionTextColor
- else:
- sectionColor = self.sectionColor
- sectionTextColor = self.sectionTextColor
- write('<tr><td align=right bgcolor="#%s" width=6>-</td>'
- '<td bgcolor="#%s"><a href="%s"><font color="#%s">%s'
- '</font></a></td></tr>'
- % (sectionColor, sectionColor, request.sibLink(link), sectionTextColor, name))
- write("</table>")
-
-# moved from template.py
-from twisted.web.woven import template
-from twisted.python import components
-
-class WebWidgetNodeMutator(template.NodeMutator):
- """A WebWidgetNodeMutator replaces the node that is passed in to generate
- with the result of generating the twisted.web.widget instance it adapts.
- """
- def generate(self, request, node):
- widget = self.data
- displayed = widget.display(request)
- try:
- html = string.join(displayed)
- except:
- pr = Presentation()
- pr.tmpl = displayed
- #strList = pr.display(request)
- html = string.join(displayed)
- stringMutator = template.StringNodeMutator(html)
- return stringMutator.generate(request, node)
-
-components.registerAdapter(WebWidgetNodeMutator, Widget, template.INodeMutator)
-
-import static
diff --git a/tools/buildbot/pylibs/twisted/web/woven/FlashConduit.fla b/tools/buildbot/pylibs/twisted/web/woven/FlashConduit.fla
deleted file mode 100644
index 7406364..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/FlashConduit.fla
+++ /dev/null
Binary files differ
diff --git a/tools/buildbot/pylibs/twisted/web/woven/FlashConduit.swf b/tools/buildbot/pylibs/twisted/web/woven/FlashConduit.swf
deleted file mode 100644
index 6e0c6cd..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/FlashConduit.swf
+++ /dev/null
Binary files differ
diff --git a/tools/buildbot/pylibs/twisted/web/woven/FlashConduitGlue.html b/tools/buildbot/pylibs/twisted/web/woven/FlashConduitGlue.html
deleted file mode 100644
index 1dc6367..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/FlashConduitGlue.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<div>
- <script language="javascript" src="WebConduit2_js">
- .
- </script>
- <iframe style="width: 0; height: 0" id="woven_inputConduit" src="input_html">
- .
- </iframe>
-<!-- <iframe style="width: 100%" id="woven_outputConduit" src="?woven_hookupOutputConduitToThisFrame=1">
- </iframe>-->
-<OBJECT classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
- codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0"
- WIDTH="0" HEIGHT="0" id="FlashConduit_swf" ALIGN="">
- <PARAM NAME="movie" value="FlashConduit_swf" view="woven_flashConduitSessionView" />
- <PARAM NAME="quality" VALUE="high" />
- <PARAM NAME="bgcolor" VALUE="#FFFFFF" />
- <EMBED view="woven_flashConduitSessionView" src="FlashConduit_swf" name="FlashConduit_swf" swLiveConnect="true"
- quality="high" bgcolor="#FFFFFF" WIDTH="0" HEIGHT="0" NAME="FlashConduit_swf" ALIGN=""
- TYPE="application/x-shockwave-flash" PLUGINSPAGE="http://www.macromedia.com/go/getflashplayer">
- <!-- if neither object nor embed works, this should... -->
-<!-- <iframe style="width: 100%" id="woven_outputConduit" src="?woven_hookupOutputConduitToThisFrame=1">
- </iframe>
--->
- </EMBED>
-</OBJECT>
-</div>
diff --git a/tools/buildbot/pylibs/twisted/web/woven/WebConduit2_mozilla.js b/tools/buildbot/pylibs/twisted/web/woven/WebConduit2_mozilla.js
deleted file mode 100644
index 97dc118..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/WebConduit2_mozilla.js
+++ /dev/null
@@ -1,82 +0,0 @@
-var woven_eventQueue = []
-woven_eventQueueBusy = 0
-woven_clientSideEventNum = 0
-woven_requestingEvent = 0
-
-function woven_eventHandler(eventName, node) {
- var eventTarget = node.getAttribute('id')
- var additionalArguments = ''
- for (i = 2; i<arguments.length; i++) {
- additionalArguments += '&woven_clientSideEventArguments='
- additionalArguments += escape(eval(arguments[i]))
- }
- var source = '?woven_clientSideEventName=' + eventName + '&woven_clientSideEventTarget=' + eventTarget + additionalArguments + '&woven_clientSideEventNum=' + woven_clientSideEventNum
- woven_clientSideEventNum += 1
-
- woven_eventQueue.unshift(source)
- if (!woven_eventQueueBusy) {
- woven_sendTopEvent()
- }
- return false
-}
-
-function woven_sendTopEvent() {
- woven_eventQueueBusy = 1
- var url = woven_eventQueue.shift()
- var input = document.getElementById('woven_inputConduit')
-
- input.src = url
-}
-
-function woven_requestNextEvent() {
- var output = document.getElementById('woven_outputConduit')
-
- if (output) { output.src = '?woven_hookupOutputConduitToThisFrame=1&woven_clientSideEventNum=' + woven_clientSideEventNum.toString()}
-}
-
-function woven_clientToServerEventComplete() {
- woven_requestNextEvent()
-
- if (woven_eventQueue.length) {
- woven_sendTopEvent()
- } else {
- woven_eventQueueBusy = 0
- }
- var focus = document.getElementById('woven_firstResponder')
- focus.focus()
-}
-
-function woven_attemptFocus(theNode) {
- // focus the first input element in the new node
- if (theNode.tagName == 'INPUT') {
- theNode.focus()
- return 1
- } else {
-/* for (i=0; i<theNode.childNodes.length; i++) { */
-/* if(woven_attemptFocus(theNode.childNodes[i])) { */
-/* return 1 */
-/* } */
-/* } */
- return 0
- }
-}
-
-function woven_replaceElement(theId, htmlStr) {
-
- var oldNode = document.getElementById(theId)
- var newNode = document.createElement('span')
- newNode.innerHTML = htmlStr
- oldNode.parentNode.replaceChild(newNode.firstChild, oldNode)
- //woven_attemptFocus(newNode)
- woven_requestNextEvent()
- //alert('blah')
-}
-
-function woven_appendChild(theId, htmlStr) {
- woven_requestNextEvent()
-
- var container = document.getElementById(theId)
- var newNode = document.createElement('span')
- newNode.innerHTML = htmlStr
- container.appendChild(newNode.firstChild)
-}
diff --git a/tools/buildbot/pylibs/twisted/web/woven/WebConduit2_msie.js b/tools/buildbot/pylibs/twisted/web/woven/WebConduit2_msie.js
deleted file mode 100644
index 9d281bb..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/WebConduit2_msie.js
+++ /dev/null
@@ -1,105 +0,0 @@
-var InternetExplorer = navigator.appName.indexOf('Microsoft') != 1
-function FlashConduit_swf_DoFSCommand(command, args) {
- eval(args)
-}
-
-if (InternetExplorer) {
- if (navigator.userAgent.indexOf('Windows') != -1) {
- document.write('<SCRIPT LANGUAGE=VBScript\>\n')
- document.write('on error resume next\n')
- document.write('Sub FlashConduit_swf_FSCommand(ByVal command, ByVal args)\n')
- document.write('call FlashConduit_swf_DoFSCommand(command, args)\n')
- document.write('end sub\n')
- document.write('</SCRIPT\>\n')
- }
-
-}
-
-var woven_eventQueue = []
-woven_eventQueueBusy = 0
-woven_clientSideEventNum = 0
-
-function woven_eventHandler(eventName, node) {
- var eventTarget = node.getAttribute('id')
- var additionalArguments = ''
- for (i = 2; i<arguments.length; i++) {
- additionalArguments += '&woven_clientSideEventArguments='
- additionalArguments += escape(eval(arguments[i]))
- }
- var source = '?woven_clientSideEventName=' + eventName + '&woven_clientSideEventTarget=' + eventTarget + additionalArguments + '&woven_clientSideEventNum=' + woven_clientSideEventNum
- woven_clientSideEventNum += 1
-
- woven_eventQueue = woven_eventQueue.concat(source)
- if (!woven_eventQueueBusy) {
- woven_sendTopEvent()
- }
- return false
-}
-
-function woven_sendTopEvent() {
- woven_eventQueueBusy = 1
- var url = woven_eventQueue[0]
- woven_eventQueue = woven_eventQueue.slice(1)
- var input = document.getElementById('woven_inputConduit')
-
- input.src = url
-}
-
-function woven_clientToServerEventComplete() {
- if (this.woven_eventQueue.length) {
- this.woven_sendTopEvent()
- } else {
- this.woven_eventQueueBusy = 0
- }
- var focus = document.getElementById('woven_firstResponder')
- if (focus) {
- focus.focus()
- if (focus.getAttribute('clearOnFocus')) {
- focus.value=''
- }
- }
- document.scrollTop = 999999999
-}
-
-function woven_attemptFocus(theNode) {
- // focus the first input element in the new node
- if (theNode.tagName == 'INPUT') {
- theNode.focus()
- return 1
- } else {
-/* for (i=0; i<theNode.childNodes.length; i++) { */
-/* if(woven_attemptFocus(theNode.childNodes[i])) { */
-/* return 1 */
-/* } */
-/* } */
- return 0
- }
-}
-
-function woven_replaceElement(theId, htmlStr) {
- //alert(woven_eventQueue.length)
- var oldNode = document.getElementById(theId)
- if (oldNode) {
- if (oldNode.parentNode) {
- var created = document.createElement('span')
- created.innerHTML = htmlStr
- if (created.firstChild) {
- oldNode.parentNode.replaceChild(created.firstChild, oldNode)
- var newNode = document.getElementById(theId)
- //woven_attemptFocus(newNode)
- }
- }
- }
-}
-
-function woven_appendChild(theId, htmlStr) {
- var container = document.getElementById(theId)
- var newNode = document.createElement('span')
- newNode.innerHTML = htmlStr
- container.appendChild(newNode.firstChild)
-}
-
-function woven_removeChild(theId) {
- var theElement = document.getElementById(theId)
- theElement.parentNode.removeChild(theElement)
-}
diff --git a/tools/buildbot/pylibs/twisted/web/woven/WebConduitGlue.html b/tools/buildbot/pylibs/twisted/web/woven/WebConduitGlue.html
deleted file mode 100644
index ba02e15..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/WebConduitGlue.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<div>
- <script language="javascript" src="WebConduit2_js">
- .
- </script>
- <iframe style="width: 0; height: 0" id="woven_inputConduit" src="input_html">
- .
- </iframe>
- <iframe style="width: 100%" id="woven_outputConduit" src="?woven_hookupOutputConduitToThisFrame=1">
- .
- </iframe>
-</div>
diff --git a/tools/buildbot/pylibs/twisted/web/woven/__init__.py b/tools/buildbot/pylibs/twisted/web/woven/__init__.py
deleted file mode 100644
index 51dfd75..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-# __init__.py
-
-"""Woven, the Web Object Visualization Environment."""
diff --git a/tools/buildbot/pylibs/twisted/web/woven/controller.py b/tools/buildbot/pylibs/twisted/web/woven/controller.py
deleted file mode 100644
index a7aca0c..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/controller.py
+++ /dev/null
@@ -1,436 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_woven -*-
-#
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-from __future__ import nested_scopes
-
-__version__ = "$Revision: 1.67 $"[11:-2]
-
-import os
-import cgi
-import types
-
-from twisted.python import log
-from twisted.python import components
-from twisted.python import failure
-from zope.interface import implements
-from twisted.web import resource, server, static
-from twisted.web.woven import interfaces, utils
-from twisted.web import woven
-from twisted.web import microdom
-from twisted.web.static import redirectTo, addSlash
-
-import warnings
-from time import time as now
-
-def controllerFactory(controllerClass):
- return lambda request, node, model: controllerClass(model)
-
-def controllerMethod(controllerClass):
- return lambda self, request, node, model: controllerClass(model)
-
-
-class Controller(resource.Resource):
- """
- A Controller which handles to events from the user. Such events
- are `web request', `form submit', etc.
-
- I should be the IResource implementor for your Models (and
- L{registerControllerForModel} makes this so).
- """
-
- implements(interfaces.IController)
- setupStacks = 1
- addSlash = 1 # Should this controller add a slash to the url automatically?
- controllerLibraries = []
- viewFactory = None
- templateDirectory = ""
- def __init__(self, m, inputhandlers=None, view=None, controllers=None, templateDirectory = None):
- #self.start = now()
- resource.Resource.__init__(self)
- self.model = m
- # It's the responsibility of the calling code to make sure setView is
- # called on this controller before it's rendered.
- self.view = None
- self.subcontrollers = []
- if self.setupStacks:
- self.setupControllerStack()
- if inputhandlers is None and controllers is None:
- self._inputhandlers = []
- elif inputhandlers:
- print "The inputhandlers arg is deprecated, please use controllers instead"
- self._inputhandlers = inputhandlers
- else:
- self._inputhandlers = controllers
- if templateDirectory is not None:
- self.templateDirectory = templateDirectory
- self._valid = {}
- self._invalid = {}
- self._process = {}
- self._parent = None
-
- def setupControllerStack(self):
- self.controllerStack = utils.Stack([])
- from twisted.web.woven import input
- if input not in self.controllerLibraries:
- self.controllerLibraries.append(input)
- for library in self.controllerLibraries:
- self.importControllerLibrary(library)
- self.controllerStack.push(self)
-
- def importControllerLibrary(self, namespace):
- if not hasattr(namespace, 'getSubcontroller'):
- namespace.getSubcontroller = utils.createGetFunction(namespace)
- self.controllerStack.push(namespace)
-
- def getSubcontroller(self, request, node, model, controllerName):
- controller = None
- cm = getattr(self, 'wcfactory_' +
- controllerName, None)
- if cm is None:
- cm = getattr(self, 'factory_' +
- controllerName, None)
- if cm is not None:
- warnings.warn("factory_ methods are deprecated; please use "
- "wcfactory_ instead", DeprecationWarning)
- if cm:
- if cm.func_code.co_argcount == 1 and not type(cm) == types.LambdaType:
- warnings.warn("A Controller Factory takes "
- "(request, node, model) "
- "now instead of (model)", DeprecationWarning)
- controller = controllerFactory(model)
- else:
- controller = cm(request, node, model)
- return controller
-
- def setSubcontrollerFactory(self, name, factory, setup=None):
- setattr(self, "wcfactory_" + name, lambda request, node, m:
- factory(m))
-
- def setView(self, view):
- self.view = view
-
- def setNode(self, node):
- self.node = node
-
- def setUp(self, request, *args):
- """
- @type request: L{twisted.web.server.Request}
- """
- pass
-
- def getChild(self, name, request):
- """
- Look for a factory method to create the object to handle the
- next segment of the URL. If a wchild_* method is found, it will
- be called to produce the Resource object to handle the next
- segment of the path. If a wchild_* method is not found,
- getDynamicChild will be called with the name and request.
-
- @param name: The name of the child being requested.
- @type name: string
- @param request: The HTTP request being handled.
- @type request: L{twisted.web.server.Request}
- """
- if not name:
- method = "index"
- else:
- method = name.replace('.', '_')
- f = getattr(self, "wchild_%s" % method, None)
- if f:
- return f(request)
- else:
- child = self.getDynamicChild(name, request)
- if child is None:
- return resource.Resource.getChild(self, name, request)
- else:
- return child
-
- def getDynamicChild(self, name, request):
- """
- This method is called when getChild cannot find a matching wchild_*
- method in the Controller. Override me if you wish to have dynamic
- handling of child pages. Should return a Resource if appropriate.
- Return None to indicate no resource found.
-
- @param name: The name of the child being requested.
- @type name: string
- @param request: The HTTP request being handled.
- @type request: L{twisted.web.server.Request}
- """
- pass
-
- def wchild_index(self, request):
- """By default, we return ourself as the index.
- Override this to provide different behavior
- for a URL that ends in a slash.
- """
- self.addSlash = 0
- return self
-
- def render(self, request):
- """
- Trigger any inputhandlers that were passed in to this Page,
- then delegate to the View for traversing the DOM. Finally,
- call gatheredControllers to deal with any InputHandlers that
- were constructed from any controller= tags in the
- DOM. gatheredControllers will render the page to the browser
- when it is done.
- """
- if self.addSlash and request.uri.split('?')[0][-1] != '/':
- return redirectTo(addSlash(request), request)
- # Handle any inputhandlers that were passed in to the controller first
- for ih in self._inputhandlers:
- ih._parent = self
- ih.handle(request)
- self._inputhandlers = []
- for key, value in self._valid.items():
- key.commit(request, None, value)
- self._valid = {}
- return self.renderView(request)
-
- def makeView(self, model, templateFile=None, parentCount=0):
- if self.viewFactory is None:
- self.viewFactory = self.__class__
- v = self.viewFactory(model, templateFile=templateFile, templateDirectory=self.templateDirectory)
- v.parentCount = parentCount
- v.tapestry = self
- v.importViewLibrary(self)
- return v
-
- def renderView(self, request):
- if self.view is None:
- if self.viewFactory is not None:
- self.setView(self.makeView(self.model, None))
- else:
- self.setView(interfaces.IView(self.model, None))
- self.view.setController(self)
- return self.view.render(request, doneCallback=self.gatheredControllers)
-
- def gatheredControllers(self, v, d, request):
- process = {}
- request.args = {}
- for key, value in self._valid.items():
- key.commit(request, None, value)
- process[key.submodel] = value
- self.process(request, **process)
- #log.msg("Sending page!")
- self.pageRenderComplete(request)
- utils.doSendPage(v, d, request)
- #v.unlinkViews()
-
- #print "Page time: ", now() - self.start
- #return view.View.render(self, request, block=0)
-
- def aggregateValid(self, request, input, data):
- self._valid[input] = data
-
- def aggregateInvalid(self, request, input, data):
- self._invalid[input] = data
-
- def process(self, request, **kwargs):
- if kwargs:
- log.msg("Processing results: ", kwargs)
-
- def setSubmodel(self, submodel):
- self.submodel = submodel
-
- def handle(self, request):
- """
- By default, we don't do anything
- """
- pass
-
- def exit(self, request):
- """We are done handling the node to which this controller was attached.
- """
- pass
-
- def domChanged(self, request, widget, node):
- parent = getattr(self, '_parent', None)
- if parent is not None:
- parent.domChanged(request, widget, node)
-
- def pageRenderComplete(self, request):
- """Override this to recieve notification when the view rendering
- process is complete.
- """
- pass
-
-WOVEN_PATH = os.path.split(woven.__file__)[0]
-
-class LiveController(Controller):
- """A Controller that encapsulates logic that makes it possible for this
- page to be "Live". A live page can have it's content updated after the
- page has been sent to the browser, and can translate client-side
- javascript events into server-side events.
- """
- pageSession = None
- def render(self, request):
- """First, check to see if this request is attempting to hook up the
- output conduit. If so, do it. Otherwise, unlink the current session's
- View from the MVC notification infrastructure, then render the page
- normally.
- """
- # Check to see if we're hooking up an output conduit
- sess = request.getSession(interfaces.IWovenLivePage)
- #print "REQUEST.ARGS", request.args
- if request.args.has_key('woven_hookupOutputConduitToThisFrame'):
- sess.hookupOutputConduit(request)
- return server.NOT_DONE_YET
- if request.args.has_key('woven_clientSideEventName'):
- try:
- request.d = microdom.parseString('<xml/>', caseInsensitive=0, preserveCase=0)
- eventName = request.args['woven_clientSideEventName'][0]
- eventTarget = request.args['woven_clientSideEventTarget'][0]
- eventArgs = request.args.get('woven_clientSideEventArguments', [])
- #print "EVENT", eventName, eventTarget, eventArgs
- return self.clientToServerEvent(request, eventName, eventTarget, eventArgs)
- except:
- fail = failure.Failure()
- self.view.renderFailure(fail, request)
- return server.NOT_DONE_YET
-
- # Unlink the current page in this user's session from MVC notifications
- page = sess.getCurrentPage()
- #request.currentId = getattr(sess, 'currentId', 0)
- if page is not None:
- page.view.unlinkViews()
- sess.setCurrentPage(None)
- #print "PAGE SESSION IS NONE"
- self.pageSession = None
- return Controller.render(self, request)
-
- def clientToServerEvent(self, request, eventName, eventTarget, eventArgs):
- """The client sent an asynchronous event to the server.
- Locate the View object targeted by this event and attempt
- to call onEvent on it.
- """
- sess = request.getSession(interfaces.IWovenLivePage)
- self.view = sess.getCurrentPage().view
- #request.d = self.view.d
- print "clientToServerEvent", eventTarget
- target = self.view.subviews[eventTarget]
- print "target, parent", target, target.parent
- #target.parent = self.view
- #target.controller._parent = self
-
- ## From the time we call onEvent until it returns, we want all
- ## calls to IWovenLivePage.sendScript to be appended to this
- ## list so we can spit them out in the response, immediately
- ## below.
- scriptOutput = []
- orig = sess.sendScript
- sess.sendScript = scriptOutput.append
- target.onEvent(request, eventName, *eventArgs)
- sess.sendScript = orig
-
- scriptOutput.append('parent.woven_clientToServerEventComplete()')
-
- #print "GATHERED JS", scriptOutput
-
- return '''<html>
-<body>
- <script language="javascript">
- %s
- </script>
- %s event sent to %s (%s) with arguments %s.
-</body>
-</html>''' % ('\n'.join(scriptOutput), eventName, cgi.escape(str(target)), eventTarget, eventArgs)
-
- def gatheredControllers(self, v, d, request):
- Controller.gatheredControllers(self, v, d, request)
- sess = request.getSession(interfaces.IWovenLivePage)
- self.pageSession = sess
- sess.setCurrentPage(self)
- sess.currentId = request.currentId
-
- def domChanged(self, request, widget, node):
- sess = request.getSession(interfaces.IWovenLivePage)
- print "domchanged"
- if sess is not None:
- if not hasattr(node, 'getAttribute'):
- return
- page = sess.getCurrentPage()
- if page is None:
- return
- nodeId = node.getAttribute('id')
- #logger.warn("DOM for %r is changing to %s", nodeId, node.toprettyxml())
- nodeXML = node.toxml()
- nodeXML = nodeXML.replace("\\", "\\\\")
- nodeXML = nodeXML.replace("'", "\\'")
- nodeXML = nodeXML.replace('"', '\\"')
- nodeXML = nodeXML.replace('\n', '\\n')
- nodeXML = nodeXML.replace('\r', ' ')
- nodeXML = nodeXML.replace('\b', ' ')
- nodeXML = nodeXML.replace('\t', ' ')
- nodeXML = nodeXML.replace('\000', ' ')
- nodeXML = nodeXML.replace('\v', ' ')
- nodeXML = nodeXML.replace('\f', ' ')
-
- js = "parent.woven_replaceElement('%s', '%s')" % (nodeId, nodeXML)
- #for key in widget.subviews.keys():
- # view.subviews[key].unlinkViews()
- oldNode = page.view.subviews[nodeId]
- for id, subview in oldNode.subviews.items():
- subview.unlinkViews()
- topSubviews = page.view.subviews
- #print "Widgetid, subviews", id(widget), widget.subviews
- if widget.subviews:
- def recurseSubviews(w):
- #print "w.subviews", w.subviews
- topSubviews.update(w.subviews)
- for id, sv in w.subviews.items():
- recurseSubviews(sv)
- #print "recursing"
- recurseSubviews(widget)
- #page.view.subviews.update(widget.subviews)
- sess.sendScript(js)
-
- def wchild_WebConduit2_js(self, request):
- #print "returning js file"
- h = request.getHeader("user-agent")
- if h.count("MSIE"):
- fl = "WebConduit2_msie.js"
- else:
- fl = "WebConduit2_mozilla.js"
-
- return static.File(os.path.join(WOVEN_PATH, fl))
-
- def wchild_FlashConduit_swf(self, request):
- #print "returning flash file"
- h = request.getHeader("user-agent")
- if h.count("MSIE"):
- fl = "FlashConduit.swf"
- else:
- fl = "FlashConduit.swf"
- return static.File(os.path.join(WOVEN_PATH, fl))
-
- def wchild_input_html(self, request):
- return BlankPage()
-
-
-class BlankPage(resource.Resource):
- def render(self, request):
- return "<html>This space intentionally left blank</html>"
-
-
-WController = Controller
-
-def registerControllerForModel(controller, model):
- """
- Registers `controller' as an adapter of `model' for IController, and
- optionally registers it for IResource, if it implements it.
-
- @param controller: A class that implements L{interfaces.IController}, usually a
- L{Controller} subclass. Optionally it can implement
- L{resource.IResource}.
- @param model: Any class, but probably a L{twisted.web.woven.model.Model}
- subclass.
- """
- components.registerAdapter(controller, model, interfaces.IController)
- if resource.IResource.implementedBy(controller):
- components.registerAdapter(controller, model, resource.IResource)
-
diff --git a/tools/buildbot/pylibs/twisted/web/woven/dirlist.py b/tools/buildbot/pylibs/twisted/web/woven/dirlist.py
deleted file mode 100644
index 4889efe..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/dirlist.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""Directory listing."""
-
-# system imports
-from os.path import join as joinpath
-import urllib, os
-
-# sibling imports
-import page, model, widgets, view
-
-# twisted imports
-from twisted.web.microdom import lmx
-from twisted.web.domhelpers import RawText
-from twisted.python.filepath import FilePath
-from twisted.web.static import File, getTypeAndEncoding
-
-
-class DirectoryLister(page.Page):
- template = '''
- <html>
- <head>
- <title model="header"> </title>
- <style>
- .even-dir { background-color: #efe0ef }
- .even { background-color: #eee }
- .odd-dir {background-color: #f0d0ef }
- .odd { background-color: #dedede }
- .icon { text-align: center }
- .listing {
- margin-left: auto;
- margin-right: auto;
- width: 50%;
- padding: 0.1em;
- }
-
- body { border: 0; padding: 0; margin: 0; background-color: #efefef; }
- h1 {padding: 0.1em; background-color: #777; color: white; border-bottom: thin white dashed;}
-
- </style>
- </head>
-
- <body>
- <h1 model="header"> </h1>
-
- <table view="List" model="listing">
- <tr pattern="listHeader">
- <th>Filename</th>
- <th>Content type</th>
- <th>Content encoding</th>
- </tr>
- <tr class="even" pattern="listItem">
- <td><a model="link" view="Link" /></td>
- <td model="type" view="Text"></td>
- <td model="encoding" view="Text"></td>
- </tr>
- <tr class="odd" pattern="listItem">
- <td><a model="link" view="Link" /></td>
- <td model="type" view="Text"></td>
- <td model="encoding" view="Text"></td>
- </tr>
- </table>
-
- </body>
- </html>
- '''
-
- def __init__(self, pathname, dirs=None,
- contentTypes=File.contentTypes,
- contentEncodings=File.contentEncodings,
- defaultType='text/html'):
- self.contentTypes = contentTypes
- self.contentEncodings = contentEncodings
- self.defaultType = defaultType
- # dirs allows usage of the File to specify what gets listed
- self.dirs = dirs
- self.path = pathname
- page.Page.__init__(self)
-
- def wmfactory_listing(self, request):
- if self.dirs is None:
- directory = os.listdir(self.path)
- directory.sort()
- else:
- directory = self.dirs
-
- files = []; dirs = []
-
- for path in directory:
- url = urllib.quote(path, "/")
- if os.path.isdir(os.path.join(self.path, path)):
- url = url + '/'
- dirs.append({'link':{"text": path + "/", "href":url},
- 'type': '[Directory]', 'encoding': ''})
- else:
- mimetype, encoding = getTypeAndEncoding(path, self.contentTypes,
- self.contentEncodings,
- self.defaultType)
- files.append({
- 'link': {"text": path, "href": url},
- 'type': '[%s]' % mimetype,
- 'encoding': (encoding and '[%s]' % encoding or '')})
-
- return files + dirs
-
- def wmfactory_header(self, request):
- return "Directory listing for %s" % urllib.unquote(request.uri)
-
- def __repr__(self):
- return '<DirectoryLister of %r>' % self.path
-
- __str__ = __repr__
diff --git a/tools/buildbot/pylibs/twisted/web/woven/flashconduit.py b/tools/buildbot/pylibs/twisted/web/woven/flashconduit.py
deleted file mode 100644
index 36e7920..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/flashconduit.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from twisted.internet.protocol import Factory
-from twisted.protocols.basic import LineReceiver
-from twisted.python import log
-from twisted.web.woven import interfaces
-
-
-class FlashConduit(LineReceiver):
- delimiter = '\0'
- keepalive = 1
- def connectionMade(self):
- print "connection with flash movie opened"
- #self.transport.write("alert('helllllllo')\0")
-
- def connectionLost(self, reason):
- print "connection lost"
- #self.lp.unhookOutputConduit()
-
- def lineReceived(self, line):
- session = self.factory.site.getSession(line)
- self.lp = lp = session.getComponent(interfaces.IWovenLivePage)
- lp.hookupOutputConduit(self)
-
- def writeScript(self, data):
- #print "writing javascript", data
- self.transport.write(data + '\0')
-
- def finish(self):
- pass
-
-
-class FlashConduitFactory(Factory):
- protocol = FlashConduit
-
- def __init__(self, site):
- self.site = site \ No newline at end of file
diff --git a/tools/buildbot/pylibs/twisted/web/woven/form.py b/tools/buildbot/pylibs/twisted/web/woven/form.py
deleted file mode 100644
index 749d0d8..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/form.py
+++ /dev/null
@@ -1,575 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_woven -*-
-#
-# WORK IN PROGRESS: HARD HAT REQUIRED
-#
-
-from __future__ import nested_scopes
-
-# Twisted Imports
-
-from twisted.python import formmethod, failure
-from twisted.python.components import registerAdapter
-from twisted.web import domhelpers, resource, util
-from twisted.internet import defer
-
-# Sibling Imports
-from twisted.web.woven import model, view, controller, widgets, input, interfaces
-
-from twisted.web.microdom import parseString, lmx, Element
-
-
-#other imports
-import math
-
-# map formmethod.Argument to functions that render them:
-_renderers = {}
-
-def registerRenderer(argumentClass, renderer):
- """Register a renderer for a given argument class.
-
- The renderer function should act in the same way
- as the 'input_XXX' methods of C{FormFillerWidget}.
- """
- assert callable(renderer)
- global _renderers
- _renderers[argumentClass] = renderer
-
-
-class FormFillerWidget(widgets.Widget):
-
- SPANNING_TYPES = ["hidden", "submit"]
-
- def getValue(self, request, argument):
- """Return value for form input."""
- if not self.model.alwaysDefault:
- values = request.args.get(argument.name, None)
- if values:
- try:
- return argument.coerce(values[0])
- except formmethod.InputError:
- return values[0]
- return argument.default
-
- def getValues(self, request, argument):
- """Return values for form input."""
- if not self.model.alwaysDefault:
- values = request.args.get(argument.name, None)
- if values:
- try:
- return argument.coerce(values)
- except formmethod.InputError:
- return values
- return argument.default
-
- def createShell(self, request, node, data):
- """Create a `shell' node that will hold the additional form
- elements, if one is required.
- """
- return lmx(node).table(border="0")
-
- def input_single(self, request, content, model, templateAttributes={}):
- """
- Returns a text input node built based upon the node model.
- Optionally takes an already-coded DOM node merges that
- information with the model's information. Returns a new (??)
- lmx node.
- """
- #in a text field, only the following options are allowed (well, more
- #are, but they're not supported yet - can add them in later)
- attribs = ['type', 'name', 'value', 'size', 'maxlength',
- 'readonly'] #only MSIE recognizes readonly and disabled
-
- arguments = {}
- for attrib in attribs:
- #model hints and values override anything in the template
- val = model.getHint(attrib, templateAttributes.get(attrib, None))
- if val:
- arguments[attrib] = str(val)
-
- value = self.getValue(request, model)
- if value:
- arguments["value"] = str(value)
-
- arguments["type"] = "text" #these are default
- arguments["name"] = model.name
-
- return content.input(**arguments)
-
- def input_string(self, request, content, model, templateAttributes={}):
- if not templateAttributes.has_key("size"):
- templateAttributes["size"] = '60'
- return self.input_single(request, content, model, templateAttributes)
-
- input_integer = input_single
- input_integerrange = input_single
- input_float = input_single
-
- def input_text(self, request, content, model, templateAttributes={}):
- r = content.textarea(
- cols=str(model.getHint('cols',
- templateAttributes.get('cols', '60'))),
- rows=str(model.getHint('rows',
- templateAttributes.get('rows', '10'))),
- name=model.name,
- wrap=str(model.getHint('wrap',
- templateAttributes.get('wrap', "virtual"))))
- r.text(str(self.getValue(request, model)))
- return r
-
- def input_hidden(self, request, content, model, templateAttributes={}):
- return content.input(type="hidden",
- name=model.name,
- value=str(self.getValue(request, model)))
-
- def input_submit(self, request, content, model, templateAttributes={}):
- arguments = {}
- val = model.getHint("onClick", templateAttributes.get("onClick", None))
- if val:
- arguments["onClick"] = val
- arguments["type"] = "submit"
- arguments["name"] = model.name
- div = content.div()
- for tag, value, desc in model.choices:
- args = arguments.copy()
- args["value"] = tag
- div.input(**args)
- div.text(" ")
- if model.reset:
- div.input(type="reset")
- return div
-
- def input_choice(self, request, content, model, templateAttributes={}):
- # am I not evil? allow onChange js events
- arguments = {}
- val = model.getHint("onChange", templateAttributes.get("onChange", None))
- if val:
- arguments["onChange"] = val
- arguments["name"] = model.name
- s = content.select(**arguments)
- default = self.getValues(request, model)
- for tag, value, desc in model.choices:
- kw = {}
- if value in default:
- kw = {'selected' : '1'}
- s.option(value=tag, **kw).text(desc)
- return s
-
- def input_group(self, request, content, model, groupValues, inputType,
- templateAttributes={}):
- """
- Base code for a group of objects. Checkgroup will use this, as
- well as radiogroup. In the attributes, rows means how many rows
- the group should be arranged into, cols means how many cols the
- group should be arranged into. Columns take precedence over
- rows: if both are specified, the output will always generate the
- correct number of columns. However, if the number of elements
- in the group exceed (or is smaller than) rows*cols, then the
- number of rows will be off. A cols attribute of 1 will mean that
- all the elements will be listed one underneath another. The
- default is a rows attribute of 1: everything listed next to each
- other.
- """
- rows = model.getHint('rows', templateAttributes.get('rows', None))
- cols = model.getHint('cols', templateAttributes.get('cols', None))
- if rows:
- rows = int(rows)
- if cols:
- cols = int(cols)
-
- defaults = self.getValues(request, model)
- if (rows and rows>1) or (cols and cols>1): #build a table
- s = content.table(border="0")
- if cols:
- breakat = cols
- else:
- breakat = math.ceil(float(len(groupValues))/rows)
- for i in range(0, len(groupValues), breakat):
- tr = s.tr()
- for j in range(0, breakat):
- if i+j >= len(groupValues):
- break
- tag, value, desc = groupValues[i+j]
- kw = {}
- if value in defaults:
- kw = {'checked' : '1'}
- tr.td().input(type=inputType, name=model.name,
- value=tag, **kw).text(desc)
-
- else:
- s = content.div()
- for tag, value, desc in groupValues:
- kw = {}
- if value in defaults:
- kw = {'checked' : '1'}
- s.input(type=inputType, name=model.name,
- value=tag, **kw).text(desc)
- if cols:
- s.br()
-
- return s
-
- def input_checkgroup(self, request, content, model, templateAttributes={}):
- return self.input_group(request, content, model, model.flags,
- "checkbox", templateAttributes)
-
- def input_radiogroup(self, request, content, model, templateAttributes={}):
- return self.input_group(request, content, model, model.choices,
- "radio", templateAttributes)
-
- #I don't know why they're the same, but they were. So I removed the
- #excess code. Maybe someone should look into removing it entirely.
- input_flags = input_checkgroup
-
- def input_boolean(self, request, content, model, templateAttributes={}):
- kw = {}
- if self.getValue(request, model):
- kw = {'checked' : '1'}
- return content.input(type="checkbox", name=model.name, **kw)
-
- def input_file(self, request, content, model, templateAttributes={}):
- kw = {}
- for attrib in ['size', 'accept']:
- val = model.getHint(attrib, templateAttributes.get(attrib, None))
- if val:
- kw[attrib] = str(val)
- return content.input(type="file", name=model.name, **kw)
-
- def input_date(self, request, content, model, templateAttributes={}):
- breakLines = model.getHint('breaklines', 1)
- date = self.getValues(request, model)
- if date == None:
- year, month, day = "", "", ""
- else:
- year, month, day = date
- div = content.div()
- div.text("Year: ")
- div.input(type="text", size="4", maxlength="4", name=model.name, value=str(year))
- if breakLines:
- div.br()
- div.text("Month: ")
- div.input(type="text", size="2", maxlength="2", name=model.name, value=str(month))
- if breakLines:
- div.br()
- div.text("Day: ")
- div.input(type="text", size="2", maxlength="2", name=model.name, value=str(day))
- return div
-
- def input_password(self, request, content, model, templateAttributes={}):
- return content.input(
- type="password",
- size=str(templateAttributes.get('size', "60")),
- name=model.name)
-
- def input_verifiedpassword(self, request, content, model, templateAttributes={}):
- breakLines = model.getHint('breaklines', 1)
- values = self.getValues(request, model)
- if isinstance(values, (str, unicode)):
- values = (values, values)
- if not values:
- p1, p2 = "", ""
- elif len(values) == 1:
- p1, p2 = values, ""
- elif len(values) == 2:
- p1, p2 = values
- else:
- p1, p2 = "", ""
- div = content.div()
- div.text("Password: ")
- div.input(type="password", size="20", name=model.name, value=str(p1))
- if breakLines:
- div.br()
- div.text("Verify: ")
- div.input(type="password", size="20", name=model.name, value=str(p2))
- return div
-
-
- def convergeInput(self, request, content, model, templateNode):
- name = model.__class__.__name__.lower()
- if _renderers.has_key(model.__class__):
- imeth = _renderers[model.__class__]
- else:
- imeth = getattr(self,"input_"+name)
-
- return imeth(request, content, model, templateNode.attributes).node
-
- def createInput(self, request, shell, model, templateAttributes={}):
- name = model.__class__.__name__.lower()
- if _renderers.has_key(model.__class__):
- imeth = _renderers[model.__class__]
- else:
- imeth = getattr(self,"input_"+name)
- if name in self.SPANNING_TYPES:
- td = shell.tr().td(valign="top", colspan="2")
- return (imeth(request, td, model).node, shell.tr().td(colspan="2").node)
- else:
- if model.allowNone:
- required = ""
- else:
- required = " *"
- tr = shell.tr()
- tr.td(align="right", valign="top").text(model.getShortDescription()+":"+required)
- content = tr.td(valign="top")
- return (imeth(request, content, model).node,
- content.div(_class="formDescription"). # because class is a keyword
- text(model.getLongDescription()).node)
-
- def setUp(self, request, node, data):
- # node = widgets.Widget.generateDOM(self,request,node)
- lmn = lmx(node)
- if not node.hasAttribute('action'):
- lmn['action'] = (request.prepath+request.postpath)[-1]
- if not node.hasAttribute("method"):
- lmn['method'] = 'post'
- lmn['enctype'] = 'multipart/form-data'
- self.errorNodes = errorNodes = {} # name: nodes which trap errors
- self.inputNodes = inputNodes = {}
- for errorNode in domhelpers.findElementsWithAttribute(node, 'errorFor'):
- errorNodes[errorNode.getAttribute('errorFor')] = errorNode
- argz={}
- # list to figure out which nodes are in the template already and which aren't
- hasSubmit = 0
- argList = self.model.fmethod.getArgs()
- for arg in argList:
- if isinstance(arg, formmethod.Submit):
- hasSubmit = 1
- argz[arg.name] = arg
- inNodes = domhelpers.findElements(
- node,
- lambda n: n.tagName.lower() in ('textarea', 'select', 'input',
- 'div'))
- for inNode in inNodes:
- t = inNode.getAttribute("type")
- if t and t.lower() == "submit":
- hasSubmit = 1
- if not inNode.hasAttribute("name"):
- continue
- nName = inNode.getAttribute("name")
- if argz.has_key(nName):
- #send an empty content shell - we just want the node
- inputNodes[nName] = self.convergeInput(request, lmx(),
- argz[nName], inNode)
- inNode.parentNode.replaceChild(inputNodes[nName], inNode)
- del argz[nName]
- # TODO:
- # * some arg types should only have a single node (text, string, etc)
- # * some should have multiple nodes (choice, checkgroup)
- # * some have a bunch of ancillary nodes that are possible values (menu, radiogroup)
- # these should all be taken into account when walking through the template
- if argz:
- shell = self.createShell(request, node, data)
- # create inputs, in the same order they were passed to us:
- for remArg in [arg for arg in argList if argz.has_key(arg.name)]:
- inputNode, errorNode = self.createInput(request, shell, remArg)
- errorNodes[remArg.name] = errorNode
- inputNodes[remArg.name] = inputNode
-
- if not hasSubmit:
- lmn.input(type="submit")
-
-
-class FormErrorWidget(FormFillerWidget):
- def setUp(self, request, node, data):
- FormFillerWidget.setUp(self, request, node, data)
- for k, f in self.model.err.items():
- en = self.errorNodes[k]
- tn = self.inputNodes[k]
- en.setAttribute('class', 'formError')
- tn.setAttribute('class', 'formInputError')
- en.childNodes[:]=[] # gurfle, CLEAR IT NOW!@#
- if isinstance(f, failure.Failure):
- f = f.getErrorMessage()
- lmx(en).text(str(f))
-
-
-class FormDisplayModel(model.MethodModel):
- def initialize(self, fmethod, alwaysDefault=False):
- self.fmethod = fmethod
- self.alwaysDefault = alwaysDefault
-
-class FormErrorModel(FormDisplayModel):
- def initialize(self, fmethod, args, err):
- FormDisplayModel.initialize(self, fmethod)
- self.args = args
- if isinstance(err, failure.Failure):
- err = err.value
- if isinstance(err, Exception):
- self.err = getattr(err, "descriptions", {})
- self.desc = err
- else:
- self.err = err
- self.desc = "Please try again"
-
- def wmfactory_description(self, request):
- return str(self.desc)
-
-class _RequestHack(model.MethodModel):
- def wmfactory_hack(self, request):
- rv = [[str(a), repr(b)] for (a, b)
- in request._outDict.items()]
- #print 'hack', rv
- return rv
-
-class FormProcessor(resource.Resource):
- def __init__(self, formMethod, callback=None, errback=None):
- resource.Resource.__init__(self)
- self.formMethod = formMethod
- if callback is None:
- callback = self.viewFactory
- self.callback = callback
- if errback is None:
- errback = self.errorViewFactory
- self.errback = errback
-
- def getArgs(self, request):
- """Return the formmethod.Arguments.
-
- Overridable hook to allow pre-processing, e.g. if we want to enable
- on them depending on one of the inputs.
- """
- return self.formMethod.getArgs()
-
- def render(self, request):
- outDict = {}
- errDict = {}
- for methodArg in self.getArgs(request):
- valmethod = getattr(self,"mangle_"+
- (methodArg.__class__.__name__.lower()), None)
- tmpval = request.args.get(methodArg.name)
- if valmethod:
- # mangle the argument to a basic datatype that coerce will like
- tmpval = valmethod(tmpval)
- # coerce it
- try:
- cv = methodArg.coerce(tmpval)
- outDict[methodArg.name] = cv
- except:
- errDict[methodArg.name] = failure.Failure()
- if errDict:
- # there were problems processing the form
- return self.errback(self.errorModelFactory(
- request.args, outDict, errDict)).render(request)
- else:
- try:
- if self.formMethod.takesRequest:
- outObj = self.formMethod.call(request=request, **outDict)
- else:
- outObj = self.formMethod.call(**outDict)
- except formmethod.FormException, e:
- err = request.errorInfo = self.errorModelFactory(
- request.args, outDict, e)
- return self.errback(err).render(request)
- else:
- request._outDict = outDict # CHOMP CHOMP!
- # I wanted better default behavior for debugging, so I could
- # see the arguments passed, but there is no channel for this in
- # the existing callback structure. So, here it goes.
- if isinstance(outObj, defer.Deferred):
- def _ebModel(err):
- if err.trap(formmethod.FormException):
- mf = self.errorModelFactory(request.args, outDict,
- err.value)
- return self.errback(mf)
- raise err
- (outObj
- .addCallback(self.modelFactory)
- .addCallback(self.callback)
- .addErrback(_ebModel))
- return util.DeferredResource(outObj).render(request)
- else:
- return self.callback(self.modelFactory(outObj)).render(
- request)
-
- def errorModelFactory(self, args, out, err):
- return FormErrorModel(self.formMethod, args, err)
-
- def errorViewFactory(self, m):
- v = view.View(m)
- v.template = '''
- <html>
- <head>
- <title> Form Error View </title>
- <style>
- .formDescription {color: green}
- .formError {color: red; font-weight: bold}
- .formInputError {color: #900}
- </style>
- </head>
- <body>
- Error: <span model="description" />
- <form model=".">
- </form>
- </body>
- </html>
- '''
- return v
-
- def modelFactory(self, outObj):
- adapt = interfaces.IModel(outObj, outObj)
- # print 'factorizing', adapt
- return adapt
-
- def viewFactory(self, model):
- # return interfaces.IView(model)
- if model is None:
- bodyStr = '''
- <table model="hack" style="background-color: #99f">
- <tr pattern="listItem" view="Widget">
- <td model="0" style="font-weight: bold">
- </td>
- <td model="1">
- </td>
- </tr>
- </table>
- '''
- model = _RequestHack()
- else:
- bodyStr = '<div model="." />'
- v = view.View(model)
- v.template = '''
- <html>
- <head>
- <title> Thank You </title>
- </head>
- <body>
- <h1>Thank You for Using Woven</h1>
- %s
- </body>
- </html>
- ''' % bodyStr
- return v
-
- # manglizers
-
- def mangle_single(self, args):
- if args:
- return args[0]
- else:
- return ''
-
- mangle_string = mangle_single
- mangle_text = mangle_single
- mangle_integer = mangle_single
- mangle_password = mangle_single
- mangle_integerrange = mangle_single
- mangle_float = mangle_single
- mangle_choice = mangle_single
- mangle_boolean = mangle_single
- mangle_hidden = mangle_single
- mangle_submit = mangle_single
- mangle_file = mangle_single
- mangle_radiogroup = mangle_single
-
- def mangle_multi(self, args):
- if args is None:
- return []
- return args
-
- mangle_checkgroup = mangle_multi
- mangle_flags = mangle_multi
-
-from twisted.python.formmethod import FormMethod
-
-view.registerViewForModel(FormFillerWidget, FormDisplayModel)
-view.registerViewForModel(FormErrorWidget, FormErrorModel)
-registerAdapter(FormDisplayModel, FormMethod, interfaces.IModel)
-
diff --git a/tools/buildbot/pylibs/twisted/web/woven/guard.py b/tools/buildbot/pylibs/twisted/web/woven/guard.py
deleted file mode 100644
index ab5d56b..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/guard.py
+++ /dev/null
@@ -1,383 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_woven -*-
-
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-#
-
-"""Resource protection for Woven. If you wish to use twisted.cred to protect
-your Woven application, you are probably most interested in
-L{UsernamePasswordWrapper}.
-"""
-
-from __future__ import nested_scopes
-
-__version__ = "$Revision: 1.34 $"[11:-2]
-
-import random
-import time
-import md5
-import urllib
-
-# Twisted Imports
-
-from twisted.python import log, components
-from twisted.web.resource import Resource, IResource
-from twisted.web.util import redirectTo, Redirect, DeferredResource
-from twisted.web.static import addSlash
-from twisted.internet import reactor
-from twisted.cred.error import LoginFailed, UnauthorizedLogin
-
-def _sessionCookie():
- return md5.new("%s_%s" % (str(random.random()) , str(time.time()))).hexdigest()
-
-class GuardSession(components.Componentized):
- """A user's session with a system.
-
- This utility class contains no functionality, but is used to
- represent a session.
- """
- def __init__(self, guard, uid):
- """Initialize a session with a unique ID for that session.
- """
- components.Componentized.__init__(self)
- self.guard = guard
- self.uid = uid
- self.expireCallbacks = []
- self.checkExpiredID = None
- self.setLifetime(60)
- self.services = {}
- self.portals = {}
- self.touch()
-
- def _getSelf(self, interface=None):
- self.touch()
- if interface is None:
- return self
- else:
- return self.getComponent(interface)
-
- # Old Guard interfaces
-
- def clientForService(self, service):
- x = self.services.get(service)
- if x:
- return x[1]
- else:
- return x
-
- def setClientForService(self, ident, perspective, client, service):
- if self.services.has_key(service):
- p, c, i = self.services[service]
- p.detached(c, ident)
- del self.services[service]
- else:
- self.services[service] = perspective, client, ident
- perspective.attached(client, ident)
- # this return value is useful for services that need to do asynchronous
- # stuff.
- return client
-
- # New Guard Interfaces
-
- def resourceForPortal(self, port):
- return self.portals.get(port)
-
- def setResourceForPortal(self, rsrc, port, logout):
- self.portalLogout(port)
- self.portals[port] = rsrc, logout
- return rsrc
-
- def portalLogout(self, port):
- p = self.portals.get(port)
- if p:
- r, l = p
- try: l()
- except: log.err()
- del self.portals[port]
-
- # timeouts and expiration
-
- def setLifetime(self, lifetime):
- """Set the approximate lifetime of this session, in seconds.
-
- This is highly imprecise, but it allows you to set some general
- parameters about when this session will expire. A callback will be
- scheduled each 'lifetime' seconds, and if I have not been 'touch()'ed
- in half a lifetime, I will be immediately expired.
- """
- self.lifetime = lifetime
-
- def notifyOnExpire(self, callback):
- """Call this callback when the session expires or logs out.
- """
- self.expireCallbacks.append(callback)
-
- def expire(self):
- """Expire/logout of the session.
- """
- log.msg("expired session %s" % self.uid)
- del self.guard.sessions[self.uid]
- for c in self.expireCallbacks:
- try:
- c()
- except:
- log.err()
- self.expireCallbacks = []
- if self.checkExpiredID:
- self.checkExpiredID.cancel()
- self.checkExpiredID = None
-
- def touch(self):
- self.lastModified = time.time()
-
- def checkExpired(self):
- self.checkExpiredID = None
- # If I haven't been touched in 15 minutes:
- if time.time() - self.lastModified > self.lifetime / 2:
- if self.guard.sessions.has_key(self.uid):
- self.expire()
- else:
- log.msg("no session to expire: %s" % self.uid)
- else:
- log.msg("session given the will to live for %s more seconds" % self.lifetime)
- self.checkExpiredID = reactor.callLater(self.lifetime,
- self.checkExpired)
- def __getstate__(self):
- d = self.__dict__.copy()
- if d.has_key('checkExpiredID'):
- del d['checkExpiredID']
- return d
-
- def __setstate__(self, d):
- self.__dict__.update(d)
- self.touch()
- self.checkExpired()
-
-INIT_SESSION = 'session-init'
-
-def _setSession(wrap, req, cook):
- req.session = wrap.sessions[cook]
- req.getSession = req.session._getSelf
-
-def urlToChild(request, *ar, **kw):
- pp = request.prepath.pop()
- orig = request.prePathURL()
- request.prepath.append(pp)
- c = '/'.join(ar)
- if orig[-1] == '/':
- # this SHOULD only happen in the case where the URL is just the hostname
- ret = orig + c
- else:
- ret = orig + '/' + c
- args = request.args.copy()
- args.update(kw)
- if args:
- ret += '?'+urllib.urlencode(args)
- return ret
-
-def redirectToSession(request, garbage):
- rd = Redirect(urlToChild(request, *request.postpath, **{garbage:1}))
- rd.isLeaf = 1
- return rd
-
-SESSION_KEY='__session_key__'
-
-class SessionWrapper(Resource):
-
- sessionLifetime = 1800
-
- def __init__(self, rsrc, cookieKey=None):
- Resource.__init__(self)
- self.resource = rsrc
- if cookieKey is None:
- cookieKey = "woven_session_" + _sessionCookie()
- self.cookieKey = cookieKey
- self.sessions = {}
-
- def render(self, request):
- return redirectTo(addSlash(request), request)
-
- def getChild(self, path, request):
- if not request.prepath:
- return None
- cookie = request.getCookie(self.cookieKey)
- setupURL = urlToChild(request, INIT_SESSION, *([path]+request.postpath))
- request.setupSessionURL = setupURL
- request.setupSession = lambda: Redirect(setupURL)
- if path.startswith(SESSION_KEY):
- key = path[len(SESSION_KEY):]
- if key not in self.sessions:
- return redirectToSession(request, '__start_session__')
- self.sessions[key].setLifetime(self.sessionLifetime)
- if cookie == key:
- # /sessionized-url/${SESSION_KEY}aef9c34aecc3d9148/foo
- # ^
- # we are this getChild
- # with a matching cookie
- return redirectToSession(request, '__session_just_started__')
- else:
- # We attempted to negotiate the session but failed (the user
- # probably has cookies disabled): now we're going to return the
- # resource we contain. In general the getChild shouldn't stop
- # there.
- # /sessionized-url/${SESSION_KEY}aef9c34aecc3d9148/foo
- # ^ we are this getChild
- # without a cookie (or with a mismatched cookie)
- _setSession(self, request, key)
- return self.resource
- elif cookie in self.sessions:
- # /sessionized-url/foo
- # ^ we are this getChild
- # with a session
- _setSession(self, request, cookie)
- return getResource(self.resource, path, request)
- elif path == INIT_SESSION:
- # initialize the session
- # /sessionized-url/session-init
- # ^ this getChild
- # without a session
- newCookie = _sessionCookie()
- request.addCookie(self.cookieKey, newCookie, path="/")
- sz = self.sessions[newCookie] = GuardSession(self, newCookie)
- sz.checkExpired()
- rd = Redirect(urlToChild(request, SESSION_KEY+newCookie,
- *request.postpath))
- rd.isLeaf = 1
- return rd
- else:
- # /sessionized-url/foo
- # ^ we are this getChild
- # without a session
- request.getSession = lambda interface=None: None
- return getResource(self.resource, path, request)
-
-def getResource(resource, path, request):
- if resource.isLeaf:
- request.postpath.insert(0, request.prepath.pop())
- return resource
- else:
- return resource.getChildWithDefault(path, request)
-
-INIT_PERSPECTIVE = 'perspective-init'
-DESTROY_PERSPECTIVE = 'perspective-destroy'
-
-from twisted.python import formmethod as fm
-from twisted.web.woven import form
-
-
-newLoginSignature = fm.MethodSignature(
- fm.String("username", "",
- "Username", "Your user name."),
- fm.Password("password", "",
- "Password", "Your password."),
- fm.Submit("submit", choices=[("Login", "", "")], allowNone=1),
- )
-
-from twisted.cred.credentials import UsernamePassword, Anonymous
-
-class UsernamePasswordWrapper(Resource):
- """I bring a C{twisted.cred} Portal to the web. Use me to provide different Resources
- (usually entire pages) based on a user's authentication details.
-
- A C{UsernamePasswordWrapper} is a
- L{Resource<twisted.web.resource.Resource>}, and is usually wrapped in a
- L{SessionWrapper} before being inserted into the site tree.
-
- The L{Realm<twisted.cred.portal.IRealm>} associated with your
- L{Portal<twisted.cred.portal.Portal>} should be prepared to accept a
- request for an avatar that implements the L{twisted.web.resource.IResource}
- interface. This avatar should probably be something like a Woven
- L{Page<twisted.web.woven.page.Page>}. That is, it should represent a whole
- web page. Once you return this avatar, requests for it's children do not go
- through guard.
-
- If you want to determine what unauthenticated users see, make sure your
- L{Portal<twisted.cred.portal.Portal>} has a checker associated that allows
- anonymous access. (See L{twisted.cred.checkers.AllowAnonymousAccess})
-
- """
-
- def __init__(self, portal, callback=None, errback=None):
- """Constructs a UsernamePasswordWrapper around the given portal.
-
- @param portal: A cred portal for your web application. The checkers
- associated with this portal must be able to accept username/password
- credentials.
- @type portal: L{twisted.cred.portal.Portal}
-
- @param callback: Gets called after a successful login attempt.
- A resource that redirects to "." will display the avatar resource.
- If this parameter isn't provided, defaults to a standard Woven
- "Thank You" page.
- @type callback: A callable that accepts a Woven
- L{model<twisted.web.woven.interfaces.IModel>} and returns a
- L{IResource<twisted.web.resource.Resource>}.
-
- @param errback: Gets called after a failed login attempt.
- If this parameter is not provided, defaults to a the standard Woven
- form error (i.e. The original form on a page of its own, with
- errors noted.)
- @type errback: A callable that accepts a Woven
- L{model<twisted.web.woven.interfaces.IModel>} and returns a
- L{IResource<twisted.web.resource.Resource>}.
- """
- Resource.__init__(self)
- self.portal = portal
- self.callback = callback
- self.errback = errback
-
- def _ebFilter(self, f):
- f.trap(LoginFailed, UnauthorizedLogin)
- raise fm.FormException(password="Login failed, please enter correct username and password.")
-
- def getChild(self, path, request):
- s = request.getSession()
- if s is None:
- return request.setupSession()
- if path == INIT_PERSPECTIVE:
- def loginSuccess(result):
- interface, avatarAspect, logout = result
- s.setResourceForPortal(avatarAspect, self.portal, logout)
-
- def triggerLogin(username, password, submit=None):
- return self.portal.login(
- UsernamePassword(username, password),
- None,
- IResource
- ).addCallback(
- loginSuccess
- ).addErrback(
- self._ebFilter
- )
-
- return form.FormProcessor(
- newLoginSignature.method(
- triggerLogin
- ),
- callback=self.callback,
- errback=self.errback
- )
- elif path == DESTROY_PERSPECTIVE:
- s.portalLogout(self.portal)
- return Redirect(".")
- else:
- r = s.resourceForPortal(self.portal)
- if r:
- ## Delegate our getChild to the resource our portal says is the right one.
- return getResource(r[0], path, request)
- else:
- return DeferredResource(
- self.portal.login(Anonymous(), None, IResource
- ).addCallback(
- lambda (interface, avatarAspect, logout):
- getResource(s.setResourceForPortal(avatarAspect,
- self.portal, logout),
- path, request)))
-
-
-
-from twisted.web.woven import interfaces, utils
-## Dumb hack until we have an ISession and use interface-to-interface adaption
-components.registerAdapter(utils.WovenLivePage, GuardSession, interfaces.IWovenLivePage)
-
diff --git a/tools/buildbot/pylibs/twisted/web/woven/input.py b/tools/buildbot/pylibs/twisted/web/woven/input.py
deleted file mode 100644
index 7d7d956..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/input.py
+++ /dev/null
@@ -1,347 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_woven -*-
-#
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-# dominput
-
-import os
-import inspect
-
-from twisted.internet import defer
-from twisted.python import log
-from twisted.python.reflect import qual
-
-from twisted.web import domhelpers
-from twisted.web.woven import template, controller, utils
-
-__version__ = "$Revision: 1.34 $"[11:-2]
-
-controllerFactory = controller.controllerFactory
-
-
-class InputHandler(controller.Controller):
- """
- An InputHandler is like a controller, but it operates on something
- contained inside of C{self.model} instead of directly on C{self.model}.
- For example, a Handler whose C{model} has been set to C{"foo"} will handle
- C{self.model.foo}.
-
- The handler's job is to interpret the request and:
-
- 1. Check for valid input
- 2. If the input is valid, update the model
- 3. Use any special API of the view widget to change the view (other
- than what the view updates automatically from the model) e.g. in the
- case of an error, tell the view to report an error to the user
- 4. Return a success value; by default these values are simply recorded
- and the page is rendered, but these values could be used to determine
- what page to display next, etc.
- """
- invalidErrorText = "Error!"
- setupStacks = 0
- def __init__(self, model=None,
- parent=None,
- name=None,
- check=None,
- commit = None,
- invalidErrorText = None,
- submodel=None,
- controllerStack=None):
- self.controllerStack = controllerStack
- controller.Controller.__init__(self, model)
- self._check = check
- self._commit = commit
- self._errback = None
- self._parent = parent
- if invalidErrorText is not None:
- self.invalidErrorText = invalidErrorText
- if submodel is not None:
- self.submodel = submodel
- if name is not None:
- self.inputName = name
-
- def initialize(self):
- pass
-
- def setNode(self, node):
- self.node = node
-
- def getInput(self, request):
- """
- Return the data associated with this handler from the request, if any.
- """
- name = getattr(self, 'inputName', self.submodel)
- input = request.args.get(name, None)
- if input:
- return input
-
- def handle(self, request):
- self.initialize()
- data = self.getInput(request)
- success = self.check(request, data)
- if isinstance(success, defer.Deferred):
- success.addCallback(self.dispatchCheckResult, request, data)
- success.addErrback(utils.renderFailure, request)
- return success
- self.dispatchCheckResult(success, request, data)
-
- def dispatchCheckResult(self, success, request, data):
- if success is not None:
- if success:
- result = self.handleValid(request, data)
- else:
- result = self.handleInvalid(request, data)
- if isinstance(result, defer.Deferred):
- return result
-
- def check(self, request, data):
- """
- Check whether the input in the request is valid for this handler
- and return a boolean indicating validity.
- """
- if self._check is None:
- raise NotImplementedError(qual(self.__class__)+'.check')
- # self._check is probably a bound method or simple function that
- # doesn't have a reference to this InputHandler; pass it
- return self._check(self, request, data)
-
- def handleValid(self, request, data):
- """
- It has been determined that the input for this handler is valid;
- however, that does not mean the entire form is valid.
- """
- self._parent.aggregateValid(request, self, data)
-
- def aggregateValid(self, request, inputhandler, data):
- """By default we just pass the method calls all the way up to the root
- Controller. However, an intelligent InputHandler could override this
- and implement a state machine that waits for all data to be collected
- and then fires.
- """
- self._parent.aggregateValid(request, inputhandler, data)
-
- def handleInvalid(self, request, data):
- """
- Once it has been determined that the input is invalid, we should
- tell our view to report this fact to the user.
- """
- self._parent.aggregateInvalid(request, self, data)
- self.view.setError(request, self.invalidErrorText)
-
- def aggregateInvalid(self, request, inputhandler, data):
- """By default we just pass this method call all the way up to the root
- Controller.
- """
- self._parent.aggregateInvalid(request, inputhandler, data)
-
- def commit(self, request, node, data):
- """
- It has been determined that the input for the entire form is completely
- valid; it is now safe for all handlers to commit changes to the model.
- """
- if self._commit is None:
- data = str(data)
- if data != self.view.getData():
- self.model.setData(data)
- self.model.notify({'request': request, self.submodel: data})
- else:
- func = self._commit
- if hasattr(func, 'im_func'):
- func = func.im_func
- args, varargs, varkw, defaults = inspect.getargspec(func)
- if args[1] == 'request':
- self._commit(request, data)
- else:
- self._commit(data)
-
-
-class DefaultHandler(InputHandler):
- def handle(self, request):
- """
- By default, we don't do anything
- """
- pass
-
-
-class SingleValue(InputHandler):
- def getInput(self, request):
- name = getattr(self, 'inputName', self.submodel)
- input = request.args.get(name, None)
- if input:
- return input[0]
-
-
-class Anything(SingleValue):
- """
- Handle anything except for None
- """
- def check(self, request, data):
- if data is not None:
- return 1
- return None
-
-
-class Integer(SingleValue):
- """
- Only allow a single integer
- """
- def check(self, request, data):
- if data is None: return None
- try:
- int(data)
- return 1
- except (TypeError, ValueError):
- return 0
-
- def handleInvalid(self, request, data):
- self.invalidErrorText = "%s is not an integer. Please enter an integer." % data
- SingleValue.handleInvalid(self, request, data)
-
-
-class Float(SingleValue):
- """
- Only allow a single float
- """
- def check(self, request, data):
- if data is None: return None
- try:
- float(data)
- return 1
- except (TypeError, ValueError):
- return 0
-
- def handleInvalid(self, request, data):
- self.invalidErrorText = "%s is not an float. Please enter a float." % data
- SingleValue.handleInvalid(self, request, data)
-
-
-class List(InputHandler):
- def check(self, request, data):
- return None
-
-
-class DictAggregator(Anything):
- """An InputHandler for a <form> tag, for triggering a function
- when all of the form's individual inputs have been validated.
- Also for use gathering a dict of arguments to pass to a parent's
- aggregateValid if no commit function is passed.
-
- Usage example::
- <form controller="theForm" action="">
- <input controller="Integer"
- view="InputText" model="anInteger" />
- <input controller="Anything"
- view="InputText" model="aString" />
- <input type="submit" />
- </form>
-
- def theCommitFunction(anInteger=None, aString=None):
- '''Note how the keyword arguments match up with the leaf model
- names above
- '''
- print "Yay", anInteger, aString
-
- class CMyController(controller.Controller):
- def wcfactory_theForm(self, request, node, m):
- return input.FormAggregator(m, commit=theCommitFunction)
- """
- def aggregateValid(self, request, inputhandler, data):
- """Aggregate valid input from inputhandlers below us, into a dictionary.
- """
- self._valid[inputhandler] = data
-
- def aggregateInvalid(self, request, inputhandler, data):
- self._invalid[inputhandler] = data
-
- def exit(self, request):
- """This is the node complete message
- """
- if self._commit:
- # Introspect the commit function to see what
- # keyword arguments it takes
- func = self._commit
- if hasattr(func, 'im_func'):
- func = func.im_func
- args, varargs, varkw, defaults = inspect.getargspec(
- func)
- wantsRequest = len(args) > 1 and args[1] == 'request'
-
- if self._invalid:
- # whoops error!!!1
- if self._errback:
- self._errback(request, self._invalid)
- elif self._valid:
- # We've got all the input
- # Gather it into a dict and call the commit function
- results = {}
- for item in self._valid:
- results[item.model.name] = self._valid[item]
- if self._commit:
- if wantsRequest:
- self._commit(request, **results)
- else:
- self._commit(**results)
- else:
- self._parent.aggregateValid(request, self, results)
- return results
-
-
-class ListAggregator(Anything):
- def aggregateValid(self, request, inputhandler, data):
- """Aggregate valid input from inputhandlers below us into a
- list until we have all input from controllers below us to pass
- to the commit function that was passed to the constructor or
- our parent's aggregateValid.
- """
- if not hasattr(self, '_validList'):
- self._validList = []
- self._validList.append(data)
-
- def aggregateInvalid(self, request, inputhandler, data):
- if not hasattr(self, '_invalidList'):
- self._invalidList = []
- self._invalidList.append(data)
-
- def exit(self, request):
- if self._commit:
- # Introspect the commit function to see what
- #arguments it takes
- func = self._commit
- if hasattr(func, 'im_func'):
- func = func.im_func
- args, varargs, varkw, defaults = inspect.getargspec(func)
- self.numArgs = len(args)
- wantsRequest = args[1] == 'request'
- if wantsRequest:
- numArgs -= 1
- else:
- # Introspect the template to see if we still have
- # controllers that will be giving us input
-
- # aggregateValid is called before the view renders the node, so
- # we can count the number of controllers below us the first time
- # we are called
- if not hasattr(self, 'numArgs'):
- self.numArgs = len(domhelpers.findElementsWithAttributeShallow(
- self.view.node, "controller"))
-
- if self._invalidList:
- self._parent.aggregateInvalid(request, self, self._invalidList)
- else:
- if self._commit:
- if wantsRequest:
- self._commit(request, *self._validList)
- else:
- self._commit(*self._validList)
- self._parent.aggregateValid(request, self, self._invalidList)
-
- def commit(self, request, node, data):
- """If we're using the ListAggregator, we don't want the list of items
- to be rerendered
- xxx Need to have a "node complete" message sent to the controller
- so we can reset state, so controllers can be re-run or ignore input the second time
- """
- pass
-
diff --git a/tools/buildbot/pylibs/twisted/web/woven/interfaces.py b/tools/buildbot/pylibs/twisted/web/woven/interfaces.py
deleted file mode 100644
index 3c2c2ad..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/interfaces.py
+++ /dev/null
@@ -1,198 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_woven -*-
-
-__version__ = "$Revision: 1.13 $"[11:-2]
-
-from zope.interface import Interface
-
-class IModel(Interface):
- """A MVC Model."""
- def addView(view):
- """Add a view for the model to keep track of.
- """
-
- def removeView(view):
- """Remove a view that the model no longer should keep track of.
- """
-
- def notify(changed=None):
- """Notify all views that something was changed on me.
- Passing a dictionary of {'attribute': 'new value'} in changed
- will pass this dictionary to the view for increased performance.
- If you don't want to do this, don't, and just use the traditional
- MVC paradigm of querying the model for things you're interested
- in.
- """
-
- def getData():
- """Return the raw data contained by this Model object, if it is a
- wrapper. If not, return self.
- """
-
- def setData(request, data):
- """Set the raw data referenced by this Model object, if it is a
- wrapper. This is done by telling our Parent model to setSubmodel
- the new data. If this object is not a wrapper, keep the data
- around and return it for subsequent getData calls.
- """
-
- def lookupSubmodel(request, submodelPath):
- """Return an IModel implementor for the given submodel path
- string. This path may be any number of elements separated
- by /. The default implementation splits on "/" and calls
- getSubmodel until the path is exhausted. You will not normally
- need to override this behavior.
- """
-
- def getSubmodel(request, submodelName):
- """Return an IModel implementor for the submodel named
- "submodelName". If this object contains simple data types,
- they can be adapted to IModel using
- model.adaptToIModel(m, parent, name) before returning.
- """
-
- def setSubmodel(request, submodelName, data):
- """Set the given data as a submodel of this model. The data
- need not implement IModel, since getSubmodel should adapt
- the data to IModel before returning it.
- """
-
-
-class IView(Interface):
- """A MVC View"""
- def __init__(model, controller=None):
- """A view must be told what its model is, and may be told what its
- controller is, but can also look up its controller if none specified.
- """
-
- def modelChanged(changed):
- """Dispatch changed messages to any update_* methods which
- may have been defined, then pass the update notification on
- to the controller.
- """
-
- def controllerFactory():
- """Hook for subclasses to customize the controller that is associated
- with the model associated with this view.
-
- Default behavior: Look up a component that implements IController
- for the self.model instance.
- """
-
- def setController(controller):
- """Set the controller that this view is related to."""
-
- def importViewLibrary(moduleOrObject):
- """Import the given object or module into this View's view namespace
- stack. If the given object or module has a getSubview function or
- method, it will be called when a node has a view="foo" attribute.
- If no getSubview method is defined, a default one will be provided
- which looks for the literal name in the namespace.
- """
-
- def getSubview(request, node, model, viewName):
- """Look for a view named "viewName" to handle the node "node".
- When a node <div view="foo" /> is present in the template, this
- method will be called with viewName set to "foo".
-
- Return None if this View doesn't want to provide a Subview for
- the given name.
- """
-
- def setSubviewFactory(name, factory, setup=None):
- """Set the callable "factory", which takes a model and should
- return a Widget, to be called by the default implementation of
- getSubview when the viewName "name" is present in the template.
-
- This would generally be used like this:
-
- view.setSubviewFactory("foo", MyFancyWidgetClass)
-
- This is equivalent to::
-
- def wvfactory_foo(self, request, node, m):
- return MyFancyWidgetClass(m)
-
- Which will cause an instance of MyFancyWidgetClass to be
- instanciated when template node <div view="foo" /> is encountered.
-
- If setup is passed, it will be passed to new instances returned
- from this factory as a setup method. The setup method is called
- each time the Widget is generated. Setup methods take (request,
- widget, model) as arguments.
-
- This is equivalent to::
-
- def wvupdate_foo(self, request, widget, model):
- # whatever you want
- """
-
- def __adapt__(adaptable, default):
- if hasattr(adaptable, 'original'):
- return IView(adaptable.original, default)
- return default
-
-
-class IController(Interface):
- """A MVC Controller"""
- def setView(view):
- """Set the view that this controller is related to.
- """
-
- def importControllerLibrary(moduleOrObject):
- """Import the given object or module into this Controllers's
- controller namespace stack. If the given object or module has a
- getSubcontroller function or method, it will be called when a node
- has a controller="foo" attribute. If no getSubcontroller method is
- defined, a default one will be provided which looks for the literal
- name in the namespace.
- """
-
- def getSubcontroller(request, node, model, controllerName):
- """Look for a controller named "controllerName" to handle the node
- "node". When a node <div controller="foo" /> is present in the
- template, this method will be called with controllerName set to "foo".
-
- Return None if this Controller doesn't want to provide a Subcontroller
- for the given name.
- """
-
- def setSubcontrollerFactory(name, factory):
- """Set the callable "factory", which takes a model and should
- return an InputHandler, to be called by the default implementation of
- getSubview when the controllerName "name" is present in the template.
-
- This would generally be used like this::
-
- view.setSubcontrollerFactory("foo", MyFancyInputHandlerClass)
-
- This is equivalent to::
-
- def wcfactory_foo(self, request, node, m):
- return MyFancyInputHandlerClass(m)
-
- Which will cause an instance of MyFancyInputHandlerClass to be
- instanciated when template node <div controller="foo" /> is
- encountered.
- """
-
- def __adapt__(adaptable, default):
- if hasattr(adaptable, 'original'):
- return IController(adaptable.original, default)
- return default
-
-
-class IWovenLivePage(Interface):
- def getCurrentPage():
- """Return the current page object contained in this session.
- """
-
- def setCurrentPage(page):
- """Set the current page object contained in this session.
- """
-
- def sendJavaScript(js):
- """Send "js" to the live page's persistent output conduit for
- execution in the browser. If there is no conduit connected yet,
- save the js and write it as soon as the output conduit is
- connected.
- """
diff --git a/tools/buildbot/pylibs/twisted/web/woven/model.py b/tools/buildbot/pylibs/twisted/web/woven/model.py
deleted file mode 100644
index 90153c2..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/model.py
+++ /dev/null
@@ -1,487 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_woven -*-
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-__version__ = "$Revision: 1.53 $"[11:-2]
-
-import types
-import weakref
-import warnings
-
-from zope.interface import implements
-
-from twisted.python import components, reflect
-from twisted.internet import defer
-
-from twisted.web.woven import interfaces
-
-class _Nothing: pass
-
-def adaptToIModel(m, parent=None, submodel=None):
- adapted = interfaces.IModel(m, None)
- if adapted is None:
- adapted = Wrapper(m)
- adapted.parent = parent
- adapted.name = submodel
- return adapted
-
-
-class Model:
- """
- A Model which keeps track of views which are looking at it in order
- to notify them when the model changes.
- """
- implements(interfaces.IModel)
-
- def __init__(self, *args, **kwargs):
- if len(args):
- self.original = args[0]
- else:
- self.original = self
- self.name = ''
- self.parent = None
- self.views = []
- self.subviews = {}
- self.submodels = {}
- self._getter = kwargs.get('getter')
- self._setter = kwargs.get('setter')
- self.cachedFor = None
- self.initialize(*args, **kwargs)
-
- def __getstate__(self):
- self.views = []
- self.subviews = {}
- self.submodels = {}
- return self.__dict__
-
- def invalidateCache(self):
- """Invalidate the cache for this object, so the next time
- getData is called, it's getter method is called again.
- """
- self.cachedFor = None
-
- def initialize(self, *args, **kwargs):
- """
- Hook for subclasses to initialize themselves without having to
- mess with the __init__ chain.
- """
- pass
-
- def addView(self, view):
- """
- Add a view for the model to keep track of.
- """
- if view not in [ref() for ref in self.views]:
- self.views.append(weakref.ref(view))
-
- def addSubview(self, name, subview):
- subviewList = self.subviews.get(name, [])
- subviewList.append(weakref.ref(subview))
- self.subviews[name] = subviewList
-
- def removeView(self, view):
- """
- Remove a view that the model no longer should keep track of.
- """
- # AM: loop on a _copy_ of the list, since we're changing it!!!
- for weakref in list(self.views):
- ref = weakref()
- if ref is view or ref is None:
- self.views.remove(weakref)
-
- def setGetter(self, getter):
- self._getter = getter
-
- def setSetter(self, setter):
- self._setter = setter
-
- def notify(self, changed=None):
- """
- Notify all views that something was changed on me.
- Passing a dictionary of {'attribute': 'new value'} in changed
- will pass this dictionary to the view for increased performance.
- If you don't want to do this, don't, and just use the traditional
- MVC paradigm of querying the model for things you're interested
- in.
- """
- self.cachedFor = None
- if changed is None: changed = {}
- retVal = []
- # AM: loop on a _copy_ of the list, since we're changing it!!!
- for view in list(self.views):
- ref = view()
- if ref is not None:
- retVal.append((ref, ref.modelChanged(changed)))
- else:
- self.views.remove(view)
- for key, value in self.subviews.items():
- if value.wantsAllNotifications or changed.has_key(key):
- for item in list(value):
- ref = item()
- if ref is not None:
- retVal.append((ref, ref.modelChanged(changed)))
- else:
- value.remove(item)
- return retVal
-
- protected_names = ['initialize', 'addView', 'addSubview', 'removeView', 'notify', 'getSubmodel', 'setSubmodel', 'getData', 'setData']
- allowed_names = []
-
- def lookupSubmodel(self, request, submodelName):
- """
- Look up a full submodel name. I will split on `/' and call
- L{getSubmodel} on each element in the 'path'.
-
- Override me if you don't want 'traversing'-style lookup, but
- would rather like to look up a model based on the entire model
- name specified.
-
- If you override me to return Deferreds, make sure I look up
- values in a cache (created by L{setSubmodel}) before doing a
- regular Deferred lookup.
-
- XXX: Move bits of this docstring to interfaces.py
- """
- if not submodelName:
- return None
-
- # Special case: If the first character is /
- # Start at the bottom of the model stack
- currentModel = self
- if submodelName[0] == '/':
- while currentModel.parent is not None:
- currentModel = currentModel.parent
- submodelName = submodelName[1:]
-
- submodelList = submodelName.split('/') #[:-1]
-# print "submodelList", submodelList
- for element in submodelList:
- if element == '.' or element == '':
- continue
- elif element == '..':
- currentModel = currentModel.parent
- else:
- currentModel = currentModel.getSubmodel(request, element)
- if currentModel is None:
- return None
- return currentModel
-
- def submodelCheck(self, request, name):
- """Check if a submodel name is allowed. Subclass me to implement a
- name security policy.
- """
- if self.allowed_names:
- return (name in self.allowed_names)
- else:
- return (name and name[0] != '_' and name not in self.protected_names)
-
-
- def submodelFactory(self, request, name):
- warnings.warn("Warning: default Model lookup strategy is changing:"
- "use either AttributeModel or MethodModel for now.",
- DeprecationWarning)
- if hasattr(self, name):
- return getattr(self, name)
- else:
- return None
-
- def getSubmodel(self, request, name):
- """
- Get the submodel `name' of this model. If I ever return a
- Deferred, then I ought to check for cached values (created by
- L{setSubmodel}) before doing a regular Deferred lookup.
- """
- if self.submodels.has_key(name):
- return self.submodels[name]
- if not self.submodelCheck(request, name):
- return None
- m = self.submodelFactory(request, name)
- if m is None:
- return None
- sm = adaptToIModel(m, self, name)
- self.submodels[name] = sm
- return sm
-
- def setSubmodel(self, request=None, name=None, value=None):
- """
- Set a submodel on this model. If getSubmodel or lookupSubmodel
- ever return a Deferred, I ought to set this in a place that
- lookupSubmodel/getSubmodel know about, so they can use it as a
- cache.
- """
- if self.submodelCheck(request, name):
- if self.submodels.has_key(name):
- del self.submodels[name]
- setattr(self, name, value)
-
- def dataWillChange(self):
- pass
-
- def getData(self, request):
- if self.cachedFor != id(request) and self._getter is not None:
- self.cachedFor = id(request)
- self.dataWillChange()
- self.orig = self.original = self._getter(request)
- return self.original
-
- def setData(self, request, data):
- if self._setter is not None:
- self.cachedFor = None
- return self._setter(request, data)
- else:
- if hasattr(self, 'parent') and self.parent:
- self.parent.setSubmodel(request, self.name, data)
- self.orig = self.original = data
-
-
-class MethodModel(Model):
- """Look up submodels with wmfactory_* methods.
- """
-
- def submodelCheck(self, request, name):
- """Allow any submodel for which I have a submodel.
- """
- return hasattr(self, "wmfactory_"+name)
-
- def submodelFactory(self, request, name):
- """Call a wmfactory_name method on this model.
- """
- meth = getattr(self, "wmfactory_"+name)
- return meth(request)
-
- def getSubmodel(self, request=None, name=None):
- if name is None:
- warnings.warn("Warning! getSubmodel should now take the request as the first argument")
- name = request
- request = None
-
- cached = self.submodels.has_key(name)
- sm = Model.getSubmodel(self, request, name)
- if sm is not None:
- if not cached:
- sm.cachedFor = id(request)
- sm._getter = getattr(self, "wmfactory_"+name)
- return sm
-
-
-class AttributeModel(Model):
- """Look up submodels as attributes with hosts.allow/deny-style security.
- """
- def submodelFactory(self, request, name):
- if hasattr(self, name):
- return getattr(self, name)
- else:
- return None
-
-
-#backwards compatibility
-WModel = Model
-
-
-class Wrapper(Model):
- """
- I'm a generic wrapper to provide limited interaction with the
- Woven models and submodels.
- """
- parent = None
- name = None
- def __init__(self, orig):
- Model.__init__(self)
- self.orig = self.original = orig
-
- def dataWillChange(self):
- pass
-
- def __repr__(self):
- myLongName = reflect.qual(self.__class__)
- return "<%s instance at 0x%x: wrapped data: %s>" % (myLongName,
- id(self), self.original)
-
-
-class ListModel(Wrapper):
- """
- I wrap a Python list and allow it to interact with the Woven
- models and submodels.
- """
- def dataWillChange(self):
- self.submodels = {}
-
- def getSubmodel(self, request=None, name=None):
- if name is None and type(request) is type(""):
- warnings.warn("Warning!")
- name = request
- request = None
- if self.submodels.has_key(name):
- return self.submodels[name]
- orig = self.original
- try:
- i = int(name)
- except:
- return None
- if i > len(orig):
- return None
- sm = adaptToIModel(orig[i], self, name)
- self.submodels[name] = sm
- return sm
-
- def setSubmodel(self, request=None, name=None, value=None):
- if value is None:
- warnings.warn("Warning!")
- value = name
- name = request
- request = None
- self.original[int(name)] = value
-
- def __len__(self):
- return len(self.original)
-
- def __getitem__(self, name):
- return self.getSubmodel(None, str(name))
-
- def __setitem__(self, name, value):
- self.setSubmodel(None, str(name), value)
-
- def __repr__(self):
- myLongName = reflect.qual(self.__class__)
- return "<%s instance at 0x%x: wrapped data: %s>" % (myLongName,
- id(self), self.original)
-
-
-class StringModel(ListModel):
-
- """ I wrap a Python string and allow it to interact with the Woven models
- and submodels. """
-
- def setSubmodel(self, request=None, name=None, value=None):
- raise ValueError("Strings are immutable.")
-
-
-# pyPgSQL returns "PgResultSet" instances instead of lists, which look, act
-# and breathe just like lists. pyPgSQL really shouldn't do this, but this works
-try:
- from pyPgSQL import PgSQL
- components.registerAdapter(ListModel, PgSQL.PgResultSet, interfaces.IModel)
-except:
- pass
-
-class DictionaryModel(Wrapper):
- """
- I wrap a Python dictionary and allow it to interact with the Woven
- models and submodels.
- """
- def dataWillChange(self):
- self.submodels = {}
-
- def getSubmodel(self, request=None, name=None):
- if name is None and type(request) is type(""):
- warnings.warn("getSubmodel must get a request argument now")
- name = request
- request = None
- if self.submodels.has_key(name):
- return self.submodels[name]
- orig = self.original
- if name not in orig:
- return None
- sm = adaptToIModel(orig[name], self, name)
- self.submodels[name] = sm
- return sm
-
- def setSubmodel(self, request=None, name=None, value=None):
- if value is None:
- warnings.warn("Warning!")
- value = name
- name = request
- request = None
- self.original[name] = value
-
-
-class AttributeWrapper(Wrapper):
- """
- I wrap an attribute named "name" of the given parent object.
- """
- def __init__(self, parent, name):
- self.original = None
- parent = ObjectWrapper(parent)
- Wrapper.__init__(self, parent.getSubmodel(None, name))
- self.parent = parent
- self.name = name
-
-
-class ObjectWrapper(Wrapper):
- """
- I may wrap an object and allow it to interact with the Woven models
- and submodels. By default, I am not registered for use with anything.
- """
- def getSubmodel(self, request=None, name=None):
- if name is None and type(request) is type(""):
- warnings.warn("Warning!")
- name = request
- request = None
- if self.submodels.has_key(name):
- return self.submodels[name]
- sm = adaptToIModel(getattr(self.original, name), self, name)
- self.submodels[name] = sm
- return sm
-
- def setSubmodel(self, request=None, name=None, value=None):
- if value is None:
- warnings.warn("Warning!")
- value = name
- name = request
- request = None
- setattr(self.original, name, value)
-
-class UnsafeObjectWrapper(ObjectWrapper):
- """
- I may wrap an object and allow it to interact with the Woven models
- and submodels. By default, I am not registered for use with anything.
- I am unsafe because I allow methods to be called. In fact, I am
- dangerously unsafe. Be wary or I will kill your security model!
- """
- def getSubmodel(self, request=None, name=None):
- if name is None and type(request) is type(""):
- warnings.warn("Warning!")
- name = request
- request = None
- if self.submodels.has_key(name):
- return self.submodels[name]
- value = getattr(self.original, name)
- if callable(value):
- return value()
- sm = adaptToIModel(value, self, name)
- self.submodels = sm
- return sm
-
-
-class DeferredWrapper(Wrapper):
- def setData(self, request=None, data=_Nothing):
- if data is _Nothing:
- warnings.warn("setData should be called with request as first arg")
- data = request
- request = None
- if isinstance(data, defer.Deferred):
- self.original = data
- else:
- views, subviews = self.views, self.subviews
- new = adaptToIModel(data, self.parent, self.name)
- self.__class__ = new.__class__
- self.__dict__ = new.__dict__
- self.views, self.subviews = views, subviews
-
-class Link(AttributeModel):
- def __init__(self, href, text):
- AttributeModel.__init__(self)
- self.href = href
- self.text = text
-
-try:
- components.registerAdapter(StringModel, types.StringType, interfaces.IModel)
- components.registerAdapter(ListModel, types.ListType, interfaces.IModel)
- components.registerAdapter(ListModel, types.TupleType, interfaces.IModel)
- components.registerAdapter(DictionaryModel, types.DictionaryType, interfaces.IModel)
- components.registerAdapter(DeferredWrapper, defer.Deferred, interfaces.IModel)
- components.registerAdapter(DeferredWrapper, defer.DeferredList, interfaces.IModel)
-except ValueError:
- # The adapters were already registered
- pass
diff --git a/tools/buildbot/pylibs/twisted/web/woven/page.py b/tools/buildbot/pylibs/twisted/web/woven/page.py
deleted file mode 100644
index 11e7485..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/page.py
+++ /dev/null
@@ -1,105 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_woven -*-
-#
-# page.py
-
-__version__ = "$Revision: 1.23 $"[11:-2]
-
-from twisted.python import reflect
-from twisted.web import resource
-from twisted.web.woven import model, view, controller, interfaces, template
-
-class Page(model.MethodModel, controller.Controller, view.View):
- """
- @cvar appRoot: Set this to True if you want me to call
- request.rememberRootURL() in my getChild, so you can later use
- request.getRootURL() to get the URL to this "application"'s root
- resource. (You don't have to worry if there will be multiple
- instances of this Page involved in a single request; I'll only
- call it for the upper-most instance).
- """
-
- appRoot = False
-
- def __init__(self, *args, **kwargs):
- templateFile = kwargs.setdefault('templateFile', None)
- inputhandlers = kwargs.setdefault('inputhandlers', None)
- controllers = kwargs.setdefault('controllers', None)
- templateDirectory = kwargs.setdefault('templateDirectory', None)
- template = kwargs.setdefault('template', None)
-
- del kwargs['templateFile']
- del kwargs['inputhandlers']
- del kwargs['controllers']
- del kwargs['templateDirectory']
- del kwargs['template']
-
- model.Model.__init__(self, *args, **kwargs)
- if len(args):
- self.model = args[0]
- else:
- self.model = self
-
- controller.Controller.__init__(self, self.model,
- inputhandlers=inputhandlers,
- controllers=controllers)
- self.view = self
- view.View.__init__(self, self.model, controller=self,
- templateFile=templateFile,
- templateDirectory = templateDirectory,
- template = template)
- self.controller = self
- self.controllerRendered = 0
-
- def getChild(self, name, request):
- # Don't call the rememberURL if we already did once; That way
- # we can support an idiom of setting appName as a class
- # attribue *even if* the same class is used more than once in
- # a hierarchy of Pages.
- if self.appRoot and not request.getRootURL():
- request.rememberRootURL()
- return controller.Controller.getChild(self, name, request)
-
-
- def renderView(self, request):
- return view.View.render(self, request,
- doneCallback=self.gatheredControllers)
-
-class LivePage(model.MethodModel, controller.LiveController, view.LiveView):
-
- appRoot = False
-
- def __init__(self, m=None, templateFile=None, inputhandlers=None,
- templateDirectory=None, controllers=None, *args, **kwargs):
- template = kwargs.setdefault('template', None)
- del kwargs['template']
-
- model.Model.__init__(self, *args, **kwargs)
- if m is None:
- self.model = self
- else:
- self.model = m
-
- controller.LiveController.__init__(self, self.model,
- inputhandlers=inputhandlers,
- controllers=controllers)
- self.view = self
- view.View.__init__(self, self.model, controller=self,
- templateFile=templateFile,
- templateDirectory=templateDirectory,
- template=template)
- self.controller = self
- self.controllerRendered = 0
-
-
- def getChild(self, name, request):
- # Don't call the rememberPath if we already did once; That way
- # we can support an idiom of setting appName as a class
- # attribue *even if* the same class is used more than once in
- # a hierarchy of Pages.
- if self.appRoot and not request.getRootURL():
- request.rememberRootURL()
- return controller.Controller.getChild(self, name, request)
-
- def renderView(self, request):
- return view.View.render(self, request,
- doneCallback=self.gatheredControllers)
diff --git a/tools/buildbot/pylibs/twisted/web/woven/simpleguard.py b/tools/buildbot/pylibs/twisted/web/woven/simpleguard.py
deleted file mode 100644
index 65c1ad4..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/simpleguard.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-#
-
-"""
-A simple guard framework for implementing web sites that only need
-'Anonymous' vs 'Logged on' distinction, but nothing more.
-
-If you need
- - multiple levels of access, or
- - multiple-interface applications, or
- - anything else more complex than 'Logged on' and 'Not logged on'
-
-you need to use twisted.web.woven.guard directly.
-"""
-
-from twisted.cred import portal, checkers as checkerslib
-from twisted.web import resource, util
-from twisted.web.woven import guard
-from zope.interface import implements
-
-
-class Authenticated:
-
- def __init__(self, name=None):
- self.name = name
-
- def __nonzero__(self):
- return bool(self.name)
-
-
-class MarkAuthenticatedResource:
-
- implements(resource.IResource)
-
- isLeaf = False
-
- def __init__(self, resource, name):
- self.authenticated = Authenticated(name)
- self.resource = resource
-
- def render(self, request):
- request.setComponent(Authenticated, self.authenticated)
- return self.resource.render(request)
-
- def getChildWithDefault(self, path, request):
- request.setComponent(Authenticated, self.authenticated)
- return self.resource.getChildWithDefault(path, request)
-
-
-class MarkingRealm:
-
- implements(portal.IRealm)
-
- def __init__(self, resource, nonauthenticated=None):
- self.resource = resource
- self.nonauthenticated = (nonauthenticated or
- MarkAuthenticatedResource(resource, None))
-
- def requestAvatar(self, avatarId, mind, *interfaces):
- if resource.IResource not in interfaces:
- raise NotImplementedError("no interface")
- if avatarId:
- return (resource.IResource,
- MarkAuthenticatedResource(self.resource, avatarId),
- lambda:None)
- else:
- return resource.IResource, self.nonauthenticated, lambda:None
-
-
-def parentRedirect(_):
- return util.ParentRedirect()
-
-def guardResource(resource, checkers, callback=parentRedirect, errback=None,
- nonauthenticated=None):
- myPortal = portal.Portal(MarkingRealm(resource, nonauthenticated))
- for checker in checkers+[checkerslib.AllowAnonymousAccess()]:
- myPortal.registerChecker(checker)
- un = guard.UsernamePasswordWrapper(myPortal,
- callback=callback, errback=errback)
- return guard.SessionWrapper(un)
diff --git a/tools/buildbot/pylibs/twisted/web/woven/tapestry.py b/tools/buildbot/pylibs/twisted/web/woven/tapestry.py
deleted file mode 100644
index 11b6042..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/tapestry.py
+++ /dev/null
@@ -1,170 +0,0 @@
-
-"""
-Woven object collections.
-
-THIS MODULE IS HIGHLY EXPERIMENTAL AND MAY BE DEPRECATED SOON.
-"""
-
-from __future__ import nested_scopes
-
-__version__ = "$Revision: 1.13 $"[11:-2]
-
-
-import warnings
-warnings.warn("The tapestry module is deprecated. Use page instead.", DeprecationWarning, 1)
-
-# System Imports
-import sys
-import os
-
-# Twisted Imports
-
-from twisted.internet.defer import Deferred
-
-from twisted.web.resource import Resource, IResource
-from twisted.web.static import redirectTo, addSlash, File, Data
-from twisted.web.server import NOT_DONE_YET
-from twisted.web import util
-
-from twisted.python.reflect import qual
-
-# Sibling Imports
-from twisted.web.woven.view import View
-
-_ChildJuggler = util.DeferredResource
-
-class ModelLoader(Resource):
- """Resource for loading models. (see loadModel)
- """
- def __init__(self, parent, templateFile=None):
- Resource.__init__(self)
- self.parent = parent
- self.templateFile = templateFile
-
- def modelClass(self, other):
- return other
-
- def getChild(self, path, request):
- d = self.loadModel(path, request)
- templateFile = (self.templateFile or self.__class__.__name__+'.html')
- d.addCallback(
- lambda result: self.parent.makeView(self.modelClass(result),
- templateFile, 1))
- return util.DeferredResource(d)
-
- def loadModelNow(self, path, request):
- """Override this rather than loadModel if your model-loading is
- synchronous.
- """
- raise NotImplementedError("%s.loadModelNow" % (reflect.qual(self.__class__)))
-
- def loadModel(self, path, request):
- """Load a model, for the given path and request.
-
- @rtype: L{Deferred}
- """
- from twisted.internet.defer import execute
- return execute(self.loadModelNow, path, request)
-
-
-from twisted.web import microdom
-from twisted.web import domhelpers
-
-class TapestryView(View):
- tapestry = None
- parentCount = 0
- def lookupTemplate(self, request):
- fullFile = os.path.join(self.templateDirectory, self.templateFile)
- document = microdom.parse(open(fullFile))
- if self.tapestry:
- return self.tapestry.templateMutate(document, self.parentCount)
- return document
-
-class Tapestry(Resource):
- """
- I am a top-level aggregation of Woven objects: a full `site' or
- `application'.
- """
- viewFactory = TapestryView
- def __init__(self, templateDirectory, viewFactory=None, metaTemplate=None):
- """
- Create a tapestry with a specified template directory.
- """
- Resource.__init__(self)
- self.templateDirectory = templateDirectory
- if viewFactory is not None:
- self.viewFactory = viewFactory
- if metaTemplate:
- self.metaTemplate = microdom.parse(open(
- os.path.join(templateDirectory, metaTemplate)))
- else:
- self.metaTemplate = None
-
- def templateMutate(self, document, parentCount=0):
- if self.metaTemplate:
- newDoc = self.metaTemplate.cloneNode(1)
- if parentCount:
- dotdot = parentCount * '../'
- for ddname in 'href', 'src', 'action':
- for node in domhelpers.findElementsWithAttribute(newDoc, ddname):
- node.setAttribute(ddname, dotdot + node.getAttribute(ddname))
- ttl = domhelpers.findNodesNamed(newDoc, "title")[0]
- ttl2 = domhelpers.findNodesNamed(document, "title")[0]
- ttl.childNodes[:] = []
- for n in ttl2.childNodes:
- ttl.appendChild(n)
- body = domhelpers.findElementsWithAttribute(newDoc, "class", "__BODY__")[0]
- body2 = domhelpers.findNodesNamed(document, "body")[0]
- ndx = body.parentNode.childNodes.index(body)
- body.parentNode.childNodes[ndx:ndx+1] = body2.childNodes
- for n in body2.childNodes:
- n.parentNode = body.parentNode
- f = open("garbage.html", "wb")
- f.write(newDoc.toprettyxml())
- return newDoc
- return document
-
- def makeView(self, model, name, parentCount=0):
- v = self.viewFactory(model, name)
- v.parentCount = parentCount
- v.templateDirectory = self.templateDirectory
- v.tapestry = self
- v.importViewLibrary(self)
- return v
-
- def getSubview(self, request, node, model, viewName):
- mod = sys.modules[self.__class__.__module__]
- # print "I'm getting a subview", mod, viewName
-
- # try just the name
- vm = getattr(mod, viewName, None)
- if vm:
- return vm(model)
-
- # try the name + a V
- vn2 = "V"+viewName.capitalize()
- vm = getattr(mod, vn2, None)
- if vm:
- return vm(model)
-
- vm = getattr(self, 'wvfactory_'+viewName, None)
- if vm:
- return vm(request, node, model)
-
- def render(self, request):
- return redirectTo(addSlash(request), request)
-
- def getChild(self, path, request):
- if path == '': path = 'index'
- path = path.replace(".","_")
- cm = getattr(self, "wchild_"+path, None)
- if cm:
- p = cm(request)
- if isinstance(p, Deferred):
- return util.DeferredResource(p)
- adapter = IResource(p, None)
- if adapter is not None:
- return adapter
- # maybe we want direct support for ModelLoader?
- # cl = getattr(self, "wload_"+path, None) #???
- return Resource.getChild(self, path, request)
diff --git a/tools/buildbot/pylibs/twisted/web/woven/template.py b/tools/buildbot/pylibs/twisted/web/woven/template.py
deleted file mode 100644
index a25ab43..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/template.py
+++ /dev/null
@@ -1,374 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_woven -*-
-#
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""
-DOMTemplate
-
-Most templating systems provide commands that you embed
-in the HTML to repeat elements, include fragments from other
-files, etc. This works fairly well for simple constructs and people
-tend to get a false sense of simplicity from this. However, in my
-experience, as soon as the programmer wants to make the logic
-even slightly more complicated, the templating system must be
-bent and abused in ways it was never meant to be used.
-
-The theory behind DOMTemplate is that Python code instead
-of template syntax in the HTML should be used to manipulate
-the structure of the HTML. DOMTemplate uses the DOM, a w3c
-standard tree-based representation of an HTML document that
-provides an API that allows you to traverse nodes in the tree,
-examine their attributes, move, add, and delete them. It is a
-fairly low level API, meaning it takes quite a bit of code to get
-a bit done, but it is standard -- learn the DOM once, you can
-use it from ActionScript, JavaScript, Java, C++, whatever.
-
-A DOMTemplate subclass must do two things: indicate which
-template it wants to use, and indicate which elements it is
-interested in.
-
-A short example::
-
- | class Test(DOMTemplate):
- | template = '''
- | <html><head><title>Foo</title></head><body>
- |
- | <div view="Test">
- | This test node will be replaced
- | </div>
- |
- | </body></html>
- | '''
- |
- | def factory_test(self, request, node):
- | '''
- | The test method will be called with the request and the
- | DOM node that the test method was associated with.
- | '''
- | # self.d has been bound to the main DOM "document" object
- | newNode = self.d.createTextNode("Testing, 1,2,3")
- |
- | # Replace the test node with our single new text node
- | return newNode
-"""
-
-import warnings
-
-try:
- import cPickle as pickle
-except ImportError:
- import pickle
-
-import string, os, sys, stat, types
-from twisted.web import microdom
-
-from twisted.python import components
-from twisted.web import resource, html
-from twisted.web.resource import Resource
-from twisted.web.woven import controller, utils, interfaces
-
-from twisted.internet import defer
-from twisted.python import failure
-from twisted.internet import reactor, defer
-from twisted.python import log
-from zope.interface import implements, Interface
-
-from twisted.web.server import NOT_DONE_YET
-STOP_RENDERING = 1
-RESTART_RENDERING = 2
-
-
-
-class INodeMutator(Interface):
- """A component that implements NodeMutator knows how to mutate
- DOM based on the instructions in the object it wraps.
- """
- def generate(request, node):
- """The generate method should do the work of mutating the DOM
- based on the object this adapter wraps.
- """
- pass
-
-
-class NodeMutator:
- implements(INodeMutator)
- def __init__(self, data):
- self.data = data
-
-class NodeNodeMutator(NodeMutator):
- """A NodeNodeMutator replaces the node that is passed in to generate
- with the node it adapts.
- """
- def __init__(self, data):
- assert data is not None
- NodeMutator.__init__(self, data)
-
- def generate(self, request, node):
- if self.data is not node:
- parent = node.parentNode
- if parent:
- parent.replaceChild(self.data, node)
- else:
- log.msg("Warning: There was no parent for node %s; node not mutated." % node)
- return self.data
-
-
-class NoneNodeMutator(NodeMutator):
- def generate(self, request, node):
- return node # do nothing
- child = request.d.createTextNode("None")
- node.parentNode.replaceChild(child, node)
-
-
-class StringNodeMutator(NodeMutator):
- """A StringNodeMutator replaces the node that is passed in to generate
- with the string it adapts.
- """
- def generate(self, request, node):
- if self.data:
- try:
- child = microdom.parseString(self.data)
- except Exception, e:
- log.msg("Error parsing return value, probably invalid xml:", e)
- child = request.d.createTextNode(self.data)
- else:
- child = request.d.createTextNode(self.data)
- nodeMutator = NodeNodeMutator(child)
- return nodeMutator.generate(request, node)
-
-
-components.registerAdapter(NodeNodeMutator, microdom.Node, INodeMutator)
-components.registerAdapter(NoneNodeMutator, type(None), INodeMutator)
-components.registerAdapter(StringNodeMutator, type(""), INodeMutator)
-
-
-class DOMTemplate(Resource):
- """A resource that renders pages using DOM."""
-
- isLeaf = 1
- templateFile = ''
- templateDirectory = ''
- template = ''
- _cachedTemplate = None
-
- def __init__(self, templateFile = None):
- """
- @param templateFile: The name of a file containing a template.
- @type templateFile: String
- """
- Resource.__init__(self)
- if templateFile:
- self.templateFile = templateFile
-
- self.outstandingCallbacks = 0
- self.failed = 0
-
- def render(self, request):
- template = self.getTemplate(request)
- if template:
- self.d = microdom.parseString(template)
- else:
- if not self.templateFile:
- raise AttributeError, "%s does not define self.templateFile to operate on" % self.__class__
- self.d = self.lookupTemplate(request)
- self.handleDocument(request, self.d)
- return NOT_DONE_YET
-
- def getTemplate(self, request):
- """
- Override this if you want to have your subclass look up its template
- using a different method.
- """
- return self.template
-
- def lookupTemplate(self, request):
- """
- Use acquisition to look up the template named by self.templateFile,
- located anywhere above this object in the heirarchy, and use it
- as the template. The first time the template is used it is cached
- for speed.
- """
- if self.template:
- return microdom.parseString(self.template)
- if not self.templateDirectory:
- mod = sys.modules[self.__module__]
- if hasattr(mod, '__file__'):
- self.templateDirectory = os.path.split(mod.__file__)[0]
- # First see if templateDirectory + templateFile is a file
- templatePath = os.path.join(self.templateDirectory, self.templateFile)
- # Check to see if there is an already compiled copy of it
- templateName = os.path.splitext(self.templateFile)[0]
- compiledTemplateName = '.' + templateName + '.pxp'
- compiledTemplatePath = os.path.join(self.templateDirectory, compiledTemplateName)
- # No? Compile and save it
- if (not os.path.exists(compiledTemplatePath) or
- os.stat(compiledTemplatePath)[stat.ST_MTIME] < os.stat(templatePath)[stat.ST_MTIME]):
- compiledTemplate = microdom.parse(templatePath)
- pickle.dump(compiledTemplate, open(compiledTemplatePath, 'wb'), 1)
- else:
- compiledTemplate = pickle.load(open(compiledTemplatePath, "rb"))
- return compiledTemplate
-
- def setUp(self, request, document):
- pass
-
- def handleDocument(self, request, document):
- """
- Handle the root node, and send the page if there are no
- outstanding callbacks when it returns.
- """
- try:
- request.d = document
- self.setUp(request, document)
- # Don't let outstandingCallbacks get to 0 until the
- # entire tree has been recursed
- # If you don't do this, and any callback has already
- # completed by the time the dispatchResultCallback
- # is added in dispachResult, then sendPage will be
- # called prematurely within dispatchResultCallback
- # resulting in much gnashing of teeth.
- self.outstandingCallbacks += 1
- for node in document.childNodes:
- request.currentParent = node
- self.handleNode(request, node)
- self.outstandingCallbacks -= 1
- if not self.outstandingCallbacks:
- return self.sendPage(request)
- except:
- self.renderFailure(None, request)
-
- def dispatchResult(self, request, node, result):
- """
- Check a given result from handling a node and hand it to a process*
- method which will convert the result into a node and insert it
- into the DOM tree. Return the new node.
- """
- if not isinstance(result, defer.Deferred):
- adapter = INodeMutator(result, None)
- if adapter is None:
- raise NotImplementedError(
- "Your factory method returned %s, but there is no "
- "INodeMutator adapter registerred for %s." %
- (result, getattr(result, "__class__",
- None) or type(result)))
- result = adapter.generate(request, node)
- if isinstance(result, defer.Deferred):
- self.outstandingCallbacks += 1
- result.addCallback(self.dispatchResultCallback, request, node)
- result.addErrback(self.renderFailure, request)
- # Got to wait until the callback comes in
- return result
-
- def recurseChildren(self, request, node):
- """
- If this node has children, handle them.
- """
- request.currentParent = node
- if not node: return
- if type(node.childNodes) == type(""): return
- if node.hasChildNodes():
- for child in node.childNodes:
- self.handleNode(request, child)
-
- def dispatchResultCallback(self, result, request, node):
- """
- Deal with a callback from a deferred, dispatching the result
- and recursing children.
- """
- self.outstandingCallbacks -= 1
- node = self.dispatchResult(request, node, result)
- self.recurseChildren(request, node)
- if not self.outstandingCallbacks:
- return self.sendPage(request)
-
- def handleNode(self, request, node):
- """
- Handle a single node by looking up a method for it, calling the method
- and dispatching the result.
-
- Also, handle all childNodes of this node using recursion.
- """
- if not hasattr(node, 'getAttribute'): # text node?
- return node
-
- viewName = node.getAttribute('view')
- if viewName:
- method = getattr(self, "factory_" + viewName, None)
- if not method:
- raise NotImplementedError, "You specified view name %s on a node, but no factory_%s method was found." % (viewName, viewName)
-
- result = method(request, node)
- node = self.dispatchResult(request, node, result)
-
- if not isinstance(node, defer.Deferred):
- self.recurseChildren(request, node)
-
- def sendPage(self, request):
- """
- Send the results of the DOM mutation to the browser.
- """
- page = str(self.d.toxml())
- request.write(page)
- request.finish()
- return page
-
- def renderFailure(self, failure, request):
- try:
- xml = request.d.toxml()
- except:
- xml = ""
-# if not hasattr(request, 'channel'):
-# log.msg("The request got away from me before I could render an error page.")
-# log.err(failure)
-# return failure
- if not self.failed:
- self.failed = 1
- if failure:
- request.write("<html><head><title>%s: %s</title></head><body>\n" % (html.escape(str(failure.type)), html.escape(str(failure.value))))
- else:
- request.write("<html><head><title>Failure!</title></head><body>\n")
- utils.renderFailure(failure, request)
- request.write("<h3>Here is the partially processed DOM:</h3>")
- request.write("\n<pre>\n")
- request.write(html.escape(xml))
- request.write("\n</pre>\n")
- request.write("</body></html>")
- request.finish()
- return failure
-
-##########################################
-# Deprecation zone
-# Wear a hard hat
-##########################################
-
-
-# DOMView is now deprecated since the functionality was merged into domtemplate
-DOMView = DOMTemplate
-
-# DOMController is now renamed woven.controller.Controller
-class DOMController(controller.Controller, Resource):
- """
- A simple controller that automatically passes responsibility on to the view
- class registered for the model. You can override render to perform
- more advanced template lookup logic.
- """
-
- def __init__(self, *args, **kwargs):
- log.msg("DeprecationWarning: DOMController is deprecated; it has been renamed twisted.web.woven.controller.Controller.\n")
- controller.Controller.__init__(self, *args, **kwargs)
- Resource.__init__(self)
-
- def setUp(self, request):
- pass
-
- def render(self, request):
- self.setUp(request)
- self.view = interfaces.IView(self.model, None)
- self.view.setController(self)
- return self.view.render(request)
-
- def process(self, request, **kwargs):
- log.msg("Processing results: ", kwargs)
- return RESTART_RENDERING
diff --git a/tools/buildbot/pylibs/twisted/web/woven/utils.py b/tools/buildbot/pylibs/twisted/web/woven/utils.py
deleted file mode 100644
index 472ac51..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/utils.py
+++ /dev/null
@@ -1,198 +0,0 @@
-from __future__ import nested_scopes
-
-from types import ClassType
-
-from twisted.web import server
-from twisted.web import util as webutil
-from twisted.web.woven import interfaces
-from twisted.python import failure, log, components
-from zope.interface import implements
-
-def renderFailure(fail, request):
- if not fail:
- fail = failure.Failure()
- log.err(fail)
- request.write(webutil.formatFailure(fail))
- #request.finish()
-
-
-def doSendPage(self, d, request):
- page = str(d.toprettyxml())
- request.setHeader('content-length', str(len(page)))
- request.write(page)
- request.finish()
- return page
-
-
-class Script:
- type="javascript1.2"
- def __init__(self, script):
- self.script = script
-
-
-class WovenLivePage:
- implements(interfaces.IWovenLivePage)
-
- currentPage = None
- def __init__(self, session):
- self.session = session
- self.output = None
- self.input = None
- self.cached = []
- self.inputCache = []
-
- def getCurrentPage(self):
- """Return the current page object contained in this session.
- """
- return self.currentPage
-
- def setCurrentPage(self, page):
- """Set the current page object contained in this session.
- """
- self.currentPage = page
-
- def write(self, text):
- """Write "text" to the live page's persistent output conduit.
- If there is no conduit connected yet, save the text and write it
- as soon as the output conduit is connected.
- """
- if self.output is None:
- self.cached.append(text)
- print "CACHING", `self.cached`
- else:
- if isinstance(text, Script):
- if hasattr(self.output, 'writeScript'):
- self.output.writeScript(text.script)
- return
- text = '<script language="%s">%s</script>\r\n' % (text.type, text.script)
- print "WRITING", text
- if text[-1] != '\n':
- text += '\n'
- self.output.write(text)
-
- def sendScript(self, js):
- self.write(Script(js))
- if self.output is not None and not getattr(self.output, 'keepalive', None):
- print "## woot, teh connection was open"
- ## Close the connection; the javascript will have to open it again to get the next event.
- self.output.finish()
- self.output = None
-
- def hookupOutputConduit(self, request):
- """Hook up the given request as the output conduit for this
- session.
- """
- print "TOOT! WE HOOKED UP OUTPUT!", `self.cached`
- self.output = request
- for text in self.cached:
- self.write(text)
- if self.cached:
- self.cached = []
- if not getattr(self.output, 'keepalive', None):
- ## Close the connection; the javascript will have to open it again to get the next event.
- request.finish()
- self.output = None
-
- def unhookOutputConduit(self):
- self.output = None
-
- def hookupInputConduit(self, obj):
- """Hook up the given object as the input conduit for this
- session.
- """
- print "HOOKING UP", self.inputCache
- self.input = obj
- for text in self.inputCache:
- self.pushThroughInputConduit(text)
- self.inputCache = []
- print "DONE HOOKING", self.inputCache
-
- def pushThroughInputConduit(self, inp):
- """Push some text through the input conduit.
- """
- print "PUSHING INPUT", inp
- if self.input is None:
- self.inputCache.append(inp)
- else:
- self.input(inp)
-
-class Stack:
- def __init__(self, stack=None):
- if stack is None:
- self.stack = []
- else:
- self.stack = stack
-
- def push(self, item):
- self.stack.insert(0, item)
-
- def pop(self):
- if self.stack:
- return self.stack.pop(0)
-
- def peek(self):
- for x in self.stack:
- if x is not None:
- return x
-
- def poke(self, item):
- self.stack[0] = item
-
- def clone(self):
- return Stack(self.stack[:])
-
- def __len__(self):
- return len(self.stack)
-
- def __getitem__(self, item):
- return self.stack[item]
-
-
-class GetFunction:
- def __init__(self, namespace):
- self.namespace = namespace
-
- def __call__(self, request, node, model, viewName):
- """Get a name from my namespace.
- """
- from twisted.web.woven import widgets
- if viewName == "None":
- return widgets.DefaultWidget(model)
-
- vc = getattr(self.namespace, viewName, None)
- # don't call modules and random crap in the namespace, only widgets
- if vc and isinstance(vc, (type, ClassType)) and issubclass(vc, widgets.Widget):
- return vc(model)
-
-
-def createGetFunction(namespace):
- return GetFunction(namespace)
-
-
-class SetId:
- def __init__(self, theId):
- self.theId = theId
-
- def __call__(self, request, wid, data):
- id = wid.attributes.get('id', None)
- if not id:
- wid.setAttribute('id', self.theId)
- else:
- top = wid
- while getattr(top, 'parent', None) is not None:
- top = top.parent
- if top.subviews.has_key(self.theId):
- del top.subviews[self.theId]
- top.subviews[id] = wid
- if wid.parent.subviews.has_key(self.theId):
- del wid.parent.subviews[self.theId]
- wid.parent.subviews[id] = wid
-
-
-def createSetIdFunction(theId):
- return SetId(theId)
-
-
-
-components.registerAdapter(WovenLivePage, server.Session, interfaces.IWovenLivePage)
-
diff --git a/tools/buildbot/pylibs/twisted/web/woven/view.py b/tools/buildbot/pylibs/twisted/web/woven/view.py
deleted file mode 100644
index d792fc7..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/view.py
+++ /dev/null
@@ -1,687 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_woven -*-
-#
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-from __future__ import nested_scopes
-
-__version__ = "$Revision: 1.91 $"[11:-2]
-
-# Sibling imports
-import interfaces
-import utils
-import controller
-from utils import doSendPage
-import model
-
-# Twisted imports
-from twisted.internet import defer
-from twisted.python import components
-from twisted.python import log
-from twisted.web import resource, microdom, html, error
-from twisted.web.server import NOT_DONE_YET
-from zope.interface import implements
-
-try:
- import cPickle as pickle
-except ImportError:
- import pickle
-
-import os
-import sys
-import stat
-import warnings
-import types
-
-
-def peek(stack):
- if stack is None:
- return None
- it = None
- while it is None and stack is not None:
- it, stack = stack
- return it
-
-
-def poke(stack, new):
- it, stack = stack
- return (new, stack)
-
-
-def filterStack(stack):
- returnVal = []
- while stack is not None:
- it, stack = stack
- if it is not None:
- returnVal.append(it)
- return returnVal
-
-
-def viewFactory(viewClass):
- return lambda request, node, model: viewClass(model)
-
-def viewMethod(viewClass):
- return lambda self, request, node, model: viewClass(model)
-
-
-templateCache = {}
-
-
-class View:
- implements(resource.IResource, interfaces.IView)
- # wvfactory_xxx method signature: request, node, model; returns Widget
- # wvupdate_xxx method signature: request, widget, data; mutates widget
- # based on data (not necessarily an IModel;
- # has been unwrapped at this point)
-
- wantsAllNotifications = 0
- templateFile = ''
- templateDirectory = ''
- template = ''
-
- isLeaf = 1
-
- def getChild(self, path, request):
- return error.NoResource("No such child resource.")
-
- def getChildWithDefault(self, path, request):
- return self.getChild(path, request)
-
- viewLibraries = []
- setupStacks = 1
- livePage = 0
- doneCallback = None
- templateNode = None
- def __init__(self, m, templateFile=None, templateDirectory=None, template=None, controller=None, doneCallback=None, modelStack=None, viewStack=None, controllerStack=None):
- """
- A view must be told what its model is, and may be told what its
- controller is, but can also look up its controller if none specified.
- """
- if not interfaces.IModel.providedBy(m):
- m = model.adaptToIModel(m, None, None)
- self.model = self.mainModel = m
- # It's the responsibility of the calling code to make sure
- # setController is called on this view before it's rendered.
- self.controller = None
- self.subviews = {}
- if self.setupStacks:
- self.modelStack = None
- self.viewStack = None
- self.controllerStack = None
- if doneCallback is None and self.doneCallback is None:
- self.doneCallback = doSendPage
- else:
- print "DoneCallback", doneCallback
- self.doneCallback = doneCallback
- if template is not None:
- self.template = template
- if templateFile is not None:
- self.templateFile = templateFile
- if templateDirectory is not None:
- self.templateDirectory = templateDirectory
-
- self.outstandingCallbacks = 0
- self.outstandingNodes = []
- self.failed = 0
- self.setupMethods = []
-
- def setupAllStacks(self):
- self.modelStack = (self.model, None)
- self.controllerStack = (self.controller, (input, None))
- self.setupViewStack()
-
- def setUp(self, request, d):
- pass
-
- def setupViewStack(self):
- self.viewStack = None
- if widgets not in self.viewLibraries:
- self.viewLibraries.append(widgets)
- for library in self.viewLibraries:
- if not hasattr(library, 'getSubview'):
- library.getSubview = utils.createGetFunction(library)
- self.viewStack = (library, self.viewStack)
- self.viewStack = (self, self.viewStack)
-
- def importViewLibrary(self, namespace):
- self.viewLibraries.append(namespace)
- return self
-
- def render(self, request, doneCallback=None):
- if not getattr(request, 'currentId', 0):
- request.currentId = 0
- request.currentPage = self
- if self.controller is None:
- self.controller = controller.Controller(self.model)
- if doneCallback is not None:
- self.doneCallback = doneCallback
- else:
- self.doneCallback = doSendPage
- self.setupAllStacks()
- template = self.getTemplate(request)
- if template:
- self.d = microdom.parseString(template, caseInsensitive=0, preserveCase=0)
- else:
- if not self.templateFile:
- raise AttributeError, "%s does not define self.templateFile to operate on" % self.__class__
- self.d = self.lookupTemplate(request)
- request.d = self.d
- self.handleDocument(request, self.d)
- return NOT_DONE_YET
-
- def getTemplate(self, request):
- """
- Override this if you want to have your subclass look up its template
- using a different method.
- """
- return self.template
-
- def lookupTemplate(self, request):
- """
- Use acquisition to look up the template named by self.templateFile,
- located anywhere above this object in the heirarchy, and use it
- as the template. The first time the template is used it is cached
- for speed.
- """
- if self.template:
- return microdom.parseString(self.template, caseInsensitive=0, preserveCase=0)
- if not self.templateDirectory:
- mod = sys.modules[self.__module__]
- if hasattr(mod, '__file__'):
- self.templateDirectory = os.path.split(mod.__file__)[0]
- # First see if templateDirectory + templateFile is a file
- templatePath = os.path.join(self.templateDirectory, self.templateFile)
- if not os.path.exists(templatePath):
- raise RuntimeError, "The template %r was not found." % templatePath
- # Check to see if there is an already parsed copy of it
- mtime = os.path.getmtime(templatePath)
- cachedTemplate = templateCache.get(templatePath, None)
- compiledTemplate = None
-
- if cachedTemplate is not None:
- if cachedTemplate[0] == mtime:
- compiledTemplate = templateCache[templatePath][1].cloneNode(deep=1)
-
- if compiledTemplate is None:
- compiledTemplate = microdom.parse(templatePath, caseInsensitive=0, preserveCase=0)
- templateCache[templatePath] = (mtime, compiledTemplate.cloneNode(deep=1))
- return compiledTemplate
-
- def handleDocument(self, request, document):
- """Handle the root node, and send the page if there are no
- outstanding callbacks when it returns.
- """
- try:
- request.d = document
- self.setUp(request, document)
- # Don't let outstandingCallbacks get to 0 until the
- # entire tree has been recursed
- # If you don't do this, and any callback has already
- # completed by the time the dispatchResultCallback
- # is added in dispachResult, then sendPage will be
- # called prematurely within dispatchResultCallback
- # resulting in much gnashing of teeth.
- self.outstandingNodes = document.childNodes[:] + [1]
- self.outstandingNodes.reverse()
-
- self.outstandingCallbacks += 1
- self.handleOutstanding(request)
- self.outstandingCallbacks -= 1
- if not self.outstandingCallbacks:
- return self.sendPage(request)
- except:
- self.renderFailure(None, request)
-
- def handleOutstanding(self, request):
- while self.outstandingNodes:
- node = self.outstandingNodes.pop()
- if node is 1:
- self.modelStack = self.modelStack[1]
- self.viewStack = self.viewStack[1]
- if self.controllerStack is not None:
- controller, self.controllerStack = self.controllerStack
- if controller is not None:
- controller.exit(request)
- attrs = getattr(node, 'attributes', None)
- if (attrs is not None and
- (attrs.get('model') or attrs.get('view') or attrs.get('controller'))):
- self.outstandingNodes.append(1)
- self.handleNode(request, node)
- else:
- if attrs is not None and (attrs.get('view') or attrs.get('controller')):
- self.outstandingNodes.append(node)
- if hasattr(node, 'childNodes') and node.childNodes:
- self.recurseChildren(request, node)
-
- def recurseChildren(self, request, node):
- """If this node has children, handle them.
- """
- new = node.childNodes[:]
- new.reverse()
- self.outstandingNodes.extend(new)
-
- def dispatchResult(self, request, node, result):
- """Check a given result from handling a node and look up a NodeMutator
- adapter which will convert the result into a node and insert it
- into the DOM tree. Return the new node.
- """
- if not isinstance(result, defer.Deferred):
- if node.parentNode is not None:
- node.parentNode.replaceChild(result, node)
- else:
- raise RuntimeError, "We're dying here, please report this immediately"
- else:
- self.outstandingCallbacks += 1
- result.addCallback(self.dispatchResultCallback, request, node)
- result.addErrback(self.renderFailure, request)
- # Got to wait until the callback comes in
- return result
-
- def modelChanged(self, changed):
- """Rerender this view, because our model has changed.
- """
- # arg. this needs to go away.
- request = changed.get('request', None)
- oldNode = self.node
- #import pdb; pdb.set_trace()
- newNode = self.generate(request, oldNode)
- returnNode = self.dispatchResult(request, oldNode, newNode)
- self.handleNewNode(request, returnNode)
- self.handleOutstanding(request)
- self.controller.domChanged(request, self, returnNode)
-
- def generate(self, request, node):
- """Allow a view to be used like a widget. Will look up the template
- file and return it in place of the incoming node.
- """
- newNode = self.lookupTemplate(request).childNodes[0]
- newNode.setAttribute('id', 'woven_id_%s' % id(self))
- self.node = newNode
- return newNode
-
- def setController(self, controller):
- self.controller = controller
- self.controllerStack = (controller, self.controllerStack)
-
- def setNode(self, node):
- if self.templateNode == None:
- self.templateNode = node
- self.node = node
-
- def setSubmodel(self, name):
- self.submodel = name
-
- def getNodeModel(self, request, node, submodel):
- """
- Get the model object associated with this node. If this node has a
- model= attribute, call getSubmodel on the current model object.
- If not, return the top of the model stack.
- """
- parent = None
- if submodel:
- if submodel == '.':
- m = peek(self.modelStack)
- else:
- modelStack = self.modelStack
- while modelStack is not None:
- parent, modelStack = modelStack
- if parent is None:
- continue
- m = parent.lookupSubmodel(request, submodel)
- if m is not None:
- #print "model", m
- break
- else:
- raise Exception("Node had a model=%s "
- "attribute, but the submodel was not "
- "found in %s." % (submodel,
- filterStack(self.modelStack)))
- else:
- m = None
- self.modelStack = (m, self.modelStack)
- if m is not None:
-# print "M NAME", m.name
-# if parent is not m:
-# m.parent = parent
-# if not getattr(m, 'name', None):
-# m.name = submodel
- return m
- #print `submodel`, self.getTopOfModelStack()
- if submodel:
- return peek(self.modelStack)
- return None
-
- def getNodeController(self, request, node, submodel, model):
- """
- Get a controller object to handle this node. If the node has no
- controller= attribute, first check to see if there is an IController
- adapter for our model.
- """
- controllerName = node.attributes.get('controller')
- controller = None
-
- if model is None:
- model = peek(self.modelStack)
-
- # Look up a controller factory.
- if controllerName:
- #if not node.hasAttribute('name'):
- # warnings.warn("POTENTIAL ERROR: %s had a controller, but not a "
- # "'name' attribute." % node)
- controllerStack = self.controllerStack
- while controllerStack is not None:
- namespace, controllerStack = controllerStack
- if namespace is None:
- continue
- controller = namespace.getSubcontroller(request, node, model, controllerName)
- if controller is not None:
- break
- else:
- raise NotImplementedError("You specified controller name %s on "
- "a node, but no wcfactory_%s method "
- "was found in %s." % (controllerName,
- controllerName,
- filterStack(self.controllerStack)
- ))
- elif node.attributes.get("model"):
- # If no "controller" attribute was specified on the node, see if
- # there is a IController adapter registerred for the model.
- controller = interfaces.IController(
- model,
- None)
-
- return controller
-
-
- def getSubview(self, request, node, model, viewName):
- """Get a sub-view from me.
-
- @returns: L{widgets.Widget}
- """
- view = None
- vm = getattr(self, 'wvfactory_' + viewName, None)
- if vm is None:
- vm = getattr(self, 'factory_' + viewName, None)
- if vm is not None:
- warnings.warn("factory_ methods are deprecated; please use "
- "wvfactory_ instead", DeprecationWarning)
- if vm:
- if vm.func_code.co_argcount == 3 and not type(vm) == types.LambdaType:
- warnings.warn("wvfactory_ methods take (request, node, "
- "model) instead of (request, node) now. \n"
- "Please instantiate your widgets with a "
- "reference to model instead of self.model",
- DeprecationWarning)
- self.model = model
- view = vm(request, node)
- self.model = self.mainModel
- else:
- view = vm(request, node, model)
-
- setupMethod = getattr(self, 'wvupdate_' + viewName, None)
- if setupMethod:
- if view is None:
- view = widgets.Widget(model)
- view.setupMethods.append(setupMethod)
- return view
-
-
- def getNodeView(self, request, node, submodel, model):
- view = None
- viewName = node.attributes.get('view')
-
- if model is None:
- model = peek(self.modelStack)
-
- # Look up a view factory.
- if viewName:
- viewStack = self.viewStack
- while viewStack is not None:
- namespace, viewStack = viewStack
- if namespace is None:
- continue
- try:
- view = namespace.getSubview(request, node, model, viewName)
- except AttributeError:
- # Was that from something in the viewStack that didn't
- # have a getSubview?
- if not hasattr(namespace, "getSubview"):
- log.msg("Warning: There is no getSubview on %r" %
- (namespace,))
- continue
- else:
- # No, something else is really broken.
- raise
- if view is not None:
- break
- else:
- raise NotImplementedError(
- "You specified view name %s on a node %s, but no "
- "wvfactory_%s method was found in %s. (Or maybe they were "
- "found but they returned None.)" % (
- viewName, node, viewName,
- filterStack(self.viewStack)))
- elif node.attributes.get("model"):
- # If no "view" attribute was specified on the node, see if there
- # is a IView adapter registerred for the model.
- # First, see if the model is Componentized.
- if isinstance(model, components.Componentized):
- view = model.getAdapter(interfaces.IView)
- if not view and hasattr(model, '__class__'):
- view = interfaces.IView(model, None)
-
- return view
-
- def handleNode(self, request, node):
- submodelName = node.attributes.get('model')
- if submodelName is None:
- submodelName = ""
- model = self.getNodeModel(request, node, submodelName)
- view = self.getNodeView(request, node, submodelName, model)
- controller = self.getNodeController(request, node, submodelName, model)
- if view or controller:
- if model is None:
- model = peek(self.modelStack)
- if not view or not isinstance(view, View):
- view = widgets.DefaultWidget(model)
-
- if not controller:
- controller = input.DefaultHandler(model)
-
- prevView, stack = self.viewStack
- while isinstance(prevView, widgets.DefaultWidget) and stack is not None:
- prevView, stack = stack
- if prevView is None:
- prevMod = None
- else:
- prevMod = prevView.model
- if model is not prevMod and not isinstance(view, widgets.DefaultWidget):
- model.addView(view)
- submodelList = [x.name for x in filterStack(self.modelStack) if x.name]
- submodelList.reverse()
- submodelName = '/'.join(submodelList)
- if not getattr(view, 'submodel', None):
- view.submodel = submodelName
-
- theId = node.attributes.get("id")
- if self.livePage and not theId:
- theId = "woven_id_%d" % id(view)
- view.setupMethods.append(utils.createSetIdFunction(theId))
- view.outgoingId = theId
- #print "SET AN ID", theId
- self.subviews[theId] = view
- view.parent = peek(self.viewStack)
- view.parent.subviews[theId] = view
- # If a Widget was constructed directly with a model that so far
- # is not in modelspace, we should put it on the stack so other
- # Widgets below this one can find it.
- if view.model is not peek(self.modelStack):
- self.modelStack = poke(self.modelStack, view.model)
-
- cParent = peek(self.controllerStack)
- if controller._parent is None or cParent != controller:
- controller._parent = cParent
-
- self.controllerStack = (controller, self.controllerStack)
- self.viewStack = (view, self.viewStack)
-
- view.viewStack = self.viewStack
- view.controllerStack = self.controllerStack
- view.modelStack = self.modelStack
-
- view.setController(controller)
- view.setNode(node)
-
- if not getattr(controller, 'submodel', None):
- controller.setSubmodel(submodelName)
-
- controller.setView(view)
- controller.setNode(node)
-
- controllerResult = controller.handle(request)
- if controllerResult is not None:
- ## It's a deferred
- controller
- self.outstandingCallbacks += 1
- controllerResult.addCallback(
- self.handleControllerResults,
- request,
- node,
- controller,
- view)
- controllerResult.addErrback(self.renderFailure, request)
- else:
- viewResult = view.generate(request, node)
- returnNode = self.dispatchResult(request, node, viewResult)
- self.handleNewNode(request, returnNode)
- else:
- self.controllerStack = (controller, self.controllerStack)
- self.viewStack = (view, self.viewStack)
-
- def handleControllerResults(self,
- controllerResult, request, node, controller, view):
- """Handle a deferred from a controller.
- """
- self.outstandingCallbacks -= 1
- if isinstance(controllerResult, defer.Deferred):
- self.outstandingCallbacks += 1
- controllerResult.addCallback(
- self.handleControllerResults,
- request,
- node,
- controller,
- view)
- controllerResult.addErrback(self.renderFailure, request)
- else:
- viewResult = view.generate(request, node)
- returnNode = self.dispatchResult(request, node, viewResult)
- self.handleNewNode(request, returnNode)
- return controllerResult
-
- def handleNewNode(self, request, returnNode):
- if not isinstance(returnNode, defer.Deferred):
- self.recurseChildren(request, returnNode)
- else:
- # TODO: Need to handle deferreds here?
- pass
-
- def sendPage(self, request):
- """
- Check to see if handlers recorded any errors before sending the page
- """
- self.doneCallback(self, self.d, request)
-
- def setSubviewFactory(self, name, factory, setup=None, *args, **kwargs):
- setattr(self, "wvfactory_" + name, lambda request, node, m:
- factory(m, *args, **kwargs))
- if setup:
- setattr(self, "wvupdate_" + name, setup)
-
- def __setitem__(self, key, value):
- pass
-
- def unlinkViews(self):
- #print "unlinking views"
- self.model.removeView(self)
- for key, value in self.subviews.items():
- value.unlinkViews()
-# value.model.removeView(value)
-
- def dispatchResultCallback(self, result, request, node):
- """Deal with a callback from a deferred, checking to see if it is
- ok to send the page yet or not.
- """
- self.outstandingCallbacks -= 1
- #node = self.dispatchResult(request, node, result)
- #self.recurseChildren(request, node)
- if not self.outstandingCallbacks:
- self.sendPage(request)
- return result
-
- def renderFailure(self, failure, request):
- try:
- xml = request.d.toprettyxml()
- except:
- xml = ""
-# if not hasattr(request, 'channel'):
-# log.msg("The request got away from me before I could render an error page.")
-# log.err(failure)
-# return failure
- if not self.failed:
- self.failed = 1
- if failure:
- request.write("<html><head><title>%s: %s</title></head><body>\n" % (html.escape(str(failure.type)), html.escape(str(failure.value))))
- else:
- request.write("<html><head><title>Failure!</title></head><body>\n")
- utils.renderFailure(failure, request)
- request.write("<h3>Here is the partially processed DOM:</h3>")
- request.write("\n<pre>\n")
- request.write(html.escape(xml))
- request.write("\n</pre>\n")
- request.write("</body></html>")
- request.finish()
- return failure
-
-class LiveView(View):
- livePage = 1
- def wvfactory_webConduitGlue(self, request, node, m):
- if request.getHeader("user-agent").count("MSIE"):
- return View(m, templateFile="FlashConduitGlue.html")
- else:
- return View(m, templateFile="WebConduitGlue.html")
-
- def wvupdate_woven_flashConduitSessionView(self, request, wid, mod):
- #print "updating flash thingie"
- uid = request.getSession().uid
- n = wid.templateNode
- if n.attributes.has_key('src'):
- n.attributes['src'] = n.attributes.get('src') + '?twisted_session=' + str(uid)
- else:
- n.attributes['value'] = n.attributes.get('value') + '?twisted_session=' + str(uid)
- #print wid.templateNode.toxml()
-
-
-#backwards compatibility
-WView = View
-
-
-def registerViewForModel(view, model):
- """
- Registers `view' as an adapter of `model' for L{interfaces.IView}.
- """
- components.registerAdapter(view, model, interfaces.IView)
-# adapter = resource.IResource(model, None)
-# if adapter is None and resource.IResource.providedBy(view):
-# components.registerAdapter(view, model, resource.IResource)
-
-
-
-#sibling imports::
-
-# If no widget/handler was found in the container controller or view, these
-# modules will be searched.
-
-import input
-import widgets
-
diff --git a/tools/buildbot/pylibs/twisted/web/woven/widgets.py b/tools/buildbot/pylibs/twisted/web/woven/widgets.py
deleted file mode 100644
index 6028338..0000000
--- a/tools/buildbot/pylibs/twisted/web/woven/widgets.py
+++ /dev/null
@@ -1,1036 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_woven -*-
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-# DOMWidgets
-
-from __future__ import nested_scopes
-
-import urllib
-import warnings
-from twisted.web.microdom import parseString, Element, Node
-from twisted.web import domhelpers
-
-
-#sibling imports
-import model
-import template
-import view
-import utils
-import interfaces
-
-from twisted.python import components, failure
-from twisted.python import reflect
-from twisted.python import log
-from twisted.internet import defer
-
-viewFactory = view.viewFactory
-document = parseString("<xml />", caseInsensitive=0, preserveCase=0)
-
-missingPattern = Element("div", caseInsensitive=0, preserveCase=0)
-missingPattern.setAttribute("style", "border: dashed red 1px; margin: 4px")
-
-"""
-DOMWidgets are views which can be composed into bigger views.
-"""
-
-DEBUG = 0
-
-_RAISE = 1
-
-class Dummy:
- pass
-
-class Widget(view.View):
- """
- A Widget wraps an object, its model, for display. The model can be a
- simple Python object (string, list, etc.) or it can be an instance
- of L{model.Model}. (The former case is for interface purposes, so that
- the rest of the code does not have to treat simple objects differently
- from Model instances.)
-
- If the model is-a Model, there are two possibilities:
-
- - we are being called to enable an operation on the model
- - we are really being called to enable an operation on an attribute
- of the model, which we will call the submodel
-
- @cvar tagName: The tag name of the element that this widget creates. If this
- is None, then the original Node will be cloned.
- @cvar wantsAllNotifications: Indicate that this widget wants to recieve every
- change notification from the main model, not just notifications that affect
- its model.
- @ivar model: If the current model is an L{model.Model}, then the result of
- model.getData(). Otherwise the original object itself.
- """
- # wvupdate_xxx method signature: request, widget, data; returns None
-
- # Don't do lots of work setting up my stacks; they will be passed to me
- setupStacks = 0
-
- # Should we clear the node before we render the widget?
- clearNode = 0
-
- # If some code has to ask if a widget is livePage, the answer is yes
- livePage = 1
-
- tagName = None
- def __init__(self, model = None, submodel = None, setup = None, controller = None, viewStack=None, *args, **kwargs):
- """
- @type model: L{interfaces.IModel}
-
- @param submodel: see L{Widget.setSubmodel}
- @type submodel: String
-
- @type setup: Callable
- """
- self.errorFactory = Error
- self.controller = controller
- self.become = None
- self._reset()
- view.View.__init__(self, model)
- self.node = None
- self.templateNode = None
- if submodel:
- self.submodel = submodel
- else:
- self.submodel = ""
- if setup:
- self.setupMethods = [setup]
- else:
- self.setupMethods = []
- self.viewStack = viewStack
- self.initialize(*args, **kwargs)
-
- def _reset(self):
- self.attributes = {}
- self.slots = {}
- self._children = []
-
- def initialize(self, *args, **kwargs):
- """
- Use this method instead of __init__ to initialize your Widget, so you
- don't have to deal with calling the __init__ of the superclass.
- """
- pass
-
- def setSubmodel(self, submodel):
- """
- I use the submodel to know which attribute in self.model I am responsible for
- """
- self.submodel = submodel
-
- def getData(self, request=None):
- """
- I have a model; however since I am a widget I am only responsible
- for a portion of that model. This method returns the portion I am
- responsible for.
-
- The return value of this may be a Deferred; if it is, then
- L{setData} will be called once the result is available.
- """
- return self.model.getData(request)
-
- def setData(self, request=None, data=None):
- """
- If the return value of L{getData} is a Deferred, I am called
- when the result of the Deferred is available.
- """
- self.model.setData(request, data)
-
- def add(self, item):
- """
- Add `item' to the children of the resultant DOM Node of this widget.
-
- @type item: A DOM node or L{Widget}.
- """
- self._children.append(item)
-
- def appendChild(self, item):
- """
- Add `item' to the children of the resultant DOM Node of this widget.
-
- @type item: A DOM node or L{Widget}.
- """
- self._children.append(item)
-
- def insert(self, index, item):
- """
- Insert `item' at `index' in the children list of the resultant DOM Node
- of this widget.
-
- @type item: A DOM node or L{Widget}.
- """
- self._children.insert(index, item)
-
- def setNode(self, node):
- """
- Set a node for this widget to use instead of creating one programatically.
- Useful for looking up a node in a template and using that.
- """
- # self.templateNode should always be the original, unmutated
- # node that was in the HTML template.
- if self.templateNode == None:
- self.templateNode = node
- self.node = node
-
- def cleanNode(self, node):
- """
- Do your part, prevent infinite recursion!
- """
- if not DEBUG:
- if node.attributes.has_key('model'):
- del node.attributes['model']
- if node.attributes.has_key('view'):
- del node.attributes['view']
- if node.attributes.has_key('controller'):
- del node.attributes['controller']
- return node
-
- def generate(self, request, node):
- data = self.getData(request)
- if isinstance(data, defer.Deferred):
- data.addCallback(self.setDataCallback, request, node)
- data.addErrback(utils.renderFailure, request)
- return data
- return self._regenerate(request, node, data)
-
- def _regenerate(self, request, node, data):
- self._reset()
- self.setUp(request, node, data)
- for setupMethod in self.setupMethods:
- setupMethod(request, self, data)
- # generateDOM should always get a reference to the
- # templateNode from the original HTML
- result = self.generateDOM(request, self.templateNode or node)
- if DEBUG:
- result.attributes['woven_class'] = reflect.qual(self.__class__)
- return result
-
- def setDataCallback(self, result, request, node):
- if isinstance(self.getData(request), defer.Deferred):
- self.setData(request, result)
- data = self.getData(request)
- if isinstance(data, defer.Deferred):
- import warnings
- warnings.warn("%r has returned a Deferred multiple times for the "
- "same request; this is a potential infinite loop."
- % self.getData)
- data.addCallback(self.setDataCallback, request, node)
- data.addErrback(utils.renderFailure, request)
- return data
-
- newNode = self._regenerate(request, node, result)
- returnNode = self.dispatchResult(request, node, newNode)
- # isinstance(Element) added because I was having problems with
- # this code trying to call setAttribute on my RawTexts -radix 2003-5-28
- if hasattr(self, 'outgoingId') and isinstance(returnNode, Element):
- returnNode.attributes['id'] = self.outgoingId
- self.handleNewNode(request, returnNode)
- self.handleOutstanding(request)
- if self.subviews:
- self.getTopModel().subviews.update(self.subviews)
- self.controller.domChanged(request, self, returnNode)
-
- ## We need to return the result along the callback chain
- ## so that any other views which added a setDataCallback
- ## to the same deferred will get the correct data.
- return result
-
- def setUp(self, request, node, data):
- """
- Override this method to set up your Widget prior to generateDOM. This
- is a good place to call methods like L{add}, L{insert}, L{__setitem__}
- and L{__getitem__}.
-
- Overriding this method obsoletes overriding generateDOM directly, in
- most cases.
-
- @type request: L{twisted.web.server.Request}.
- @param node: The DOM node which this Widget is operating on.
- @param data: The Model data this Widget is meant to operate upon.
- """
- pass
-
- def generateDOM(self, request, node):
- """
- @returns: A DOM Node to replace the Node in the template that this
- Widget handles. This Node is created based on L{tagName},
- L{children}, and L{attributes} (You should populate these
- in L{setUp}, probably).
- """
- if self.become:
- #print "becoming"
- become = self.become
- self.become = None
- parent = node.parentNode
- node.parentNode = None
- old = node.cloneNode(1)
- node.parentNode = parent
- gen = become.generateDOM(request, node)
- if old.attributes.has_key('model'):
- del old.attributes['model']
- del old.attributes['controller']
- gen.appendChild(old)
- self.node = gen
- return gen
- if DEBUG:
- template = node.toxml()
- log.msg(template)
- if not self.tagName:
- self.tagName = self.templateNode.tagName
- if node is not self.templateNode or self.tagName != self.templateNode.tagName:
- parent = node.parentNode
- node = document.createElement(self.tagName, caseInsensitive=0, preserveCase=0)
- node.parentNode = parent
- else:
- parentNode = node.parentNode
- node.parentNode = None
- if self.clearNode:
- new = node.cloneNode(0)
- else:
- new = node.cloneNode(1)
- node.parentNode = parentNode
- node = self.cleanNode(new)
- #print "NICE CLEAN NODE", node.toxml(), self._children
- node.attributes.update(self.attributes)
- for item in self._children:
- if hasattr(item, 'generate'):
- parentNode = node.parentNode
- node.parentNode = None
- item = item.generate(request, node.cloneNode(1))
- node.parentNode = parentNode
- node.appendChild(item)
- #print "WE GOT A NODE", node.toxml()
- self.node = node
- return self.node
-
- def modelChanged(self, payload):
- request = payload.get('request', None)
- if request is None:
- request = Dummy()
- request.d = document
- oldNode = self.node
- if payload.has_key(self.submodel):
- data = payload[self.submodel]
- else:
- data = self.getData(request)
- newNode = self._regenerate(request, oldNode, data)
- returnNode = self.dispatchResult(request, oldNode, newNode)
- # shot in the dark: this seems to make *my* code work. probably will
- # break if returnNode returns a Deferred, as it's supposed to be able
- # to do -glyph
-# self.viewStack.push(self)
-# self.controller.controllerStack.push(self.controller)
- self.handleNewNode(request, returnNode)
- self.handleOutstanding(request)
- self.controller.domChanged(request, self, returnNode)
-
- def __setitem__(self, item, value):
- """
- Convenience syntax for adding attributes to the resultant DOM Node of
- this widget.
- """
- assert value is not None
- self.attributes[item] = value
-
- setAttribute = __setitem__
-
- def __getitem__(self, item):
- """
- Convenience syntax for getting an attribute from the resultant DOM Node
- of this widget.
- """
- return self.attributes[item]
-
- getAttribute = __getitem__
-
- def setError(self, request, message):
- """
- Convenience method for allowing a Controller to report an error to the
- user. When this is called, a Widget of class self.errorFactory is instanciated
- and set to self.become. When generate is subsequently called, self.become
- will be responsible for mutating the DOM instead of this widget.
- """
- #print "setError called", self
- id = self.attributes.get('id', '')
-
- self.become = self.errorFactory(self.model, message)
- self.become['id'] = id
-# self.modelChanged({'request': request})
-
- def getTopModel(self):
- """Get a reference to this page's top model object.
- """
- top = self.model
- while top.parent is not None:
- top = top.parent
- return top
-
- def getAllPatterns(self, name, default=missingPattern, clone=1, deep=1):
- """Get all nodes below this one which have a matching pattern attribute.
- """
- if self.slots.has_key(name):
- slots = self.slots[name]
- else:
- sm = self.submodel.split('/')[-1]
- slots = domhelpers.locateNodes(self.templateNode, name + 'Of', sm)
- if not slots:
-# slots = domhelpers.locateNodes(self.templateNode, "pattern", name, noNesting=1)
- matcher = lambda n, name=name: isinstance(n, Element) and \
- n.attributes.has_key("pattern") and n.attributes["pattern"] == name
- recurseMatcher = lambda n: isinstance(n, Element) and not n.attributes.has_key("view") and not n.attributes.has_key('model')
- slots = domhelpers.findNodesShallowOnMatch(self.templateNode, matcher, recurseMatcher)
- if not slots:
- msg = 'WARNING: No template nodes were found '\
- '(tagged %s="%s"'\
- ' or pattern="%s") for node %s (full submodel path %s)' % (name + "Of",
- sm, name, self.templateNode, `self.submodel`)
- if default is _RAISE:
- raise Exception(msg)
- if DEBUG:
- warnings.warn(msg)
- if default is missingPattern:
- newNode = missingPattern.cloneNode(1)
- newNode.appendChild(document.createTextNode(msg))
- return [newNode]
- if default is None:
- return None
- return [default]
- self.slots[name] = slots
- if clone:
- return [x.cloneNode(deep) for x in slots]
- return slots
-
- def getPattern(self, name, default=missingPattern, clone=1, deep=1):
- """Get a named slot from the incoming template node. Returns a copy
- of the node and all its children. If there was more than one node with
- the same slot identifier, they will be returned in a round-robin fashion.
- """
- slots = self.getAllPatterns(name, default=default, clone=0)
- if slots is None:
- return None
- slot = slots.pop(0)
- slots.append(slot)
- if clone:
- parentNode = slot.parentNode
- slot.parentNode = None
- clone = slot.cloneNode(deep)
- if clone.attributes.has_key('pattern'):
- del clone.attributes['pattern']
- elif clone.attributes.has_key(name + 'Of'):
- del clone.attributes[name + 'Of']
- slot.parentNode = parentNode
- if DEBUG:
- clone.attributes['ofPattern'] = name + 'Of'
- clone.attributes['nameOf'] = self.submodel.split('/')[-1]
- return clone
- if DEBUG:
- slot.attributes['ofPattern'] = name + 'Of'
- slot.attributes['nameOf'] = self.submodel.split('/')[-1]
- return slot
-
- def addUpdateMethod(self, updateMethod):
- """Add a method to this widget that will be called when the widget
- is being rendered. The signature for this method should be
- updateMethod(request, widget, data) where widget will be the
- instance you are calling addUpdateMethod on.
- """
- self.setupMethods.append(updateMethod)
-
- def addEventHandler(self, eventName, handler, *args):
- """Add an event handler to this widget. eventName is a string
- indicating which javascript event handler should cause this
- handler to fire. Handler is a callable that has the signature
- handler(request, widget, *args).
- """
- def handlerUpdateStep(request, widget, data):
- extraArgs = ''
- for x in args:
- extraArgs += " ,'" + x.replace("'", "\\'") + "'"
- widget[eventName] = "return woven_eventHandler('%s', this%s)" % (eventName, extraArgs)
- setattr(self, 'wevent_' + eventName, handler)
- self.addUpdateMethod(handlerUpdateStep)
-
- def onEvent(self, request, eventName, *args):
- """Dispatch a client-side event to an event handler that was
- registered using addEventHandler.
- """
- eventHandler = getattr(self, 'wevent_' + eventName, None)
- if eventHandler is None:
- raise NotImplementedError("A client side '%s' event occurred,"
- " but there was no event handler registered on %s." %
- (eventName, self))
-
- eventHandler(request, self, *args)
-
-
-class DefaultWidget(Widget):
- def generate(self, request, node):
- """
- By default, we just return the node unchanged
- """
- self.cleanNode(node)
- if self.become:
- become = self.become
- self.become = None
- parent = node.parentNode
- node.parentNode = None
- old = node.cloneNode(1)
- node.parentNode = parent
- gen = become.generateDOM(request, node)
- del old.attributes['model']
- gen.appendChild(self.cleanNode(old))
- return gen
- return node
-
- def modelChanged(self, payload):
- """We're not concerned if the model has changed.
- """
- pass
-
-
-class Attributes(Widget):
- """Set attributes on a node.
-
- Assumes model is a dictionary of attributes.
- """
-
- def setUp(self, request, node, data):
- for k, v in data.items():
- self[k] = v
-
-
-class Text(Widget):
- """
- A simple Widget that renders some text.
- """
- def __init__(self, model, raw=0, clear=1, *args, **kwargs):
- """
- @param model: The text to render.
- @type model: A string or L{model.Model}.
- @param raw: A boolean that specifies whether to render the text as
- a L{domhelpers.RawText} or as a DOM TextNode.
- """
- self.raw = raw
- self.clearNode = clear
- Widget.__init__(self, model, *args, **kwargs)
-
- def generate(self, request, node):
- if self.templateNode is None:
- if self.raw:
- return domhelpers.RawText(str(self.getData(request)))
- else:
- return document.createTextNode(str(self.getData(request)))
- return Widget.generate(self, request, node)
-
- def setUp(self, request, node, data):
- if self.raw:
- textNode = domhelpers.RawText(str(data))
- else:
- textNode = document.createTextNode(str(data))
- self.appendChild(textNode)
-
-
-class ParagraphText(Widget):
- """
- Like a normal text widget, but it takes line breaks in the text and
- formats them as HTML paragraphs.
- """
- def setUp(self, request, node, data):
- nSplit = data.split('\n')
- for line in nSplit:
- if line.strip():
- para = request.d.createElement('p', caseInsensitive=0, preserveCase=0)
- para.appendChild(request.d.createTextNode(line))
- self.add(para)
-
-class Image(Widget):
- """
- A simple Widget that creates an `img' tag.
- """
- tagName = 'img'
- border = '0'
- def setUp(self, request, node, data):
- self['border'] = self.border
- self['src'] = data
-
-
-class Error(Widget):
- tagName = 'span'
- def __init__(self, model, message="", *args, **kwargs):
- Widget.__init__(self, model, *args, **kwargs)
- self.message = message
-
- def generateDOM(self, request, node):
- self['style'] = 'color: red'
- self.add(Text(" " + self.message))
- return Widget.generateDOM(self, request, node)
-
-
-class Div(Widget):
- tagName = 'div'
-
-
-class Span(Widget):
- tagName = 'span'
-
-
-class Br(Widget):
- tagName = 'br'
-
-
-class Input(Widget):
- tagName = 'input'
- def setSubmodel(self, submodel):
- self.submodel = submodel
- self['name'] = submodel
-
- def setUp(self, request, node, data):
- if not self.attributes.has_key('name') and not node.attributes.get('name'):
- if self.submodel:
- id = self.submodel
- else:
- id = self.attributes.get('id', node.attributes.get('id'))
- self['name'] = id
- if data is None:
- data = ''
- if not self.attributes.has_key('value'):
- self['value'] = str(data)
-
-
-class CheckBox(Input):
- def setUp(self, request, node, data):
- self['type'] = 'checkbox'
- Input.setUp(self, request, node, data)
-
-
-class RadioButton(Input):
- def setUp(self, request, node, data):
- self['type'] = 'radio'
- Input.setUp(self, request, node, data)
-
-
-class File(Input):
- def setUp(self, request, node, data):
- self['type'] = 'file'
- Input.setUp(self, request, node, data)
-
-
-class Hidden(Input):
- def setUp(self, request, node, data):
- self['type'] = 'hidden'
- Input.setUp(self, request, node, data)
-
-
-class InputText(Input):
- def setUp(self, request, node, data):
- self['type'] = 'text'
- Input.setUp(self, request, node, data)
-
-
-class PasswordText(Input):
- """
- I render a password input field.
- """
- def setUp(self, request, node, data):
- self['type'] = 'password'
- Input.setUp(self, request, node, data)
-
-
-class Button(Input):
- def setUp(self, request, node, data):
- self['type'] = 'button'
- Input.setUp(self, request, node, data)
-
-
-class Select(Input):
- tagName = 'select'
-
-
-class Option(Widget):
- tagName = 'option'
- def initialize(self):
- self.text = ''
-
- def setText(self, text):
- """
- Set the text to be displayed within the select menu.
- """
- self.text = text
-
- def setValue(self, value):
- self['value'] = str(value)
-
- def setUp(self, request, node, data):
- self.add(Text(self.text or data))
- if data is None:
- data = ''
- if not self.attributes.has_key('value'):
- self['value'] = str(data)
-
-class Anchor(Widget):
- tagName = 'a'
- trailingSlash = ''
- def initialize(self):
- self.baseHREF = ''
- self.parameters = {}
- self.raw = 0
- self.text = ''
-
- def setRaw(self, raw):
- self.raw = raw
-
- def setLink(self, href):
- self.baseHREF= href
-
- def setParameter(self, key, value):
- self.parameters[key] = value
-
- def setText(self, text):
- self.text = text
-
- def setUp(self, request, node, data):
- href = self.baseHREF
- params = urllib.urlencode(self.parameters)
- if params:
- href = href + '?' + params
- self['href'] = href or str(data) + self.trailingSlash
- if data is None:
- data = ""
- self.add(Text(self.text or data, self.raw, 0))
-
-
-class SubAnchor(Anchor):
- def initialize(self):
- warnings.warn(
- "SubAnchor is deprecated, you might want either Anchor or DirectoryAnchor",
- DeprecationWarning)
- Anchor.initialize(self)
-
-
-
-class DirectoryAnchor(Anchor):
- trailingSlash = '/'
-
-
-def appendModel(newNode, modelName):
- if newNode is None: return
- curModel = newNode.attributes.get('model')
- if curModel is None:
- newModel = str(modelName)
- else:
- newModel = '/'.join((curModel, str(modelName)))
- newNode.attributes['model'] = newModel
-
-
-class List(Widget):
- """
- I am a widget which knows how to generateDOM for a python list.
-
- A List should be specified in the template HTML as so::
-
- | <ul model="blah" view="List">
- | <li pattern="emptyList">This will be displayed if the list
- | is empty.</li>
- | <li pattern="listItem" view="Text">Foo</li>
- | </ul>
-
- If you have nested lists, you may also do something like this::
-
- | <table model="blah" view="List">
- | <tr pattern="listHeader"><th>A</th><th>B</th></tr>
- | <tr pattern="emptyList"><td colspan='2'>***None***</td></tr>
- | <tr pattern="listItem">
- | <td><span view="Text" model="1" /></td>
- | <td><span view="Text" model="2" /></td>
- | </tr>
- | <tr pattern="listFooter"><td colspan="2">All done!</td></tr>
- | </table>
-
- Where blah is the name of a list on the model; eg::
-
- | self.model.blah = ['foo', 'bar']
-
- """
- tagName = None
- defaultItemView = "DefaultWidget"
- def generateDOM(self, request, node):
- node = Widget.generateDOM(self, request, node)
- listHeaders = self.getAllPatterns('listHeader', None)
- listFooters = self.getAllPatterns('listFooter', None)
- emptyLists = self.getAllPatterns('emptyList', None)
- domhelpers.clearNode(node)
- if listHeaders:
- node.childNodes.extend(listHeaders)
- for n in listHeaders: n.parentNode = node
- data = self.getData(request)
- if data:
- self._iterateData(node, self.submodel, data)
- elif emptyLists:
- node.childNodes.extend(emptyLists)
- for n in emptyLists: n.parentNode = node
- if listFooters:
- node.childNodes.extend(listFooters)
- for n in listFooters: n.parentNode = node
- return node
-
- def _iterateData(self, parentNode, submodel, data):
- currentListItem = 0
- retVal = [None] * len(data)
- for itemNum in range(len(data)):
- # theory: by appending copies of the li node
- # each node will be handled once we exit from
- # here because handleNode will then recurse into
- # the newly appended nodes
-
- newNode = self.getPattern('listItem')
- if newNode.getAttribute('model') == '.':
- newNode.removeAttribute('model')
- elif not newNode.attributes.get("view"):
- newNode.attributes["view"] = self.defaultItemView
- appendModel(newNode, itemNum)
- retVal[itemNum] = newNode
- newNode.parentNode = parentNode
-# parentNode.appendChild(newNode)
- parentNode.childNodes.extend(retVal)
-
-
-class KeyedList(List):
- """
- I am a widget which knows how to display the values stored within a
- Python dictionary..
-
- A KeyedList should be specified in the template HTML as so::
-
- | <ul model="blah" view="KeyedList">
- | <li pattern="emptyList">This will be displayed if the list is
- | empty.</li>
- | <li pattern="keyedListItem" view="Text">Foo</li>
- | </ul>
-
- I can take advantage of C{listHeader}, C{listFooter} and C{emptyList}
- items just as a L{List} can.
- """
- def _iterateData(self, parentNode, submodel, data):
- """
- """
- currentListItem = 0
- keys = data.keys()
- # Keys may be a tuple, if this is not a true dictionary but a dictionary-like object
- if hasattr(keys, 'sort'):
- keys.sort()
- for key in keys:
- newNode = self.getPattern('keyedListItem')
- if not newNode:
- newNode = self.getPattern('item', _RAISE)
- if newNode:
- warnings.warn("itemOf= is deprecated, "
- "please use listItemOf instead",
- DeprecationWarning)
-
- appendModel(newNode, key)
- if not newNode.attributes.get("view"):
- newNode.attributes["view"] = "DefaultWidget"
- parentNode.appendChild(newNode)
-
-
-class ColumnList(Widget):
- def __init__(self, model, columns=1, start=0, end=0, *args, **kwargs):
- Widget.__init__(self, model, *args, **kwargs)
- self.columns = columns
- self.start = start
- self.end = end
-
- def setColumns(self, columns):
- self.columns = columns
-
- def setStart(self, start):
- self.start = start
-
- def setEnd(self, end):
- self.end = end
-
- def setUp(self, request, node, data):
- pattern = self.getPattern('columnListRow', clone=0)
- if self.end:
- listSize = self.end - self.start
- if listSize > len(data):
- listSize = len(data)
- else:
- listSize = len(data)
- for itemNum in range(listSize):
- if itemNum % self.columns == 0:
- row = self.getPattern('columnListRow')
- domhelpers.clearNode(row)
- node.appendChild(row)
-
- newNode = self.getPattern('columnListItem')
-
- appendModel(newNode, itemNum + self.start)
- if not newNode.attributes.get("view"):
- newNode.attributes["view"] = "DefaultWidget"
- row.appendChild(newNode)
- node.removeChild(pattern)
- return node
-
-
-class Bold(Widget):
- tagName = 'b'
-
-
-class Table(Widget):
- tagName = 'table'
-
-
-class Row(Widget):
- tagName = 'tr'
-
-
-class Cell(Widget):
- tagName = 'td'
-
-
-class RawText(Widget):
- def generateDOM(self, request, node):
- self.node = domhelpers.RawText(self.getData(request))
- return self.node
-
-from types import StringType
-
-class Link(Widget):
- """A utility class for generating <a href='foo'>bar</a> tags.
- """
- tagName = 'a'
- def setUp(self, request, node, data):
- # TODO: we ought to support Deferreds here for both text and href!
- if isinstance(data, StringType):
- node.tagName = self.tagName
- node.attributes["href"] = data
- else:
- data = self.model
- txt = data.getSubmodel(request, "text").getData(request)
- if not isinstance(txt, Node):
- txt = document.createTextNode(txt)
- lnk = data.getSubmodel(request, "href").getData(request)
- self['href'] = lnk
- node.tagName = self.tagName
- domhelpers.clearNode(node)
- node.appendChild(txt)
-
-class RootRelativeLink(Link):
- """
- Just like a regular Link, only it makes the href relative to the
- appRoot (that is, request.getRootURL()).
- """
- def setUp(self, request, node, data):
- # hack, hack: some juggling so I can type less and share more
- # code with Link
- st = isinstance(data, StringType)
- if st:
- data = request.getRootURL() + '/' + data
- Link.setUp(self, request, node, data)
- if not st:
- self['href'] = request.getRootURL() + '/' + self['href']
-
-class ExpandMacro(Widget):
- """A Macro expansion widget modeled after the METAL expander
- in ZPT/TAL/METAL. Usage:
-
- In the Page that is being rendered, place the ExpandMacro widget
- on the node you want replaced with the Macro, and provide nodes
- tagged with fill-slot= attributes which will fill slots in the Macro::
-
- def wvfactory_myMacro(self, request, node, model):
- return ExpandMacro(
- model,
- macroFile="MyMacro.html",
- macroName="main")
-
- <div view="myMacro">
- <span fill-slot="greeting">Hello</span>
- <span fill-slot="greetee">World</span>
- </div>
-
- Then, in your Macro template file ("MyMacro.html" in the above
- example) designate a node as the macro node, and nodes
- inside that as the slot nodes::
-
- <div macro="main">
- <h3><span slot="greeting" />, <span slot="greetee" />!</h3>
- </div>
- """
- def __init__(self, model, macroTemplate = "", macroFile="", macroFileDirectory="", macroName="", **kwargs):
- self.macroTemplate = macroTemplate
- self.macroFile=macroFile
- self.macroFileDirectory=macroFileDirectory
- self.macroName=macroName
- Widget.__init__(self, model, **kwargs)
-
- def generate(self, request, node):
- if self.macroTemplate:
- templ = view.View(
- self.model,
- template = self.macroTemplate).lookupTemplate(request)
- else:
- templ = view.View(
- self.model,
- templateFile=self.macroFile,
- templateDirectory=self.macroFileDirectory).lookupTemplate(request)
-
- ## We are going to return the macro node from the metatemplate,
- ## after replacing any slot= nodes in it with fill-slot= nodes from `node'
- macrolist = domhelpers.locateNodes(templ.childNodes, "macro", self.macroName)
- assert len(macrolist) == 1, ("No macro or more than "
- "one macro named %s found." % self.macroName)
-
- macro = macrolist[0]
- del macro.attributes['macro']
- slots = domhelpers.findElementsWithAttributeShallow(macro, "slot")
- for slot in slots:
- slotName = slot.attributes.get("slot")
- fillerlist = domhelpers.locateNodes(node.childNodes, "fill-slot", slotName)
- assert len(fillerlist) <= 1, "More than one fill-slot found with name %s" % slotName
- if len(fillerlist):
- filler = fillerlist[0]
- filler.tagName = filler.endTagName = slot.tagName
- del filler.attributes['fill-slot']
- del slot.attributes['slot']
- filler.attributes.update(slot.attributes)
- slot.parentNode.replaceChild(filler, slot)
-
- return macro
-
-class DeferredWidget(Widget):
- def setDataCallback(self, result, request, node):
- model = result
- view = None
- if isinstance(model, components.Componentized):
- view = model.getAdapter(interfaces.IView)
- if not view and hasattr(model, '__class__'):
- view = interfaces.IView(model, None)
-
- if view:
- view["id"] = self.attributes.get('id', '')
- view.templateNode = node
- view.controller = self.controller
- return view.setDataCallback(result, request, node)
- else:
- return Widget.setDataCallback(self, result, request, node)
-
-
-class Break(Widget):
- """Break into pdb when this widget is rendered. Mildly
- useful for debugging template structure, model stacks,
- etc.
- """
- def setUp(self, request, node, data):
- import pdb; pdb.set_trace()
-
-
-view.registerViewForModel(Text, model.StringModel)
-view.registerViewForModel(List, model.ListModel)
-view.registerViewForModel(KeyedList, model.DictionaryModel)
-view.registerViewForModel(Link, model.Link)
-view.registerViewForModel(DeferredWidget, model.DeferredWrapper)
diff --git a/tools/buildbot/pylibs/twisted/web/xmlrpc.py b/tools/buildbot/pylibs/twisted/web/xmlrpc.py
deleted file mode 100644
index 70be322..0000000
--- a/tools/buildbot/pylibs/twisted/web/xmlrpc.py
+++ /dev/null
@@ -1,414 +0,0 @@
-# -*- test-case-name: twisted.web.test.test_xmlrpc -*-
-#
-# Copyright (c) 2001-2007 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""
-A generic resource for publishing objects via XML-RPC.
-
-Requires xmlrpclib (comes standard with Python 2.2 and later, otherwise can be
-downloaded from http://www.pythonware.com/products/xmlrpc/).
-
-Maintainer: U{Itamar Shtull-Trauring<mailto:twisted@itamarst.org>}
-"""
-from __future__ import nested_scopes
-
-__version__ = "$Revision: 1.32 $"[11:-2]
-
-# System Imports
-import xmlrpclib
-import urlparse
-
-# Sibling Imports
-from twisted.web import resource, server, http
-from twisted.internet import defer, protocol, reactor
-from twisted.python import log, reflect, failure
-
-# These are deprecated, use the class level definitions
-NOT_FOUND = 8001
-FAILURE = 8002
-
-
-# Useful so people don't need to import xmlrpclib directly
-Fault = xmlrpclib.Fault
-Binary = xmlrpclib.Binary
-Boolean = xmlrpclib.Boolean
-DateTime = xmlrpclib.DateTime
-
-class NoSuchFunction(Fault):
- """
- There is no function by the given name.
- """
-
-
-class Handler:
- """
- Handle a XML-RPC request and store the state for a request in progress.
-
- Override the run() method and return result using self.result,
- a Deferred.
-
- We require this class since we're not using threads, so we can't
- encapsulate state in a running function if we're going to have
- to wait for results.
-
- For example, lets say we want to authenticate against twisted.cred,
- run a LDAP query and then pass its result to a database query, all
- as a result of a single XML-RPC command. We'd use a Handler instance
- to store the state of the running command.
- """
-
- def __init__(self, resource, *args):
- self.resource = resource # the XML-RPC resource we are connected to
- self.result = defer.Deferred()
- self.run(*args)
-
- def run(self, *args):
- # event driven equivalent of 'raise UnimplementedError'
- self.result.errback(
- NotImplementedError("Implement run() in subclasses"))
-
-
-class XMLRPC(resource.Resource):
- """
- A resource that implements XML-RPC.
-
- You probably want to connect this to '/RPC2'.
-
- Methods published can return XML-RPC serializable results, Faults,
- Binary, Boolean, DateTime, Deferreds, or Handler instances.
-
- By default methods beginning with 'xmlrpc_' are published.
-
- Sub-handlers for prefixed methods (e.g., system.listMethods)
- can be added with putSubHandler. By default, prefixes are
- separated with a '.'. Override self.separator to change this.
- """
-
- # Error codes for Twisted, if they conflict with yours then
- # modify them at runtime.
- NOT_FOUND = 8001
- FAILURE = 8002
-
- isLeaf = 1
- separator = '.'
- allowedMethods = ('POST',)
-
- def __init__(self, allowNone=False):
- resource.Resource.__init__(self)
- self.subHandlers = {}
- self.allowNone = allowNone
-
- def putSubHandler(self, prefix, handler):
- self.subHandlers[prefix] = handler
-
- def getSubHandler(self, prefix):
- return self.subHandlers.get(prefix, None)
-
- def getSubHandlerPrefixes(self):
- return self.subHandlers.keys()
-
- def render_POST(self, request):
- request.content.seek(0, 0)
- request.setHeader("content-type", "text/xml")
- try:
- args, functionPath = xmlrpclib.loads(request.content.read())
- except Exception, e:
- f = Fault(self.FAILURE, "Can't deserialize input: %s" % (e,))
- self._cbRender(f, request)
- else:
- try:
- function = self._getFunction(functionPath)
- except Fault, f:
- self._cbRender(f, request)
- else:
- defer.maybeDeferred(function, *args).addErrback(
- self._ebRender
- ).addCallback(
- self._cbRender, request
- )
- return server.NOT_DONE_YET
-
- def _cbRender(self, result, request):
- if isinstance(result, Handler):
- result = result.result
- if not isinstance(result, Fault):
- result = (result,)
- try:
- s = xmlrpclib.dumps(result, methodresponse=True,
- allow_none=self.allowNone)
- except Exception, e:
- f = Fault(self.FAILURE, "Can't serialize output: %s" % (e,))
- s = xmlrpclib.dumps(f, methodresponse=True,
- allow_none=self.allowNone)
- request.setHeader("content-length", str(len(s)))
- request.write(s)
- request.finish()
-
- def _ebRender(self, failure):
- if isinstance(failure.value, Fault):
- return failure.value
- log.err(failure)
- return Fault(self.FAILURE, "error")
-
- def _getFunction(self, functionPath):
- """
- Given a string, return a function, or raise NoSuchFunction.
-
- This returned function will be called, and should return the result
- of the call, a Deferred, or a Fault instance.
-
- Override in subclasses if you want your own policy. The default
- policy is that given functionPath 'foo', return the method at
- self.xmlrpc_foo, i.e. getattr(self, "xmlrpc_" + functionPath).
- If functionPath contains self.separator, the sub-handler for
- the initial prefix is used to search for the remaining path.
- """
- if functionPath.find(self.separator) != -1:
- prefix, functionPath = functionPath.split(self.separator, 1)
- handler = self.getSubHandler(prefix)
- if handler is None:
- raise NoSuchFunction(self.NOT_FOUND,
- "no such subHandler %s" % prefix)
- return handler._getFunction(functionPath)
-
- f = getattr(self, "xmlrpc_%s" % functionPath, None)
- if not f:
- raise NoSuchFunction(self.NOT_FOUND,
- "function %s not found" % functionPath)
- elif not callable(f):
- raise NoSuchFunction(self.NOT_FOUND,
- "function %s not callable" % functionPath)
- else:
- return f
-
- def _listFunctions(self):
- """
- Return a list of the names of all xmlrpc methods.
- """
- return reflect.prefixedMethodNames(self.__class__, 'xmlrpc_')
-
-
-class XMLRPCIntrospection(XMLRPC):
- """
- Implement the XML-RPC Introspection API.
-
- By default, the methodHelp method returns the 'help' method attribute,
- if it exists, otherwise the __doc__ method attribute, if it exists,
- otherwise the empty string.
-
- To enable the methodSignature method, add a 'signature' method attribute
- containing a list of lists. See methodSignature's documentation for the
- format. Note the type strings should be XML-RPC types, not Python types.
- """
-
- def __init__(self, parent):
- """
- Implement Introspection support for an XMLRPC server.
-
- @param parent: the XMLRPC server to add Introspection support to.
- """
-
- XMLRPC.__init__(self)
- self._xmlrpc_parent = parent
-
- def xmlrpc_listMethods(self):
- """
- Return a list of the method names implemented by this server.
- """
- functions = []
- todo = [(self._xmlrpc_parent, '')]
- while todo:
- obj, prefix = todo.pop(0)
- functions.extend([prefix + name for name in obj._listFunctions()])
- todo.extend([ (obj.getSubHandler(name),
- prefix + name + obj.separator)
- for name in obj.getSubHandlerPrefixes() ])
- return functions
-
- xmlrpc_listMethods.signature = [['array']]
-
- def xmlrpc_methodHelp(self, method):
- """
- Return a documentation string describing the use of the given method.
- """
- method = self._xmlrpc_parent._getFunction(method)
- return (getattr(method, 'help', None)
- or getattr(method, '__doc__', None) or '')
-
- xmlrpc_methodHelp.signature = [['string', 'string']]
-
- def xmlrpc_methodSignature(self, method):
- """
- Return a list of type signatures.
-
- Each type signature is a list of the form [rtype, type1, type2, ...]
- where rtype is the return type and typeN is the type of the Nth
- argument. If no signature information is available, the empty
- string is returned.
- """
- method = self._xmlrpc_parent._getFunction(method)
- return getattr(method, 'signature', None) or ''
-
- xmlrpc_methodSignature.signature = [['array', 'string'],
- ['string', 'string']]
-
-
-def addIntrospection(xmlrpc):
- """
- Add Introspection support to an XMLRPC server.
-
- @param xmlrpc: The xmlrpc server to add Introspection support to.
- """
- xmlrpc.putSubHandler('system', XMLRPCIntrospection(xmlrpc))
-
-
-class QueryProtocol(http.HTTPClient):
-
- def connectionMade(self):
- self.sendCommand('POST', self.factory.path)
- self.sendHeader('User-Agent', 'Twisted/XMLRPClib')
- self.sendHeader('Host', self.factory.host)
- self.sendHeader('Content-type', 'text/xml')
- self.sendHeader('Content-length', str(len(self.factory.payload)))
- if self.factory.user:
- auth = '%s:%s' % (self.factory.user, self.factory.password)
- auth = auth.encode('base64').strip()
- self.sendHeader('Authorization', 'Basic %s' % (auth,))
- self.endHeaders()
- self.transport.write(self.factory.payload)
-
- def handleStatus(self, version, status, message):
- if status != '200':
- self.factory.badStatus(status, message)
-
- def handleResponse(self, contents):
- self.factory.parseResponse(contents)
-
-
-payloadTemplate = """<?xml version="1.0"?>
-<methodCall>
-<methodName>%s</methodName>
-%s
-</methodCall>
-"""
-
-
-class _QueryFactory(protocol.ClientFactory):
-
- deferred = None
- protocol = QueryProtocol
-
- def __init__(self, path, host, method, user=None, password=None,
- allowNone=False, args=()):
- self.path, self.host = path, host
- self.user, self.password = user, password
- self.payload = payloadTemplate % (method,
- xmlrpclib.dumps(args, allow_none=allowNone))
- self.deferred = defer.Deferred()
-
- def parseResponse(self, contents):
- if not self.deferred:
- return
- try:
- response = xmlrpclib.loads(contents)
- except:
- deferred, self.deferred = self.deferred, None
- deferred.errback(failure.Failure())
- else:
- deferred, self.deferred = self.deferred, None
- deferred.callback(response[0][0])
-
- def clientConnectionLost(self, _, reason):
- if self.deferred is not None:
- deferred, self.deferred = self.deferred, None
- deferred.errback(reason)
-
- clientConnectionFailed = clientConnectionLost
-
- def badStatus(self, status, message):
- deferred, self.deferred = self.deferred, None
- deferred.errback(ValueError(status, message))
-
-
-
-class Proxy:
- """
- A Proxy for making remote XML-RPC calls.
-
- Pass the URL of the remote XML-RPC server to the constructor.
-
- Use proxy.callRemote('foobar', *args) to call remote method
- 'foobar' with *args.
-
- @ivar queryFactory: object returning a factory for XML-RPC protocol. Mainly
- useful for tests.
- """
- queryFactory = _QueryFactory
-
- def __init__(self, url, user=None, password=None, allowNone=False):
- """
- @type url: C{str}
- @param url: The URL to which to post method calls. Calls will be made
- over SSL if the scheme is HTTPS. If netloc contains username or
- password information, these will be used to authenticate, as long as
- the C{user} and C{password} arguments are not specified.
-
- @type user: C{str} or None
- @param user: The username with which to authenticate with the server
- when making calls. If specified, overrides any username information
- embedded in C{url}. If not specified, a value may be taken from C{url}
- if present.
-
- @type password: C{str} or None
- @param password: The password with which to authenticate with the
- server when making calls. If specified, overrides any password
- information embedded in C{url}. If not specified, a value may be taken
- from C{url} if present.
-
- @type allowNone: C{bool} or None
- @param allowNone: allow the use of None values in parameters. It's
- passed to the underlying xmlrpclib implementation. Default to False.
- """
- scheme, netloc, path, params, query, fragment = urlparse.urlparse(url)
- netlocParts = netloc.split('@')
- if len(netlocParts) == 2:
- userpass = netlocParts.pop(0).split(':')
- self.user = userpass.pop(0)
- try:
- self.password = userpass.pop(0)
- except:
- self.password = None
- else:
- self.user = self.password = None
- hostport = netlocParts[0].split(':')
- self.host = hostport.pop(0)
- try:
- self.port = int(hostport.pop(0))
- except:
- self.port = None
- self.path = path
- if self.path in ['', None]:
- self.path = '/'
- self.secure = (scheme == 'https')
- if user is not None:
- self.user = user
- if password is not None:
- self.password = password
- self.allowNone = allowNone
-
- def callRemote(self, method, *args):
- factory = self.queryFactory(
- self.path, self.host, method, self.user,
- self.password, self.allowNone, args)
- if self.secure:
- from twisted.internet import ssl
- reactor.connectSSL(self.host, self.port or 443,
- factory, ssl.ClientContextFactory())
- else:
- reactor.connectTCP(self.host, self.port or 80, factory)
- return factory.deferred
-
-__all__ = ["XMLRPC", "Handler", "NoSuchFunction", "Fault", "Proxy"]
-