diff -Nru twisted-web-10.0.0/debian/changelog twisted-web-11.1.0/debian/changelog --- twisted-web-10.0.0/debian/changelog 2012-01-16 20:12:48.000000000 +0000 +++ twisted-web-11.1.0/debian/changelog 2012-01-16 19:54:50.000000000 +0000 @@ -1,3 +1,45 @@ +twisted-web (11.1.0-1~ppa1~lucid1) lucid; urgency=low + + * Rebuild package for use in PPA. + * Build using dh_pycentral instead of dh_python2 because Maverick + and earlier either don't have dh_python2 or have a version of + dh_python2 that doesn't satisfy the build dependencies. + + -- Jessica McKellar Mon, 16 Jan 2012 14:53:47 -0500 + +twisted-web (11.1.0-1) unstable; urgency=low + + * New upstream version. + + -- Matthias Klose Wed, 21 Dec 2011 12:50:45 +0100 + +twisted-web (11.0.0-1) unstable; urgency=low + + * New upstream version. + + -- Matthias Klose Mon, 18 Apr 2011 22:53:08 +0200 + +twisted-web (10.2.0-1.1) unstable; urgency=low + + * Non-maintainer upload (just a rebuild to add Python 2.7 and + dropPython 2.5 support) + + -- Piotr Ożarowski Sat, 16 Apr 2011 13:00:20 +0200 + +twisted-web (10.2.0-1) unstable; urgency=low + + * New upstream version. + * Conflict with python2.3-minimal. Closes: #574934. + + -- Matthias Klose Thu, 24 Feb 2011 11:55:40 +0100 + +twisted-web (10.1.0-1) unstable; urgency=low + + * New upstream release. + * Build using dh_python2 instead of dh_pycentral. + + -- Matthias Klose Wed, 21 Jul 2010 10:24:43 +0200 + twisted-web (10.0.0-1) unstable; urgency=low * New upstream release diff -Nru twisted-web-10.0.0/debian/control twisted-web-11.1.0/debian/control --- twisted-web-10.0.0/debian/control 2012-01-16 20:12:48.000000000 +0000 +++ twisted-web-11.1.0/debian/control 2012-01-16 19:53:00.000000000 +0000 @@ -3,13 +3,13 @@ Priority: optional Maintainer: Matthias Klose Uploaders: Free Ekanayaka -Build-Depends: debhelper (>= 5.0.37.1), python-central (>= 0.6.7), python-all, python-twisted-core (>= 10.0), patch +Build-Depends: debhelper (>= 5.0.37.1), python-central (>= 0.6.7), python-all, python-twisted-core (>= 11.1), patch XS-Python-Version: all Standards-Version: 3.8.4 Package: python-twisted-web Architecture: all -Depends: ${python:Depends}, python-twisted-core (>= 10.0), ${misc:Depends} +Depends: ${python:Depends}, python-twisted-core (>= 11.1), ${misc:Depends} Conflicts: python-twisted (<< 2.1), python2.3-twisted-web, python2.4-twisted-web Replaces: python-twisted (<< 2.1), python2.3-twisted-web, python2.4-twisted-web XB-Python-Version: ${python:Versions} diff -Nru twisted-web-10.0.0/debian/source/format twisted-web-11.1.0/debian/source/format --- twisted-web-10.0.0/debian/source/format 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/debian/source/format 2012-01-16 20:12:49.000000000 +0000 @@ -0,0 +1 @@ +3.0 (quilt) diff -Nru twisted-web-10.0.0/debian/watch twisted-web-11.1.0/debian/watch --- twisted-web-10.0.0/debian/watch 2012-01-16 20:12:48.000000000 +0000 +++ twisted-web-11.1.0/debian/watch 2011-02-24 10:57:20.000000000 +0000 @@ -1,2 +1,2 @@ version=3 -http://tmrc.mit.edu/mirror/twisted/Web/(\d\.\d)/ TwistedWeb-([\d\.]*)\.tar\.bz2 +http://tmrc.mit.edu/mirror/twisted/Web/(\d+\.\d)/ TwistedWeb-([\d\.]*)\.tar\.bz2 diff -Nru twisted-web-10.0.0/doc/examples/advogato.py twisted-web-11.1.0/doc/examples/advogato.py --- twisted-web-10.0.0/doc/examples/advogato.py 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/examples/advogato.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. # diff -Nru twisted-web-10.0.0/doc/examples/httpclient.py twisted-web-11.1.0/doc/examples/httpclient.py --- twisted-web-10.0.0/doc/examples/httpclient.py 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/examples/httpclient.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. import sys diff -Nru twisted-web-10.0.0/doc/examples/index.html twisted-web-11.1.0/doc/examples/index.html --- twisted-web-10.0.0/doc/examples/index.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/examples/index.html 2011-11-17 10:51:15.000000000 +0000 @@ -91,6 +91,6 @@

Index

- Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/examples/lj.rpy.py twisted-web-11.1.0/doc/examples/lj.rpy.py --- twisted-web-10.0.0/doc/examples/lj.rpy.py 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/examples/lj.rpy.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. # diff -Nru twisted-web-10.0.0/doc/examples/proxy.py twisted-web-11.1.0/doc/examples/proxy.py --- twisted-web-10.0.0/doc/examples/proxy.py 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/examples/proxy.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,5 +1,5 @@ -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. diff -Nru twisted-web-10.0.0/doc/examples/soap.py twisted-web-11.1.0/doc/examples/soap.py --- twisted-web-10.0.0/doc/examples/soap.py 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/examples/soap.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. # diff -Nru twisted-web-10.0.0/doc/examples/webguard.py twisted-web-11.1.0/doc/examples/webguard.py --- twisted-web-10.0.0/doc/examples/webguard.py 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/examples/webguard.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2008 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. import sys diff -Nru twisted-web-10.0.0/doc/examples/web.py twisted-web-11.1.0/doc/examples/web.py --- twisted-web-10.0.0/doc/examples/web.py 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/examples/web.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,5 +1,4 @@ - -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. @@ -10,7 +9,7 @@ # be transmitted to the client. from twisted.internet import reactor -from twisted.web import static, server, vhost, twcgi, script, trp +from twisted.web import static, server, vhost, twcgi, script root = static.File("static") root.processors = { @@ -19,7 +18,6 @@ '.php': twcgi.PHPScript, '.epy': script.PythonScript, '.rpy': script.ResourceScript, - '.trp': trp.ResourceUnpickler, } root.putChild('vhost', vhost.VHostMonsterResource()) site = server.Site(root) diff -Nru twisted-web-10.0.0/doc/howto/client.html twisted-web-11.1.0/doc/howto/client.html --- twisted-web-10.0.0/doc/howto/client.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/client.html 2011-11-17 10:51:14.000000000 +0000 @@ -18,7 +18,7 @@ The Agent
  • +
  • HTTP over SSL
  • Following redirects
  • Using a HTTP proxy
  • Handling HTTP cookies
  • Conclusion
  • @@ -30,10 +30,10 @@

    This document describes how to use the HTTP client included in Twisted - Web. After reading it, you should be able to make HTTP requests using - Twisted Web. You will be able to specify the request method, headers, - and body and you will be able to retrieve the response code, headers, and - body. + Web. After reading it, you should be able to make HTTP and HTTPS + requests using Twisted Web. You will be able to specify the request + method, headers, and body and you will be able to retrieve the response + code, headers, and body.

    @@ -41,9 +41,13 @@

    - This document assumes that you are familiar with Deferreds and Failures, and producers and consumers. + + This document assumes that you are familiar with Deferreds and Failures, and producers and consumers. It also assumes you are familiar with the basic concepts of HTTP, such - as requests and responses, methods, headers, and message bodies. + as requests and responses, methods, headers, and message bodies. The + HTTPS section of this document also assumes you are somewhat familiar with + SSL and have read about using SSL in + Twisted.

    @@ -53,8 +57,8 @@

    Issuing Requests

    - The twisted.web.client.Agent class is the entry - point into the client API. Requests are issued using the request method, which + The twisted.web.client.Agent class is the entry + point into the client API. Requests are issued using the request method, which takes as parameters a request method, a request URI, the request headers, and an object which can produce the request body (if there is to be one). The agent is responsible for connection setup. Because of this, it @@ -112,17 +116,19 @@ As may be obvious, this issues a new GET request for / to the web server on example.com. Agent is responsible for resolving the hostname into an IP address and connecting - to it on port 80. It is also responsible for cleaning up the connection - afterwards. This code sends a request which includes one custom header, - User-Agent. The last argument passed to Agent.request is - None, though, so the request has no body. + to it on port 80 (for HTTP URIs), port 443 (for HTTPS + URIs), or on the port number specified in the URI itself. It is also + responsible for cleaning up the connection afterwards. This code sends + a request which includes one custom header, User-Agent. The + last argument passed to Agent.request is None, + though, so the request has no body.

    Sending a request which does include a body requires passing an object - providing twisted.web.iweb.IBodyProducer + providing twisted.web.iweb.IBodyProducer to Agent.request. This interface extends the more general - IPushProducer + IPushProducer by adding a new length attribute and adding several constraints to the way the producer and consumer interact.

    @@ -130,8 +136,8 @@
    • The length attribute must be a non-negative integer or the constant - twisted.web.iweb.UNKNOWN_LENGTH. If the - length is known, it will be used to specify the value for the + twisted.web.iweb.UNKNOWN_LENGTH. If the length is known, + it will be used to specify the value for the Content-Length header in the request. If the length is unknown the attribute should be set to UNKNOWN_LENGTH. Since more servers support Content-Length, if a length can be @@ -139,14 +145,14 @@
    • - An additional method is required on IEntityBodyProvider + An additional method is required on IBodyProducer implementations: startProducing. This method is used to associate a consumer with the producer. It should return a Deferred which fires when all data has been produced.
    • - IEntityBodyProvider implementations should never call the + IBodyProducer implementations should never call the consumer's unregisterProducer method. Instead, when it has produced all of the data it is going to produce, it should only fire the Deferred returned by startProducing. @@ -154,12 +160,12 @@

    - For additional details about the requirements of IBodyProducer implementations, see + For additional details about the requirements of IBodyProducer implementations, see the API documentation.

    - Here's a simple IEntityBodyProvider implementation which + Here's a simple IBodyProducer implementation which writes an in-memory string to the consumer:

    @@ -265,6 +271,77 @@ Issue a request with a body. - listings/client/sendbody.py
    +

    + If you want to upload a file or you just have some data in a string, you + don't have to copy StringProducer though. Instead, you can + use FileBodyProducer. + This IBodyProducer implementation works with any file-like + object (so use it with a StringIO if your upload data is + already in memory as a string); the idea is the same + as StringProducer from the previous example, but with a + little extra code to only send data as fast as the server will take it. +

    + +

    1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +

    from StringIO import StringIO + +from twisted.internet import reactor +from twisted.web.client import Agent +from twisted.web.http_headers import Headers + +from twisted.web.client import FileBodyProducer + +agent = Agent(reactor) +body = FileBodyProducer(StringIO("hello, world")) +d = agent.request( + 'GET', + 'http://example.com/', + Headers({'User-Agent': ['Twisted Web Client Example'], + 'Content-Type': ['text/x-greeting']}), + body) + +def cbResponse(ignored): + print 'Response received' +d.addCallback(cbResponse) + +def cbShutdown(ignored): + reactor.stop() +d.addBoth(cbShutdown) + +reactor.run() +
    + Another way to issue a request with a body. + - listings/client/filesendbody.py
    + +

    + FileBodyProducer closes the file when it no longer needs it. +

    +

    Receiving Responses

    @@ -290,15 +367,15 @@

    If the request succeeds, though, the Deferred will fire with - a Response. This + a Response. This happens as soon as all the response headers have been received. It happens before any of the response body, if there is one, is processed. The Response object has several attributes giving the response information: its code, version, phrase, and headers, as well as the length of the body to expect. The Response object also - has a method which makes the response body available: deliverBody. - Using the attributes of the response object and this method, here's an - example which displays part of the response to a request: + has a method which makes the response body available: deliverBody. Using the + attributes of the response object and this method, here's an example which + displays part of the response to a request:

    1 @@ -406,9 +483,9 @@ been completely delivered, the protocol's connectionLost method is called. It is important to inspect the Failure passed to connectionLost. If the response body has been - completely received, the failure will wrap a twisted.web.client.ResponseDone exception. This + completely received, the failure will wrap a twisted.web.client.ResponseDone exception. This indicates that it is known that all data has been received. It - is also possible for the failure to wrap a twisted.web.http.PotentialDataLoss exception: this + is also possible for the failure to wrap a twisted.web.http.PotentialDataLoss exception: this indicates that the server framed the response such that there is no way to know when the entire response body has been received. Only HTTP/1.0 servers should behave this way. Finally, it is possible for @@ -420,7 +497,7 @@ Just as protocols associated with a TCP connection are given a transport, so will be a protocol passed to deliverBody. Since it makes no sense to write more data to the connection at this stage of the - request, though, the transport only provides IPushProducer. This allows the + request, though, the transport only provides IPushProducer. This allows the protocol to control the flow of the response data: a call to the transport's pauseProducing method will pause delivery; a later call to resumeProducing will resume it. If it is @@ -441,9 +518,275 @@ stopProducing on its transport.

    +

    HTTP over SSL

    + +

    + Everything you've read so far applies whether the scheme of the request + URI is HTTP or HTTPS. However, to control the SSL + negotiation performed when an HTTPS URI is requested, there's + one extra object to pay attention to: the SSL context factory. +

    + +

    + Agent's constructor takes an optional second argument, a + context factory. This is an object like the context factory described + in Using SSL in Twisted but has + one small difference. The getContext method of this factory + accepts the address from the URL being requested. This allows it to + return a context object which verifies that the server's certificate + matches the URL being requested. +

    + +

    + Here's an example which shows how to use Agent to request + an HTTPS URL with no certificate verification. +

    + +

    1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +

    from twisted.python.log import err +from twisted.web.client import Agent +from twisted.internet import reactor +from twisted.internet.ssl import ClientContextFactory + +class WebClientContextFactory(ClientContextFactory): + def getContext(self, hostname, port): + return ClientContextFactory.getContext(self) + +def display(response): + print "Received response" + print response + +def main(): + contextFactory = WebClientContextFactory() + agent = Agent(reactor, contextFactory) + d = agent.request("GET", "https://example.com/") + d.addCallbacks(display, err) + d.addCallback(lambda ignored: reactor.stop()) + reactor.run() + +if __name__ == "__main__": + main() +
    + +

    + The important point to notice here is that getContext now + accepts two arguments, a hostname and a port number. These two arguments, + a str and an int, give the address to which a + connection is being established to request an HTTPS URL. Because an agent + might make multiple requests over a single connection, + getContext may not be called once for each request. A second + or later request for a URL with the same hostname as a previous request + may re-use an existing connection, and therefore will re-use the + previously returned context object. +

    + +

    + To configure SSL options or enable certificate verification or hostname + checking, provide a context factory which creates suitably configured + context objects. +

    + +

    Following redirects

    + +

    + By itself, Agent doesn't follow HTTP redirects (responses + with 301, 302, 303, 307 status codes and a location header + field). You need to use the twisted.web.client.RedirectAgent class to do so. It + implements a rather strict behavior of the RFC, meaning it will redirect + 301 and 302 as 307, only on GET and HEAD + requests. +

    +

    + The following example shows how to have a redirect-enabled agent. +

    + +

    1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +

    from twisted.python.log import err +from twisted.web.client import Agent, RedirectAgent +from twisted.internet import reactor + +def display(response): + print "Received response" + print response + +def main(): + agent = RedirectAgent(Agent(reactor)) + d = agent.request("GET", "http://example.com/") + d.addCallbacks(display, err) + d.addCallback(lambda ignored: reactor.stop()) + reactor.run() + +if __name__ == "__main__": + main() +
    + +

    Using a HTTP proxy

    + +

    + To be able to use HTTP proxies with an agent, you can use the twisted.web.client.ProxyAgent class. It supports the + same interface as Agent, but takes the endpoint of the proxy + as initializer argument. +

    + +

    + Here's an example demonstrating the use of an HTTP proxy running on + localhost:8000. +

    + +

    1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +

    from twisted.python.log import err +from twisted.web.client import ProxyAgent +from twisted.internet import reactor +from twisted.internet.endpoints import TCP4ClientEndpoint + +def display(response): + print "Received response" + print response + +def main(): + endpoint = TCP4ClientEndpoint(reactor, "localhost", 8000) + agent = ProxyAgent(endpoint) + d = agent.request("GET", "https://example.com/") + d.addCallbacks(display, err) + d.addCallback(lambda ignored: reactor.stop()) + reactor.run() + +if __name__ == "__main__": + main() +
    + +

    + Please refer to the endpoints documentation for + more information about how they work and the twisted.internet.endpoints API documentation to learn + what other kinds of endpoints exist. +

    + +

    Handling HTTP cookies

    + +

    + An existing agent instance can be wrapped with + twisted.web.client.CookieAgent to automatically + store, send and track HTTP cookies. A CookieJar + instance, from the Python standard library module + cookielib, is + used to store the cookie information. An example of using + CookieAgent to perform a request and display the collected + cookies might look like this: +

    + +

    1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +

    from cookielib import CookieJar + +from twisted.internet import reactor +from twisted.python import log +from twisted.web.client import Agent, CookieAgent + +def displayCookies(response, cookieJar): + print 'Received response' + print response + print 'Cookies:', len(cookieJar) + for cookie in cookieJar: + print cookie + +def main(): + cookieJar = CookieJar() + agent = CookieAgent(Agent(reactor), cookieJar) + + d = agent.request('GET', 'http://www.google.com/') + d.addCallback(displayCookies, cookieJar) + d.addErrback(log.err) + d.addCallback(lambda ignored: reactor.stop()) + reactor.run() + +if __name__ == "__main__": + main() +
    + Storing cookies with CookieAgent + - listings/client/cookies.py
    +

    Conclusion -

    +

    You should now understand the basics of the Twisted Web HTTP client. In @@ -464,6 +807,6 @@

    Index

    - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/formindepth.html twisted-web-11.1.0/doc/howto/formindepth.html --- twisted-web-10.0.0/doc/howto/formindepth.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/formindepth.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ - - -Twisted Documentation: Form In Depth - - - - -

    Form In Depth

    -
      -
      - - -

      XXX: To be written

      - -
      - -

      Index

      - Version: 10.0.0 - - \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/glossary.html twisted-web-11.1.0/doc/howto/glossary.html --- twisted-web-10.0.0/doc/howto/glossary.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/glossary.html 2011-11-17 10:51:14.000000000 +0000 @@ -17,8 +17,8 @@
      resource
      An object accessible via HTTP at one or more URIs. In Twisted Web, - a resource is represented by an object which provides twisted.web.resource.IResource and most often is - a subclass of twisted.web.resource.Resource. For example, here + a resource is represented by an object which provides twisted.web.resource.IResource and most often is + a subclass of twisted.web.resource.Resource. For example, here is a resource which represents a simple HTML greeting.

      1 @@ -37,6 +37,6 @@

      Index

      - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/index.html twisted-web-11.1.0/doc/howto/index.html --- twisted-web-10.0.0/doc/howto/index.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/index.html 2011-11-17 10:51:14.000000000 +0000 @@ -23,10 +23,12 @@ @@ -45,6 +47,6 @@

      Index

      - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/listings/client/cookies.py twisted-web-11.1.0/doc/howto/listings/client/cookies.py --- twisted-web-10.0.0/doc/howto/listings/client/cookies.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/client/cookies.py 2011-06-27 16:55:57.000000000 +0000 @@ -0,0 +1,25 @@ +from cookielib import CookieJar + +from twisted.internet import reactor +from twisted.python import log +from twisted.web.client import Agent, CookieAgent + +def displayCookies(response, cookieJar): + print 'Received response' + print response + print 'Cookies:', len(cookieJar) + for cookie in cookieJar: + print cookie + +def main(): + cookieJar = CookieJar() + agent = CookieAgent(Agent(reactor), cookieJar) + + d = agent.request('GET', 'http://www.google.com/') + d.addCallback(displayCookies, cookieJar) + d.addErrback(log.err) + d.addCallback(lambda ignored: reactor.stop()) + reactor.run() + +if __name__ == "__main__": + main() diff -Nru twisted-web-10.0.0/doc/howto/listings/client/filesendbody.py twisted-web-11.1.0/doc/howto/listings/client/filesendbody.py --- twisted-web-10.0.0/doc/howto/listings/client/filesendbody.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/client/filesendbody.py 2011-06-24 00:42:51.000000000 +0000 @@ -0,0 +1,26 @@ +from StringIO import StringIO + +from twisted.internet import reactor +from twisted.web.client import Agent +from twisted.web.http_headers import Headers + +from twisted.web.client import FileBodyProducer + +agent = Agent(reactor) +body = FileBodyProducer(StringIO("hello, world")) +d = agent.request( + 'GET', + 'http://example.com/', + Headers({'User-Agent': ['Twisted Web Client Example'], + 'Content-Type': ['text/x-greeting']}), + body) + +def cbResponse(ignored): + print 'Response received' +d.addCallback(cbResponse) + +def cbShutdown(ignored): + reactor.stop() +d.addBoth(cbShutdown) + +reactor.run() diff -Nru twisted-web-10.0.0/doc/howto/listings/element_1.py twisted-web-11.1.0/doc/howto/listings/element_1.py --- twisted-web-10.0.0/doc/howto/listings/element_1.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/element_1.py 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,12 @@ +from twisted.web.template import Element, renderer, XMLFile + +class ExampleElement(Element): + loader = XMLFile('template-1.xml') + + @renderer + def header(self, request, tag): + return tag('Header.') + + @renderer + def footer(self, request, tag): + return tag('Footer.') diff -Nru twisted-web-10.0.0/doc/howto/listings/element_2.py twisted-web-11.1.0/doc/howto/listings/element_2.py --- twisted-web-10.0.0/doc/howto/listings/element_2.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/element_2.py 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,12 @@ +from twisted.web.template import Element, renderer, XMLFile, tags + +class ExampleElement(Element): + loader = XMLFile('template-1.xml') + + @renderer + def header(self, request, tag): + return tag(tags.b('Header.')) + + @renderer + def footer(self, request, tag): + return tag(tags.b('Footer.')) diff -Nru twisted-web-10.0.0/doc/howto/listings/element_3.py twisted-web-11.1.0/doc/howto/listings/element_3.py --- twisted-web-10.0.0/doc/howto/listings/element_3.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/element_3.py 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,12 @@ +from twisted.web.template import Element, renderer, XMLFile, tags + +class ExampleElement(Element): + loader = XMLFile('template-1.xml') + + @renderer + def header(self, request, tag): + return tag(tags.p('Header.'), id='header') + + @renderer + def footer(self, request, tag): + return tag(tags.p('Footer.'), id='footer') diff -Nru twisted-web-10.0.0/doc/howto/listings/iteration-1.py twisted-web-11.1.0/doc/howto/listings/iteration-1.py --- twisted-web-10.0.0/doc/howto/listings/iteration-1.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/iteration-1.py 2011-10-04 22:35:21.000000000 +0000 @@ -0,0 +1,16 @@ +from twisted.web.template import Element, renderer, XMLFile, flattenString + +class WidgetsElement(Element): + loader = XMLFile('iteration-1.xml') + + widgetData = ['gadget', 'contraption', 'gizmo', 'doohickey'] + + @renderer + def widgets(self, request, tag): + for widget in self.widgetData: + yield tag.clone().fillSlots(widgetName=widget) + +def printResult(result): + print result + +flattenString(None, WidgetsElement()).addCallback(printResult) diff -Nru twisted-web-10.0.0/doc/howto/listings/iteration-1.xml twisted-web-11.1.0/doc/howto/listings/iteration-1.xml --- twisted-web-10.0.0/doc/howto/listings/iteration-1.xml 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/iteration-1.xml 2011-10-04 22:35:21.000000000 +0000 @@ -0,0 +1,3 @@ +
        +
      • +
      diff -Nru twisted-web-10.0.0/doc/howto/listings/iteration-output-1.xml twisted-web-11.1.0/doc/howto/listings/iteration-output-1.xml --- twisted-web-10.0.0/doc/howto/listings/iteration-output-1.xml 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/iteration-output-1.xml 2011-10-04 22:35:21.000000000 +0000 @@ -0,0 +1,3 @@ +
        +
      • gadget
      • contraption
      • gizmo
      • doohickey
      • +
      diff -Nru twisted-web-10.0.0/doc/howto/listings/output-1.html twisted-web-11.1.0/doc/howto/listings/output-1.html --- twisted-web-10.0.0/doc/howto/listings/output-1.html 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/output-1.html 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,9 @@ + + +
      Header.
      +
      +

      Content goes here.

      +
      +
      Footer.
      + + diff -Nru twisted-web-10.0.0/doc/howto/listings/output-2.html twisted-web-11.1.0/doc/howto/listings/output-2.html --- twisted-web-10.0.0/doc/howto/listings/output-2.html 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/output-2.html 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,9 @@ + + +
      Header.
      +
      +

      Content goes here.

      +
      +
      Footer.
      + + diff -Nru twisted-web-10.0.0/doc/howto/listings/output-3.html twisted-web-11.1.0/doc/howto/listings/output-3.html --- twisted-web-10.0.0/doc/howto/listings/output-3.html 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/output-3.html 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,9 @@ + + + +
      +

      Content goes here.

      +
      + + + diff -Nru twisted-web-10.0.0/doc/howto/listings/quoting_element.py twisted-web-11.1.0/doc/howto/listings/quoting_element.py --- twisted-web-10.0.0/doc/howto/listings/quoting_element.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/quoting_element.py 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,12 @@ +from twisted.web.template import Element, renderer, XMLFile + +class ExampleElement(Element): + loader = XMLFile('template-1.xml') + + @renderer + def header(self, request, tag): + return tag('<<
      >>!') + + @renderer + def footer(self, request, tag): + return tag('>>>"Footer!"<<<', id='<"fun">') diff -Nru twisted-web-10.0.0/doc/howto/listings/quoting-output.html twisted-web-11.1.0/doc/howto/listings/quoting-output.html --- twisted-web-10.0.0/doc/howto/listings/quoting-output.html 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/quoting-output.html 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,9 @@ + + +
      <<<Header>>>!
      +
      +

      Content goes here.

      +
      +
      >>>"Footer!"<<<
      + + diff -Nru twisted-web-10.0.0/doc/howto/listings/render_1.py twisted-web-11.1.0/doc/howto/listings/render_1.py --- twisted-web-10.0.0/doc/howto/listings/render_1.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/render_1.py 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,5 @@ +from twisted.web.template import flattenString +from element_1 import ExampleElement +def renderDone(output): + print output +flattenString(None, ExampleElement()).addCallback(renderDone) diff -Nru twisted-web-10.0.0/doc/howto/listings/render_2.py twisted-web-11.1.0/doc/howto/listings/render_2.py --- twisted-web-10.0.0/doc/howto/listings/render_2.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/render_2.py 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,5 @@ +from twisted.web.template import flattenString +from element_2 import ExampleElement +def renderDone(output): + print output +flattenString(None, ExampleElement()).addCallback(renderDone) diff -Nru twisted-web-10.0.0/doc/howto/listings/render_3.py twisted-web-11.1.0/doc/howto/listings/render_3.py --- twisted-web-10.0.0/doc/howto/listings/render_3.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/render_3.py 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,5 @@ +from twisted.web.template import flattenString +from element_3 import ExampleElement +def renderDone(output): + print output +flattenString(None, ExampleElement()).addCallback(renderDone) diff -Nru twisted-web-10.0.0/doc/howto/listings/render_quoting.py twisted-web-11.1.0/doc/howto/listings/render_quoting.py --- twisted-web-10.0.0/doc/howto/listings/render_quoting.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/render_quoting.py 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,5 @@ +from twisted.web.template import flattenString +from quoting_element import ExampleElement +def renderDone(output): + print output +flattenString(None, ExampleElement()).addCallback(renderDone) diff -Nru twisted-web-10.0.0/doc/howto/listings/render_slots_attrs.py twisted-web-11.1.0/doc/howto/listings/render_slots_attrs.py --- twisted-web-10.0.0/doc/howto/listings/render_slots_attrs.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/render_slots_attrs.py 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,5 @@ +from twisted.web.template import flattenString +from slots_attributes_1 import ExampleElement +def renderDone(output): + print output +flattenString(None, ExampleElement()).addCallback(renderDone) diff -Nru twisted-web-10.0.0/doc/howto/listings/render_transparent.py twisted-web-11.1.0/doc/howto/listings/render_transparent.py --- twisted-web-10.0.0/doc/howto/listings/render_transparent.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/render_transparent.py 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,5 @@ +from twisted.web.template import flattenString +from transparent_element import ExampleElement +def renderDone(output): + print output +flattenString(None, ExampleElement()).addCallback(renderDone) diff -Nru twisted-web-10.0.0/doc/howto/listings/slots_attributes_1.py twisted-web-11.1.0/doc/howto/listings/slots_attributes_1.py --- twisted-web-10.0.0/doc/howto/listings/slots_attributes_1.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/slots_attributes_1.py 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,11 @@ +from twisted.web.template import Element, renderer, XMLFile + +class ExampleElement(Element): + loader = XMLFile('slots-attributes-1.xml') + + @renderer + def person_profile(self, request, tag): + # Note how convenient it is to pass these attributes in! + tag.fillSlots(person_name='Luke', + profile_image_url='http://example.com/user.png') + return tag diff -Nru twisted-web-10.0.0/doc/howto/listings/slots-attributes-1.xml twisted-web-11.1.0/doc/howto/listings/slots-attributes-1.xml --- twisted-web-10.0.0/doc/howto/listings/slots-attributes-1.xml 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/slots-attributes-1.xml 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,6 @@ +
      + +

      +
      diff -Nru twisted-web-10.0.0/doc/howto/listings/slots-attributes-output.html twisted-web-11.1.0/doc/howto/listings/slots-attributes-output.html --- twisted-web-10.0.0/doc/howto/listings/slots-attributes-output.html 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/slots-attributes-output.html 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,4 @@ +
      + +

      Luke

      +
      diff -Nru twisted-web-10.0.0/doc/howto/listings/subviews-1.py twisted-web-11.1.0/doc/howto/listings/subviews-1.py --- twisted-web-10.0.0/doc/howto/listings/subviews-1.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/subviews-1.py 2011-10-17 22:50:37.000000000 +0000 @@ -0,0 +1,26 @@ +from twisted.web.template import ( + XMLFile, TagLoader, Element, renderer, flattenString) + +class WidgetsElement(Element): + loader = XMLFile('subviews-1.xml') + + widgetData = ['gadget', 'contraption', 'gizmo', 'doohickey'] + + @renderer + def widgets(self, request, tag): + for widget in self.widgetData: + yield WidgetElement(TagLoader(tag), widget) + +class WidgetElement(Element): + def __init__(self, loader, name): + Element.__init__(self, loader) + self._name = name + + @renderer + def name(self, request, tag): + return tag(self._name) + +def printResult(result): + print result + +flattenString(None, WidgetsElement()).addCallback(printResult) diff -Nru twisted-web-10.0.0/doc/howto/listings/subviews-1.xml twisted-web-11.1.0/doc/howto/listings/subviews-1.xml --- twisted-web-10.0.0/doc/howto/listings/subviews-1.xml 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/subviews-1.xml 2011-10-17 22:50:37.000000000 +0000 @@ -0,0 +1,3 @@ +
        +
      • +
      diff -Nru twisted-web-10.0.0/doc/howto/listings/subviews-output-1.xml twisted-web-11.1.0/doc/howto/listings/subviews-output-1.xml --- twisted-web-10.0.0/doc/howto/listings/subviews-output-1.xml 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/subviews-output-1.xml 2011-10-17 22:50:37.000000000 +0000 @@ -0,0 +1,3 @@ +
        +
      • gadget
      • contraption
      • gizmo
      • doohickey
      • +
      diff -Nru twisted-web-10.0.0/doc/howto/listings/template-1.xml twisted-web-11.1.0/doc/howto/listings/template-1.xml --- twisted-web-10.0.0/doc/howto/listings/template-1.xml 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/template-1.xml 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,9 @@ + + +
      +
      +

      Content goes here.

      +
      +
      + + diff -Nru twisted-web-10.0.0/doc/howto/listings/transparent-1.xml twisted-web-11.1.0/doc/howto/listings/transparent-1.xml --- twisted-web-10.0.0/doc/howto/listings/transparent-1.xml 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/transparent-1.xml 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,6 @@ +
      + + + +
      + diff -Nru twisted-web-10.0.0/doc/howto/listings/transparent_element.py twisted-web-11.1.0/doc/howto/listings/transparent_element.py --- twisted-web-10.0.0/doc/howto/listings/transparent_element.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/transparent_element.py 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,12 @@ +from twisted.web.template import Element, renderer, XMLFile + +class ExampleElement(Element): + loader = XMLFile('transparent-1.xml') + + @renderer + def renderer1(self, request, tag): + return tag("hello") + + @renderer + def renderer2(self, request, tag): + return tag("world") diff -Nru twisted-web-10.0.0/doc/howto/listings/transparent-output.html twisted-web-11.1.0/doc/howto/listings/transparent-output.html --- twisted-web-10.0.0/doc/howto/listings/transparent-output.html 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/transparent-output.html 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,5 @@ +
      + +hello +world +
      diff -Nru twisted-web-10.0.0/doc/howto/listings/waited-for-it.html twisted-web-11.1.0/doc/howto/listings/waited-for-it.html --- twisted-web-10.0.0/doc/howto/listings/waited-for-it.html 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/waited-for-it.html 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,8 @@ +[[[Rendering the template.]]] +
      + Before waiting ... + [[[In progress... now firing the Deferred.]]] +A value: '<value>' + ... after waiting. +
      [[[Deferred fired.]]] +[[[All done.]]] diff -Nru twisted-web-10.0.0/doc/howto/listings/waited-for-it.txt twisted-web-11.1.0/doc/howto/listings/waited-for-it.txt --- twisted-web-10.0.0/doc/howto/listings/waited-for-it.txt 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/waited-for-it.txt 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,8 @@ +[[[Rendering the template.]]] +
      + Before waiting ... + [[[In progress... now firing the Deferred.]]] +A value: '<value>' + ... after waiting. +
      [[[Deferred fired.]]] +[[[All done.]]] diff -Nru twisted-web-10.0.0/doc/howto/listings/wait_for_it.py twisted-web-11.1.0/doc/howto/listings/wait_for_it.py --- twisted-web-10.0.0/doc/howto/listings/wait_for_it.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/wait_for_it.py 2011-03-21 14:17:42.000000000 +0000 @@ -0,0 +1,32 @@ +import sys +from twisted.web.template import XMLString, Element, renderer, flatten +from twisted.internet.defer import Deferred + +sample = XMLString( + """ +
      + Before waiting ... + + ... after waiting. +
      + """) + +class WaitForIt(Element): + def __init__(self): + Element.__init__(self, loader=sample) + self.deferred = Deferred() + + @renderer + def wait(self, request, tag): + return self.deferred.addCallback( + lambda aValue: tag("A value: " + repr(aValue))) + +def done(ignore): + print("[[[Deferred fired.]]]") + +print('[[[Rendering the template.]]]') +it = WaitForIt() +flatten(None, it, sys.stdout.write).addCallback(done) +print('[[[In progress... now firing the Deferred.]]]') +it.deferred.callback("") +print('[[[All done.]]]') diff -Nru twisted-web-10.0.0/doc/howto/listings/xmlrpc-customized.py twisted-web-11.1.0/doc/howto/listings/xmlrpc-customized.py --- twisted-web-10.0.0/doc/howto/listings/xmlrpc-customized.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/listings/xmlrpc-customized.py 2011-04-16 19:05:10.000000000 +0000 @@ -0,0 +1,60 @@ +from twisted.web import xmlrpc, server + +class EchoHandler: + + def echo(self, x): + """ + Return all passed args + """ + return x + + + +class AddHandler: + + def add(self, a, b): + """ + Return sum of arguments. + """ + return a + b + + + +class Example(xmlrpc.XMLRPC): + """ + An example of using you own policy to fetch the handler + """ + + def __init__(self): + xmlrpc.XMLRPC.__init__(self) + self._addHandler = AddHandler() + self._echoHandler = EchoHandler() + + #We keep a dict of all relevant + #procedure names and callable. + self._procedureToCallable = { + 'add':self._addHandler.add, + 'echo':self._echoHandler.echo + } + + def lookupProcedure(self, procedurePath): + try: + return self._procedureToCallable[procedurePath] + except KeyError, e: + raise xmlrpc.NoSuchFunction(self.NOT_FOUND, + "procedure %s not found" % procedurePath) + + def listProcedures(self): + """ + Since we override lookupProcedure, its suggested to override + listProcedures too. + """ + return ['add', 'echo'] + + + +if __name__ == '__main__': + from twisted.internet import reactor + r = Example() + reactor.listenTCP(7080, server.Site(r)) + reactor.run() diff -Nru twisted-web-10.0.0/doc/howto/resource-templates.html twisted-web-11.1.0/doc/howto/resource-templates.html --- twisted-web-10.0.0/doc/howto/resource-templates.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/resource-templates.html 2011-11-17 10:51:14.000000000 +0000 @@ -12,18 +12,22 @@

      Overview

      -

      While high-level templating systems can be used with Twisted (for example, -Divmod Nevow, sometimes -one needs a less file-heavy system which lets one directly write HTML. While -ResourceScripts are available, they have a high overhead of coding, needing -some boring string arithmetic. ResourceTemplates fill the space between Nevow -and ResourceScript using Quixote's PTL (Python Templating Language).

      - -

      ResourceTemplates need Quixote installed. In -Debian, that means using Python 2.2 -and installing the quixote package -(apt-get install quixote). Other operating systems require -other ways to install quixote, or it can be done manually.

      +

      While high-level templating systems can be used with Twisted (for +example, Divmod +Nevow, sometimes one needs a less file-heavy system which lets one +directly write HTML. While +ResourceScript is +available, it has a high coding overhead, and requires some boring string +arithmetic. +ResourceTemplate fills the +space between Nevow and ResourceScript using Quixote's PTL (Python Templating +Language).

      + +

      ResourceTemplates need Quixote +installed. In Debian, that means +installing the python-quixote package +(apt-get install python-quixote). Other operating systems +require other ways to install Quixote, or it can be done manually.

      Configuring Twisted.Web

      @@ -44,10 +48,11 @@

      ResourceTemplates are coded in an extension of Python called the Python Templating Language. Complete documentation of the PTL -is available at the quixote web site. The web server -will expect the PTL source file to define a variable named -resource. -This should be a twisted.web.server.Resource, +is available +at the +quixote web site. The web server will expect the PTL source file +to define a variable named resource. This should be +a twisted.web.resource.Resource, whose .render method be called. Usually, you would want to define render using the keyword template rather than def.

      @@ -98,6 +103,6 @@

      Index

      - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/twisted-templates.html twisted-web-11.1.0/doc/howto/twisted-templates.html --- twisted-web-10.0.0/doc/howto/twisted-templates.html 1970-01-01 00:00:00.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/twisted-templates.html 2011-11-17 10:51:14.000000000 +0000 @@ -0,0 +1,688 @@ + + +Twisted Documentation: HTML Templating with twisted.web.template + + + + +

      HTML Templating with twisted.web.template

      + +
      + +

      A Very Quick Introduction To Templating In Python

      +

      +HTML templating is the process of transforming a template document (one which +describes style and structure, but does not itself include any content) into +some HTML output which includes information about objects in your application. +There are many, many libraries for doing this in Python: to name a few, jinja2, django templates, +and clearsilver. You can easily use +any of these libraries in your Twisted Web application, either by running them +as WSGI applications or by calling your +preferred templating system's APIs to produce their output as strings, and then +writing those strings to Request.write. +

      +

      Before we begin explaining how to use it, I'd like to stress that you +don't need to use Twisted's templating system if you prefer some other +way to generate HTML. Use it if it suits your personal style or your +application, but feel free to use other things. Twisted includes templating for +its own use, because the twisted.web server needs to produce HTML +in various places, and we didn't want to add another large dependency for that. +Twisted is not in any way incompatible with other systems, so that has +nothing to do with the fact that we use our own.

      +

      +

      +

      twisted.web.template - Why And How you Might Want to Use It

      +

      +Twisted includes a templating system, twisted.web.template. This can be convenient for Twisted +applications that want to produce some basic HTML for a web interface without an +additional dependency. +

      +

      +twisted.web.template also includes +support for Deferreds, so +you can incrementally render the output of a page based on the results of Deferreds that your application +has returned. This feature is fairly unique among templating libraries. +

      +

      +In twisted.web.template, templates are XHTML files +which also contain a special namespace for indicating dynamic portions of the +document. For example: +

      +
      +<html xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1">
      +<body>
      +  <div t:render="header" />
      +  <div id="content">
      +    <p>Content goes here.</p>
      +  </div>
      +  <div t:render="footer" />
      +</body>
      +</html>
      +
      template example - listings/template-1.xml
      +The basic unit of templating is twisted.web.template.Element. An Element is given a way of +loading a bit of markup like the above example, and knows how to +correlate render attributes within that markup to Python methods +exposed with twisted.web.template.renderer: +

      1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +

      from twisted.web.template import Element, renderer, XMLFile + +class ExampleElement(Element): + loader = XMLFile('template-1.xml') + + @renderer + def header(self, request, tag): + return tag('Header.') + + @renderer + def footer(self, request, tag): + return tag('Footer.') +
      element example - listings/element_1.py
      +In order to combine the two, we must render the element. For this simple +example, we can use the flattenString API, which will convert a +single template object - such as an Element - into a Deferred which fires with a single string, +the HTML output of the rendering process. +

      1 +2 +3 +4 +5 +

      from twisted.web.template import flattenString +from element_1 import ExampleElement +def renderDone(output): + print output +flattenString(None, ExampleElement()).addCallback(renderDone) +
      rendering snippet - listings/render_1.py
      +

      This short program cheats a little bit; we know that there are no Deferreds in the template which +require the reactor to eventually fire; therefore, we can simply add a callback +which outputs the result. Also, none of the renderer functions +require the request object, so it's acceptable to +pass None through here. (The 'request' object here is used only to +relay information about the rendering process to each renderer, so you may +always use whatever object makes sense for your application. Note, however, +that renderers from library code may require an IRequest.)

      +

      +If you run it yourself, you can see that it produces the following output: +

      +
      +<html>
      +<body>
      +  <div>Header.</div>
      +  <div id="content">
      +    <p>Content goes here.</p>
      +  </div>
      +  <div>Footer.</div>
      +</body>
      +</html>
      +
      rendering output 1 - listings/output-1.html
      +The third parameter to a renderer method is a Tag object which represents the XML element +with the t:render attribute in the template. Calling a Tag adds children to the element +in the DOM, which may be strings, more Tags, or other renderables such as Elements. +For example, to make the header and footer bold: +

      1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +

      from twisted.web.template import Element, renderer, XMLFile, tags + +class ExampleElement(Element): + loader = XMLFile('template-1.xml') + + @renderer + def header(self, request, tag): + return tag(tags.b('Header.')) + + @renderer + def footer(self, request, tag): + return tag(tags.b('Footer.')) +
      tag manipulation example - listings/element_2.py
      + +Rendering this in a similar way to the first example would produce: + +
      +<html>
      +<body>
      +  <div><b>Header.</b></div>
      +  <div id="content">
      +    <p>Content goes here.</p>
      +  </div>
      +  <div><b>Footer.</b></div>
      +</body>
      +</html>
      +
      tag manipulation output - listings/output-2.html
      + +In addition to adding children, call syntax can be used to set attributes on a +tag. For example, to change the id on the div while +adding children: + +

      1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +

      from twisted.web.template import Element, renderer, XMLFile, tags + +class ExampleElement(Element): + loader = XMLFile('template-1.xml') + + @renderer + def header(self, request, tag): + return tag(tags.p('Header.'), id='header') + + @renderer + def footer(self, request, tag): + return tag(tags.p('Footer.'), id='footer') +
      attributes example - listings/element_3.py
      + +And this would produce the following page: + +
      +<html>
      +<body>
      +  <div id="header"><p>Header.</p></div>
      +  <div id="content">
      +    <p>Content goes here.</p>
      +  </div>
      +  <div id="footer"><p>Footer.</p></div>
      +</body>
      +</html>
      +
      attributes output - listings/output-3.html
      + +

      +Calling a tag mutates it, it and returns the tag itself, so you can pass it +forward and call it multiple times if you have multiple children or attributes +to add to it. twisted.web.template also exposes some +convenient objects for building more complex markup structures from within +renderer methods in the tags object. In the examples above, we've +only used tags.p and tags.b, but there should be a tags.x for each x which is a valid HTML tag. There may be +some omissions, but if you find one, please feel free to file a bug. +

      + +

      Template Attributes

      + +t:attr tags allow you to set HTML attributes +(like href in an <a href="...) on an enclosing +element. + +

      Slots

      + +t:slot tags allow you to specify "slots" which you can +conveniently fill with multiple pieces of data straight from your Python +program. + +The following example demonstrates both t:attr +and t:slot in action. Here we have a layout which displays a person's +profile on your snazzy new Twisted-powered social networking site. We use +the t:attr tag to drop in the "src" attribute on the profile picture, +where the actual value of src attribute gets specified by a t:slot +tag within the t:attr tag. Confused? It should make more +sense when you see the code: + + + +

      1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +

      from twisted.web.template import Element, renderer, XMLFile + +class ExampleElement(Element): + loader = XMLFile('slots-attributes-1.xml') + + @renderer + def person_profile(self, request, tag): + # Note how convenient it is to pass these attributes in! + tag.fillSlots(person_name='Luke', + profile_image_url='http://example.com/user.png') + return tag +
      slots and attributes element - listings/slots_attributes_1.py
      +
      +<div class="profile">
      +<img src="http://example.com/user.png" /> 
      +<p>Luke</p>
      +</div>
      +
      slots and attributes output - listings/slots-attributes-output.html
      + +

      Iteration

      + +

      Often, you will have a sequence of things, and want to render each of them, +repeating a part of the template for each one. This can be done by +cloning tag in your renderer:

      + +
      +

      1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +

      from twisted.web.template import Element, renderer, XMLFile, flattenString + +class WidgetsElement(Element): + loader = XMLFile('iteration-1.xml') + + widgetData = ['gadget', 'contraption', 'gizmo', 'doohickey'] + + @renderer + def widgets(self, request, tag): + for widget in self.widgetData: + yield tag.clone().fillSlots(widgetName=widget) + +def printResult(result): + print result + +flattenString(None, WidgetsElement()).addCallback(printResult) +
      iteration element - listings/iteration-1.py
      +
      +<ul>
      +    <li>gadget</li><li>contraption</li><li>gizmo</li><li>doohickey</li>
      +</ul>
      +
      + +

      This renderer works because a renderer can return anything that can be +rendered, not just tag. In this case, we define a generator, which +returns a thing that is iterable. We also could have returned +a list. Anything that is iterable will be rendered by twisted.web.template rendering each item in it. In +this case, each item is a copy of the tag the renderer received, each filled +with the name of a widget.

      + +

      Sub-views

      + +

      Another common pattern is to delegate the rendering logic for a small part of +the page to a separate Element. For example, the widgets from the +iteration example above might be more complicated to render. You can define +an Element subclass which can render a single widget. The renderer +method on the container can then yield instances of this +new Element subclass.

      + +
      +

      1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +

      from twisted.web.template import ( + XMLFile, TagLoader, Element, renderer, flattenString) + +class WidgetsElement(Element): + loader = XMLFile('subviews-1.xml') + + widgetData = ['gadget', 'contraption', 'gizmo', 'doohickey'] + + @renderer + def widgets(self, request, tag): + for widget in self.widgetData: + yield WidgetElement(TagLoader(tag), widget) + +class WidgetElement(Element): + def __init__(self, loader, name): + Element.__init__(self, loader) + self._name = name + + @renderer + def name(self, request, tag): + return tag(self._name) + +def printResult(result): + print result + +flattenString(None, WidgetsElement()).addCallback(printResult) +
      subview element - listings/subviews-1.py
      +
      +<ul>
      +      <li><span>gadget</span></li><li><span>contraption</span></li><li><span>gizmo</span></li><li><span>doohickey</span></li>
      +</ul>
      +
      + +

      TagLoader lets the portion of the overall template related to +widgets be re-used for WidgetElement, which is otherwise a +normal Element subclass not much different +from WidgetsElement. Notice that the name renderer on +the span tag in this template is satisfied +from WidgetElement, not WidgetsElement.

      + +

      Transparent

      + +Note how renderers, slots and attributes require you to specify a renderer on +some outer HTML element. What if you don't want to be forced to add an element +to your DOM just to drop some content into it? Maybe it messes with your +layout, and you can't get it to work in IE with that extra div +tag? Perhaps you need t:transparent, which allows you to drop some +content in without any surrounding "container" tag. For example: + + + +

      1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +

      from twisted.web.template import Element, renderer, XMLFile + +class ExampleElement(Element): + loader = XMLFile('transparent-1.xml') + + @renderer + def renderer1(self, request, tag): + return tag("hello") + + @renderer + def renderer2(self, request, tag): + return tag("world") +
      transparent element - listings/transparent_element.py
      + +
      +<div>
      +<!-- layout decision - these things need to be *siblings* -->
      +hello
      +world
      +</div>
      +
      transparent rendering output - listings/transparent-output.html
      + +

      Quoting

      + +twisted.web.template will quote any strings that place +into the DOM. This provides protection against XSS attacks, in +addition to just generally making it easy to put arbitrary strings onto a web +page, without worrying about what they might have in them. This can easily be +demonstrated with an element using the same template from our earlier examples. +Here's an element that returns some "special" characters in HTML ('<', '>', +and '"', which is special in attribute values): + +

      1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +

      from twisted.web.template import Element, renderer, XMLFile + +class ExampleElement(Element): + loader = XMLFile('template-1.xml') + + @renderer + def header(self, request, tag): + return tag('<<<Header>>>!') + + @renderer + def footer(self, request, tag): + return tag('>>>"Footer!"<<<', id='<"fun">') +
      renderers returning "special" characters - listings/quoting_element.py
      + +Note that they are all safely quoted in the output, and will appear in a web +browser just as you returned them from your Python method: + +
      +<html>
      +<body>
      +  <div>&lt;&lt;&lt;Header&gt;&gt;&gt;!</div>
      +  <div id="content">
      +    <p>Content goes here.</p>
      +  </div>
      +  <div id="&lt;&quot;fun&quot;&gt;">&gt;&gt;&gt;"Footer!"&lt;&lt;&lt;</div>
      +</body>
      +</html>
      +
      output containing "special" characters - listings/quoting-output.html
      + +

      Deferreds

      + +Finally, a simple demonstration of Deferred support, the unique feature of twisted.web.template. Simply put, any renderer may +return a Deferred which fires with some template content instead of the template +content itself. As shown above, flattenString will return a Deferred that +fires with the full content of the string. But if there's a lot of content, you +might not want to wait before starting to send some of it to your HTTP client: +for that case, you can use flatten. +It's difficult to demonstrate this directly in a browser-based application; +unless you insert very long delays before firing your Deferreds, it just looks +like your browser is instantly displaying everything. Here's an example that +just prints out some HTML template, with markers inserted for where certain +events happen: + +

      1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +

      import sys +from twisted.web.template import XMLString, Element, renderer, flatten +from twisted.internet.defer import Deferred + +sample = XMLString( + """ + <div xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1"> + Before waiting ... + <span t:render="wait"></span> + ... after waiting. + </div> + """) + +class WaitForIt(Element): + def __init__(self): + Element.__init__(self, loader=sample) + self.deferred = Deferred() + + @renderer + def wait(self, request, tag): + return self.deferred.addCallback( + lambda aValue: tag("A value: " + repr(aValue))) + +def done(ignore): + print("[[[Deferred fired.]]]") + +print('[[[Rendering the template.]]]') +it = WaitForIt() +flatten(None, it, sys.stdout.write).addCallback(done) +print('[[[In progress... now firing the Deferred.]]]') +it.deferred.callback("<value>") +print('[[[All done.]]]') +
      deferred example - listings/wait_for_it.py
      + +If you run this example, you should get the following output: + +
      +[[[Rendering the template.]]]
      +<div>
      +    Before waiting ...
      +    [[[In progress... now firing the Deferred.]]]
      +<span>A value: '&lt;value&gt;'</span>
      +    ... after waiting.
      +    </div>[[[Deferred fired.]]]
      +[[[All done.]]]
      +
      output from deferred example - listings/waited-for-it.html
      + +This demonstrates that part of the output (everything up to +"[[[In progress...") is written out immediately as it's rendered. +But once it hits the Deferred, WaitForIt's rendering needs to pause +until .callback(...) is called on that Deferred. You can see that +no further output is produced until the message indicating that the Deferred is +being fired is complete. By returning Deferreds and using flatten, you can avoid buffering large +amounts of data. + +

      A Brief Note on Formats and DOCTYPEs

      + +

      +The goal of twisted.web.template is to emit both valid HTML or XHTML. +However, in order to get the maximally standards-compliant output format you +desire, you have to know which one you want, and take a few simple steps to emit +it correctly. Many browsers will probably work with most output if you ignore +this section entirely, but the + HTML specification recommends that you specify an appropriate DOCTYPE. +

      + +

      +As a DOCTYPE declaration in your template would describe the +template itself, rather than its output, it won't be included in your output. +If you wish to annotate your template output with a DOCTYPE, you will have to +write it to the browser out of band. One way to do this would be to simply +do request.write('<!DOCTYPE html>\n') when you are ready to +begin emitting your response. The same goes for an XML DOCTYPE +declaration. +

      + +

      +twisted.web.template will remove the xmlns attributes +used to declare +the http://twistedmatrix.com/ns/twisted.web.template/0.1 namespace, +but it will not modify other namespace declaration attributes. Therefore if you +wish to serialize in HTML format, you should not use other namespaces; if you +wish to serialize to XML, feel free to insert any namespace declarations that +are appropriate, and they will appear in your output. +

      + +
      Note: +This relaxed approach is correct in many cases. However, in certain contexts - +especially <script> and <style> tags - quoting rules differ in +significant ways between HTML and XML, and between different browsers' parsers +in HTML. If you want to generate dynamic content inside a script or stylesheet, +the best option is to load the resource externally so you don't have to worry +about quoting rules. The second best option is to strictly configure your +content-types and DOCTYPE declarations for XML, whose quoting rules are simple +and compatible with the approach that twisted.web.template takes. +And, please remember: regardless of how you put it there, any user input placed +inside a <script> or <style> tag is a potential security issue. +
      + +

      A Bit of History

      +

      +Those of you who used Divmod Nevow may notice some +similarities. twisted.web.template is in fact derived from the +latest version of Nevow, but includes only the latest components from Nevow's +rendering pipeline, and does not have any of the legacy compatibility layers +that Nevow grew over time. This should make +using twisted.web.template a similar experience for many long-time +users of Twisted who have previously used Nevow for its twisted-friendly +templating, but more straightforward for new users. +

      +
      + +

      Index

      + Version: 11.1.0 + + \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/using-twistedweb.html twisted-web-11.1.0/doc/howto/using-twistedweb.html --- twisted-web-10.0.0/doc/howto/using-twistedweb.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/using-twistedweb.html 2011-11-17 10:51:14.000000000 +0000 @@ -21,10 +21,12 @@

      Index

      - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/web-development.html twisted-web-11.1.0/doc/howto/web-development.html --- twisted-web-10.0.0/doc/howto/web-development.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/web-development.html 2011-11-17 10:51:14.000000000 +0000 @@ -65,7 +65,7 @@ Later, when you want users to actually use your code, you should worry about what to do -- or rather, don't. Users may have widely different needs. Some may want to run your code in a different process, so they'll use -distributed web (twisted.web.distrib). Some may be +distributed web (twisted.web.distrib). Some may be using the twisted-web Debian package, and will drop in:

      @@ -91,16 +91,17 @@
       deployment with development, and makes sure your users will be tied to
       the file-system.

      -

      We have .rpys because they are useful and necessary. But using -them incorrectly leads to horribly unmaintainable applications. The best way to -ensure you are using them correctly is to not use them at all, until you are on -your final deployment stages. You should then find your -.rpy files will be less than 10 lines, because you will not -have more than 10 lines to write.

      +

      We have .rpys because they are useful and necessary. +But using them incorrectly leads to horribly unmaintainable +applications. The best way to ensure you are using them correctly is +to not use them at all, until you are on your final +deployment stages. You should then find your .rpy files +will be less than 10 lines, because you will not have more +than 10 lines to write.

      Index

      - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/web-in-60/asynchronous-deferred.html twisted-web-11.1.0/doc/howto/web-in-60/asynchronous-deferred.html --- twisted-web-10.0.0/doc/howto/web-in-60/asynchronous-deferred.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/web-in-60/asynchronous-deferred.html 2011-11-17 10:51:14.000000000 +0000 @@ -10,40 +10,44 @@
      -

      The previous example had a Resource that generates its response +

      The previous example had a Resource that generates its response asynchronously rather than immediately upon the call to its render method. Though it was a useful demonstration of the NOT_DONE_YET feature of Twisted Web, the example didn't reflect what a realistic application -might want to do. This example introduces Deferred, the Twisted class which is used +might want to do. This example introduces Deferred, the Twisted class which is used to provide a uniform interface to many asynchronous events, and shows you an example of using a Deferred-returning API to generate an asynchronous response to a request in Twisted Web.

      -

      Deferred is the result of two consequences of the asynchronous -programming approach. First, asynchronous code is frequently (if not always) -concerned with some data (in Python, an object) which is not yet available but -which probably will be soon. Asynchronous code needs a way to define what will -be done to the object once it does exist. It also needs a way to define how to -handle errors in the creation or acquisition of that object. These two needs are -satisfied by the callbacks and errbacks of a -Deferred. Callbacks are added to a Deferred with Deferred.addCallback; errbacks -are added with Deferred.addErrback. When the object -finally does exist, it is passed to Deferred.callback which passes it on to the -callback added with addCallback. Similarly, if an error occurs, -Deferred.errback is -called and the error is passed along to the errback added with -addErrback. Second, the events that make asynchronous code actually -work often take many different, incompatible forms. Deferred acts -as the uniform interface which lets different parts of an asynchronous -application interact and isolates them from implementation details they -shouldn't be concerned with.

      - -

      That's almost all there is to Deferred. To solidify your new understanding, -now consider this rewritten version of DelayedResource which uses a -Deferred-based delay API. It does exactly the same thing as the previous example. Only the implementation is -different.

      +

      Deferred is the result of two consequences of the +asynchronous programming approach. First, asynchronous code is +frequently (if not always) concerned with some data (in Python, an +object) which is not yet available but which probably will be +soon. Asynchronous code needs a way to define what will be done to the +object once it does exist. It also needs a way to define how to handle +errors in the creation or acquisition of that object. These two needs +are satisfied by the callbacks and errbacks of +a Deferred. Callbacks are added to +a Deferred with Deferred.addCallback; errbacks +are added with Deferred.addErrback. When the +object finally does exist, it is passed to Deferred.callback which passes it +on to the callback added with addCallback. Similarly, if +an error occurs, Deferred.errback is called and +the error is passed along to the errback added +with addErrback. Second, the events that make +asynchronous code actually work often take many different, +incompatible forms. Deferred acts as the uniform +interface which lets different parts of an asynchronous application +interact and isolates them from implementation details they shouldn't +be concerned with.

      + +

      That's almost all there is to Deferred. To solidify your new +understanding, now consider this rewritten version +of DelayedResource which uses a Deferred-based delay +API. It does exactly the same thing as the previous +example. Only the implementation is different.

      -

      First, the example must import that new API that was just mentioned, deferLater:

      +

      First, the example must import that new API that was just mentioned, deferLater:

      1

      from twisted.internet.task import deferLater @@ -59,9 +63,9 @@ from twisted.internet import reactor
      -

      With the imports done, here's the first part of the -DelayedResource implementation. Again, this part of the code is -identical to the previous version:

      +

      With the imports done, here's the first part of +the DelayedResource implementation. Again, this part of +the code is identical to the previous version:

      1 2 @@ -69,36 +73,41 @@ 4

      class DelayedResource(Resource): def _delayedRender(self, request): - request.write("Sorry to keep you waiting.") + request.write("<html><body>Sorry to keep you waiting.</body></html>") request.finish()
      -

      Next we need to define the render method. Here's where things change a -bit. Instead of using callLater, We're going to -use deferLater this -time. deferLater accepts a reactor, delay (in seconds, as with -callLater), and a function to call after the delay to produce that -elusive object discussed in the description of Deferreds. We're also going to -use _delayedRender as the callback to add to the -Deferred returned by deferLater. Since it expects the -request object as an argument, we're going to set up the deferLater -call to return a Deferred which has the request object as its -result.

      +

      Next we need to define the render method. Here's where things +change a bit. Instead of using callLater, +We're going to use deferLater this +time. deferLater accepts a reactor, delay (in seconds, as +with callLater), and a function to call after the delay +to produce that elusive object discussed in the description +of Deferreds. We're also going to +use _delayedRender as the callback to add to +the Deferred returned by deferLater. Since +it expects the request object as an argument, we're going to set up +the deferLater call to return a Deferred +which has the request object as its result.

      1 2 -

      def render_GET(self, request): - d = deferLater(reactor, 5, lambda: request) +3 +

      ... + def render_GET(self, request): + d = deferLater(reactor, 5, lambda: request)
      -

      The Deferred referenced by d now needs to have the -_delayedRender callback added to it. Once this is done, -_delayedRender will be called with the result of d -(which will be request, of course — the result of (lambda: -request)()).

      +

      The Deferred referenced by d now needs to +have the _delayedRender callback added to it. Once this +is done, _delayedRender will be called with the result +of d (which will be request, of course — the +result of (lambda: request)()).

      1 -

      d.addCallback(self._delayedRender) +2 +

      ... + d.addCallback(self._delayedRender)

      Finally, the render method still needs to return NOT_DONE_YET, @@ -106,16 +115,19 @@ example.

      1 -

      return NOT_DONE_YET +2 +

      ... + return NOT_DONE_YET
      -

      And with that, DelayedResource is now implemented based on a -Deferred. The example still isn't very realistic, but remember that -since Deferreds offer a uniform interface to many different asynchronous event -sources, this code now resembles a real application even more closely; you could -easily replace deferLater with another -Deferred-returning API and suddenly you might have a resource that -does something useful.

      +

      And with that, DelayedResource is now implemented +based on a Deferred. The example still isn't very +realistic, but remember that since Deferreds offer a +uniform interface to many different asynchronous event sources, this +code now resembles a real application even more closely; you could +easily replace deferLater with +another Deferred-returning API and suddenly you might +have a resource that does something useful.

      Finally, here's the complete, uninterrupted example source, as an rpy script:

      @@ -142,7 +154,7 @@ class DelayedResource(Resource): def _delayedRender(self, request): - request.write("Sorry to keep you waiting.") + request.write("<html><body>Sorry to keep you waiting.</body></html>") request.finish() def render_GET(self, request): @@ -156,6 +168,6 @@

      Index

      - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/web-in-60/asynchronous.html twisted-web-11.1.0/doc/howto/web-in-60/asynchronous.html --- twisted-web-10.0.0/doc/howto/web-in-60/asynchronous.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/web-in-60/asynchronous.html 2011-11-17 10:51:14.000000000 +0000 @@ -17,17 +17,21 @@ asynchronously. In this installment, we'll write a resource like this.

      A resource that generates a response asynchronously looks like one that -generates a response synchronously in many ways. The same base class, Resource, is used either way; the -same render methods are used. There are three basic differences, though.

      - -

      First, instead of returning the string which will be used as the body of the -response, the resource uses Request.write. This method can be called -repeatedly. Each call appends another string to the response body. Second, when -the entire response body has been passed to Request.write, the -application must call Request.finish. As you might expect from the -name, this ends the response. Finally, in order to make Twisted Web not end the -response as soon as the render method returns, the render method must return -NOT_DONE_YET. Consider this example:

      +generates a response synchronously in many ways. The same base +class, Resource, is used +either way; the same render methods are used. There are three basic differences, +though.

      + +

      First, instead of returning the string which will be used as the +body of the response, the resource uses Request.write. This method can be +called repeatedly. Each call appends another string to the response +body. Second, when the entire response body has been passed +to Request.write, the application must +call Request.finish. As you might expect +from the name, this ends the response. Finally, in order to make +Twisted Web not end the response as soon as the render method returns, +the render method must return NOT_DONE_YET. Consider this +example:

      1 2 @@ -47,7 +51,7 @@ class DelayedResource(Resource): def _delayedRender(self, request): - request.write("Sorry to keep you waiting.") + request.write("<html><body>Sorry to keep you waiting.</body></html>") request.finish() def render_GET(self, request): @@ -55,18 +59,20 @@ return NOT_DONE_YET

      -

      If you're not familiar with reactor.callLater, all you really -need to know about it to understand this example is that the above usage of it -arranges to have self._delayedRender(request) run about 5 seconds -after callLater is invoked from this render method and that it -returns immediately.

      - -

      All three of the elements mentioned earlier can be seen in this example. The -resource uses Request.write to set the response body. It uses -Request.finish after the entire body has been specified (all with -just one call to write in this case). Lastly, it returns -NOT_DONE_YET from its render method. So there you have it, -asynchronous rendering with Twisted Web.

      +

      If you're not familiar with the reactor callLater +method, all you really need to know about it to understand this +example is that the above usage of it arranges to +have self._delayedRender(request) run about 5 seconds +after callLater is invoked from this render method and +that it returns immediately.

      + +

      All three of the elements mentioned earlier can be seen in this +example. The resource uses Request.write to set the +response body. It uses Request.finish after the entire +body has been specified (all with just one call to write in this +case). Lastly, it returns NOT_DONE_YET from its render +method. So there you have it, asynchronous rendering with Twisted +Web.

      Here's a complete rpy script based on this resource class (see the previous example if you need a reminder about rpy scripts):

      @@ -91,7 +97,7 @@ class DelayedResource(Resource): def _delayedRender(self, request): - request.write("Sorry to keep you waiting.") + request.write("<html><body>Sorry to keep you waiting.</body></html>") request.finish() def render_GET(self, request): @@ -101,11 +107,12 @@ resource = DelayedResource()
      -

      Drop this source into a .rpy file and fire up a server using -twistd -n web --path /directory/containing/script/. You'll see that -loading the page takes 5 seconds. If you try to load a second before the first -completes, it will also take 5 seconds from the time you request it (but it -won't be delayed by any other outstanding requests).

      +

      Drop this source into a .rpy file and fire up a server +using twistd -n web --path /directory/containing/script/. +You'll see that loading the page takes 5 seconds. If you try to load a +second before the first completes, it will also take 5 seconds from +the time you request it (but it won't be delayed by any other +outstanding requests).

      Something else to consider when generating responses asynchronously is that the client may not wait around to get the response to its @@ -116,6 +123,6 @@

      Index

      - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/web-in-60/custom-codes.html twisted-web-11.1.0/doc/howto/web-in-60/custom-codes.html --- twisted-web-10.0.0/doc/howto/web-in-60/custom-codes.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/web-in-60/custom-codes.html 2011-11-17 10:51:14.000000000 +0000 @@ -10,10 +10,10 @@
      -

      The previous example introduced NoResource, a Twisted Web error -resource which responds with a 404 (not found) code. This example will -cover the APIs that NoResource uses to do this so that -you can generate your own custom response codes as desired.

      +

      The previous example introduced NoResource, a Twisted Web error resource which +responds with a 404 (not found) code. This example will cover the APIs +that NoResource uses to do this so that you can generate your own +custom response codes as desired.

      First, the now-standard import preamble:

      @@ -25,21 +25,20 @@ from twisted.internet import reactor
      -

      Now we'll define a new resource class that always returns a 402 -(payment required) response. This is really not very different from -the resources that was defined in previous examples. The fact that it -has a response code other than 200 doesn't change anything else about -its role. This will require using the request object, though, which -none of the previous examples have done.

      - -

      The Request -object has shown up in a couple of places, but so far we've ignored -it. It is a parameter to the getChild API as well as to -render methods such as render_GET. As you might have -suspected, it represents the request for which a response is to be -generated. Additionally, it also represents the response being -generated. In this example we're going to use its setResponseCode method to - you -guessed it - set the response's status code.

      +

      Now we'll define a new resource class that always returns a 402 (payment +required) response. This is really not very different from the resources that +was defined in previous examples. The fact that it has a response code other +than 200 doesn't change anything else about its role. This will require using +the request object, though, which none of the previous examples have done.

      + +

      The Request object has +shown up in a couple of places, but so far we've ignored it. It is a parameter +to the getChild +API as well as to render methods such as render_GET. As you might +have suspected, it represents the request for which a response is to be +generated. Additionally, it also represents the response being generated. In +this example we're going to use its setResponseCode method to - you guessed +it - set the response's status code.

      1 2 @@ -48,17 +47,17 @@

      class PaymentRequired(Resource): def render_GET(self, request): request.setResponseCode(402) - return "Please swipe your credit card." + return "<html><body>Please swipe your credit card.</body></html>"

      Just like the other resources I've demonstrated, this one returns a string from its render_GET method to define the body of -the response. All that's different is the call to -setResponseCode to override the default response code, +the response. All that's different is the call +to setResponseCode to override the default response code, 200, with a different one.

      -

      Finally, the code to set up the site and reactor. We'll put an -instance of the above defined resource at /buy:

      +

      Finally, the code to set up the site and reactor. We'll put an instance of +the above defined resource at /buy:

      1 2 @@ -95,7 +94,7 @@ class PaymentRequired(Resource): def render_GET(self, request): request.setResponseCode(402) - return "Please swipe your credit card." + return "<html><body>Please swipe your credit card.</body></html>" root = Resource() root.putChild("buy", PaymentRequired()) @@ -104,15 +103,14 @@ reactor.run()

      -

      Run the server and visit http://localhost:8880/buy in -your browser. It'll look pretty boring, but if you use Firefox's View -Page Info right-click menu item (or your browser's equivalent), you'll -be able to see that the server indeed sent back a 402 response -code.

      +

      Run the server and visit http://localhost:8880/buy in your +browser. It'll look pretty boring, but if you use Firefox's View Page Info +right-click menu item (or your browser's equivalent), you'll be able to see that +the server indeed sent back a 402 response code.

      Index

      - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/web-in-60/dynamic-content.html twisted-web-11.1.0/doc/howto/web-in-60/dynamic-content.html --- twisted-web-10.0.0/doc/howto/web-in-60/dynamic-content.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/web-in-60/dynamic-content.html 2011-11-17 10:51:14.000000000 +0000 @@ -13,7 +13,7 @@

      The goal of this example is to show you how to dynamically generate the contents of a page.

      -

      Taking care of some of the necessary imports first, we'll import Site and the reactor:

      +

      Taking care of some of the necessary imports first, we'll import Site and the reactor:

      1 2 @@ -25,9 +25,10 @@ protocol implementation. The reactor is the main loop that drives any Twisted application; we'll use it to actually create the listening port in a moment.

      -

      Next, we'll import one more thing from Twisted Web: Resource. An instance of -Resource (or a subclass) represents a page (technically, the entity -addressed by a URI).

      +

      Next, we'll import one more thing from Twisted +Web: Resource. An +instance of Resource (or a subclass) represents a page +(technically, the entity addressed by a URI).

      1

      from twisted.web.resource import Resource @@ -40,9 +41,10 @@

      import time
      -

      With imports taken care of, the next step is to define a -Resource subclass which has the dynamic rendering behavior we -want. Here's a resource which generates a page giving the time:

      +

      With imports taken care of, the next step is to define +a Resource subclass which has the dynamic rendering +behavior we want. Here's a resource which generates a page giving the +time:

      1 2 @@ -51,11 +53,12 @@

      class ClockPage(Resource): isLeaf = True def render_GET(self, request): - return "%s" % (time.ctime(),) + return "<html><body>%s</body></html>" % (time.ctime(),)
      -

      Setting isLeaf to True indicates that -ClockPage resources will never have any children.

      +

      Setting isLeaf to True indicates +that ClockPage resources will never have any +children.

      The render_GET method here will be called whenever the URI we hook this resource up to is requested with the GET method. The byte @@ -69,10 +72,11 @@ factory = Site(resource)

      -

      Just as with the previous static content example, this configuration puts our -resource at the very top of the URI hierarchy, ie at /. With that -Site instance, we can tell the reactor to create a TCP server and start -servicing requests:

      +

      Just as with the previous static content example, this +configuration puts our resource at the very top of the URI hierarchy, +ie at /. With that Site instance, we can +tell the reactor to create +a TCP server and start servicing requests:

      1 2 @@ -104,7 +108,7 @@ class ClockPage(Resource): isLeaf = True def render_GET(self, request): - return "%s" % (time.ctime(),) + return "<html><body>%s</body></html>" % (time.ctime(),) resource = ClockPage() factory = Site(resource) @@ -115,6 +119,6 @@

      Index

      - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/web-in-60/dynamic-dispatch.html twisted-web-11.1.0/doc/howto/web-in-60/dynamic-dispatch.html --- twisted-web-10.0.0/doc/howto/web-in-60/dynamic-dispatch.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/web-in-60/dynamic-dispatch.html 2011-11-17 10:51:14.000000000 +0000 @@ -14,11 +14,11 @@ statically configure Twisted Web to serve different content at different URLs. The goal of this example is to show you how to do this dynamically instead. Reading the previous installment if you haven't already is suggested in -order to get an overview of how URLs are treated when using Twisted Web's resource APIs.

      +order to get an overview of how URLs are treated when using Twisted Web's resource APIs.

      -

      Site (the object which -associates a listening server port with the HTTP implementation), Resource (a convenient base class -to use when defining custom pages), and reactor (the object which implements the Twisted +

      Site (the object which +associates a listening server port with the HTTP implementation), Resource (a convenient base class +to use when defining custom pages), and reactor (the object which implements the Twisted main loop) return once again:

      1 @@ -29,11 +29,12 @@ from twisted.internet import reactor

      -

      With that out of the way, here's the interesting part of this example. We're -going to define a resource which renders a whole-year calendar. The year it will -render the calendar for will be the year in the request URL. So, for example, -/2009 will render a calendar for 2009. First, here's a resource -that renders a calendar for the year passed to its initializer:

      +

      With that out of the way, here's the interesting part of this +example. We're going to define a resource which renders a whole-year +calendar. The year it will render the calendar for will be the year in +the request URL. So, for example, /2009 will render a +calendar for 2009. First, here's a resource that renders a calendar +for the year passed to its initializer:

      1 2 @@ -52,7 +53,7 @@ self.year = year def render_GET(self, request): - return "%s" % (calendar(self.year),) + return "<html><body><pre>%s</pre></body></html>" % (calendar(self.year),)

      Pretty simple - not all that different from the first dynamic resource @@ -68,7 +69,7 @@ return YearPage(int(name))

      -

      By implementing getChild here, we've just defined +

      By implementing getChild here, we've just defined how Twisted Web should find children of Calendar instances when it's resolving an URL into a resource. This implementation defines all integers as the children of Calendar (and punts on error handling, more on @@ -121,7 +122,7 @@ self.year = year def render_GET(self, request): - return "%s" % (calendar(self.year),) + return "<html><body><pre>%s</pre></body></html>" % (calendar(self.year),) class Calendar(Resource): def getChild(self, name, request): @@ -137,6 +138,6 @@

      Index

      - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/web-in-60/error-handling.html twisted-web-11.1.0/doc/howto/web-in-60/error-handling.html --- twisted-web-10.0.0/doc/howto/web-in-60/error-handling.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/web-in-60/error-handling.html 2011-11-17 10:51:14.000000000 +0000 @@ -13,7 +13,7 @@

      In this example we'll extend dynamic dispatch to return a 404 (not found) response when a client requests a non-existent URL.

      -

      As in the previous examples, we'll start with Site, Resource, and reactor imports:

      +

      As in the previous examples, we'll start with Site, Resource, and reactor imports:

      1 2 @@ -23,7 +23,7 @@ from twisted.internet import reactor

      -

      Next, we'll add one more import. NoResource is one of the pre-defined error +

      Next, we'll add one more import. NoResource is one of the pre-defined error resources provided by Twisted Web. It generates the necessary 404 response code and renders a simple html page telling the client there is no such resource.

      @@ -32,7 +32,8 @@

      Next, we'll define a custom resource which does some dynamic URL -dispatch. This example is going to be just like the previous one, where the path segment is +dispatch. This example is going to be just like +the previous one, where the path segment is interpreted as a year; the difference is that this time we'll handle requests which don't conform to that pattern by returning the not found response:

      @@ -54,10 +55,10 @@ return YearPage(year) -

      Aside from including the definition of YearPage from the -previous example, the only other thing left to do is the normal -Site and reactor setup. Here's the complete code for -this example:

      +

      Aside from including the definition of YearPage from +the previous example, the only other thing left to do is the +normal Site and reactor setup. Here's the +complete code for this example:

      1 2 @@ -100,7 +101,7 @@ self.year = year def render_GET(self, request): - return "%s" % (calendar(self.year),) + return "<html><body><pre>%s</pre></body></html>" % (calendar(self.year),) class Calendar(Resource): def getChild(self, name, request): @@ -124,6 +125,6 @@

      Index

      - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/web-in-60/handling-posts.html twisted-web-11.1.0/doc/howto/web-in-60/handling-posts.html --- twisted-web-10.0.0/doc/howto/web-in-60/handling-posts.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/web-in-60/handling-posts.html 2011-11-17 10:51:15.000000000 +0000 @@ -14,7 +14,7 @@ requests. Unlike GET requests, POST requests can have a request body - extra data after the request headers; for example, data representing the contents of an HTML form. Twisted Web makes this data available -to applications via the Request object.

      +to applications via the Request object.

      Here's an example web server which renders a static HTML form and then generates a dynamic page when that form is posted back to it. Disclaimer: While @@ -47,7 +47,7 @@ 3

      class FormPage(Resource): def render_GET(self, request): - return '' + return '<html><body><form method="POST"><input name="the-field" type="text" /></form></body></html>'

      This is similar to the resource used in a previous installment. However, we'll now add @@ -56,20 +56,24 @@

      1 2 -

      def render_POST(self, request): - return 'You submitted: %s' % (cgi.escape(request.args["the-field"][0]),) +3 +

      ... + def render_POST(self, request): + return '<html><body>You submitted: %s</body></html>' % (cgi.escape(request.args["the-field"][0]),)
      -

      The main thing to note here is the use of request.args. This is -a dictionary-like object that provides access to the contents of the form. The -keys in this dictionary are the names of inputs in the form. Each value is a -list containing strings (since there can be multiple inputs with the same name), -which is why we had to extract the first element to pass to -cgi.escape. request.args will be populated from form -contents whenever a POST request is made with a content type of -application/x-www-form-urlencoded or -multipart/form-data (it's also populated by query arguments for any -type of request).

      +

      The main thing to note here is the use +of request.args. This is a dictionary-like object that +provides access to the contents of the form. The keys in this +dictionary are the names of inputs in the form. Each value is a list +containing strings (since there can be multiple inputs with the same +name), which is why we had to extract the first element to pass +to cgi.escape. request.args will be +populated from form contents whenever a POST request is +made with a content type +of application/x-www-form-urlencoded +or multipart/form-data (it's also populated by query +arguments for any type of request).

      Finally, the example just needs the usual site creation and port setup:

      @@ -85,9 +89,10 @@ reactor.run() -

      Run the server and visit http://localhost:8880/form, submit the -form, and watch it generate a page including the value you entered into the -single field.

      +

      Run the server and +visit http://localhost:8880/form, +submit the form, and watch it generate a page including the value you entered +into the single field.

      Here's the complete source for the example:

      @@ -117,10 +122,10 @@ class FormPage(Resource): def render_GET(self, request): - return '' + return '<html><body><form method="POST"><input name="the-field" type="text" /></form></body></html>' def render_POST(self, request): - return 'You submitted: %s' % (cgi.escape(request.args["the-field"][0]),) + return '<html><body>You submitted: %s</body></html>' % (cgi.escape(request.args["the-field"][0]),) root = Resource() root.putChild("form", FormPage()) @@ -132,6 +137,6 @@

      Index

      - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/web-in-60/http-auth.html twisted-web-11.1.0/doc/howto/web-in-60/http-auth.html --- twisted-web-10.0.0/doc/howto/web-in-60/http-auth.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/web-in-60/http-auth.html 2011-11-17 10:51:15.000000000 +0000 @@ -15,42 +15,45 @@ Twisted Web's basic or digest HTTP authentication to control access to these resources.

      -

      guard, the Twisted Web -module which provides most of the APIs that will be used in this example, helps -you to +

      guard, the Twisted Web +module which provides most of the APIs that will be used in this +example, helps you to add authentication -and authorization to a -resource hierarchy. It does this by providing a resource which implements -getChild to return -a dynamically selected resource. The -selection is based on the authentication headers in the request. If those -headers indicate that the request is made on behalf of Alice, then Alice's -resource will be returned. If they indicate that it was made on behalf of Bob, -his will be returned. If the headers contain invalid credentials, an error -resource is returned. Whatever happens, once this resource is returned, URL +and authorization +to a resource hierarchy. It does this by providing a resource which +implements getChild to return +a dynamically selected +resource. The selection is based on the authentication headers in +the request. If those headers indicate that the request is made on +behalf of Alice, then Alice's resource will be returned. If they +indicate that it was made on behalf of Bob, his will be returned. If +the headers contain invalid credentials, an error resource is +returned. Whatever happens, once this resource is returned, URL traversal continues as normal from that resource.

      -

      The resource that implements this is HTTPAuthSessionWrapper, though it is directly +

      The resource that implements this is HTTPAuthSessionWrapper, though it is directly responsible for very little of the process. It will extract headers from the request and hand them off to a credentials factory to parse them according to the appropriate standards (eg HTTP Authentication: Basic and Digest Access Authentication) and then hand the -resulting credentials object off to a Portal, the core +resulting credentials object off to a Portal, the core of Twisted Cred, a system for uniform handling of authentication and authorization. We won't discuss Twisted Cred in much depth here. To make use of it with Twisted Web, the only thing you -really need to know is how to implement an IRealm.

      +really need to know is how to implement an IRealm.

      -

      You need to implement a realm because the realm is the object that actually -decides which resources are used for which users. This can be as complex or as -simple as it suitable for your application. For this example we'll keep it very -simple: each user will have a resource which is a static file listing of the -public_html directory in their UNIX home directory. First, we need -to import implements from zope.interface and IRealm from -twisted.cred.portal. Together these will let me mark this class as -a realm (this is mostly - but not entirely - a documentation thing). We'll also -need File for the actual -implementation later.

      +

      You need to implement a realm because the realm is the object that +actually decides which resources are used for which users. This can be +as complex or as simple as it suitable for your application. For this +example we'll keep it very simple: each user will have a resource +which is a static file listing of the public_html +directory in their UNIX home directory. First, we need to +import implements from zope.interface +and IRealm +from twisted.cred.portal. Together these will let me mark +this class as a realm (this is mostly - but not entirely - a +documentation thing). We'll also need File for the actual implementation +later.

      1 2 @@ -68,7 +71,7 @@ implements(IRealm)

      -

      A realm only needs to implement one method: requestAvatar. This method is called +

      A realm only needs to implement one method: requestAvatar. This method is called after any successful authentication attempt (ie, Alice supplied the right password). Its job is to return the avatar for the user who succeeded in authenticating. An avatar is just an object that represents a user. In @@ -79,10 +82,12 @@ 2 3 4 -

      def requestAvatar(self, avatarId, mind, *interfaces): - if IResource in interfaces: - return (IResource, File("/home/%s/public_html" % (avatarId,)), lambda: None) - raise NotImplementedError() +5 +

      ... + def requestAvatar(self, avatarId, mind, *interfaces): + if IResource in interfaces: + return (IResource, File("/home/%s/public_html" % (avatarId,)), lambda: None) + raise NotImplementedError()

      A few notes on this method:

      @@ -106,14 +111,14 @@
    1. Notice that the path handling code in this example is written very poorly. This example may be vulnerable to certain unintentional information disclosure attacks. This sort of problem is exactly the - reason FilePath + reason FilePath exists. However, that's an example for another day...
    2. -

      We're almost ready to set up the resource for this example. To create an -HTTPAuthSessionWrapper, though, we need two things. First, a -portal, which requires the realm above, plus at least one credentials -checker:

      +

      We're almost ready to set up the resource for this example. To +create an HTTPAuthSessionWrapper, though, we need two +things. First, a portal, which requires the realm above, plus at least +one credentials checker:

      1 2 @@ -125,15 +130,15 @@ portal = Portal(PublicHTMLRealm(), [FilePasswordDB('httpd.password')])

      -

      FilePasswordDB is the +

      FilePasswordDB is the credentials checker. It knows how to read passwd(5)-style (loosely) files to check credentials against. It is responsible for the authentication work after HTTPAuthSessionWrapper extracts the credentials from the request.

      -

      Next we need either BasicCredentialFactory or -DigestCredentialFactory. The -former knows how to challenge HTTP clients to do basic authentication; the +

      Next we need either BasicCredentialFactory +or DigestCredentialFactory. The former +knows how to challenge HTTP clients to do basic authentication; the latter, digest authentication. We'll use digest here:

      1 @@ -144,12 +149,13 @@ credentialFactory = DigestCredentialFactory("md5", "example.org")

      -

      The two parameters to this constructor are the hash algorithm and the HTTP -authentication realm which will be used. The only other valid hash algorithm is -"sha" (but be careful, MD5 is more widely supported than SHA). The HTTP -authentication realm is mostly just a string that is presented to the user to -let them know why they're authenticating (you can read more about this in the -RFC).

      +

      The two parameters to this constructor are the hash algorithm and +the HTTP authentication realm which will be used. The only other valid +hash algorithm is "sha" (but be careful, MD5 is more widely supported +than SHA). The HTTP authentication realm is mostly just a string that +is presented to the user to let them know why they're authenticating +(you can read more about this in +the RFC).

      With those things created, we can finally instantiate HTTPAuthSessionWrapper:

      @@ -163,15 +169,15 @@

      There's just one last thing that needs to be done -here. When rpy scripts were introduced, it was -mentioned that they are evaluated in an unusual context. This is the first -example that actually needs to take this into account. It so happens that -DigestCredentialFactory instances are stateful. Authentication will -only succeed if the same instance is used to both generate challenges and -examine the responses to those challenges. However, the normal mode of operation -for an rpy script is for it to be re-executed for every request. This leads to a -new -DigestCredentialFactory being created for every request, preventing +here. When rpy scripts were +introduced, it was mentioned that they are evaluated in an unusual +context. This is the first example that actually needs to take this +into account. It so happens that DigestCredentialFactory +instances are stateful. Authentication will only succeed if the same +instance is used to both generate challenges and examine the responses +to those challenges. However, the normal mode of operation for an rpy +script is for it to be re-executed for every request. This leads to a +new DigestCredentialFactory being created for every request, preventing any authentication attempt from ever succeeding.

      There are two ways to deal with this. First, and the better of the two ways, @@ -245,6 +251,6 @@

      Index

      - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/web-in-60/index.html twisted-web-11.1.0/doc/howto/web-in-60/index.html --- twisted-web-10.0.0/doc/howto/web-in-60/index.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/web-in-60/index.html 2011-11-17 10:51:14.000000000 +0000 @@ -11,10 +11,10 @@ -

      This set of examples contains short, complete applications of -twisted.web. For subjects not covered here, see -the Twisted Web tutorial and the API -documentation.

      +

      This set of examples contains short, complete applications +of twisted.web. For subjects not covered +here, see the Twisted Web +tutorial and the API documentation.

      1. Serving static content from a directory
      2. @@ -39,6 +39,6 @@

        Index

        - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/web-in-60/interrupted.html twisted-web-11.1.0/doc/howto/web-in-60/interrupted.html --- twisted-web-10.0.0/doc/howto/web-in-60/interrupted.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/web-in-60/interrupted.html 2011-11-17 10:51:14.000000000 +0000 @@ -24,7 +24,7 @@ the client connection is lost, the delayed event is cancelled and the response is never generated.

        -

        The feature this example relies on is provided by another Request method: notifyFinish. This method returns a new +

        The feature this example relies on is provided by another Request method: notifyFinish. This method returns a new Deferred which will fire with None if the request is successfully responded to or with an error otherwise - for example if the connection is lost before the response is sent.

        @@ -41,49 +41,54 @@ 7 8

        from twisted.web.resource import Resource - from twisted.web.server import NOT_DONE_YET - from twisted.internet import reactor +from twisted.web.server import NOT_DONE_YET +from twisted.internet import reactor - class DelayedResource(Resource): - def _delayedRender(self, request): - request.write("Sorry to keep you waiting.") - request.finish() +class DelayedResource(Resource): + def _delayedRender(self, request): + request.write("<html><body>Sorry to keep you waiting.</body></html>") + request.finish() -

        Before defining the render method, we're going to define an errback (an -errback being a callback that gets called when there's an error), though. This -will be the errback attached to the Deferred returned by -Request.notifyFinish. It will cancel the delayed call to -_delayedRender.

        +

        Before defining the render method, we're going to define an errback +(an errback being a callback that gets called when there's an error), +though. This will be the errback attached to the Deferred +returned by Request.notifyFinish. It will cancel the +delayed call to _delayedRender.

        1 2 -

        def _responseFailed(self, err, call): - call.cancel() +3 +

        ... + def _responseFailed(self, err, call): + call.cancel()
        -

        Finally, the render method will set up the delayed call just as it did -before, and return NOT_DONE_YET likewise. However, it will also use -Request.notifyFinish to make sure _responseFailed is -called if appropriate.

        +

        Finally, the render method will set up the delayed call just as it +did before, and return NOT_DONE_YET likewise. However, it +will also use Request.notifyFinish to make +sure _responseFailed is called if appropriate.

        1 2 3 4 -

        def render_GET(self, request): - call = reactor.callLater(5, self._delayedRender, request) - request.notifyFinish().addErrback(self._responseFailed, call) - return NOT_DONE_YET +5 +

        ... + def render_GET(self, request): + call = reactor.callLater(5, self._delayedRender, request) + request.notifyFinish().addErrback(self._responseFailed, call) + return NOT_DONE_YET
        -

        Notice that since _responseFailed needs a reference to the -delayed call object in order to cancel it, we passed that object to -addErrback. Any additional arguments passed to -addErrback (or addCallback) will be passed along to -the errback after the Failure instance which is always passed as -the first argument. Passing call here means it will be passed to -_responseFailed, where it is expected and required.

        +

        Notice that since _responseFailed needs a reference to +the delayed call object in order to cancel it, we passed that object +to addErrback. Any additional arguments passed +to addErrback (or addCallback) will be +passed along to the errback after the Failure instance which is always +passed as the first argument. Passing call here means it +will be passed to _responseFailed, where it is expected +and required.

        That covers almost all the code for this example. Here's the entire example without interruptions, as an rpy script:

        @@ -112,7 +117,7 @@ class DelayedResource(Resource): def _delayedRender(self, request): - request.write("Sorry to keep you waiting.") + request.write("<html><body>Sorry to keep you waiting.</body></html>") request.finish() def _responseFailed(self, err, call): @@ -126,8 +131,9 @@ resource = DelayedResource() -

        Toss this into example.rpy, fire it up with twistd -n web --path -., and hit http://localhost:8080/example.rpy. If +

        Toss this into example.rpy, fire it up with twistd -n +web --path ., and +hit http://localhost:8080/example.rpy. If you wait five seconds, you'll get the page content. If you interrupt the request before then, say by hitting escape (in Firefox, at least), then you'll see perhaps the most boring demonstration ever - no page content, and nothing in the @@ -136,6 +142,6 @@

        Index

        - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/web-in-60/logging-errors.html twisted-web-11.1.0/doc/howto/web-in-60/logging-errors.html --- twisted-web-10.0.0/doc/howto/web-in-60/logging-errors.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/web-in-60/logging-errors.html 2011-11-17 10:51:14.000000000 +0000 @@ -15,12 +15,13 @@ pointless work. However, it did this silently for any error. In this example, we'll modify the previous example so that it logs each failed response.

        -

        This example will use the Twisted API for logging errors. As was mentioned in -the first example covering Deferreds, -errbacks are passed an error. In the previous example, the -_responseFailed errback accepted this error as a parameter but -ignored it. The only way this example will differ is that this -_responseFailed will use that error parameter to log a message.

        +

        This example will use the Twisted API for logging errors. As was +mentioned in the first example +covering Deferreds, errbacks are passed an error. In the previous +example, the _responseFailed errback accepted this error +as a parameter but ignored it. The only way this example will differ +is that this _responseFailed will use that error +parameter to log a message.

        This example will require all of the imports required by the previous example plus one new import:

        @@ -29,20 +30,22 @@

        from twisted.python.log import err -

        The only other part of the previous example which changes is the -_responseFailed callback, which will now log the error passed to -it:

        +

        The only other part of the previous example which changes is +the _responseFailed callback, which will now log the +error passed to it:

        1 2 3 -

        def _responseFailed(self, failure, call): - call.cancel() - err(failure, "Async response demo interrupted response") +4 +

        ... + def _responseFailed(self, failure, call): + call.cancel() + err(failure, "Async response demo interrupted response")
        -

        We're passing two arguments to err here. The first is the error which is being -passed in to the callback. This is always an object of type Failure, a class which represents an +

        We're passing two arguments to err here. The first is the error which is being +passed in to the callback. This is always an object of type Failure, a class which represents an exception and (sometimes, but not always) a traceback. err will format this nicely for the log. The second argument is a descriptive string that tells someone reading the log what the source of the error was.

        @@ -76,7 +79,7 @@ class DelayedResource(Resource): def _delayedRender(self, request): - request.write("Sorry to keep you waiting.") + request.write("<html><body>Sorry to keep you waiting.</body></html>") request.finish() def _responseFailed(self, failure, call): @@ -99,6 +102,6 @@

        Index

        - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/web-in-60/rpy-scripts.html twisted-web-11.1.0/doc/howto/web-in-60/rpy-scripts.html --- twisted-web-10.0.0/doc/howto/web-in-60/rpy-scripts.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/web-in-60/rpy-scripts.html 2011-11-17 10:51:14.000000000 +0000 @@ -21,12 +21,13 @@ means fewer lines of code that aren't dedicated to the task you're trying to accomplish.

        -

        There are some disadvantages, though. An rpy script must have the extension -.rpy. This means you can't import it using the usual Python import -statement. This means it's hard to re-use code in an rpy script. This also means -you can't easily unit test it. The code in an rpy script is evaluated in an -unusual context. So, while rpy scripts may be useful for testing out ideas, -they're not recommend for much more than that.

        +

        There are some disadvantages, though. An rpy script must have the +extension .rpy. This means you can't import it using the +usual Python import statement. This means it's hard to re-use code in +an rpy script. This also means you can't easily unit test it. The code +in an rpy script is evaluated in an unusual context. So, while rpy +scripts may be useful for testing out ideas, they're not recommend for +much more than that.

        Okay, with that warning out of the way, let's dive in. First, as mentioned, rpy scripts are Python source files with the .rpy extension. So, @@ -50,18 +51,20 @@ class ClockPage(Resource): isLeaf = True def render_GET(self, request): - return "%s" % (time.ctime(),) + return "<html><body>%s</body></html>" % (time.ctime(),) resource = ClockPage() -

        You may recognize this as the resource from the first dynamic rendering example. What's -different is what you don't see: we didn't import reactor or -Site. There are no calls to listenTCP or -run. Instead, and this is the core idea for rpy scripts, we just -bound the name resource to the resource we want the script to -serve. Every rpy script must bind this name, and this name is the only thing -Twisted Web will pay attention to in an rpy script.

        +

        You may recognize this as the resource from +the first dynamic rendering +example. What's different is what you don't see: we didn't +import reactor or Site. There are no calls +to listenTCP or run. Instead, and this is +the core idea for rpy scripts, we just bound the +name resource to the resource we want the script to +serve. Every rpy script must bind this name, and this name is the only +thing Twisted Web will pay attention to in an rpy script.

        All that's left is to drop this rpy script into a Twisted Web server. There are a few ways to do this. The simplest way is with twistd:

        @@ -70,7 +73,8 @@ $ twistd -n web --path . -

        Hit http://localhost:8080/example.rpy +

        Hit +http://localhost:8080/example.rpy to see it run. You can pass other arguments here too. twistd web has options for specifying which port number to bind, whether to set up an HTTPS server, and plenty more. Other options you can pass to twistd allow @@ -81,6 +85,6 @@

        Index

        - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/web-in-60/session-basics.html twisted-web-11.1.0/doc/howto/web-in-60/session-basics.html --- twisted-web-10.0.0/doc/howto/web-in-60/session-basics.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/web-in-60/session-basics.html 2011-11-17 10:51:14.000000000 +0000 @@ -16,21 +16,22 @@ Twisted Web session API: how to get the session object for the current request and how to prematurely expire a session.

        -

        Before diving into the APIs, let's look at the big picture of sessions in -Twisted Web. Sessions are represented by instances of Session. The Site creates a new instance of -Session the first time an application asks for it for a particular -session. Session instances are kept on the Site -instance until they expire (due to inactivity or because they are explicitly -expired). Each time after the first that a particular session's -Session object is requested, it is retrieved from -the Site.

        +

        Before diving into the APIs, let's look at the big picture of +sessions in Twisted Web. Sessions are represented by instances +of Session. The Site creates a new instance +of Session the first time an application asks for it for +a particular session. Session instances are kept on +the Site instance until they expire (due to inactivity or +because they are explicitly expired). Each time after the first that a +particular session's Session object is requested, it is +retrieved from the Site.

        With the conceptual underpinnings of the upcoming API in place, here comes the example. This will be a very simple rpy script which tells a user what its unique session identifier is and lets it prematurely expire the session.

        -

        First, we'll import Resource so we can define a couple of +

        First, we'll import Resource so we can define a couple of subclasses of it:

        1 @@ -39,7 +40,7 @@

        Next we'll define the resource which tells the client what its session identifier is. This is done easily by first getting the session object -using Request.getSession and +using Request.getSession and then getting the session object's uid attribute:

        1 @@ -52,7 +53,7 @@

        To let the client expire its own session before it times out, we'll define another resource which expires whatever session it is requested with. This is -done using the Session.expire +done using the Session.expire method:

        1 @@ -65,9 +66,9 @@ return 'Your session has been expired.'

        -

        Finally, to make the example an rpy script, we'll make an instance of -ShowSession and give it an instance of ExpireSession -as a child using Resource.putChild:

        +

        Finally, to make the example an rpy script, we'll make an instance +of ShowSession and give it an instance +of ExpireSession as a child using Resource.putChild:

        1 2 @@ -115,6 +116,6 @@

        Index

        - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/web-in-60/session-endings.html twisted-web-11.1.0/doc/howto/web-in-60/session-endings.html --- twisted-web-10.0.0/doc/howto/web-in-60/session-endings.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/web-in-60/session-endings.html 2011-11-17 10:51:14.000000000 +0000 @@ -12,7 +12,7 @@

        The previous two examples introduced Twisted Web's session APIs. This included accessing the session object, storing state on it, and retrieving it -later, as well as the idea that the Session object has a lifetime which is tied to +later, as well as the idea that the Session object has a lifetime which is tied to the notional session it represents. This example demonstrates how to exert some control over that lifetime and react when it expires.

        @@ -33,10 +33,10 @@ sessionTimeout = 60
        -

        To have Twisted Web actually make use of this session class, rather than the -default, it is also necessary to override the sessionFactory attribute of -Site. We could do this with -another subclass, but we could also do it to just one instance +

        To have Twisted Web actually make use of this session class, rather +than the default, it is also necessary to override +the sessionFactory attribute of Site. We could do this with another +subclass, but we could also do it to just one instance of Site:

        1 @@ -52,11 +52,11 @@

        Sessions given out for requests served by this Site will use ShortSession and only last one minute without activity.

        -

        You can have arbitrary functions run when sessions expire, too. This can be -useful for cleaning up external resources associated with the session, tracking -usage statistics, and more. This functionality is provided via -Session.notifyOnExpire. It -accepts a single argument: a function to call when the session expires. Here's a +

        You can have arbitrary functions run when sessions expire, +too. This can be useful for cleaning up external resources associated +with the session, tracking usage statistics, and more. This +functionality is provided via Session.notifyOnExpire. It accepts a +single argument: a function to call when the session expires. Here's a trivial example which prints a message whenever a session expires:

        1 @@ -165,6 +165,6 @@

        Index

        - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/web-in-60/session-store.html twisted-web-11.1.0/doc/howto/web-in-60/session-store.html --- twisted-web-10.0.0/doc/howto/web-in-60/session-store.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/web-in-60/session-store.html 2011-11-17 10:51:14.000000000 +0000 @@ -14,8 +14,8 @@ session object.

        As was discussed previously, instances -of Session last as long as -the notional session itself does. Each time Request.getSession is called, if the session +of Session last as long as +the notional session itself does. Each time Request.getSession is called, if the session for the request is still active, then the same Session instance is returned as was returned previously. Because of this, Session instances can be used to keep other objects around for as long as the session @@ -48,9 +48,9 @@

        What?, I hear you say.

        -

        What's shown in this example is the interface and adaption-based API which -Session exposes for persisting state. There are several critical -pieces interacting here:

        +

        What's shown in this example is the interface and adaption-based +API which Session exposes for persisting state. There are +several critical pieces interacting here:

        • ICounter is an interface which serves several purposes. Like @@ -63,11 +63,11 @@ this example. It implements ICounter (again, mostly for documentation purposes). It also has a value attribute, as the interface declared.
        • -
        • The registerAdapter call sets up the +
        • The registerAdapter call sets up the relationship between its three arguments so that adaption will do what we want in this case.
        • Adaption is performed by the expression ICounter(ses). This - is read as adapt ses to ICounter. Because + is read as : adapt ses to ICounter. Because of the registerAdapter call, it is roughly equivalent to Counter(ses). However (because of certain things Session does), it also saves the Counter @@ -163,18 +163,19 @@ resource = CounterResource()
        -

        One more thing to note is the cache() call at the top of this -example. As with the previous example where this -came up, this rpy script is stateful. This time, it's the ICounter -definition and the -registerAdapter call that need to be executed only once. If we -didn't use cache, every request would define a new, different -interface named ICounter. Each of these would be a different key in -the session, so the counter would never get past one.

        +

        One more thing to note is the cache() call at the top +of this example. As with the previous +example where this came up, this rpy script is stateful. This +time, it's the ICounter definition and +the registerAdapter call that need to be executed only +once. If we didn't use cache, every request would define +a new, different interface named ICounter. Each of these +would be a different key in the session, so the counter would never +get past one.

        Index

        - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/web-in-60/static-content.html twisted-web-11.1.0/doc/howto/web-in-60/static-content.html --- twisted-web-10.0.0/doc/howto/web-in-60/static-content.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/web-in-60/static-content.html 2011-11-17 10:51:14.000000000 +0000 @@ -16,8 +16,8 @@
        • -Site, an IProtocolFactory which -glues a listening server port (IListeningPort) to the HTTPChannel +Site, an IProtocolFactory which +glues a listening server port (IListeningPort) to the HTTPChannel implementation:

          1

          from twisted.web.server import Site @@ -25,7 +25,7 @@
        • -File, an IResource which glues +File, an IResource which glues the HTTP protocol implementation to the filesystem:

          1

          from twisted.web.static import File @@ -33,7 +33,7 @@
        • -The reactor, which +The reactor, which drives the whole process, actually accepting TCP connections and moving bytes into and out of them:

          1 @@ -97,6 +97,6 @@

          Index

          - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/web-in-60/static-dispatch.html twisted-web-11.1.0/doc/howto/web-in-60/static-dispatch.html --- twisted-web-10.0.0/doc/howto/web-in-60/static-dispatch.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/web-in-60/static-dispatch.html 2011-11-17 10:51:14.000000000 +0000 @@ -21,17 +21,17 @@ root resource (the one used to construct the Site) and the first path segment, a child resource is looked up. As long as there are more path segments, this process is repeated using the result of the previous lookup and -the next path segment. For example, to handle a request for -/foo/bar, first the root's "foo" child is retrieved, -then that resource's "bar" child is retrieved, then that resource -is used to create the response.

          +the next path segment. For example, to handle a request +for "/foo/bar", first the root's "foo" child is +retrieved, then that resource's "bar" child is retrieved, then that +resource is used to create the response.

          With that out of the way, let's consider an example that can serve a few different resources at a few different URLs.

          -

          First things first: we need to import Site, the factory for HTTP servers, Resource, a convenient base class -for custom pages, and reactor, -the object which implements the Twisted main loop. We'll also import File to use as the resource at one +

          First things first: we need to import Site, the factory for HTTP servers, Resource, a convenient base class +for custom pages, and reactor, +the object which implements the Twisted main loop. We'll also import File to use as the resource at one of the example URLs.

          1 @@ -51,9 +51,9 @@

          root = Resource()
          -

          Here comes the interesting part of this example. We're now going to create -three more resources and attach them to the three URLs /foo, -/bar, and /baz:

          +

          Here comes the interesting part of this example. We're now going to +create three more resources and attach them to the three +URLs /foo, /bar, and /baz:

          1 2 @@ -74,11 +74,12 @@ reactor.run()

          -

          With this server running, http://localhost:8880/foo will serve a -listing of files from /tmp, http://localhost:8880/bar -will serve a listing of files from /lost+found, and -http://localhost:8880/baz will serve a listing of files from -/opt.

          +

          With this server running, http://localhost:8880/foo +will serve a listing of files +from /tmp, http://localhost:8880/bar will +serve a listing of files from /lost+found, +and http://localhost:8880/baz will serve a listing of +files from /opt.

          Here's the whole example uninterrupted:

          @@ -113,6 +114,6 @@

          Index

          - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/web-in-60/wsgi.html twisted-web-11.1.0/doc/howto/web-in-60/wsgi.html --- twisted-web-10.0.0/doc/howto/web-in-60/wsgi.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/web-in-60/wsgi.html 2011-11-17 10:51:14.000000000 +0000 @@ -10,10 +10,11 @@
          -

          The goal of this example is to show you how to use WSGIResource, another existing -Resource subclass, to serve -WSGI applications in a -Twisted Web server.

          +

          The goal of this example is to show you how to +use WSGIResource, +another existing Resource subclass, to +serve WSGI applications +in a Twisted Web server.

          Note thate WSGIResource is a multithreaded WSGI container. Like any other WSGI container, you can't do anything asynchronous in your WSGI @@ -54,19 +55,20 @@

          resource = WSGIResource(reactor, reactor.getThreadPool(), application)
          -

          Let's dwell on this line for a minute. The first parameter passed to -WSGIResource is the reactor. Despite the fact that the reactor is -global and any code that wants it can always just import it (as, in fact, this -rpy script simply does itself), passing it around as a parameter leaves the door -open for certain future possibilities - for example, having more than one -reactor. There are also testing implications. Consider how much easier it is to -unit test a function that accepts a reactor - perhaps a mock reactor specially -constructed to make your tests easy to write - rather than importing the real -global reactor. That's why WSGIResource requires you to pass the -reactor to it.

          +

          Let's dwell on this line for a minute. The first parameter passed +to WSGIResource is the reactor. Despite the fact that the +reactor is global and any code that wants it can always just import it +(as, in fact, this rpy script simply does itself), passing it around +as a parameter leaves the door open for certain future possibilities - +for example, having more than one reactor. There are also testing +implications. Consider how much easier it is to unit test a function +that accepts a reactor - perhaps a mock reactor specially constructed +to make your tests easy to write - rather than importing the real +global reactor. That's why WSGIResource requires you to +pass the reactor to it.

          The second parameter passed to WSGIResource is -a ThreadPool. WSGIResource +a ThreadPool. WSGIResource uses this to actually call the application object passed in to it. To keep this example short, we're passing in the reactor's internal threadpool here, letting us skip its creation and shutdown-time destruction. For finer control over how @@ -99,7 +101,7 @@

          Up to the point where the WSGIResource instance defined here exists in the resource hierarchy, the normal resource traversal rules -apply: getChild +apply: getChild will be called to handle each segment. Once the WSGIResource is encountered, though, that process stops and all further URL handling is the responsibility of the WSGI application. This application does nothing with the @@ -118,6 +120,6 @@

          Index

          - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/web-overview.html twisted-web-11.1.0/doc/howto/web-overview.html --- twisted-web-10.0.0/doc/howto/web-overview.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/web-overview.html 2011-11-17 10:51:14.000000000 +0000 @@ -39,10 +39,10 @@ single page to be rendered. The interface for making Resources is very simple; they must have a method named render which takes a single argument, which is the - Request object (an instance of twisted.web.server.Request). This render + Request object (an instance of twisted.web.server.Request). This render method must return a string, which will be returned to the web browser making the request. Alternatively, they can return a - special constant, twisted.web.server.NOT_DONE_YET, which tells + special constant, twisted.web.server.NOT_DONE_YET, which tells the web server not to close the connection; you must then use request.write(data) to render the page, and call request.finish() @@ -55,13 +55,13 @@

          Web programmers seeking a higher level abstraction than the Resource system - should look at Nevow. + should look at Nevow. Nevow is based on ideas previously developed in Twisted, but is now maintained outside of Twisted to easy development and release cycle pressures.

          Index

          - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/howto/xmlrpc.html twisted-web-11.1.0/doc/howto/xmlrpc.html --- twisted-web-10.0.0/doc/howto/xmlrpc.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/howto/xmlrpc.html 2011-11-17 10:51:14.000000000 +0000 @@ -6,19 +6,21 @@

          Creating XML-RPC Servers and Clients with Twisted

          - +

          Introduction

          -

          XML-RPC is a simple request/reply protocol that runs over HTTP. It is simple, -easy to implement and supported by most programming languages. Twisted's XML-RPC -support is implemented using the xmlrpclib library that is included with Python 2.2 and later.

          +

          XML-RPC is a simple request/reply protocol +that runs over HTTP. It is simple, easy to implement and supported by most programming +languages. Twisted's XML-RPC support is implemented using the +xmlrpclib library that is +included with Python 2.2 and later.

          Creating a XML-RPC server

          -

          Making a server is very easy - all you need to do is inherit from twisted.web.xmlrpc.XMLRPC. +

          Making a server is very easy - all you need to do is inherit from twisted.web.xmlrpc.XMLRPC. You then create methods beginning with xmlrpc_. The methods' arguments determine what arguments it will accept from XML-RPC clients. The result is what will be returned to the clients.

          @@ -26,13 +28,14 @@

          Methods published via XML-RPC can return all the basic XML-RPC types, such as strings, lists and so on (just return a regular python integer, etc). They can also raise exceptions or return Failure instances to indicate an -error has occurred, or Binary, Boolean or DateTime instances (all of these are the same as -the respective classes in xmlrpclib. In addition, XML-RPC published -methods can return Deferred instances whose results are one of the -above. This allows you to return results that can't be calculated -immediately, such as database queries. See the Deferred documentation for more details.

          +error has occurred, or Binary, Boolean or DateTime +instances (all of these are the same as the respective classes in xmlrpclib. In +addition, XML-RPC published methods can return Deferred instances whose results are one of the above. This allows +you to return results that can't be calculated immediately, such as database queries. +See the Deferred documentation for more +details.

          -

          XMLRPC instances +

          XMLRPC instances are Resource objects, and they can thus be published using a Site. The following example has two methods published via XML-RPC, add(a, b) and echo(x).

          @@ -65,10 +68,14 @@ 26 27 28 +29 +30

          from twisted.web import xmlrpc, server class Example(xmlrpc.XMLRPC): - """An example object to be published.""" + """ + An example object to be published. + """ def xmlrpc_echo(self, x): """ @@ -113,6 +120,38 @@
        +

        If the Request object is +needed by an xmlrpc_* method, it can be made available using +the twisted.web.xmlrpc.withRequest decorator. When +using this decorator, the method will be passed the request object as the first +argument, before any XML-RPC parameters. For example:

        + +

        1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +

        from twisted.web.xmlrpc import XMLRPC, withRequest +from twisted.web.server import Site + +class Example(XMLRPC): + @withRequest + def xmlrpc_headerValue(self, request, headerName): + return request.requestHeaders.getRawHeaders(headerName) + +if __name__ == '__main__': + from twisted.internet import reactor + reactor.listenTCP(7080, Site(Example())) + reactor.run() +
        +

        XML-RPC resources can also be part of a normal Twisted web server, using resource scripts. The following is an example of such a resource script:

        @@ -145,9 +184,10 @@

        Using XML-RPC sub-handlers

        XML-RPC resource can be nested so that one handler calls another if -a method with a given prefix is called. For example, to add support for -an XML-RPC method date.time() to the -Example class, you could do the following:

        +a method with a given prefix is called. For example, to add support +for an XML-RPC method date.time() to +the Example class, you could do the +following:

        1 2 @@ -177,25 +217,45 @@ 26 27 28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38

        import time from twisted.web import xmlrpc, server class Example(xmlrpc.XMLRPC): - """An example object to be published.""" + """ + An example object to be published. + """ def xmlrpc_echo(self, x): - """Return all passed args.""" + """ + Return all passed args. + """ return x def xmlrpc_add(self, a, b): - """Return sum of arguments.""" + """ + Return sum of arguments. + """ return a + b class Date(xmlrpc.XMLRPC): - """Serve the XML-RPC 'time' method.""" + """ + Serve the XML-RPC 'time' method. + """ def xmlrpc_time(self): - """Return UNIX time.""" + """ + Return UNIX time. + """ return time.time() if __name__ == '__main__': @@ -212,14 +272,146 @@ XML-RPC server. XML-RPC servers may be nested to arbitrary depths using this method.

        -

        Adding XML-RPC Introspection support

        +

        Using your own procedure getter

        + +

        Sometimes, you want to implement your own policy of getting the end implementation. +E.g. just like sub-handlers you want to divide the implementations into separate classes but +may not want to introduce XMLRPC.separator in the procedure name. +In such cases just override the lookupProcedure(self, procedurePath) +method and return the correct callable. +Raise twisted.web.xmlrpc.NoSuchFunction otherwise.

        + +

        1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +

        from twisted.web import xmlrpc, server + +class EchoHandler: + + def echo(self, x): + """ + Return all passed args + """ + return x + + + +class AddHandler: + + def add(self, a, b): + """ + Return sum of arguments. + """ + return a + b + + + +class Example(xmlrpc.XMLRPC): + """ + An example of using you own policy to fetch the handler + """ + + def __init__(self): + xmlrpc.XMLRPC.__init__(self) + self._addHandler = AddHandler() + self._echoHandler = EchoHandler() + + #We keep a dict of all relevant + #procedure names and callable. + self._procedureToCallable = { + 'add':self._addHandler.add, + 'echo':self._echoHandler.echo + } + + def lookupProcedure(self, procedurePath): + try: + return self._procedureToCallable[procedurePath] + except KeyError, e: + raise xmlrpc.NoSuchFunction(self.NOT_FOUND, + "procedure %s not found" % procedurePath) + + def listProcedures(self): + """ + Since we override lookupProcedure, its suggested to override + listProcedures too. + """ + return ['add', 'echo'] + + + +if __name__ == '__main__': + from twisted.internet import reactor + r = Example() + reactor.listenTCP(7080, server.Site(r)) + reactor.run() +
        + +

        Adding XML-RPC Introspection support

        -

        XML-RPC has an informal Introspection API that specifies three -methods in a system sub-handler which allow a client to query -a server about the server's API. Adding Introspection support to the -Example class is easy using the -XMLRPCIntrospection -class:

        +

        XML-RPC has an +informal Introspection +API that specifies three methods in a system +sub-handler which allow a client to query a server about the server's +API. Adding Introspection support to +the Example class is easy using +the XMLRPCIntrospection class:

        1 2 @@ -281,14 +473,14 @@ reactor.run()

        -

        Note the method attributes help and -signature which are used by the Introspection -API methods system.methodHelp and -system.methodSignature respectively. If no -help attribute is specified, -the method's documentation string is used instead.

        +

        Note the method attributes help +and signature which are used by the +Introspection API methods system.methodHelp +and system.methodSignature respectively. If +no help attribute is specified, the +method's documentation string is used instead.

        -

        SOAP Support

        +

        SOAP Support

        From the point of view of a Twisted developer, there is little difference between XML-RPC support and SOAP support. Here is an example of SOAP usage:

        @@ -322,7 +514,7 @@
        -

        Creating an XML-RPC Client

        +

        Creating an XML-RPC Client

        XML-RPC clients in Twisted are meant to look as something which will be familiar either to xmlrpclib or to Perspective Broker users, @@ -336,10 +528,11 @@ callRemote.

      -

      The interface Twisted presents to XML-RPC client is that of a proxy object: -twisted.web.xmlrpc.Proxy. The constructor for the -object receives a URL: it must be an HTTP or HTTPS URL. When an XML-RPC service -is described, the URL to that service will be given there.

      +

      The interface Twisted presents to XML-RPC client is that of a proxy +object: twisted.web.xmlrpc.Proxy. The +constructor for the object receives a URL: it must be an HTTP or HTTPS +URL. When an XML-RPC service is described, the URL to that service +will be given there.

      Having a proxy object, one can just call the callRemote method, which accepts a method name and a variable argument list (but no named @@ -387,13 +580,14 @@ [8, 15] -

      Serving SOAP and XML-RPC simultaneously

      +

      Serving SOAP and XML-RPC simultaneously

      -

      twisted.web.xmlrpc.XMLRPC and twisted.web.soap.SOAPPublisher are both Resources. So, to serve both XML-RPC and -SOAP in the one web server, you can use the putChild method of Resources.

      +

      twisted.web.xmlrpc.XMLRPC and twisted.web.soap.SOAPPublisher are both Resources. So, to serve both XML-RPC and +SOAP in the one web server, you can use the putChild method of Resource.

      -

      The following example uses an empty resource.Resource as the root resource for a Site, and then adds -/RPC2 and /SOAP paths to it.

      +

      The following example uses an empty resource.Resource as the root resource for +a Site, and then +adds /RPC2 and /SOAP paths to it.

      1 2 @@ -452,6 +646,6 @@

      Index

      - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/doc/index.html twisted-web-11.1.0/doc/index.html --- twisted-web-10.0.0/doc/index.html 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/doc/index.html 2011-11-17 10:51:14.000000000 +0000 @@ -20,6 +20,6 @@

      Index

      - Version: 10.0.0 + Version: 11.1.0 \ No newline at end of file diff -Nru twisted-web-10.0.0/LICENSE twisted-web-11.1.0/LICENSE --- twisted-web-10.0.0/LICENSE 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/LICENSE 2011-05-05 02:48:02.000000000 +0000 @@ -1,4 +1,4 @@ -Copyright (c) 2001-2010 +Copyright (c) 2001-2011 Allen Short Andy Gayton Andrew Bennetts @@ -12,7 +12,7 @@ Donovan Preston Eric Mangold Eyal Lotem -Itamar Shtull-Trauring +Itamar Turner-Trauring James Knight Jason A. Mobarak Jean-Paul Calderone diff -Nru twisted-web-10.0.0/NEWS twisted-web-11.1.0/NEWS --- twisted-web-10.0.0/NEWS 2010-03-09 13:13:32.000000000 +0000 +++ twisted-web-11.1.0/NEWS 2011-11-15 16:39:18.000000000 +0000 @@ -1,6 +1,189 @@ Ticket numbers in this file can be looked up by visiting http://twistedmatrix.com/trac/ticket/ +Twisted Web 11.1.0 (2011-11-15) +=============================== + +Features +-------- + - twisted.web.client.ProxyAgent is a new HTTP/1.1 web client which + adds proxy support. (#1774) + - twisted.web.client.Agent now takes optional connectTimeout and + bindAddress arguments which are forwarded to the subsequent + connectTCP/connectSSL call. (#3450) + - The new class twisted.web.client.FileBodyProducer makes it easy to + upload data in HTTP requests made using the Agent client APIs. + (#4017) + - twisted.web.xmlrpc.XMLRPC now allows its lookupProcedure method to + be overridden to change how XML-RPC procedures are dispatched. + (#4836) + - A new HTTP cookie-aware Twisted Web Agent wrapper is included in + twisted.web.client.CookieAgent (#4922) + - New class twisted.web.template.TagLoader provides an + ITemplateLoader implementation which loads already-created + twisted.web.iweb.IRenderable providers. (#5040) + - The new class twisted.web.client.RedirectAgent adds redirect + support to the HTTP 1.1 client stack. (#5157) + - twisted.web.template now supports HTML tags from the HTML5 + standard, including and