aboutsummaryrefslogtreecommitdiffstats
path: root/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/web/wsgi.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/web/wsgi.py')
-rwxr-xr-xlib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/web/wsgi.py403
1 files changed, 0 insertions, 403 deletions
diff --git a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/web/wsgi.py b/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/web/wsgi.py
deleted file mode 100755
index 0918c4d8..00000000
--- a/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/web/wsgi.py
+++ /dev/null
@@ -1,403 +0,0 @@
-# Copyright (c) Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-"""
-An implementation of
-U{Web Resource Gateway Interface<http://www.python.org/dev/peps/pep-0333/>}.
-"""
-
-__metaclass__ = type
-
-from sys import exc_info
-
-from zope.interface import implements
-
-from twisted.python.log import msg, err
-from twisted.python.failure import Failure
-from twisted.web.resource import IResource
-from twisted.web.server import NOT_DONE_YET
-from twisted.web.http import INTERNAL_SERVER_ERROR
-
-
-class _ErrorStream:
- """
- File-like object instances of which are used as the value for the
- C{'wsgi.errors'} key in the C{environ} dictionary passed to the application
- object.
-
- This simply passes writes on to L{logging<twisted.python.log>} system as
- error events from the C{'wsgi'} system. In the future, it may be desirable
- to expose more information in the events it logs, such as the application
- object which generated the message.
- """
- def write(self, bytes):
- """
- Generate an event for the logging system with the given bytes as the
- message.
-
- This is called in a WSGI application thread, not the I/O thread.
- """
- msg(bytes, system='wsgi', isError=True)
-
-
- def writelines(self, iovec):
- """
- Join the given lines and pass them to C{write} to be handled in the
- usual way.
-
- This is called in a WSGI application thread, not the I/O thread.
-
- @param iovec: A C{list} of C{'\\n'}-terminated C{str} which will be
- logged.
- """
- self.write(''.join(iovec))
-
-
- def flush(self):
- """
- Nothing is buffered, so flushing does nothing. This method is required
- to exist by PEP 333, though.
-
- This is called in a WSGI application thread, not the I/O thread.
- """
-
-
-
-class _InputStream:
- """
- File-like object instances of which are used as the value for the
- C{'wsgi.input'} key in the C{environ} dictionary passed to the application
- object.
-
- This only exists to make the handling of C{readline(-1)} consistent across
- different possible underlying file-like object implementations. The other
- supported methods pass through directly to the wrapped object.
- """
- def __init__(self, input):
- """
- Initialize the instance.
-
- This is called in the I/O thread, not a WSGI application thread.
- """
- self._wrapped = input
-
-
- def read(self, size=None):
- """
- Pass through to the underlying C{read}.
-
- This is called in a WSGI application thread, not the I/O thread.
- """
- # Avoid passing None because cStringIO and file don't like it.
- if size is None:
- return self._wrapped.read()
- return self._wrapped.read(size)
-
-
- def readline(self, size=None):
- """
- Pass through to the underlying C{readline}, with a size of C{-1} replaced
- with a size of C{None}.
-
- This is called in a WSGI application thread, not the I/O thread.
- """
- # Check for -1 because StringIO doesn't handle it correctly. Check for
- # None because files and tempfiles don't accept that.
- if size == -1 or size is None:
- return self._wrapped.readline()
- return self._wrapped.readline(size)
-
-
- def readlines(self, size=None):
- """
- Pass through to the underlying C{readlines}.
-
- This is called in a WSGI application thread, not the I/O thread.
- """
- # Avoid passing None because cStringIO and file don't like it.
- if size is None:
- return self._wrapped.readlines()
- return self._wrapped.readlines(size)
-
-
- def __iter__(self):
- """
- Pass through to the underlying C{__iter__}.
-
- This is called in a WSGI application thread, not the I/O thread.
- """
- return iter(self._wrapped)
-
-
-
-class _WSGIResponse:
- """
- Helper for L{WSGIResource} which drives the WSGI application using a
- threadpool and hooks it up to the L{Request}.
-
- @ivar started: A C{bool} indicating whether or not the response status and
- headers have been written to the request yet. This may only be read or
- written in the WSGI application thread.
-
- @ivar reactor: An L{IReactorThreads} provider which is used to call methods
- on the request in the I/O thread.
-
- @ivar threadpool: A L{ThreadPool} which is used to call the WSGI
- application object in a non-I/O thread.
-
- @ivar application: The WSGI application object.
-
- @ivar request: The L{Request} upon which the WSGI environment is based and
- to which the application's output will be sent.
-
- @ivar environ: The WSGI environment C{dict}.
-
- @ivar status: The HTTP response status C{str} supplied to the WSGI
- I{start_response} callable by the application.
-
- @ivar headers: A list of HTTP response headers supplied to the WSGI
- I{start_response} callable by the application.
-
- @ivar _requestFinished: A flag which indicates whether it is possible to
- generate more response data or not. This is C{False} until
- L{Request.notifyFinish} tells us the request is done, then C{True}.
- """
-
- _requestFinished = False
-
- def __init__(self, reactor, threadpool, application, request):
- self.started = False
- self.reactor = reactor
- self.threadpool = threadpool
- self.application = application
- self.request = request
- self.request.notifyFinish().addBoth(self._finished)
-
- if request.prepath:
- scriptName = '/' + '/'.join(request.prepath)
- else:
- scriptName = ''
-
- if request.postpath:
- pathInfo = '/' + '/'.join(request.postpath)
- else:
- pathInfo = ''
-
- parts = request.uri.split('?', 1)
- if len(parts) == 1:
- queryString = ''
- else:
- queryString = parts[1]
-
- self.environ = {
- 'REQUEST_METHOD': request.method,
- 'REMOTE_ADDR': request.getClientIP(),
- 'SCRIPT_NAME': scriptName,
- 'PATH_INFO': pathInfo,
- 'QUERY_STRING': queryString,
- 'CONTENT_TYPE': request.getHeader('content-type') or '',
- 'CONTENT_LENGTH': request.getHeader('content-length') or '',
- 'SERVER_NAME': request.getRequestHostname(),
- 'SERVER_PORT': str(request.getHost().port),
- 'SERVER_PROTOCOL': request.clientproto}
-
-
- # The application object is entirely in control of response headers;
- # disable the default Content-Type value normally provided by
- # twisted.web.server.Request.
- self.request.defaultContentType = None
-
- for name, values in request.requestHeaders.getAllRawHeaders():
- name = 'HTTP_' + name.upper().replace('-', '_')
- # It might be preferable for http.HTTPChannel to clear out
- # newlines.
- self.environ[name] = ','.join([
- v.replace('\n', ' ') for v in values])
-
- self.environ.update({
- 'wsgi.version': (1, 0),
- 'wsgi.url_scheme': request.isSecure() and 'https' or 'http',
- 'wsgi.run_once': False,
- 'wsgi.multithread': True,
- 'wsgi.multiprocess': False,
- 'wsgi.errors': _ErrorStream(),
- # Attend: request.content was owned by the I/O thread up until
- # this point. By wrapping it and putting the result into the
- # environment dictionary, it is effectively being given to
- # another thread. This means that whatever it is, it has to be
- # safe to access it from two different threads. The access
- # *should* all be serialized (first the I/O thread writes to
- # it, then the WSGI thread reads from it, then the I/O thread
- # closes it). However, since the request is made available to
- # arbitrary application code during resource traversal, it's
- # possible that some other code might decide to use it in the
- # I/O thread concurrently with its use in the WSGI thread.
- # More likely than not, this will break. This seems like an
- # unlikely possibility to me, but if it is to be allowed,
- # something here needs to change. -exarkun
- 'wsgi.input': _InputStream(request.content)})
-
-
- def _finished(self, ignored):
- """
- Record the end of the response generation for the request being
- serviced.
- """
- self._requestFinished = True
-
-
- def startResponse(self, status, headers, excInfo=None):
- """
- The WSGI I{start_response} callable. The given values are saved until
- they are needed to generate the response.
-
- This will be called in a non-I/O thread.
- """
- if self.started and excInfo is not None:
- raise excInfo[0], excInfo[1], excInfo[2]
- self.status = status
- self.headers = headers
- return self.write
-
-
- def write(self, bytes):
- """
- The WSGI I{write} callable returned by the I{start_response} callable.
- The given bytes will be written to the response body, possibly flushing
- the status and headers first.
-
- This will be called in a non-I/O thread.
- """
- def wsgiWrite(started):
- if not started:
- self._sendResponseHeaders()
- self.request.write(bytes)
- self.reactor.callFromThread(wsgiWrite, self.started)
- self.started = True
-
-
- def _sendResponseHeaders(self):
- """
- Set the response code and response headers on the request object, but
- do not flush them. The caller is responsible for doing a write in
- order for anything to actually be written out in response to the
- request.
-
- This must be called in the I/O thread.
- """
- code, message = self.status.split(None, 1)
- code = int(code)
- self.request.setResponseCode(code, message)
-
- for name, value in self.headers:
- # Don't allow the application to control these required headers.
- if name.lower() not in ('server', 'date'):
- self.request.responseHeaders.addRawHeader(name, value)
-
-
- def start(self):
- """
- Start the WSGI application in the threadpool.
-
- This must be called in the I/O thread.
- """
- self.threadpool.callInThread(self.run)
-
-
- def run(self):
- """
- Call the WSGI application object, iterate it, and handle its output.
-
- This must be called in a non-I/O thread (ie, a WSGI application
- thread).
- """
- try:
- appIterator = self.application(self.environ, self.startResponse)
- for elem in appIterator:
- if elem:
- self.write(elem)
- if self._requestFinished:
- break
- close = getattr(appIterator, 'close', None)
- if close is not None:
- close()
- except:
- def wsgiError(started, type, value, traceback):
- err(Failure(value, type, traceback), "WSGI application error")
- if started:
- self.request.transport.loseConnection()
- else:
- self.request.setResponseCode(INTERNAL_SERVER_ERROR)
- self.request.finish()
- self.reactor.callFromThread(wsgiError, self.started, *exc_info())
- else:
- def wsgiFinish(started):
- if not self._requestFinished:
- if not started:
- self._sendResponseHeaders()
- self.request.finish()
- self.reactor.callFromThread(wsgiFinish, self.started)
- self.started = True
-
-
-
-class WSGIResource:
- """
- An L{IResource} implementation which delegates responsibility for all
- resources hierarchically inferior to it to a WSGI application.
-
- @ivar _reactor: An L{IReactorThreads} provider which will be passed on to
- L{_WSGIResponse} to schedule calls in the I/O thread.
-
- @ivar _threadpool: A L{ThreadPool} which will be passed on to
- L{_WSGIResponse} to run the WSGI application object.
-
- @ivar _application: The WSGI application object.
- """
- implements(IResource)
-
- # Further resource segments are left up to the WSGI application object to
- # handle.
- isLeaf = True
-
- def __init__(self, reactor, threadpool, application):
- self._reactor = reactor
- self._threadpool = threadpool
- self._application = application
-
-
- def render(self, request):
- """
- Turn the request into the appropriate C{environ} C{dict} suitable to be
- passed to the WSGI application object and then pass it on.
-
- The WSGI application object is given almost complete control of the
- rendering process. C{NOT_DONE_YET} will always be returned in order
- and response completion will be dictated by the application object, as
- will the status, headers, and the response body.
- """
- response = _WSGIResponse(
- self._reactor, self._threadpool, self._application, request)
- response.start()
- return NOT_DONE_YET
-
-
- def getChildWithDefault(self, name, request):
- """
- Reject attempts to retrieve a child resource. All path segments beyond
- the one which refers to this resource are handled by the WSGI
- application object.
- """
- raise RuntimeError("Cannot get IResource children from WSGIResource")
-
-
- def putChild(self, path, child):
- """
- Reject attempts to add a child resource to this resource. The WSGI
- application object handles all path segments beneath this resource, so
- L{IResource} children can never be found.
- """
- raise RuntimeError("Cannot put IResource children under WSGIResource")
-
-
-__all__ = ['WSGIResource']