diff -Nru twisted-10.2.0/bin/manhole twisted-12.1.0/bin/manhole --- twisted-10.2.0/bin/manhole 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/bin/manhole 2011-06-30 12:57:11.000000000 +0000 @@ -1,21 +1,16 @@ #!/usr/bin/env python - -# Copyright (c) 2001-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. - """ This script runs GtkManhole, a client for Twisted.Manhole """ +import sys -### Twisted Preamble -# This makes sure that users don't have to set up their environment -# specially in order to run these programs from bin/. -import sys, os, string -if string.find(os.path.abspath(sys.argv[0]), os.sep+'Twisted') != -1: - sys.path.insert(0, os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), os.pardir, os.pardir))) -### end of preamble - +try: + import _preamble +except ImportError: + sys.exc_clear() from twisted.scripts import manhole manhole.run() diff -Nru twisted-10.2.0/bin/mktap twisted-12.1.0/bin/mktap --- twisted-10.2.0/bin/mktap 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/bin/mktap 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2001-2009 Twisted Matrix Laboratories. -# See LICENSE for details. - - -### Twisted Preamble -# This makes sure that users don't have to set up their environment -# specially in order to run these programs from bin/. -import sys, os, string -if string.find(os.path.abspath(sys.argv[0]), os.sep+'Twisted') != -1: - sys.path.insert(0, os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), os.pardir, os.pardir))) -if not hasattr(os, "getuid") or os.getuid() != 0: - sys.path.insert(0, os.getcwd()) -### end of preamble - -from twisted.scripts.mktap import run -run() - diff -Nru twisted-10.2.0/bin/_preamble.py twisted-12.1.0/bin/_preamble.py --- twisted-10.2.0/bin/_preamble.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/bin/_preamble.py 2011-06-30 12:57:11.000000000 +0000 @@ -0,0 +1,19 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +# This makes sure that users don't have to set up their environment +# specially in order to run these programs from bin/. + +# This helper is shared by many different actual scripts. It is not intended to +# be packaged or installed, it is only a developer convenience. By the time +# Twisted is actually installed somewhere, the environment should already be set +# up properly without the help of this tool. + +import sys, os + +path = os.path.abspath(sys.argv[0]) +while os.path.dirname(path) != path: + if os.path.exists(os.path.join(path, 'twisted', '__init__.py')): + sys.path.insert(0, path) + break + path = os.path.dirname(path) diff -Nru twisted-10.2.0/bin/pyhtmlizer twisted-12.1.0/bin/pyhtmlizer --- twisted-10.2.0/bin/pyhtmlizer 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/bin/pyhtmlizer 2011-06-30 12:57:11.000000000 +0000 @@ -1,17 +1,12 @@ #!/usr/bin/env python - -# Copyright (c) 2001-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. +import sys - -### Twisted Preamble -# This makes sure that users don't have to set up their environment -# specially in order to run these programs from bin/. -import sys, os, string -if string.find(os.path.abspath(sys.argv[0]), os.sep+'Twisted') != -1: - sys.path.insert(0, os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), os.pardir, os.pardir))) -sys.path.insert(0, os.curdir) -### end of preamble +try: + import _preamble +except ImportError: + sys.exc_clear() from twisted.scripts.htmlizer import run run() diff -Nru twisted-10.2.0/bin/tap2deb twisted-12.1.0/bin/tap2deb --- twisted-10.2.0/bin/tap2deb 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/bin/tap2deb 2011-06-30 12:57:11.000000000 +0000 @@ -1,20 +1,16 @@ #!/usr/bin/env python - -# Copyright (c) 2001-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. - """ tap2deb """ +import sys -### Twisted Preamble -# This makes sure that users don't have to set up their environment -# specially in order to run these programs from bin/. -import sys, os, string -if string.find(os.path.abspath(sys.argv[0]), os.sep+'Twisted') != -1: - sys.path.insert(0, os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), os.pardir, os.pardir))) -### end of preamble +try: + import _preamble +except ImportError: + sys.exc_clear() from twisted.scripts import tap2deb tap2deb.run() diff -Nru twisted-10.2.0/bin/tap2rpm twisted-12.1.0/bin/tap2rpm --- twisted-10.2.0/bin/tap2rpm 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/bin/tap2rpm 2011-06-30 12:57:11.000000000 +0000 @@ -1,6 +1,5 @@ #!/usr/bin/env python - -# Copyright (c) 2001-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. # based off the tap2deb code @@ -9,14 +8,12 @@ """ tap2rpm """ +import sys -### Twisted Preamble -# This makes sure that users don't have to set up their environment -# specially in order to run these programs from bin/. -import sys, os, string -if string.find(os.path.abspath(sys.argv[0]), os.sep+'Twisted') != -1: - sys.path.insert(0, os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), os.pardir, os.pardir))) -### end of preamble +try: + import _preamble +except ImportError: + sys.exc_clear() from twisted.scripts import tap2rpm tap2rpm.run() diff -Nru twisted-10.2.0/bin/tapconvert twisted-12.1.0/bin/tapconvert --- twisted-10.2.0/bin/tapconvert 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/bin/tapconvert 2011-06-30 12:57:11.000000000 +0000 @@ -1,18 +1,12 @@ #!/usr/bin/env python - -# Copyright (c) 2001-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. +import sys - -### Twisted Preamble -# This makes sure that users don't have to set up their environment -# specially in order to run these programs from bin/. -import sys, os, string -if string.find(os.path.abspath(sys.argv[0]), os.sep+'Twisted') != -1: - sys.path.insert(0, os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), os.pardir, os.pardir))) -if not hasattr(os, "getuid") or os.getuid() != 0: - sys.path.insert(0, os.getcwd()) -### end of preamble +try: + import _preamble +except ImportError: + sys.exc_clear() from twisted.scripts.tapconvert import run run() diff -Nru twisted-10.2.0/bin/trial twisted-12.1.0/bin/trial --- twisted-10.2.0/bin/trial 2010-08-11 22:23:53.000000000 +0000 +++ twisted-12.1.0/bin/trial 2011-06-30 12:57:11.000000000 +0000 @@ -1,22 +1,18 @@ #!/usr/bin/env python - -# Copyright (c) 2001-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. +import os, sys - -### Twisted Preamble -# This makes sure that users don't have to set up their environment -# specially in order to run these programs from bin/. -import sys, os, string -if string.find(os.path.abspath(sys.argv[0]), os.sep+'Twisted') != -1: - sys.path.insert(0, os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), os.pardir, os.pardir))) -if hasattr(os, "getuid") and os.getuid() != 0: - sys.path.insert(0, os.curdir) -### end of preamble +try: + import _preamble +except ImportError: + sys.exc_clear() # begin chdir armor sys.path[:] = map(os.path.abspath, sys.path) # end chdir armor +sys.path.insert(0, os.path.abspath(os.getcwd())) + from twisted.scripts.trial import run run() diff -Nru twisted-10.2.0/bin/twistd twisted-12.1.0/bin/twistd --- twisted-10.2.0/bin/twistd 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/bin/twistd 2011-06-30 12:57:11.000000000 +0000 @@ -1,19 +1,14 @@ #!/usr/bin/env python - -# Copyright (c) 2001-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. +import os, sys +try: + import _preamble +except ImportError: + sys.exc_clear() -### Twisted Preamble -# This makes sure that users don't have to set up their environment -# specially in order to run these programs from bin/. -import sys, os, string -if string.find(os.path.abspath(sys.argv[0]), os.sep+'Twisted') != -1: - sys.path.insert(0, os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), os.pardir, os.pardir))) -if hasattr(os, "getuid") and os.getuid() != 0: - sys.path.insert(0, os.path.abspath(os.getcwd())) -### end of preamble - +sys.path.insert(0, os.path.abspath(os.getcwd())) from twisted.scripts.twistd import run run() diff -Nru twisted-10.2.0/debian/changelog twisted-12.1.0/debian/changelog --- twisted-10.2.0/debian/changelog 2011-02-24 03:48:25.000000000 +0000 +++ twisted-12.1.0/debian/changelog 2012-06-21 13:41:40.000000000 +0000 @@ -1,3 +1,37 @@ +twisted (12.1.0-1~ppa1~natty1) natty; urgency=low + + * New upstream version. + * Rebuild package for use in PPA. + + -- Jessica McKellar Thu, 21 Jun 2012 09:41:14 -0400 + +twisted (12.0.0-1~ppa3~natty1) natty; urgency=low + + * New upstream version. + * Rebuild package for use in PPA. + + -- Jessica McKellar Wed, 15 Feb 2012 09:58:17 -0500 + +twisted (11.1.0-1) unstable; urgency=low + + * New upstream version. + * Drop suggestions on python-wxgtk2.6 and python-profiler. + * Fix lintian warnings. + + -- Matthias Klose Wed, 21 Dec 2011 12:29:38 +0100 + +twisted (11.0.0-2) unstable; urgency=low + + * python-twisted depends on version >= 11.0 of other packages. + + -- Matthias Klose Fri, 22 Apr 2011 12:02:59 +0200 + +twisted (11.0.0-1) unstable; urgency=low + + * New upstream version. + + -- Matthias Klose Sun, 17 Apr 2011 20:11:48 +0200 + twisted (10.2.0-1) unstable; urgency=low * New upstream version. diff -Nru twisted-10.2.0/debian/compat twisted-12.1.0/debian/compat --- twisted-10.2.0/debian/compat 2010-07-17 14:06:16.000000000 +0000 +++ twisted-12.1.0/debian/compat 2012-06-18 23:25:23.000000000 +0000 @@ -1 +1 @@ -5 +7 diff -Nru twisted-10.2.0/debian/control twisted-12.1.0/debian/control --- twisted-10.2.0/debian/control 2010-08-18 09:43:51.000000000 +0000 +++ twisted-12.1.0/debian/control 2012-06-19 02:16:58.000000000 +0000 @@ -3,20 +3,19 @@ Priority: optional Maintainer: Matthias Klose Uploaders: Free Ekanayaka -Build-Depends: debhelper (>= 5.0.37.1), python-all-dev (>= 2.6.5-13~), python-all-dbg, python-zope.interface-dbg, patch +Build-Depends: debhelper (>=7.0.50~), python-all-dev (>= 2.6.6-3~), python-all-dbg, python-zope.interface-dbg, patch Build-Conflicts: python-setuptools XS-Python-Version: all -Standards-Version: 3.9.1 +Standards-Version: 3.9.2 Package: python-twisted-core Architecture: all -Depends: ${python:Depends}, python-twisted-bin (>= ${source:Version}), python-zope.interface (>= 3.5), python (>= 2.3.5-9), ${misc:Depends} -Suggests: python-tk, python-gtk2, python-glade2, python-qt3, python-wxgtk2.8 | python-wxgtk2.6, python-profiler +Depends: ${python:Depends}, python-twisted-bin (>= ${source:Version}), python-zope.interface (>= 3.5), python (>= 2.5), ${misc:Depends} +Suggests: python-tk, python-gtk2, python-glade2, python-qt3, python-wxgtk2.8 Recommends: python-openssl, python-pam, python-serial -Conflicts: python2.3-twisted (<< 2.1.0-4), python2.4-twisted (<< 2.1.0-4), python-twisted (<< 2.1.0-4), python2.3-twisted-core, python2.4-twisted-core -Replaces: python2.3-twisted (<< 2.1.0-4), python2.4-twisted (<< 2.1.0-4), python-twisted (<< 2.1.0-4), python2.3-twisted-core, python2.4-twisted-core +Conflicts: python2.3-twisted, python2.4-twisted, python2.3-twisted-core, python2.4-twisted-core +Replaces: python2.3-twisted, python2.4-twisted, python2.3-twisted-core, python2.4-twisted-core Provides: ${python:Provides} -XB-Python-Version: ${python:Versions} Description: Event-based framework for internet applications It includes a web server, a telnet server, a multiplayer RPG engine, a generic client and server for remote object access, and APIs for creating @@ -29,7 +28,6 @@ Replaces: python2.3-twisted-bin, python2.4-twisted-bin Provides: ${python:Provides} Suggests: python-twisted-bin-dbg -XB-Python-Version: ${python:Versions} Description: Event-based framework for internet applications It includes a web server, a telnet server, a multiplayer RPG engine, a generic client and server for remote object access, and APIs for creating @@ -52,9 +50,9 @@ Priority: extra Architecture: all Depends: ${misc:Depends} -Suggests: python-twisted, twisted-doc-api +Suggests: python-twisted Recommends: www-browser | postscript-viewer | pdf-viewer -Description: The official documentation of Twisted +Description: Official documentation of Twisted This contains various HOWTOs and overviews in various formats . Twisted is an event-based framework for internet applications. @@ -62,25 +60,11 @@ generic client and server for remote object access, and APIs for creating new protocols. -#Package: twisted-doc-api -#Section: doc -#Priority: extra -#Architecture: all -#Depends: twisted-doc, ${misc:Depends} -#Description: The auto-generated API docs of Twisted -# Epydoc-generated HTML API docs of Twisted classes, modules and functions. -# . -# Twisted is an event-based framework for internet applications -# It includes a web server, a telnet server, a multiplayer RPG engine, a -# generic client and server for remote object access, and APIs for creating -# new protocols. - Package: python-twisted Architecture: all Priority: extra -Depends: ${python:Depends}, python-twisted-core (>= 10.1), python-twisted-conch (>= 1:10.1), python-twisted-mail (>= 10.1), python-twisted-lore (>= 10.1), python-twisted-names (>= 10.1), python-twisted-news (>= 10.1), python-twisted-runner (>= 10.1), python-twisted-web (>= 10.1), python-twisted-words (>= 10.1), ${misc:Depends} +Depends: ${python:Depends}, python-twisted-core (>= 12.1), python-twisted-conch (>= 1:12.1), python-twisted-mail (>= 12.1), python-twisted-lore (>= 12.1), python-twisted-names (>= 12.1), python-twisted-news (>= 12.1), python-twisted-runner (>= 12.1), python-twisted-web (>= 12.1), python-twisted-words (>= 12.1), ${misc:Depends} Provides: ${python:Provides} -XB-Python-Version: ${python:Versions} -Description: Event-based framework for internet applications (transitional package) - This is a transitional package that depends on the twisted core library and +Description: Event-based framework for internet applications (dependency package) + This is a dependency package that depends on the twisted core library and all the libraries split out to separate packages starting with Twisted-2.0.1. diff -Nru twisted-10.2.0/debian/rules twisted-12.1.0/debian/rules --- twisted-10.2.0/debian/rules 2010-07-17 14:24:53.000000000 +0000 +++ twisted-12.1.0/debian/rules 2012-06-19 02:26:52.000000000 +0000 @@ -15,6 +15,8 @@ include /usr/share/python/python.mk build: build-stamp +build-arch: build-stamp +build-indep: build-stamp build-stamp: $(PYVERS:%=build-python%) touch $@ build-python%: @@ -34,21 +36,13 @@ install-prereq: build-stamp dh_testdir dh_testroot - dh_clean -k + dh_prep install-python%: install-prereq : # python-twisted-core python$* setup.py install --root=debian/python-twisted-core --install-layout=deb -find debian/python-twisted-core -name '*.py[co]' | xargs rm -f -# for i in debian/python$*-twisted-core/usr/bin/*; do \ -# mv $$i $${i}$*; \ -# done -# mkdir -p debian/python$*-twisted-core/usr/share/man/man1 -# for i in doc/man/{manhole,*tap*,trial,twistd}.1; do \ -# iv=`basename $$i .1`$*.1; \ -# cp -p $$i debian/python$*-twisted-core/usr/share/man/man1/$$iv; \ -# done case $* in \ 1.5|2.0|2.1|2.2) ;; \ *) rm -rf debian/python-twisted-core/usr/lib/python$*/*-packages/twisted/python/pymodules; \ @@ -56,17 +50,17 @@ : # python-twisted-bin ifeq ($(DEB_HOST_ARCH_OS), linux) +ifeq ($(shell [ $* \< 2.6 ]), 0) # Only install epoll with Python < 2.6, see setup.py for details. dh_movefiles -ppython-twisted-bin \ --sourcedir=debian/python-twisted-core \ - $(call py_libdir,$*)/twisted/protocols/_c_urlarg.so \ $(call py_libdir,$*)/twisted/internet/_sigchld.so \ $(call py_libdir,$*)/twisted/python/_epoll.so \ $(call py_libdir,$*)/twisted/python/_initgroups.so \ $(call py_libdir,$*)/twisted/test/raiser.so +endif else dh_movefiles -ppython-twisted-bin \ --sourcedir=debian/python-twisted-core \ - $(call py_libdir,$*)/twisted/protocols/_c_urlarg.so \ $(call py_libdir,$*)/twisted/internet/_sigchld.so \ $(call py_libdir,$*)/twisted/python/_initgroups.so \ $(call py_libdir,$*)/twisted/test/raiser.so @@ -107,26 +101,11 @@ cp -p $$i debian/python-twisted-core/usr/share/man/man1/; \ done -# : # python-twisted-core -# mkdir -p debian/python-twisted-core/usr/bin -# for i in debian/python$(VER)-twisted-core/usr/bin/*; do \ -# iv=`basename $$i $(VER)`; \ -# ln -sf $${iv}$(VER) debian/python-twisted-core/usr/bin/$$iv; \ -# done -# mkdir -p debian/python-twisted-core/usr/share/man/man1 -# for i in debian/python$(VER)-twisted-core/usr/share/man/man1/*; do \ -# iv=`basename $$i $(VER).1`; \ -# ln -sf $${iv}$(VER).1.gz \ -# debian/python-twisted-core/usr/share/man/man1/$$iv.1.gz; \ -# done - binary-indep: build install dh_testdir dh_testroot dh_installchangelogs -i dh_installdocs -i -# rm -rf debian/twisted-doc-api/usr/share/doc/twisted-doc-api -# ln -s twisted-doc debian/twisted-doc-api/usr/share/doc/twisted-doc-api dh_installmenu -i dh_compress -i -X.py dh_fixperms -i diff -Nru twisted-10.2.0/debian/twisted-api twisted-12.1.0/debian/twisted-api --- twisted-10.2.0/debian/twisted-api 2010-07-17 14:06:16.000000000 +0000 +++ twisted-12.1.0/debian/twisted-api 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -Document: twisted-api -Title: The Twisted API Reference -Author: The Twisted Team -Abstract: This collection of autogenerated API references describes how - to use the various classes and function in Twisted -Section: Apps/Programming - -Format: HTML -Index: /usr/share/doc/twisted-doc/api/index.html -Files: /usr/share/doc/twisted-doc/api/*.html -Document: twisted-api -Title: The Twisted API Reference -Author: The Twisted Team -Abstract: This collection of autogenerated API references describes how - to use the various classes and function in Twisted -Section: Apps/Programming - -Format: HTML -Index: /usr/share/doc/twisted-doc/api/index.html -Files: /usr/share/doc/twisted-doc/api/*.html diff -Nru twisted-10.2.0/debian/watch twisted-12.1.0/debian/watch --- twisted-10.2.0/debian/watch 2010-07-17 14:27:12.000000000 +0000 +++ twisted-12.1.0/debian/watch 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -version=3 -http://tmrc.mit.edu/mirror/twisted/Twisted/(\d+\.\d)/ Twisted-([\d\.]*)\.tar\.bz2 diff -Nru twisted-10.2.0/doc/benchmarks/deferreds.py twisted-12.1.0/doc/benchmarks/deferreds.py --- twisted-10.2.0/doc/benchmarks/deferreds.py 2009-04-02 14:40:31.000000000 +0000 +++ twisted-12.1.0/doc/benchmarks/deferreds.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2007-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ diff -Nru twisted-10.2.0/doc/benchmarks/netstringreceiver.py twisted-12.1.0/doc/benchmarks/netstringreceiver.py --- twisted-10.2.0/doc/benchmarks/netstringreceiver.py 2010-07-12 15:30:22.000000000 +0000 +++ twisted-12.1.0/doc/benchmarks/netstringreceiver.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2010 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.test import proto_helpers, test_protocols diff -Nru twisted-10.2.0/doc/benchmarks/timer.py twisted-12.1.0/doc/benchmarks/timer.py --- twisted-10.2.0/doc/benchmarks/timer.py 2009-04-02 14:40:31.000000000 +0000 +++ twisted-12.1.0/doc/benchmarks/timer.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2007-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ diff -Nru twisted-10.2.0/doc/development/index.html twisted-12.1.0/doc/development/index.html --- twisted-10.2.0/doc/development/index.html 2010-11-30 03:13:22.000000000 +0000 +++ twisted-12.1.0/doc/development/index.html 2012-06-04 08:46:17.000000000 +0000 @@ -21,6 +21,6 @@

Index

- Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/development/listings/new_module_template.py twisted-12.1.0/doc/development/listings/new_module_template.py --- twisted-10.2.0/doc/development/listings/new_module_template.py 2009-06-11 11:08:54.000000000 +0000 +++ twisted-12.1.0/doc/development/listings/new_module_template.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ # -*- test-case-name: -*- -# Copyright (c) 2008 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. diff -Nru twisted-10.2.0/doc/development/naming.html twisted-12.1.0/doc/development/naming.html --- twisted-10.2.0/doc/development/naming.html 2010-11-30 03:13:22.000000000 +0000 +++ twisted-12.1.0/doc/development/naming.html 2012-06-04 08:46:17.000000000 +0000 @@ -33,6 +33,6 @@

Index

- Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/development/philosophy.html twisted-12.1.0/doc/development/philosophy.html --- twisted-10.2.0/doc/development/philosophy.html 2010-11-30 03:13:22.000000000 +0000 +++ twisted-12.1.0/doc/development/philosophy.html 2012-06-04 08:46:17.000000000 +0000 @@ -53,6 +53,6 @@

Index

- Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/development/policy/coding-standard.html twisted-12.1.0/doc/development/policy/coding-standard.html --- twisted-10.2.0/doc/development/policy/coding-standard.html 2010-11-30 03:13:22.000000000 +0000 +++ twisted-12.1.0/doc/development/policy/coding-standard.html 2012-06-04 08:46:18.000000000 +0000 @@ -14,7 +14,7 @@

Try to choose names which are both easy to remember and meaningful. Some silliness is OK at the module naming level - (see twisted.spread...) but when + (see twisted.spread...) but when choosing class names, be as precise as possible.

Try to avoid overloaded terms. This rule is often broken, @@ -36,7 +36,7 @@

Twisted development should always be - test-driven. The complete test suite in trunk@HEAD is required to + test-driven. The complete test suite in the head of the SVN trunk is required to be passing on supported platforms at all times. Regressions in the test suite are addressed by reverting whatever revisions introduced them. For @@ -47,17 +47,24 @@

Test Suite

The Twisted test suite is spread across many subpackages of the - twisted package. Many tests are in + twisted package. Many older tests are in twisted.test. Others can be found at places such as - twisted.web.test or twisted.internet.test. + twisted.web.test (for twisted.web tests) + or twisted.internet.test (for twisted.internet + tests). The latter arrangement, twisted.somepackage.test, + is preferred for new tests except when a test module already exists in + twisted.test. +

+ +

Parts of the Twisted test suite may serve as good examples of how to write tests for Twisted or for Twisted-based libraries (newer parts of the test suite are generally better examples than older parts - check when the code you are looking at was written before you use it as an example of what you should write). The names of test modules should - begin with test_ so that they are automatically discoverable by + begin with test_ so that they are automatically discoverable by test runners such as Trial. Twisted's unit tests are written using - twisted.trial, an xUnit library which has been + twisted.trial, an xUnit library which has been extensively customized for use in testing Twisted and Twisted-based libraries.

@@ -68,8 +75,9 @@ which might be broken by a particular change.

It is strongly suggested that developers learn to use Emacs, and use - the twisted-dev.el file included in the TwistedEmacs - package to bind the F9 key to run unit tests and bang on it + the twisted-dev.el file included in + twisted-emacs + to bind the F9 key to run unit tests and bang on it frequently. Support for other editors is unavailable at this time but we would love to provide it.

@@ -105,18 +113,16 @@

Copyright Header

Whenever a new file is added to the repository, add the following - license header at the top of the file, including the year the file was - added. For example:

+ license header at the top of the file:

1 2 -

# Copyright (c) 2009 Twisted Matrix Laboratories. +

# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details.
-

When you update existing files, make sure the year in the copyright - header is up to date as well. You should add a new copyright header when - it's completely missing in the file that is being edited.

+

When you update existing files, if there is no copyright header, add + one.

Whitespace

@@ -163,7 +169,7 @@ 12

# -*- test-case-name: <test module> -*- -# Copyright (c) 2008 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. @@ -319,20 +325,11 @@

Docstrings should be written in epytext format; more documentation is available in the - Epytext Markup Language documentation.

+ Epytext Markup Language documentation.

-

Additionally, to accommodate emacs users:

- -
    -
  • Single quotes of the type of the docstring's triple-quote - should be escaped. This will prevent font-lock from - accidentally fontifying large portions of the file as a - string.
  • - -
  • Code examples in docstrings should be prefixed by the | - character. This will prevent IM-Python from regarding sample - code as real functions, methods, and classes.
  • -
+

Additionally, to accommodate emacs users, single quotes of the type of + the docstring's triple-quote should be escaped. This will prevent font-lock from + accidentally fontifying large portions of the file as a string.

For example,

1 @@ -371,13 +368,13 @@ For example:: - | import wombat - | def sample(something): - | f = something.getFoo() - | f.doFooThing() - | b = wombat.foo2bar(f) - | b.doBarThing() - | return b + import wombat + def sample(something): + f = something.getFoo() + f.doFooThing() + b = wombat.foo2bar(f) + b.doBarThing() + return b """ # Optionally, actual code can go here. @@ -401,7 +398,7 @@ to run from the command-line, the following things must be done:

    -
  1. Write a module in twisted.scripts +
  2. Write a module in twisted.scripts which contains a callable global named run. This will be called by the command line part with no arguments (it will usually read sys.argv). Feel free to write more @@ -427,7 +424,20 @@ distutils will rewrite the shebang line upon installation so this policy only covers the source files in version control.

    -
  3. Add the Twisted running-from-SVN header: +
  4. For core scripts, add this Twisted running-from-SVN header: +

    1 +2 +3 +4 +5 +

    import sys +try: + import _preamble +except ImportError: + sys.clear_exc() +
    + + Or for sub-project scripts, add a modified version which also adjusts sys.path:

    1 2 3 @@ -436,16 +446,14 @@ 6 7 8 -9 -

    ### Twisted Preamble -# This makes sure that users don't have to set up their environment -# specially in order to run these programs from bin/. -import sys, os, string -if string.find(os.path.abspath(sys.argv[0]), os.sep+'Twisted') != -1: - sys.path.insert(0, os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), os.pardir, os.pardir))) -if not hasattr(os, "getuid") or os.getuid() != 0: - sys.path.insert(0, os.getcwd()) -### end of preamble +

    import sys, os +extra = os.path.dirname(os.path.dirname(sys.argv[0])) +sys.path.insert(0, extra) +try: + import _preamble +except ImportError: + sys.clear_exc() +sys.path.remove(extra)
  5. And end with: @@ -499,7 +507,7 @@ in favor of the set and frozenset builtins. When you need to use sets or frozensets in your code, please use the set and frozenset provided - by twisted.python.compat. There are some + by twisted.python.compat. There are some differences between sets.Set and set, that are explained in the set PEP. Please be sure to not rely on the behavior of one or the other @@ -578,8 +586,8 @@

    Callback Arguments

    There are several methods whose purpose is to help the user set up - callback functions, for example Deferred.addCallback or the - reactor's callLater method. To make + callback functions, for example Deferred.addCallback or the + reactor's callLater method. To make access to the callback as transparent as possible, most of these methods use **kwargs to capture arbitrary arguments that are destined for the user's callback. This allows the call to the @@ -588,7 +596,7 @@

    In these methods, take care to not have other argument names that will steal the user's callback's arguments. When sensible, prefix these - internal argument names with an underscore. For example, RemoteReference.callRemote is + internal argument names with an underscore. For example, RemoteReference.callRemote is meant to be called like this:

    1 @@ -611,15 +619,17 @@

    In this case, callRemote (and any code that uses the - **kwargs syntax) must be careful to not use name, phone, or - any other name that might overlap with a user-provided named parameter. - Therefore, callRemote is implemented with the following - signature:

    + **kwargs syntax) must be careful to not use + name, phone, or any other name that might overlap with + a user-provided named parameter. Therefore, callRemote is + implemented with the following signature:

    1 2 -

    def callRemote(self, _name, *args, **kw): - ... +3 +

    class SomeClass(object): + def callRemote(self, _name, *args, **kw): + ...

    Do whatever you can to reduce user confusion. It may also be @@ -630,7 +640,7 @@

    Special Methods

    -

    The augmented assignment protocol, defined by __iadd__ and other +

    The augmented assignment protocol, defined by __iadd__ and other similarly named methods, can be used to allow objects to be modified in place or to rebind names if an object is immutable -- both through use of the same operator. This can lead to confusing code, which in turn @@ -803,6 +813,6 @@

    Index

    - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/development/policy/doc-standard.html twisted-12.1.0/doc/development/policy/doc-standard.html --- twisted-10.2.0/doc/development/policy/doc-standard.html 2010-11-30 03:13:22.000000000 +0000 +++ twisted-12.1.0/doc/development/policy/doc-standard.html 2012-06-04 08:46:18.000000000 +0000 @@ -12,7 +12,7 @@

    Allowable Tags

    -

    Please try to restrict your HTML usage to the following tags (all only for the original logical purpose, and not whatever visual effect you see): <html>, <title>, <head>, <body>, <h1>, <h2, <h3>, <ol>, <ul>, <dl>, <li>, <dt>, <dd>, <p>, <code>, <img>, <blockquote>, <a>, <cite>, <div>, <span>, <strong>, <em>, <pre>, <q>, <table>,<tr>, <td> and <th>.

    +

    Please try to restrict your HTML usage to the following tags (all only for the original logical purpose, and not whatever visual effect you see): <html>, <title>, <head>, <body>, <h1>, <h2, <h3>, <ol>, <ul>, <dl>, <li>, <dt>, <dd>, <p>, <code>, <img>, <blockquote>, <a>, <cite>, <div>, <span>, <strong>, <em>, <pre>, <q>, <table>, <tr>, <td> and <th>.

    Please avoid using the quote sign (") for quoting, and use the relevant html tags (<q></q>) -- it is impossible to distinguish right and left quotes with the quote sign, and some more sophisticated output methods work better with that distinction.

    @@ -24,20 +24,25 @@ and shell. For example:

    python

    +

    Original markup:

    +
    -    <p>
    -    For example, this is how one defines a Resource:
    -    </p>
    +<p>
    +For example, this is how one defines a Resource:
    +</p>
     
    -    <pre class="python">
    +<pre class="python">
     from twisted.web import resource
     
     class MyResource(resource.Resource):
         def render_GET(self, request):
             return "Hello, world!"
    -    </pre>
    +</pre>
     
    +
    +

    Rendered result:

    +

    For example, this is how one defines a Resource:

    1 2 @@ -50,24 +55,30 @@ def render_GET(self, request): return "Hello, world!"

    +

    Note that you should never have leading indentation inside a <pre> block -- this makes it hard for readers to copy/paste the code.

    python-interpreter

    +

    Original markup:

    +
    -    <pre class="python-interpreter">
    -    &gt;&gt;&gt; from twisted.web import resource
    -    &gt;&gt;&gt; class MyResource(resource.Resource):
    -    ...     def render_GET(self, request):
    -    ...         return "Hello, world!"
    -    ...
    -    &gt;&gt;&gt; MyResource().render_GET(None)
    -    "Hello, world!"
    -    </pre>
    +<pre class="python-interpreter">
    +&gt;&gt;&gt; from twisted.web import resource
    +&gt;&gt;&gt; class MyResource(resource.Resource):
    +...     def render_GET(self, request):
    +...         return "Hello, world!"
    +...
    +&gt;&gt;&gt; MyResource().render_GET(None)
    +"Hello, world!"
    +</pre>
     
    +
    +

    Rendered result:

    +
     >>> from twisted.web import resource
     >>> class MyResource(resource.Resource):
    @@ -77,17 +88,24 @@
     >>> MyResource().render_GET(None)
     "Hello, world!"
     
    +

    shell

    +

    Original markup:

    +
         <pre class="shell">
         $ twistd web --path /var/www
         </pre>
     
    +
    +

    Rendered result:

    +
     $ twistd web --path /var/www
     
    +

    Code inside paragraph text

    @@ -106,39 +124,29 @@ to the module or classname. This is to help keep the documentation clearer and less cluttered by allowing links to API docs that don't need the module name.

    +

    Original markup:

    +
             <p>
    -    To add a <code class="API">twisted.web.widgets.Widget</code>
    +    To add a <code class="API">twisted.web.static.File</code>
         instance to a <code class="API"
    -    base="twisted.web.widgets">Gadget</code> instance, do 
    -    <code class="python">myGadget.putWidget("widgetPath",
    -    MyWidget())</code>.  
    -        </p>
    -    
    -        <p> 
    -    (implementation note: the widgets are stored in the <code
    -    class="python">gadgetInstance.widgets</code> attribute,
    -    which is a
    -    list.)
    +    base="twisted.web.resource">Resource</code> instance, do 
    +    <code class="python">myResource.putChild("resourcePath",
    +    File("/tmp"))</code>.  
             </p>
         
     
    +
    -
    +

    Rendered result:

    +

    - To add a twisted.web.widgets.Widget - instance to a Gadget + To add a twisted.web.static.File + instance to a Resource instance, do - myGadget.putWidget("widgetPath", MyWidget()). -

    - -

    - (implementation note: the widgets are stored in the gadgetInstance.widgets attribute, - which is a - list.) + myResource.putChild("resourcePath", File("/tmp")).

    - -
    +

    Headers

    @@ -183,6 +191,6 @@

    Index

    - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/development/policy/index.html twisted-12.1.0/doc/development/policy/index.html --- twisted-10.2.0/doc/development/policy/index.html 2010-11-30 03:13:22.000000000 +0000 +++ twisted-12.1.0/doc/development/policy/index.html 2012-06-04 08:46:17.000000000 +0000 @@ -28,6 +28,6 @@

    Index

    - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/development/policy/svn-dev.html twisted-12.1.0/doc/development/policy/svn-dev.html --- twisted-10.2.0/doc/development/policy/svn-dev.html 2010-11-30 03:13:22.000000000 +0000 +++ twisted-12.1.0/doc/development/policy/svn-dev.html 2012-06-04 08:46:18.000000000 +0000 @@ -21,10 +21,10 @@

    Checkout

    -

    Subversion tutorials can be found elsewhere, see in particular +

    Subversion tutorials can be found elsewhere, see in particular the Subversion homepage. The relevant data you need to check out a copy of the Twisted tree is available on -the development +the development page, and is as follows:

    @@ -34,15 +34,15 @@
     

    Alternate tree names

    By using svn co svn://svn.twistedmatrix.com/svn/Twisted/trunk -otherdir, you can put the workspace tree in a directory other than +otherdir, you can put the workspace tree in a directory other than Twisted. I do this (with a name like Twisted-Subversion) to remind myself that this tree comes from Subversion and not from a released version (like Twisted-1.0.5). This practice can cause a few problems, because there are a few places in the Twisted tree that need to know where the tree starts, so they can add it to sys.path without requiring the user manually set their PYTHONPATH. These functions walk the -current directory up to the root, looking for a directory named -Twisted (sometimes exactly that, sometimes with a +current directory up to the root, looking for a directory named +Twisted (sometimes exactly that, sometimes with a .startswith test). Generally these are test scripts or other administrative tools which expect to be launched from somewhere inside the tree (but not necessarily from the top).

    @@ -57,31 +57,32 @@

    Combinator

    -

    In order to simplify the use of Subversion, we typically use -Divmod Combinator. +

    In order to simplify the use of Subversion, we typically use +Divmod Combinator. You may find it to be useful, too. In particular, because Twisted uses branches for almost all feature development, if you plan to contribute to Twisted you will probably find Combinator very useful. For more details, -see the Combinator website, as well as the - +see the Combinator website, as well as the + UQDS page.

    Compiling C extensions

    -There are currently several C extension modules in Twisted: -twisted.protocols._c_urlarg, twisted.internet.cfsupport, -twisted.internet.iocpreactor._iocp, and twisted.python._epoll. These modules +There are currently several C extension modules in Twisted: +twisted.internet.cfsupport, +twisted.internet.iocpreactor._iocp, +and twisted.python._epoll. These modules are optional, but you'll have to compile them if you want to experience their features, performance improvements, or bugs. There are two approaches.

    The first is to do a regular distutils ./setup.py build, which -will create a directory under build/ to hold both the generated +will create a directory under build/ to hold both the generated .so files as well as a copy of the 600-odd .py files that make up Twisted. If you do this, you will need to set your PYTHONPATH to something like MyDir/Twisted/build/lib.linux-i686-2.5 in order to -run code against the Subversion twisted (as opposed to whatever's installed in +run code against the Subversion twisted (as opposed to whatever's installed in /usr/lib/python2.5 or wherever python usually looks). In addition, you will need to re-run the build command every time you change a .py file. The build/lib.foo @@ -94,7 +95,7 @@ you're using the .py files in place too, removing the confusion a forgotten rebuild could cause with the separate build/ directory above. To build the C modules in place, do ./setup.py build_ext -i. You only need to -re-run this command when you change the C files. Note that +re-run this command when you change the C files. Note that setup.py is not Make, it does not always get the dependencies right (.h files in particular), so if you are hacking on the cReactor you may need to manually delete the .o files before @@ -118,21 +119,21 @@

    ./bin/trial twisted/test/test_defer.py
    -

    To run any tests that are related to a code file, like +

    To run any tests that are related to a code file, like twisted/protocols/imap4.py, do:

    ./bin/trial --testmodule twisted/mail/imap4.py
    -

    This depends upon the .py file having an appropriate +

    This depends upon the .py file having an appropriate test-case-name tag that indicates which test cases provide coverage. See the Test Standards document for -details about using test-case-name. In this example, the +details about using test-case-name. In this example, the twisted.mail.test.test_imap test will be run.

    Many tests create temporary files in /tmp or ./_trial_temp, but everything in /tmp should be deleted when the test finishes. Sometimes these -cleanup calls are commented out by mistake, so if you see a stray -/tmp/@12345.1 directory, it is probably from test_dirdbm or test_popsicle. +cleanup calls are commented out by mistake, so if you see a stray +/tmp/@12345.1 directory, it is probably from test_dirdbm or test_popsicle. Look for an rmtree that has been commented out and complain to the last developer who touched that file.

    @@ -147,13 +148,13 @@ instead.

    To build the HTML form of the howto/ docs, do the following. Note that -the index file will be placed in doc/howto/index.html.

    +the index file will be placed in doc/core/howto/index.html.

    -./bin/lore/lore -p --config template=doc/howto/template.tpl doc/howto/*.xhtml
    +./bin/lore/lore -p --config template=doc/core/howto/template.tpl doc/core/howto/*.xhtml
     
    -

    To run hlint over a single Lore document, such as +

    To run hlint over a single Lore document, such as doc/development/policy/svn-dev.xhtml, do the following. This is useful because the HTML conversion may bail without a useful explanation if it sees mismatched tags.

    @@ -163,11 +164,11 @@

    To convert it to HTML (including markup, interpolation of examples, -footnote processing, etc), do the following. The results will be placed in +footnote processing, etc), do the following. The results will be placed in doc/development/policy/svn-dev.html:

    -./bin/lore/lore -p --config template=doc/howto/template.tpl \
    +./bin/lore/lore -p --config template=doc/core/howto/template.tpl \
        doc/development/policy/svn-dev.xhtml
     
    @@ -175,13 +176,13 @@ include a -l argument to bin/lore/lore. Links in the .xhtml file are to .xhtml targets: when the .xhtml is turned into .html, the link targets are supposed to be turned into .html also. In addition to this, -Lore markup of the form <code class="API"> is supposed to +Lore markup of the form <code class="API"> is supposed to turn into a link to the corresponding API reference page. These links will probably be wrong unless the correct base URL is provided to Lore.

    Committing and Post-commit Hooks

    -

    Twisted uses a customized +

    Twisted uses a customized trac-post-commit-hook to enable ticket updates based on svn commit logs. When making a branch for a ticket, the branch name should end @@ -204,26 +205,26 @@ My longer description of the changes made.

-

The Twisted Coding Standard +

The Twisted Coding Standard elaborates on commit messages and source control.

Emacs

-

A minor mode for development with Twisted using Emacs is available. See -emacs/twisted-dev.el for several utility functions which make -it easier to grep for methods, run test cases, etc.

+

A minor mode for development with Twisted using Emacs is available. See +twisted-dev.el, provided by twisted-emacs, +for several utility functions which make it easier to grep for methods, run test cases, etc.

Building Debian packages

Our support for building Debian packages has fallen into disrepair. We would very much like to restore this functionality, but until we do so, if -you are interested in this, you are on your own. See +you are interested in this, you are on your own. See stdeb for one possible approach to this.

Index

- Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/development/policy/test-standard.html twisted-12.1.0/doc/development/policy/test-standard.html --- twisted-10.2.0/doc/development/policy/test-standard.html 2010-11-30 03:13:22.000000000 +0000 +++ twisted-12.1.0/doc/development/policy/test-standard.html 2012-06-04 08:46:18.000000000 +0000 @@ -6,7 +6,7 @@

Unit Tests in Twisted

- +
@@ -104,10 +104,10 @@

PyUnit provides a large number of assertion methods to be used when writing tests. Many of these are redundant. For consistency, Twisted unit tests should use the assert forms rather than the - fail forms. Also, use assertEquals, - assertNotEquals, and assertAlmostEquals rather - than assertEqual, assertNotEqual, and - assertAlmostEqual. assertTrue is also + fail forms. Also, use assertEqual, + assertNotEqual, and assertAlmostEqual rather + than assertEquals, assertNotEquals, and + assertAlmostEquals. assertTrue is also preferred over assert_. You may notice this convention is not followed everywhere in the Twisted codebase. If you are changing some test code and notice the wrong method being used in nearby code, @@ -117,7 +117,42 @@ specifying at a high level the intent of the test. That is, a description that users of the method would understand.

-

Skipping tests, TODO items

+

Test Implementation Guidelines

+ +

Here are some guidelines to follow when writing tests for the Twisted + test suite. Many tests predate these guidelines and so do not follow them. + When in doubt, follow the guidelines given here, not the example of old unit + tests.

+ +

Real I/O

+ +

Most unit tests should avoid performing real, platform-implemented I/O + operations. Real I/O is slow, unreliable, and unwieldy. When implementing + a protocol, twisted.test.proto_helpers.StringTransport can be + used instead of a real TCP transport. StringTransport is fast, + deterministic, and can easily be used to exercise all possible network + behaviors.

+ +

Real Time

+ +

Most unit tests should also avoid waiting for real time to pass. Unit + tests which construct and advance + a twisted.internet.task.Clock are fast and + deterministic.

+ +

The Global Reactor

+ +

Since unit tests are avoiding real I/O and real time, they can usually + avoid using a real reactor. The only exceptions to this are unit tests for + a real reactor implementation. Unit tests for protocol implementations or + other application code should not use a reactor. Unit tests for real + reactor implementations should not use the global reactor, but should + instead use twisted.internet.test.reactormixins.ReactorBuilder + so they can be applied to all of the reactor implementations automatically. + In no case should new unit tests use the global reactor.

+ + +

Skipping tests, TODO items

Trial, the Twisted unit test framework, has some extensions which are designed to encourage developers to add new tests. One common situation is @@ -127,7 +162,7 @@ these limitations to be a bug.

To make it easy to test as much as possible, some tests may be skipped in -certain situations. Individual test cases can raise the +certain situations. Individual test cases can raise the SkipTest exception to indicate that they should be skipped, and the remainder of the test is not run. In the summary (the very last thing printed, at the bottom of the test output) the test is counted as a @@ -138,10 +173,12 @@ 2 3 4 -

def test_sshClient(self): - if not ssh_path: - raise unittest.SkipTest("cannot find ssh, nothing to test") - foo() # do actual test after the SkipTest +5 +

class SSHClientTests(unittest.TestCase): + def test_sshClient(self): + if not ssh_path: + raise unittest.SkipTest("cannot find ssh, nothing to test") + foo() # do actual test after the SkipTest

You can also set the .skip attribute on the method, with a @@ -152,9 +189,11 @@

1 2 3 -

def test_thing(self): - dotest() -test_thing.skip = "disabled locally" +4 +

class SomeThingTests(unittest.TestCase): + def test_thing(self): + dotest() + test_thing.skip = "disabled locally"

1 @@ -198,7 +237,7 @@ ...

-

.todo and Testing New Functionality

+

.todo and Testing New Functionality

Two good practices which arise from the XP development process are sometimes at odds with each other:

@@ -266,15 +305,15 @@ to add a test marked todo to trunk. When you do, consider whether a ticket in the issue tracker would be more useful.

-

Line Coverage Information

+

Line Coverage Information

Trial provides line coverage information, which is very useful to ensure old code has decent coverage. Passing the --coverage option to -to Trial will generate the coverage information in a file called +to Trial will generate the coverage information in a file called coverage which can be found in the _trial_temp folder. This option requires Python 2.3.3 or newer.

-

Associating Test Cases With Source Files

+

Associating Test Cases With Source Files

Please add a test-case-name tag to the source file that is covered by your new test. This is a comment at the beginning of the file @@ -315,17 +354,18 @@

The test-case-name tag will allow trial --testmodule twisted/dir/myfile.py to determine which test cases need to be run to exercise the code in myfile.py. Several tools (as -well as twisted-dev.el's F9 command) use this to automatically +well as 's +twisted-dev.el's F9 command) use this to automatically run the right tests.

- +

Index

- Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/development/policy/writing-standard.html twisted-12.1.0/doc/development/policy/writing-standard.html --- twisted-10.2.0/doc/development/policy/writing-standard.html 2010-11-30 03:13:22.000000000 +0000 +++ twisted-12.1.0/doc/development/policy/writing-standard.html 2012-06-04 08:46:18.000000000 +0000 @@ -248,7 +248,7 @@ impose upon authors the need to have a few dummy functions: in Twisted documentation the most common example is where a function is needed to generate a Deferred and fire it after some time has passed. An example - might be this, where deferLater is used to fire a callback + might be this, where deferLater is used to fire a callback after a period of time:

1 @@ -308,6 +308,6 @@

Index

- Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/development/security.html twisted-12.1.0/doc/development/security.html --- twisted-10.2.0/doc/development/security.html 2010-11-30 03:13:22.000000000 +0000 +++ twisted-12.1.0/doc/development/security.html 2012-06-04 08:46:17.000000000 +0000 @@ -38,6 +38,6 @@

Index

- Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/examples/bananabench.py twisted-12.1.0/doc/examples/bananabench.py --- twisted-10.2.0/doc/examples/bananabench.py 2006-12-23 05:02:47.000000000 +0000 +++ twisted-12.1.0/doc/examples/bananabench.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-10.2.0/doc/examples/courier.py twisted-12.1.0/doc/examples/courier.py --- twisted-10.2.0/doc/examples/courier.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/examples/courier.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ diff -Nru twisted-10.2.0/doc/examples/cred.py twisted-12.1.0/doc/examples/cred.py --- twisted-10.2.0/doc/examples/cred.py 2006-04-23 23:07:11.000000000 +0000 +++ twisted-12.1.0/doc/examples/cred.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-10.2.0/doc/examples/dbcred.py twisted-12.1.0/doc/examples/dbcred.py --- twisted-10.2.0/doc/examples/dbcred.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/examples/dbcred.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2001-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ diff -Nru twisted-10.2.0/doc/examples/echoclient.py twisted-12.1.0/doc/examples/echoclient.py --- twisted-10.2.0/doc/examples/echoclient.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/examples/echoclient.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2001-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. diff -Nru twisted-10.2.0/doc/examples/echoclient_ssl.py twisted-12.1.0/doc/examples/echoclient_ssl.py --- twisted-10.2.0/doc/examples/echoclient_ssl.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/examples/echoclient_ssl.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2001-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from OpenSSL import SSL diff -Nru twisted-10.2.0/doc/examples/echoclient_udp.py twisted-12.1.0/doc/examples/echoclient_udp.py --- twisted-10.2.0/doc/examples/echoclient_udp.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/examples/echoclient_udp.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2001-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. diff -Nru twisted-10.2.0/doc/examples/echoserv.py twisted-12.1.0/doc/examples/echoserv.py --- twisted-10.2.0/doc/examples/echoserv.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/examples/echoserv.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2001-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.internet.protocol import Protocol, Factory diff -Nru twisted-10.2.0/doc/examples/echoserv_ssl.py twisted-12.1.0/doc/examples/echoserv_ssl.py --- twisted-10.2.0/doc/examples/echoserv_ssl.py 2004-08-25 08:36:30.000000000 +0000 +++ twisted-12.1.0/doc/examples/echoserv_ssl.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-10.2.0/doc/examples/echoserv_udp.py twisted-12.1.0/doc/examples/echoserv_udp.py --- twisted-10.2.0/doc/examples/echoserv_udp.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/examples/echoserv_udp.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2001-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.internet.protocol import DatagramProtocol diff -Nru twisted-10.2.0/doc/examples/filewatch.py twisted-12.1.0/doc/examples/filewatch.py --- twisted-10.2.0/doc/examples/filewatch.py 2004-08-25 08:36:30.000000000 +0000 +++ twisted-12.1.0/doc/examples/filewatch.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-10.2.0/doc/examples/ftpclient.py twisted-12.1.0/doc/examples/ftpclient.py --- twisted-10.2.0/doc/examples/ftpclient.py 2005-10-07 19:35:05.000000000 +0000 +++ twisted-12.1.0/doc/examples/ftpclient.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-10.2.0/doc/examples/ftpserver.py twisted-12.1.0/doc/examples/ftpserver.py --- twisted-10.2.0/doc/examples/ftpserver.py 2008-08-31 21:06:11.000000000 +0000 +++ twisted-12.1.0/doc/examples/ftpserver.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. """ diff -Nru twisted-10.2.0/doc/examples/gpsfix.py twisted-12.1.0/doc/examples/gpsfix.py --- twisted-10.2.0/doc/examples/gpsfix.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/examples/gpsfix.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2001-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ diff -Nru twisted-10.2.0/doc/examples/index.html twisted-12.1.0/doc/examples/index.html --- twisted-10.2.0/doc/examples/index.html 2010-11-30 03:13:23.000000000 +0000 +++ twisted-12.1.0/doc/examples/index.html 2012-06-04 08:46:17.000000000 +0000 @@ -6,7 +6,7 @@

Twisted code examples

- +
@@ -42,7 +42,7 @@

Perspective Broker

-

ROW (Twisted Enterprise)

-
    -
  • row_example.py - using twisted.enterpise.row to load objects - from a database and manipulate them.
  • -
  • row_schema.sql - sample statements to populate tables for - row_example.py
  • -
  • row_util.py - definitions of row classes for - row_example.py
  • -
- -

Cred

+

Cred

  • cred.py - Authenticate a user with an in-memory username/password database
  • dbcred.py - Using a database backend to authenticate a user
-

GUI

+

GUI

-

FTP examples

+

FTP examples

  • ftpclient.py - example of using the FTP client
  • ftpserver.py - create an FTP server which @@ -86,15 +76,22 @@ files for authenticated users from /home.
-

Logging

+

Logging

+

POSIX Specific Tricks

+ +

Miscellaneous

  • shaper.py - example of rate-limiting your web server
  • @@ -109,8 +106,9 @@ in Twisted
  • longex2.py - using generators to do long calculations
  • stdin.py - reading a line at a time from standard input - without blocking the reactor.
  • -
  • filewatch.py - write the content of a file to standard out + without blocking the reactor
  • +
  • streaming.py - example of a push producer/consumer system
  • +
  • filewatch.py - write the content of a file to standard out one line at a time
  • shoutcast.py - example Shoutcast client
  • gpsfix.py - example using the SerialPort transport and GPS @@ -118,10 +116,10 @@
  • wxacceptance.py - acceptance tests for wxreactor
  • postfix.py - test application for PostfixTCPMapServer
- +

Index

- Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/examples/mouse.py twisted-12.1.0/doc/examples/mouse.py --- twisted-10.2.0/doc/examples/mouse.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/examples/mouse.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ diff -Nru twisted-10.2.0/doc/examples/pbbenchserver.py twisted-12.1.0/doc/examples/pbbenchserver.py --- twisted-10.2.0/doc/examples/pbbenchserver.py 2006-04-23 23:07:11.000000000 +0000 +++ twisted-12.1.0/doc/examples/pbbenchserver.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2006 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. diff -Nru twisted-10.2.0/doc/examples/pbechoclient.py twisted-12.1.0/doc/examples/pbechoclient.py --- twisted-10.2.0/doc/examples/pbechoclient.py 2004-08-25 08:36:30.000000000 +0000 +++ twisted-12.1.0/doc/examples/pbechoclient.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-10.2.0/doc/examples/pbecho.py twisted-12.1.0/doc/examples/pbecho.py --- twisted-10.2.0/doc/examples/pbecho.py 2009-03-01 15:45:17.000000000 +0000 +++ twisted-12.1.0/doc/examples/pbecho.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2006 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. if __name__ == '__main__': diff -Nru twisted-10.2.0/doc/examples/pbgtk2.py twisted-12.1.0/doc/examples/pbgtk2.py --- twisted-10.2.0/doc/examples/pbgtk2.py 2009-11-10 21:15:06.000000000 +0000 +++ twisted-12.1.0/doc/examples/pbgtk2.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. diff -Nru twisted-10.2.0/doc/examples/pbinterop.py twisted-12.1.0/doc/examples/pbinterop.py --- twisted-10.2.0/doc/examples/pbinterop.py 2004-08-25 08:36:30.000000000 +0000 +++ twisted-12.1.0/doc/examples/pbinterop.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-10.2.0/doc/examples/pbsimpleclient.py twisted-12.1.0/doc/examples/pbsimpleclient.py --- twisted-10.2.0/doc/examples/pbsimpleclient.py 2004-08-25 08:36:30.000000000 +0000 +++ twisted-12.1.0/doc/examples/pbsimpleclient.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-10.2.0/doc/examples/pbsimple.py twisted-12.1.0/doc/examples/pbsimple.py --- twisted-10.2.0/doc/examples/pbsimple.py 2004-08-25 08:36:30.000000000 +0000 +++ twisted-12.1.0/doc/examples/pbsimple.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-10.2.0/doc/examples/postfix.py twisted-12.1.0/doc/examples/postfix.py --- twisted-10.2.0/doc/examples/postfix.py 2009-03-31 15:03:34.000000000 +0000 +++ twisted-12.1.0/doc/examples/postfix.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ @@ -26,4 +26,4 @@ f = postfix.PostfixTCPMapDictServerFactory(d) port = reactor.listenTCP(4242, f, interface='127.0.0.1') -reactor.run() \ No newline at end of file +reactor.run() diff -Nru twisted-10.2.0/doc/examples/ptyserv.py twisted-12.1.0/doc/examples/ptyserv.py --- twisted-10.2.0/doc/examples/ptyserv.py 2002-10-02 05:50:15.000000000 +0000 +++ twisted-12.1.0/doc/examples/ptyserv.py 2012-04-07 16:45:03.000000000 +0000 @@ -1,3 +1,16 @@ +# Copyright (c) Twisted Matrix Laboratories +# See LICENSE for details + +""" +A PTY server that spawns a shell upon connection. + +Run this example by typing in: +> python ptyserv.py + +Telnet to the server once you start it by typing in: +> telnet localhost 5823 +""" + from twisted.internet import reactor, protocol class FakeTelnet(protocol.Protocol): diff -Nru twisted-10.2.0/doc/examples/pyuidemo.py twisted-12.1.0/doc/examples/pyuidemo.py --- twisted-10.2.0/doc/examples/pyuidemo.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/examples/pyuidemo.py 2012-04-14 00:36:38.000000000 +0000 @@ -1,8 +1,16 @@ #!/usr/bin/env python -# Copyright (c) 2001-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. +""" +Displays a frame with two buttons and a background image, using pyui library. + +Run this example by typing in: + python pyuidemo.py + +Select "Quit" button to exit demo. +""" import pyui from twisted.internet import reactor, pyuisupport diff -Nru twisted-10.2.0/doc/examples/recvfd.py twisted-12.1.0/doc/examples/recvfd.py --- twisted-10.2.0/doc/examples/recvfd.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/examples/recvfd.py 2012-04-26 13:46:20.000000000 +0000 @@ -0,0 +1,90 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Client-side of an example for sending file descriptors between processes over +UNIX sockets. This client connects to a server listening on a UNIX socket and +waits for one file descriptor to arrive over the connection. It displays the +name of the file and the first 80 bytes it contains, then exits. + +To runb this example, run this program with one argument: a path giving the UNIX +socket the server side of this example is already listening on. For example: + + $ python recvfd.py /tmp/sendfd.sock + +See sendfd.py for the server side of this example. +""" + +if __name__ == '__main__': + import recvfd + raise SystemExit(recvfd.main()) + +import os, sys + +from zope.interface import implements + +from twisted.python.log import startLogging +from twisted.python.filepath import FilePath +from twisted.internet.defer import Deferred +from twisted.internet.interfaces import IFileDescriptorReceiver +from twisted.internet.protocol import Factory +from twisted.protocols.basic import LineOnlyReceiver +from twisted.internet.endpoints import UNIXClientEndpoint +from twisted.internet import reactor + +class ReceiveFDProtocol(LineOnlyReceiver): + implements(IFileDescriptorReceiver) + + descriptor = None + + def __init__(self): + self.whenDisconnected = Deferred() + + + def fileDescriptorReceived(self, descriptor): + # Record the descriptor sent to us + self.descriptor = descriptor + + + def lineReceived(self, line): + if self.descriptor is None: + print "Received %r without receiving descriptor!" % (line,) + else: + # Use the previously received descriptor, along with the newly + # provided information about which file it is, to present some + # information to the user. + data = os.read(self.descriptor, 80) + print "Received %r from the server." % (line,) + print "First 80 bytes are:\n%r\n" % (data,) + os.close(self.descriptor) + self.transport.loseConnection() + + + def connectionLost(self, reason): + self.whenDisconnected.callback(None) + + + +def main(): + address = FilePath(sys.argv[1]) + + startLogging(sys.stdout) + + factory = Factory() + factory.protocol = ReceiveFDProtocol + factory.quiet = True + + endpoint = UNIXClientEndpoint(reactor, address.path) + connected = endpoint.connect(factory) + + def succeeded(client): + return client.whenDisconnected + def failed(reason): + print "Could not connect:", reason.getErrorMessage() + def disconnected(ignored): + reactor.stop() + + connected.addCallbacks(succeeded, failed) + connected.addCallback(disconnected) + + reactor.run() diff -Nru twisted-10.2.0/doc/examples/rotatinglog.py twisted-12.1.0/doc/examples/rotatinglog.py --- twisted-10.2.0/doc/examples/rotatinglog.py 2004-08-25 08:36:30.000000000 +0000 +++ twisted-12.1.0/doc/examples/rotatinglog.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-10.2.0/doc/examples/row_example.py twisted-12.1.0/doc/examples/row_example.py --- twisted-10.2.0/doc/examples/row_example.py 2004-01-04 18:56:20.000000000 +0000 +++ twisted-12.1.0/doc/examples/row_example.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,105 +0,0 @@ -import random - -from twisted.internet import reactor - -from twisted.enterprise import adbapi, row, reflector, sqlreflector - -from row_util import * - -""" This example show using twisted.enterpise.row to load objects from -a database and manipulate them. -""" - -manager = None - -def gotRooms(rooms): - print "got Rooms.", rooms - if not rooms: - print "no rooms found!" - reactor.stop() - - for room in rooms: - print "room ", room - for child in room.furniture: - print "furn ", child - if hasattr(child, "childRows"): - for inner in child.childRows: - print "inner ", inner - - room.moveTo( int(random.random() * 100) , int(random.random() * 100) ) - manager.updateRow(room).addCallback(onUpdate) - -def gotFurniture(furniture): - for f in furniture: - print f - reactor.stop() - -def onUpdate(data): - print "updated row." - # create a new room - global newRoom - newRoom = RoomRow() - newRoom.assignKeyAttr("roomId", kf.getNextKey()) - newRoom.town_id = 20 - newRoom.name = 'newRoom1' - newRoom.owner = 'fred' - newRoom.posx = 100 - newRoom.posy = 100 - newRoom.width = 15 - newRoom.height = 20 - - #insert row into database - manager.insertRow(newRoom).addCallback(onInsert) - -def onInsert(data): - global newRoom - print "row inserted" - print newRoom.roomId - manager.deleteRow(newRoom).addCallback(onDelete) - -def onDelete(data): - print "row deleted." - return manager.loadObjectsFrom("furniture", whereClause=[("furnId",reflector.EQUAL,53)], forceChildren=1 ).addCallback(onSelected) - -def onSelected(furn): - for f in furn: - print "\ngot Furn:", f - if hasattr(f, "childRows"): - for l in f.childRows: - print " ", l - reactor.stop() - -def gotRooms2(rooms): - print "got more rooms", rooms - reactor.stop() - -def tick(): - reactor.callLater(0.5, tick) - -newRoom = None - - -# use this line for postgresql test -dbpool = adbapi.ConnectionPool("pyPgSQL.PgSQL", database="test") - -# use this line for SQLite test -#dbpool = adbapi.ConnectionPool("sqlite", db="test") - -# use this line for Interbase / Firebird -#dbpool = adbapi.ConnectionPool("kinterbasdb", dsn="localhost:/test.gdb",user="SYSDBA",password="masterkey") - -# use this for MySQL -#dbpool = adbapi.ConnectionPool("MySQLdb", db="test", passwd="pass") - - -def kickOffTests(ignoredResult=0): - global manager - manager = sqlreflector.SQLReflector(dbpool, [RoomRow, FurnitureRow, RugRow, LampRow]) - manager.loadObjectsFrom("testrooms", forceChildren=1).addCallback(gotRooms) - -kf = KeyFactory(100000, 50000) - -# make sure we can be shut down on windows. -reactor.callLater(0.5, tick) -reactor.callLater(0.4, kickOffTests) -reactor.run() diff -Nru twisted-10.2.0/doc/examples/row_schema.sql twisted-12.1.0/doc/examples/row_schema.sql --- twisted-10.2.0/doc/examples/row_schema.sql 2002-10-11 02:43:34.000000000 +0000 +++ twisted-12.1.0/doc/examples/row_schema.sql 1970-01-01 00:00:00.000000000 +0000 @@ -1,65 +0,0 @@ -DROP TABLE testrooms; -DROP TABLE furniture; -DROP TABLE rugs; -DROP TABLE lamps; - -CREATE TABLE testrooms -( - roomId int PRIMARY KEY, - town_id int, - name varchar(64), - owner varchar(64), - posx int, - posy int, - width int, - height int -); - -CREATE TABLE furniture -( - furnId int PRIMARY KEY, - roomId int, - name varchar(64), - posx int, - posy int -); - -CREATE TABLE rugs -( - rugId int PRIMARY KEY, - roomId int, - name varchar(64) -); - -CREATE TABLE lamps -( - lampId int PRIMARY KEY, - furnId int, - furnName varchar(64), - lampName varchar(64) -); - - -INSERT INTO testrooms VALUES (10, 100, 'testroom1', 'someguy', 10, 10, 20, 20); -INSERT INTO testrooms VALUES (11, 100, 'testroom2', 'someguy', 30, 10, 20, 20); -INSERT INTO testrooms VALUES (12, 100, 'testroom3', 'someguy', 50, 10, 20, 20); - -INSERT INTO furniture VALUES (50, 10, 'chair1', 10, 10); -INSERT INTO furniture VALUES (51, 10, 'chair2', 14, 10); -INSERT INTO furniture VALUES (52, 12, 'chair3', 14, 10); -INSERT INTO furniture VALUES (53, 12, 'chair4', 10, 12); -INSERT INTO furniture VALUES (54, 12, 'chair5', 18, 13); -INSERT INTO furniture VALUES (55, 12, 'couch', 22, 3); - -INSERT INTO rugs VALUES (81, 10, 'a big rug'); -INSERT INTO rugs VALUES (82, 10, 'a blue rug'); -INSERT INTO rugs VALUES (83, 11, 'a red rug'); -INSERT INTO rugs VALUES (84, 11, 'a green rug'); -INSERT INTO rugs VALUES (85, 12, 'a dirty rug'); - -INSERT INTO lamps VALUES (21, 50, 'chair1', 'a big lamp1'); -INSERT INTO lamps VALUES (22, 50, 'chair1', 'a big lamp2'); -INSERT INTO lamps VALUES (23, 53, 'chair4', 'a big lamp3'); -INSERT INTO lamps VALUES (24, 53, 'chair4', 'a big lamp4'); -INSERT INTO lamps VALUES (25, 53, 'chair4', 'a big lamp5'); -INSERT INTO lamps VALUES (26, 54, 'couch', 'a big lamp6'); diff -Nru twisted-10.2.0/doc/examples/row_util.py twisted-12.1.0/doc/examples/row_util.py --- twisted-10.2.0/doc/examples/row_util.py 2008-02-22 10:13:08.000000000 +0000 +++ twisted-12.1.0/doc/examples/row_util.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,103 +0,0 @@ -from twisted.enterprise import row - - -################################################## -########## Definitions of Row Classes ############ -################################################## - -class KeyFactory: - """This is a lame, but simple way to generate keys. - For real code, use the database instead.""" - def __init__(self, minimum, pool): - self.min = minimum - self.pool = minimum + pool - self.current = self.min - - def getNextKey(self): - next = self.current + 1 - self.current = next - if self.current >= self.pool: - raise ValueError("Key factory key pool exceeded.") - return next - -def myRowFactory(rowClass, data, kw): - newRow = rowClass() - newRow.__dict__.update(kw) - return newRow - -class RoomRow(row.RowObject): - rowColumns = [ - ("roomId", "int"), - ("town_id", "int"), - ("name", "varchar"), - ("owner", "varchar"), - ("posx", "int"), - ("posy", "int"), - ("width", "int"), - ("height", "int") - ] - rowKeyColumns = [("roomId","int")] - rowTableName = "testrooms" - rowFactoryMethod = [myRowFactory] - - def __init__(self): - self.furniture = [] - - def addStuff(self, stuff): - self.furniture.append(stuff) - - def moveTo(self, x, y): - self.posx = x - self.posy = y - - def __repr__(self): - return "" % (self.roomId, self.name, self.owner, self.posx, self.posy) - -class FurnitureRow(row.RowObject): - rowColumns = [ - ("furnId", "int"), - ("roomId", "int"), - ("name", "varchar"), - ("posx", "int"), - ("posy", "int") - ] - rowKeyColumns = [("furnId","int")] - rowTableName = "furniture" - rowForeignKeys = [("testrooms", [("roomId","int")], [("roomId","int")], "addStuff", 1) ] - - def __repr__(self): - return "Furniture #%s: room #%s (%s) (%s,%s)" % (self.furnId, self.roomId, self.name, self.posx, self.posy) - -class RugRow(row.RowObject): - rowColumns = [ - ("rugId", "int"), - ("roomId", "int"), - ("name", "varchar") - ] - rowKeyColumns = [("rugId","int")] - rowTableName = "rugs" - rowFactoryMethod = [myRowFactory] - rowForeignKeys = [( "testrooms", [("roomId","int")],[("roomId","int")], "addStuff", 1) ] - - def __repr__(self): - return "Rug %#s: room #%s, (%s)" % (self.rugId, self.roomId, self.name) - -class LampRow(row.RowObject): - rowColumns = [ - ("lampId", "int"), - ("furnId", "int"), - ("furnName", "varchar"), - ("lampName", "varchar") - ] - rowKeyColumns = [("lampId","int")] - rowTableName = "lamps" - rowForeignKeys = [("furniture", - [("furnId","int"),("furnName", "varchar")], # child table columns (this table) - [("furnId","int"),("name", "varchar")], # parent table columns (the other table) - None, - 1) - ] - # NOTE: this has no containerMethod so children will be added to "childRows" - - def __repr__(self): - return "Lamp #%s" % self.lampId diff -Nru twisted-10.2.0/doc/examples/sendfd.py twisted-12.1.0/doc/examples/sendfd.py --- twisted-10.2.0/doc/examples/sendfd.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/examples/sendfd.py 2012-04-26 13:46:20.000000000 +0000 @@ -0,0 +1,83 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Server-side of an example for sending file descriptors between processes over +UNIX sockets. This server accepts connections on a UNIX socket and sends one +file descriptor to them, along with the name of the file it is associated with. + +To run this example, run this program with two arguments: a path giving a UNIX +socket to listen on (must not exist) and a path to a file to send to clients +which connect (must exist). For example: + + $ python sendfd.py /tmp/sendfd.sock /etc/motd + +It will listen for client connections until stopped (eg, using Control-C). Most +interesting behavior happens on the client side. + +See recvfd.py for the client side of this example. +""" + +if __name__ == '__main__': + import sendfd + raise SystemExit(sendfd.main()) + +import sys + +from twisted.python.log import startLogging +from twisted.python.filepath import FilePath +from twisted.internet.protocol import Factory +from twisted.protocols.basic import LineOnlyReceiver +from twisted.internet import reactor + +class SendFDProtocol(LineOnlyReceiver): + def connectionMade(self): + # Open the desired file and keep a reference to it - keeping it open + # until we know the other side has it. Closing it early will prevent + # it from actually being sent. + self.fObj = self.factory.content.open() + + # Tell the transport to send it. It is not necessarily sent when this + # method returns. The reactor may need to run for a while longer before + # that happens. + self.transport.sendFileDescriptor(self.fObj.fileno()) + + # Send along *at least* one byte, since one file descriptor was sent. + # In this case, send along the name of the file to let the other side + # have some idea what they're getting. + self.sendLine(self.factory.content.path) + + # Give the other side a minute to deal with this. If they don't close + # the connection by then, we will do it for them. + self.timeoutCall = reactor.callLater(60, self.transport.loseConnection) + + + def connectionLost(self, reason): + # Clean up the file object, it is no longer needed. + self.fObj.close() + self.fObj = None + + # Clean up the timeout, if necessary. + if self.timeoutCall.active(): + self.timeoutCall.cancel() + self.timeoutCall = None + + +def main(): + address = FilePath(sys.argv[1]) + content = FilePath(sys.argv[2]) + + if address.exists(): + raise SystemExit("Cannot listen on an existing path") + + if not content.isfile(): + raise SystemExit("Content file must exist") + + startLogging(sys.stdout) + + serverFactory = Factory() + serverFactory.content = content + serverFactory.protocol = SendFDProtocol + + port = reactor.listenUNIX(address.path, serverFactory) + reactor.run() diff -Nru twisted-10.2.0/doc/examples/shoutcast.py twisted-12.1.0/doc/examples/shoutcast.py --- twisted-10.2.0/doc/examples/shoutcast.py 2009-03-31 14:25:25.000000000 +0000 +++ twisted-12.1.0/doc/examples/shoutcast.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ @@ -23,4 +23,4 @@ port = int(sys.argv[2]) protocol.ClientCreator(reactor, Test).connectTCP(host, port) -reactor.run() \ No newline at end of file +reactor.run() diff -Nru twisted-10.2.0/doc/examples/simpleclient.py twisted-12.1.0/doc/examples/simpleclient.py --- twisted-10.2.0/doc/examples/simpleclient.py 2005-10-30 16:54:09.000000000 +0000 +++ twisted-12.1.0/doc/examples/simpleclient.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-10.2.0/doc/examples/simpleserv.py twisted-12.1.0/doc/examples/simpleserv.py --- twisted-10.2.0/doc/examples/simpleserv.py 2004-08-25 08:36:30.000000000 +0000 +++ twisted-12.1.0/doc/examples/simpleserv.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-10.2.0/doc/examples/stdin.py twisted-12.1.0/doc/examples/stdin.py --- twisted-10.2.0/doc/examples/stdin.py 2004-08-25 08:36:30.000000000 +0000 +++ twisted-12.1.0/doc/examples/stdin.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-10.2.0/doc/examples/stdiodemo.py twisted-12.1.0/doc/examples/stdiodemo.py --- twisted-10.2.0/doc/examples/stdiodemo.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/examples/stdiodemo.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ diff -Nru twisted-10.2.0/doc/examples/streaming.py twisted-12.1.0/doc/examples/streaming.py --- twisted-10.2.0/doc/examples/streaming.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/examples/streaming.py 2011-04-11 17:29:12.000000000 +0000 @@ -0,0 +1,103 @@ +#!/usr/bin/env python + +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +This is a sample implementation of a Twisted push producer/consumer system. It +consists of a TCP server which asks the user how many random integers they +want, and it sends the result set back to the user, one result per line, +and finally closes the connection. +""" + +from sys import stdout +from random import randrange + +from zope.interface import implements +from twisted.python.log import startLogging +from twisted.internet import interfaces, reactor +from twisted.internet.protocol import Factory +from twisted.protocols.basic import LineReceiver + + +class Producer(object): + """ + Send back the requested number of random integers to the client. + """ + + implements(interfaces.IPushProducer) + + def __init__(self, proto, count): + self._proto = proto + self._goal = count + self._produced = 0 + self._paused = False + + def pauseProducing(self): + """ + When we've produced data too fast, pauseProducing() will be called + (reentrantly from within resumeProducing's sendLine() method, most + likely), so set a flag that causes production to pause temporarily. + """ + self._paused = True + print 'Pausing connection from %s' % self._proto.transport.getPeer() + + def resumeProducing(self): + """ + Resume producing integers. + + This tells the push producer to (re-)add itself to the main loop and + produce integers for its consumer until the requested number of integers + were returned to the client. + """ + self._paused = False + + while not self._paused and self._produced < self._goal: + next_int = randrange(0, 10000) + self._proto.sendLine('%d' % next_int) + self._produced += 1 + + if self._produced == self._goal: + self._proto.transport.unregisterProducer() + self._proto.transport.loseConnection() + + def stopProducing(self): + """ + When a consumer has died, stop producing data for good. + """ + self._produced = self._goal + + +class ServeRandom(LineReceiver): + """ + Serve up random integers. + """ + + def connectionMade(self): + """ + Once the connection is made we ask the client how many random integers + the producer should return. + """ + print 'Connection made from %s' % self.transport.getPeer() + self.sendLine('How many random integers do you want?') + + def lineReceived(self, line): + """ + This checks how many random integers the client expects in return and + tells the producer to start generating the data. + """ + count = int(line.strip()) + print 'Client requested %d random integers!' % count + producer = Producer(self, count) + self.transport.registerProducer(producer, True) + producer.resumeProducing() + + def connectionLost(self, reason): + print 'Connection lost from %s' % self.transport.getPeer() + + +startLogging(stdout) +factory = Factory() +factory.protocol = ServeRandom +reactor.listenTCP(1234, factory) +reactor.run() diff -Nru twisted-10.2.0/doc/examples/testlogging.py twisted-12.1.0/doc/examples/testlogging.py --- twisted-10.2.0/doc/examples/testlogging.py 2004-08-25 08:36:30.000000000 +0000 +++ twisted-12.1.0/doc/examples/testlogging.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-10.2.0/doc/examples/threadedselect/blockingdemo.py twisted-12.1.0/doc/examples/threadedselect/blockingdemo.py --- twisted-10.2.0/doc/examples/threadedselect/blockingdemo.py 2006-10-04 11:53:22.000000000 +0000 +++ twisted-12.1.0/doc/examples/threadedselect/blockingdemo.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-10.2.0/doc/examples/threadedselect/Cocoa/SimpleWebClient/Twistzilla.py twisted-12.1.0/doc/examples/threadedselect/Cocoa/SimpleWebClient/Twistzilla.py --- twisted-10.2.0/doc/examples/threadedselect/Cocoa/SimpleWebClient/Twistzilla.py 2006-10-04 11:53:22.000000000 +0000 +++ twisted-12.1.0/doc/examples/threadedselect/Cocoa/SimpleWebClient/Twistzilla.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-10.2.0/doc/examples/tkinterdemo.py twisted-12.1.0/doc/examples/tkinterdemo.py --- twisted-10.2.0/doc/examples/tkinterdemo.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/examples/tkinterdemo.py 2012-04-14 00:53:12.000000000 +0000 @@ -0,0 +1,44 @@ +#!/usr/bin/env python + +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + + +""" +An example of using Twisted with Tkinter. +Displays a frame with buttons that responds to mouse clicks. + +Run this example by typing in: + python tkinterdemo.py +""" + + +from Tkinter import Tk, Frame, Button, LEFT +from twisted.internet import reactor, tksupport + + +class App(object): + + def onQuit(self): + print "Quit!" + reactor.stop() + + def onButton(self): + print "Hello!" + + def __init__(self, master): + frame = Frame(master) + frame.pack() + + q = Button(frame, text="Quit!", command=self.onQuit) + b = Button(frame, text="Hello!", command=self.onButton) + + q.pack(side=LEFT) + b.pack(side=LEFT) + + +if __name__ == '__main__': + root = Tk() + tksupport.install(root) + app = App(root) + reactor.run() diff -Nru twisted-10.2.0/doc/examples/wxacceptance.py twisted-12.1.0/doc/examples/wxacceptance.py --- twisted-10.2.0/doc/examples/wxacceptance.py 2006-12-24 21:12:36.000000000 +0000 +++ twisted-12.1.0/doc/examples/wxacceptance.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2006 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ diff -Nru twisted-10.2.0/doc/examples/wxdemo.py twisted-12.1.0/doc/examples/wxdemo.py --- twisted-10.2.0/doc/examples/wxdemo.py 2008-07-27 19:27:34.000000000 +0000 +++ twisted-12.1.0/doc/examples/wxdemo.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2006 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """Demo of wxPython integration with Twisted.""" diff -Nru twisted-10.2.0/doc/howto/amp.html twisted-12.1.0/doc/howto/amp.html --- twisted-10.2.0/doc/howto/amp.html 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/amp.html 2012-06-04 08:46:18.000000000 +0000 @@ -0,0 +1,349 @@ + + +Twisted Documentation: <b>A</b>synchronous <b>M</b>essaging <b>P</b>rotocol Overview + + + + +

Asynchronous Messaging Protocol Overview

+ +
+ + +

The purpose of this guide is to describe the uses for and usage of twisted.protocols.amp beyond what is explained in the API documentation. It will show you how to implement an AMP server which can respond to commands or interact directly with individual messages. It will also show you how to implement an AMP client which can issue commands to a server.

+ +

AMP is a bidirectional command/response-oriented protocol intended to be extended with application-specific request types and handlers. Various simple data types are supported and support for new data types can be added by applications.

+ +

Setting Up

+ +

AMP runs over a stream-oriented connection-based protocol, such as TCP or SSL. Before you can use any features of the AMP protocol, you need a connection. The protocol class to use to establish an AMP connection is AMP. Connection setup works as it does for almost all protocols in Twisted. For example, you can set up a listening AMP server using a server endpoint:

+ +

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

from twisted.protocols.amp import AMP +from twisted.internet import reactor +from twisted.internet.protocol import Factory +from twisted.internet.endpoints import TCP4ServerEndpoint +from twisted.application.service import Application +from twisted.application.internet import StreamServerEndpointService + +application = Application("basic AMP server") + +endpoint = TCP4ServerEndpoint(reactor, 8750) +factory = Factory() +factory.protocol = AMP +service = StreamServerEndpointService(endpoint, factory) +service.setServiceParent(application) +
+ +

And you can connect to an AMP server using a client endpoint:

+ +

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 +

if __name__ == '__main__': + import basic_client + raise SystemExit(basic_client.main()) + +from sys import stdout + +from twisted.python.log import startLogging, err +from twisted.protocols.amp import AMP +from twisted.internet import reactor +from twisted.internet.protocol import Factory +from twisted.internet.endpoints import TCP4ClientEndpoint + +def connect(): + endpoint = TCP4ClientEndpoint(reactor, "127.0.0.1", 8750) + factory = Factory() + factory.protocol = AMP + return endpoint.connect(factory) + + +def main(): + startLogging(stdout) + + d = connect() + d.addErrback(err, "Connection failed") + def done(ignored): + reactor.stop() + d.addCallback(done) + + reactor.run() +
+ +

Commands

+ +

Either side of an AMP connection can issue a command to the other side. Each kind of command is represented as a subclass of Command. A Command defines arguments, response values, and error conditions.

+ +

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

from twisted.protocols.amp import Integer, String, Unicode, Command + +class UsernameUnavailable(Exception): + pass + +class RegisterUser(Command): + arguments = [('username', Unicode()), + ('publickey', String())] + + response = [('uid', Integer())] + + errors = {UsernameUnavailable: 'username-unavailable'} +
+ +

The definition of the command's signature - its arguments, response, and possible error conditions - is separate from the implementation of the behavior to execute when the command is received. The Command subclass only defines the former.

+ +

Commands are issued by calling callRemote on either side of the connection. This method returns a Deferred which eventually fires with the result of the command.

+ +

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 +

if __name__ == '__main__': + import command_client + raise SystemExit(command_client.main()) + +from sys import stdout + +from twisted.python.log import startLogging, err +from twisted.protocols.amp import Integer, String, Unicode, Command +from twisted.internet import reactor + +from basic_client import connect + +class UsernameUnavailable(Exception): + pass + + +class RegisterUser(Command): + arguments = [('username', Unicode()), + ('publickey', String())] + + response = [('uid', Integer())] + + errors = {UsernameUnavailable: 'username-unavailable'} + + +def main(): + startLogging(stdout) + + d = connect() + def connected(protocol): + return protocol.callRemote( + RegisterUser, + username=u'alice', + publickey='ssh-rsa AAAAB3NzaC1yc2 alice@actinium') + d.addCallback(connected) + + def registered(result): + print 'Registration result:', result + d.addCallback(registered) + + d.addErrback(err, "Failed to register") + + def finished(ignored): + reactor.stop() + d.addCallback(finished) + + reactor.run() +
+ +

Locators

+ + +

The logic for handling a command can be specified as an object separate from the AMP instance which interprets and formats bytes over the network.

+ +

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

from twisted.protocols.amp import CommandLocator +from twisted.python.filepath import FilePath + +class UsernameUnavailable(Exception): + pass + +class UserRegistration(CommandLocator): + uidCounter = 0 + + @RegisterUser.responder + def register(self, username, publickey): + path = FilePath(username) + if path.exists(): + raise UsernameUnavailable() + self.uidCounter += 1 + path.setContent('%d %s\n' % (self.uidCounter, publickey)) + return self.uidCounter +
+ +

When you define a separate CommandLocator subclass, use it by passing an instance of it to the AMP initializer.

+ +

1 +2 +

factory = Factory() +factory.protocol = lambda: AMP(locator=UserRegistration()) +
+ +

If no locator is passed in, AMP acts as its own locator. Command responders can be defined on an AMP subclass, just as the responder was defined on the UserRegistration example above.

+ +

Box Receivers

+ +

AMP conversations consist of an exchange of messages called boxes. A box consists of a sequence of pairs of key and value (for example, the pair username and alice). Boxes are generally represented as dict instances. Normally boxes are passed back and forth to implement the command request/response features described above. The logic for handling each box can be specified as an object separate from the AMP instance.

+ +

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

from zope.interface import implements + +from twisted.protocols.amp import IBoxReceiver + +class BoxReflector(object): + implements(IBoxReceiver) + + def startReceivingBoxes(self, boxSender): + self.boxSender = boxSender + + def ampBoxReceived(self, box): + self.boxSender.sendBox(box) + + def stopReceivingBoxes(self, reason): + self.boxSender = None +
+ +

These methods parallel those of IProtocol. Startup notification is given by startReceivingBoxes. The argument passed to it is an IBoxSender provider, which can be used to send boxes back out over the network. ampBoxReceived delivers notification for a complete box having been received. And last, stopReceivingBoxes notifies the object that no more boxes will be received and no more can be sent. The argument passed to it is a Failure which may contain details about what caused the conversation to end.

+ +

To use a custom IBoxReceiver, pass it to the AMP initializer.

+ +

1 +2 +

factory = Factory() +factory.protocol = lambda: AMP(boxReceiver=BoxReflector()) +
+ +

If no box receiver is passed in, AMP acts as its own box receiver. It handles boxes by treating them as command requests or responses and delivering them to the appropriate responder or as a result to a callRemote Deferred.

+ +
+ +

Index

+ Version: 12.1.0 + + \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/application.html twisted-12.1.0/doc/howto/application.html --- twisted-10.2.0/doc/howto/application.html 2010-11-30 03:13:18.000000000 +0000 +++ twisted-12.1.0/doc/howto/application.html 2012-06-04 08:46:20.000000000 +0000 @@ -6,7 +6,7 @@

Using the Twisted Application Framework

- +
@@ -43,17 +43,17 @@ recommended tool for running Twisted applications.

-

The core component of the Twisted Application infrastructure is the twisted.application.service.Application object — an +

The core component of the Twisted Application infrastructure is the twisted.application.service.Application object — an object which represents your application. However, Application doesn't provide anything that you'd want to manipulate directly. Instead, Application acts as -a container of any Services (objects implementing IService) that your application +a container of any Services (objects implementing IService) that your application provides. Most of your interaction with the Application infrastructure will be done through Services.

By Service, we mean anything in your application that can be started and stopped. Typical services include web servers, FTP servers and SSH clients. Your Application object can contain many services, and can even -contain structured hierarchies of Services using IServiceCollections.

+contain structured hierarchies of Services using IServiceCollections.

Here's a simple example of constructing an Application object which represents an echo server that runs on TCP port 7001.

@@ -102,8 +102,8 @@

twistd and tac

To handle start-up and configuration of your Twisted application, the -Twisted Application infrastructure uses .tac files. -.tac are Python files which configure an Application object and assign this +Twisted Application infrastructure uses .tac files. +.tac are Python files which configure an Application object and assign this object to the top-level variable application.

The following is a simple example of a .tac file:

@@ -178,12 +178,12 @@ service.setServiceParent(application)
-

twistd is a program that runs Twisted applications using a -.tac file. In its most simple form, it takes a single argument +

twistd is a program that runs Twisted applications using a +.tac file. In its most simple form, it takes a single argument -y and a tac file name. For example, you can run the above server with the command twistd -y service.tac.

-

By default, twistd daemonizes and logs to a file called +

By default, twistd daemonizes and logs to a file called twistd.log. More usually, when debugging, you will want your application to run in the foreground and log to the command line. To run the above file like this, use the command twistd -noy @@ -191,17 +191,39 @@

For more information, see the twistd man page.

-

Customizing twistd logging in a .tac application

+

Customizing twistd logging

-The logging behavior can be customized through an API -accessible from .tac files. The ILogObserver component can be -set on an Application in order to customize the default log observer that +twistd logging can be customized using the command +line. This requires that a log observer factory be +importable. Given a file named my.py with the code: +

+ +

1 +2 +3 +4 +

from twisted.python.log import FileLogObserver + +def logger(): + return FileLogObserver(open("/tmp/my.log", "w")).emit +
+ +

+invoking twistd --logger my.logger ... will log +to a file named /tmp/my.log (this simple example could easily be +replaced with use of the --logfile parameter to twistd). +

+ +

+Alternatively, the logging behavior can be customized through an API +accessible from .tac files. The ILogObserver component can be +set on an Application in order to customize the default log observer that twistd will use.

-Here is an example of how to use DailyLogFile, which rotates the log once +Here is an example of how to use DailyLogFile, which rotates the log once per day.

@@ -223,16 +245,16 @@

invoking twistd -y my.tac will create a log file -at/tmp/my.log. +at /tmp/my.log.

Services provided by Twisted

Twisted provides several services that you want to know about.

-

Each of these services (except TimerService) has a corresponding +

Each of these services (except TimerService) has a corresponding connect or listen method on the reactor, and the constructors for -the services take the same arguments as the reactor methods. The +the services take the same arguments as the reactor methods. The connect methods are for clients and the listen methods are for servers. For example, TCPServer corresponds to reactor.listenTCP and TCPClient corresponds to reactor.connectTCP.

@@ -248,8 +270,8 @@ Services which allow you to make connections and listen for connections on TCP ports.
@@ -260,8 +282,8 @@
Services which listen and make connections over UNIX sockets.
@@ -271,8 +293,8 @@
Services which allow you to make SSL connections and run SSL servers.
@@ -282,7 +304,7 @@
Services which allow you to send and receive data over UDP

See also the UDP documentation.

@@ -294,8 +316,8 @@
Services which send and receive data over UNIX datagram sockets.
@@ -304,11 +326,11 @@
A server for UDP socket methods that support multicast.
-
TimerService
+
TimerService
A service to periodically call a function. @@ -318,12 +340,12 @@

Service Collection

-

IServiceCollection objects contain -IService objects. -IService objects can be added to IServiceCollection by calling setServiceParent and detached -by using disownServiceParent.

+

IServiceCollection objects contain +IService objects. +IService objects can be added to IServiceCollection by calling setServiceParent and detached +by using disownServiceParent.

-

The standard implementation of IServiceCollection is MultiService, which also implements +

The standard implementation of IServiceCollection is MultiService, which also implements IService. MultiService is useful for creating a new Service which combines two or more existing Services. For example, you could create a DNS Service as a MultiService which has a TCP and a UDP Service as children.

@@ -371,6 +393,6 @@

Index

- Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/basics.html twisted-12.1.0/doc/howto/basics.html --- twisted-10.2.0/doc/howto/basics.html 2010-11-30 03:13:18.000000000 +0000 +++ twisted-12.1.0/doc/howto/basics.html 2012-06-04 08:46:19.000000000 +0000 @@ -12,13 +12,12 @@

Application

-

Twisted programs usually work with -twisted.application.service.Application. -This class usually holds all persistent configuration of -a running server -- ports to bind to, places where connections -to must be kept or attempted, periodic actions to do and almost -everything else. It is the root object in a tree of services implementing -IService.

+

Twisted programs usually work +with twisted.application.service.Application. +This class usually holds all persistent configuration of a running +server -- ports to bind to, places where connections to must be kept +or attempted, periodic actions to do and almost everything else. It is +the root object in a tree of services implementing IService.

Other HOWTOs describe how to write custom code for Applications, but this one describes how to use already written code (which can be @@ -52,10 +51,11 @@ object called application is used, use the -y option.

-

When twistd runs, it records its process id in a -twistd.pid file (this can be configured via a command line -switch). In order to shutdown the twistd process, kill that -pid (usually you would do kill `cat twistd.pid`). +

When twistd runs, it records its process +id in a twistd.pid file (this can be configured via a +command line switch). In order to shutdown +the twistd process, kill that pid (usually +you would do kill `cat twistd.pid`).

As always, the gory details are in the manual page.

@@ -63,24 +63,27 @@

OS Integration

-If you have an Application that runs with twistd, -you can easily deploy it on RedHat Linux or Debian GNU/Linux based systems -using the tap2deb or tap2rpm tools. These take a Twisted Application file (of -any of the supported formats — Python source, XML or pickle), and build a -Debian or RPM package (respectively) that installs the Application as a system -service. The package includes the Application file, a default -/etc/init.d/ script that starts and stops the process with twistd, -and post-installation scripts that configure the Application to be run in the -appropriate init levels. +If you have an Application that runs +with twistd, you can easily deploy it on +RedHat Linux or Debian GNU/Linux based systems using +the tap2deb +or tap2rpm tools. These take a Twisted +Application file (of any of the supported formats — Python source, XML +or pickle), and build a Debian or RPM package (respectively) that +installs the Application as a system service. The package includes the +Application file, a default /etc/init.d/ script that +starts and stops the process with twistd, and post-installation +scripts that configure the Application to be run in the appropriate +init levels.

-
Note: -tap2rpm and tap2deb do -not package your entire application and dependent code, just the Twisted -Application file. You will need to find some other way to package your Python -code, such as distutils' bdist_rpm -command. +
Note: tap2rpm +and tap2deb do not package your entire +application and dependent code, just the Twisted Application file. You +will need to find some other way to package your Python code, such +as distutils' +bdist_rpm command.

@@ -92,6 +95,6 @@

Index

- Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/book.tex twisted-12.1.0/doc/howto/book.tex --- twisted-10.2.0/doc/howto/book.tex 2009-07-23 19:53:43.000000000 +0000 +++ twisted-12.1.0/doc/howto/book.tex 2012-01-17 13:37:12.000000000 +0000 @@ -31,15 +31,13 @@ \chapter{Introduction} \input{vision.tex} -\input{overview.tex} -\input{internet-overview.tex} -\chapter{Tutorial} + +\chapter{Getting Started} \input{servers.tex} \input{clients.tex} -\input{quotes.tex} -\input{design.tex} +\input{trial.tex} \input{tutorial/index.tex} \input{tutorial/intro.tex} \input{tutorial/protocol.tex} @@ -52,65 +50,80 @@ \input{tutorial/client.tex} \input{tutorial/library.tex} \input{tutorial/configuration.tex} +\input{quotes.tex} +\input{design.tex} + -\chapter{Low-Level Twisted } +\chapter{Networking and Other Event Sources} +\input{internet-overview.tex} \input{reactor-basics.tex} +\input{ssl.tex} \input{udp.tex} \input{process.tex} \input{defer.tex} \input{gendefer.tex} -\input{deferredindepth.tex} \input{time.tex} \input{threading.tex} +\input{producers.tex} \input{choosing-reactor.tex} -\chapter{High-Level Twisted} -\input{basics.tex} -\input{plugin.tex} -\input{tap.tex} +\chapter{High-Level Infrastructure} + +\input{endpoints.tex} \input{components.tex} \input{cred.tex} +\input{plugin.tex} + + +\chapter{Deploying Twisted Applications} + +\input{basics.tex} \input{application.tex} +\input{tap.tex} + \chapter{Utilities} -\input{options.tex} \input{logging.tex} +\input{constants.tex} +\input{rdbms.tex} +\input{options.tex} \input{dirdbm.tex} -\input{telnet.tex} \input{testing.tex} -\chapter{Twisted RDBMS support} -\input{rdbms.tex} -\input{row.tex} +\chapter{Asynchronous Messaging Protocol (AMP)} + +\input{amp.tex} + \chapter{Perspective Broker} + \input{pb.tex} \input{pb-intro.tex} \input{pb-usage.tex} +\input{pb-clients.tex} \input{pb-copyable.tex} \input{pb-cred.tex} +\input{pb-limits.tex} + \chapter{Manual Pages} -\input{../man/manhole-man.tex} +\input{../man/trial-man.tex} +\clearpage +\input{../man/twistd-man.tex} \clearpage \input{../man/tap2deb-man.tex} \clearpage \input{../man/tap2rpm-man.tex} -\clearpage -\input{../man/tapconvert-man.tex} -\clearpage -\input{../man/trial-man.tex} -\clearpage -\input{../man/twistd-man.tex} + \chapter{Appendix} \input{glossary.tex} -\input{../specifications/banana.tex} +\input{debug-with-emacs.tex} \end{document} diff -Nru twisted-10.2.0/doc/howto/choosing-reactor.html twisted-12.1.0/doc/howto/choosing-reactor.html --- twisted-10.2.0/doc/howto/choosing-reactor.html 2010-11-30 03:13:15.000000000 +0000 +++ twisted-12.1.0/doc/howto/choosing-reactor.html 2012-06-04 08:46:20.000000000 +0000 @@ -6,18 +6,19 @@

Choosing a Reactor and GUI Toolkit Integration

- +

Overview

-

Twisted provides a variety of implementations of the twisted.internet.reactor. The specialized +

Twisted provides a variety of implementations of the twisted.internet.reactor. The specialized implementations are suited for different purposes and are designed to integrate better with particular platforms.

-

The select()-based reactor is Twisted's - cross-platform reactor.

+

The epoll()-based reactor is Twisted's default on + Linux. Other platforms use poll(), or the most + cross-platform reactor, select().

Platform-specific reactor implementations exist for:

@@ -40,6 +41,7 @@

Index

- Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/clients.html twisted-12.1.0/doc/howto/clients.html --- twisted-10.2.0/doc/howto/clients.html 2010-11-30 03:13:14.000000000 +0000 +++ twisted-12.1.0/doc/howto/clients.html 2012-06-04 08:46:19.000000000 +0000 @@ -21,7 +21,7 @@

At the base, the place where you actually implement the protocol parsing and handling, is the Protocol class. This class will usually be descended - from twisted.internet.protocol.Protocol. Most + from twisted.internet.protocol.Protocol. Most protocol handlers inherit either from this class or from one of its convenience children. An instance of the protocol class will be instantiated when you connect to the server and will go away when the connection is @@ -29,8 +29,8 @@ Protocol.

The persistent configuration is kept in a Factory - class, which usually inherits from twisted.internet.protocol.Factory - (or twisted.internet.protocol.ClientFactory: see + class, which usually inherits from twisted.internet.protocol.Factory + (or twisted.internet.protocol.ClientFactory: see below). The default factory class just instantiates the Protocol and then sets the protocol's factory attribute to point to itself (the factory). This lets the Protocol access, and @@ -81,17 +81,17 @@

This protocol connects to the server, sends it a welcome message, and then terminates the connection.

-

The connectionMade event is +

The connectionMade event is usually where set up of the Protocol object happens, as well as any initial greetings (as in the WelcomeMessage protocol above). Any tearing down of - Protocol-specific objects is done in connectionLost.

+ Protocol-specific objects is done in connectionLost.

Simple, single-use clients

In many cases, the protocol only needs to connect to the server once, and the code just wants to get a connected instance of the protocol. In those - cases twisted.internet.endpoints provides the + cases twisted.internet.endpoints provides the appropriate API.

1 @@ -112,6 +112,9 @@ 16 17 18 +19 +20 +21

from twisted.internet import reactor from twisted.internet.protocol import Factory, Protocol from twisted.internet.endpoints import TCP4ClientEndpoint @@ -120,16 +123,19 @@ def sendMessage(self, msg): self.transport.write("MESSAGE %s\n" % msg) +class GreeterFactory(Factory): + def buildProtocol(self, addr): + return Greeter() + def gotProtocol(p): p.sendMessage("Hello") reactor.callLater(1, p.sendMessage, "This is sent in a second") reactor.callLater(2, p.transport.loseConnection) -factory = Factory() -factory.protocol = Greeter point = TCP4ClientEndpoint(reactor, "localhost", 1234) -d = point.connect(factory) +d = point.connect(GreeterFactory()) d.addCallback(gotProtocol) +reactor.run()

Regardless of the type of client endpoint, the way to set up a new @@ -137,7 +143,7 @@ in a factory. This means it's easy to change the mechanism you're using to connect, without changing the rest of your program. For example, to run the greeter example over SSL, the only change required is to instantiate an - SSL4ClientEndpoint instead of a + SSL4ClientEndpoint instead of a TCP4ClientEndpoint. To take advantage of this, functions and methods which initiates a new connection should generally accept an endpoint as an argument and let the caller construct it, rather than taking @@ -149,14 +155,14 @@ see the documentation for the endpoints API.

-

Note: If you've used ClientFactory before, +

Note: If you've used ClientFactory before, make sure you remember that the connect method takes a Factory, not a ClientFactory. Even if you pass a ClientFactory to endpoint.connect, its clientConnectionFailed and clientConnectionLost - methods.

+ methods will not be called.
-

You may come across code using ClientCreator, an older API which is not as flexible as +

You may come across code using ClientCreator, an older API which is not as flexible as the endpoint API. Rather than calling connect on an endpoint, such code will look like this:

@@ -167,6 +173,7 @@ 5 6 7 +8

from twisted.internet.protocol import ClientCreator ... @@ -174,6 +181,7 @@ creator = ClientCreator(reactor, Greeter) d = creator.connectTCP("localhost", 1234) d.addCallback(gotProtocol) +reactor.run()

In general, the endpoint API should be preferred in new code, as it lets @@ -188,7 +196,7 @@

To use the lower-level connection APIs, you will need to call one of the reactor.connect* methods directly. For these cases, you need a - ClientFactory. + ClientFactory. The ClientFactory is in charge of creating the Protocol and also receives events relating to the connection state. This allows it to do things like reconnect in the event of a @@ -249,8 +257,8 @@ reactor.run() -

Note that clientConnectionFailed - is called when a connection could not be established, and that clientConnectionLost +

Note that clientConnectionFailed + is called when a connection could not be established, and that clientConnectionLost is called when a connection was made and then disconnected.

Reconnection

@@ -279,7 +287,7 @@

However, most programs that want this functionality should - implement ReconnectingClientFactory instead, + implement ReconnectingClientFactory instead, which tries to reconnect if a connection is lost or fails and which exponentially delays repeated reconnect attempts.

@@ -481,6 +489,8 @@ 130 131 132 +133 +134

# twisted imports from twisted.words.protocols import irc from twisted.internet import reactor, protocol @@ -584,13 +594,15 @@ A new protocol instance will be created each time we connect to the server. """ - # the class of the protocol to build when new connection is made - protocol = LogBot - def __init__(self, channel, filename): self.channel = channel self.filename = filename + def buildProtocol(self, addr): + p = LogBot() + p.factory = self + return p + def clientConnectionLost(self, connector, reason): """If we get disconnected, reconnect to server.""" connector.connect() @@ -648,6 +660,9 @@ 20 21 22 +23 +24 +25

from twisted.words.protocols import irc from twisted.internet import protocol @@ -665,11 +680,14 @@ class LogBotFactory(protocol.ClientFactory): - protocol = LogBot - def __init__(self, channel, filename): self.channel = channel self.filename = filename + + def buildProtocol(self, addr): + p = LogBot() + p.factory = self + return p

When the protocol is created, it gets a reference to the factory as @@ -677,19 +695,39 @@ its logic. In the case of LogBot, it opens the file and connects to the channel stored in the factory.

+

Factories have a default implementation of buildProtocol + that does the same thing the example above does, using + the protocol attribute of the factory to create the protocol + instance. In the example above, the factory could be rewritten to look + like this:

+ +

1 +2 +3 +4 +5 +6 +

class LogBotFactory(protocol.ClientFactory): + protocol = LogBot + + def __init__(self, channel, filename): + self.channel = channel + self.filename = filename +
+

Further Reading

-

The Protocol +

The Protocol class used throughout this document is a base implementation - of IProtocol + of IProtocol used in most Twisted applications for convenience. To learn about the complete IProtocol interface, see the API documentation for - IProtocol.

+ IProtocol.

The transport attribute used in some examples in this - document provides the ITCPTransport interface. To learn + document provides the ITCPTransport interface. To learn about the complete interface, see the API documentation - for ITCPTransport.

+ for ITCPTransport.

Interface classes are a way of specifying what methods and attributes an object has and how they behave. See the @@ -698,6 +736,6 @@

Index

- Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/components.html twisted-12.1.0/doc/howto/components.html --- twisted-10.2.0/doc/howto/components.html 2010-11-30 03:13:16.000000000 +0000 +++ twisted-12.1.0/doc/howto/components.html 2012-06-04 08:46:18.000000000 +0000 @@ -19,14 +19,15 @@ systems, especially when multiple inheritance is involved. One solution is to use delegation instead of inheritance where appropriate. Delegation is simply the act of asking another object to perform a task -for an object. To support this design pattern, which is often referred to as the -components pattern because it involves many small interacting components, -interfaces and adapters were created by the Zope 3 team.

+for an object. To support this design pattern, which is often referred to as +the components pattern because it involves many small interacting +components, interfaces and adapters were created by the Zope +3 team.

Interfaces are simply markers which objects can use to say I -implement this interface. Other objects may then make requests like +implement this interface. Other objects may then make requests like Please give me an object which implements interface X for object type Y. -Objects which implement an interface for another object type are called +Objects which implement an interface for another object type are called adapters.

The superclass-subclass relationship is said to be an is-a relationship. @@ -140,23 +141,25 @@ inheritance to break code into small reusable chunks. Let us continue with the Multiple Inheritance example, though, because it is often used in practice.

-

What if both the Color and the Area base class defined the same method, -perhaps calculate? Where would the implementation come from? The -implementation that is located for Square().calculate() depends on -the method resolution order, or MRO, and can change when programmers change -seemingly unrelated things by refactoring classes in other parts of the system, -causing obscure bugs. Our first thought might be to change the calculate method -name to avoid name clashes, to perhaps calculateArea and -calculateColor. While explicit, this change could potentially -require a large number of changes throughout a system, and is error-prone, -especially when attempting to integrate two systems which you didn't write.

+

What if both the Color and the Area base class defined the same +method, perhaps calculate? Where would the implementation +come from? The implementation that is located +for Square().calculate() depends on the method resolution +order, or MRO, and can change when programmers change seemingly +unrelated things by refactoring classes in other parts of the system, +causing obscure bugs. Our first thought might be to change the +calculate method name to avoid name clashes, to +perhaps calculateArea and calculateColor. +While explicit, this change could potentially require a large number +of changes throughout a system, and is error-prone, especially when +attempting to integrate two systems which you didn't write.

Let's imagine another example. We have an electric appliance, say a hair -dryer. The hair dryer is american voltage. We have two electric sockets, one of -them an american 110 Volt socket, and one of them a foreign 220 Volt socket. If -we plug the hair dryer into the 220 Volt socket, it is going to expect 110 Volt +dryer. The hair dryer is American voltage. We have two electric sockets, one of +them an American 120 Volt socket, and one of them a United Kingdom 240 Volt socket. If +we plug the hair dryer into the 240 Volt socket, it is going to expect 120 Volt current and errors will result. Going back and changing the hair dryer to -support both plug110Volt and plug220Volt methods would +support both plug120Volt and plug240Volt methods would be tedious, and what if we decided we needed to plug the hair dryer into yet another type of socket? For example:

@@ -177,7 +180,7 @@ 15

class HairDryer: def plug(self, socket): - if socket.voltage() == 110: + if socket.voltage() == 120: print "I was plugged in properly and am operating." else: print "I was plugged in improperly and " @@ -185,11 +188,11 @@ class AmericanSocket: def voltage(self): - return 110 + return 120 -class ForeignSocket: +class UKSocket: def voltage(self): - return 220 + return 240

Given these classes, the following operations can be performed:

@@ -199,14 +202,14 @@ >>> am = AmericanSocket() >>> hd.plug(am) I was plugged in properly and am operating. ->>> fs = ForeignSocket() ->>> hd.plug(fs) +>>> uk = UKSocket() +>>> hd.plug(uk) I was plugged in improperly and now you have no hair dryer any more. -

We are going to attempt to solve this problem by writing an Adapter for the -ForeignSocket which converts the voltage for use with an American +

We are going to attempt to solve this problem by writing an Adapter for +the UKSocket which converts the voltage for use with an American hair dryer. An Adapter is a class which is constructed with one and only one argument, the adaptee or original object. In this example, we will show all code involved for clarity:

@@ -229,8 +232,8 @@
 >>> hd = HairDryer()
->>> fs = ForeignSocket()
->>> adapted = AdaptToAmericanSocket(fs)
+>>> uk = UKSocket()
+>>> adapted = AdaptToAmericanSocket(uk)
 >>> hd.plug(adapted)
 I was plugged in properly and am operating.
 
@@ -250,7 +253,7 @@ infrastructure. If each piece of code which wished to use an adapted object had to explicitly construct the adapter itself, the coupling between components would be too tight. We would like to achieve loose coupling, and this is -where twisted.python.components comes in.

+where twisted.python.components comes in.

First, we need to discuss Interfaces in more detail. As we mentioned earlier, an Interface is nothing more than a class which is used as a marker. @@ -263,11 +266,13 @@ 4 5 6 +7

from zope.interface import Interface class IAmericanSocket(Interface): def voltage(): - """Return the voltage produced by this socket object, as an integer. + """ + Return the voltage produced by this socket object, as an integer. """ @@ -278,9 +283,8 @@ distinguishes an Interface definition from a Class.

Now that we have a defined Interface, we can talk about objects using terms -like this: The AmericanSocket class implements the -IAmericanSocket interface and Please give me an object which -adapts ForeignSocket to the IAmericanSocket +like this: The AmericanSocket class implements the IAmericanSocket interface and Please give me an object which +adapts UKSocket to the IAmericanSocket interface. We can make declarations about what interfaces a certain class implements, and we can request adapters which implement a certain interface for a specific class.

@@ -302,15 +306,16 @@ implements(IAmericanSocket) def voltage(self): - return 110 + return 120 -

So, to declare that a class implements an interface, we simply call -zope.interface.implements at the class level.

+

So, to declare that a class implements an interface, we simply +call zope.interface.implements at the class level.

-

Now, let's say we want to rewrite the AdaptToAmericanSocket -class as a real adapter. In this case we also specify it as implementing -IAmericanSocket:

+

Now, let's say we want to rewrite +the AdaptToAmericanSocket class as a real adapter. In +this case we also specify it as +implementing IAmericanSocket:

1 2 @@ -334,7 +339,7 @@ def __init__(self, original): """ - Pass the original ForeignSocket object as original + Pass the original UKSocket object as original """ self.original = original @@ -344,12 +349,13 @@

Notice how we placed the implements declaration on this adapter class. So far, we have not achieved anything by using components other than requiring us -to type more. In order for components to be useful, we must use the -component registry. Since AdaptToAmericanSocket implements -IAmericanSocket and regulates the voltage of a -ForeignSocket object, we can register +to type more. In order for components to be useful, we must use the +component registry. Since AdaptToAmericanSocket +implements +IAmericanSocket and regulates the voltage of a +UKSocket object, we can register AdaptToAmericanSocket as an IAmericanSocket adapter -for the ForeignSocket class. It is easier to see how this is +for the UKSocket class. It is easier to see how this is done in code than to describe it:

1 @@ -396,11 +402,11 @@ implements(IAmericanSocket) def voltage(self): - return 110 + return 120 -class ForeignSocket: +class UKSocket: def voltage(self): - return 220 + return 240 class AdaptToAmericanSocket: @@ -414,7 +420,7 @@ components.registerAdapter( AdaptToAmericanSocket, - ForeignSocket, + UKSocket, IAmericanSocket)

@@ -425,27 +431,26 @@
 >>> IAmericanSocket.implementedBy(AmericanSocket)
 True
->>> IAmericanSocket.implementedBy(ForeignSocket)
+>>> IAmericanSocket.implementedBy(UKSocket)
 False
 >>> am = AmericanSocket() 
->>> fs = ForeignSocket()
+>>> uk = UKSocket()
 >>> IAmericanSocket.providedBy(am)
 True
->>> IAmericanSocket.providedBy(fs)
+>>> IAmericanSocket.providedBy(uk)
 False
 

As you can see, the AmericanSocket instance claims to -implement IAmericanSocket, but the ForeignSocket -does not. If we wanted to use the HairDryer with the -AmericanSocket, we could know that it would be safe to do so by +implement IAmericanSocket, but the UKSocket +does not. If we wanted to use the HairDryer with the AmericanSocket, we could know that it would be safe to do so by checking whether it implements IAmericanSocket. However, if we -decide we want to use HairDryer with a ForeignSocket +decide we want to use HairDryer with a UKSocket instance, we must adapt it to IAmericanSocket before doing so. We use the interface object to do this:

->>> IAmericanSocket(fs)
+>>> IAmericanSocket(uk)
 <__main__.AdaptToAmericanSocket instance at 0x1a5120>
 
@@ -453,8 +458,7 @@ looks in the adapter registry for an adapter which implements the interface for the given instance's class. If it finds one, it constructs an instance of the Adapter class, passing the constructor the original instance, and returns it. -Now the HairDryer can safely be used with the adapted -ForeignSocket. But what happens if we attempt to adapt an object +Now the HairDryer can safely be used with the adapted UKSocket. But what happens if we attempt to adapt an object which already implements IAmericanSocket? We simply get back the original instance:

@@ -474,7 +478,7 @@

class HairDryer: def plug(self, socket): adapted = IAmericanSocket(socket) - assert adapted.voltage() == 110, "BOOM" + assert adapted.voltage() == 120, "BOOM" print "I was plugged in properly and am operating"
@@ -485,11 +489,11 @@
 >>> am = AmericanSocket()
->>> fs = ForeignSocket()
+>>> uk = UKSocket()
 >>> hd = HairDryer()
 >>> hd.plug(am)
 I was plugged in properly and am operating
->>> hd.plug(fs)
+>>> hd.plug(uk)
 I was plugged in properly and am operating
 
@@ -501,8 +505,8 @@ subclass declares that it implements another interface, the implements will be inherited by default.

-

For example, pb.Root is a class -which implements IPBRoot. This interface indicates that an +

For example, pb.Root is a class +which implements IPBRoot. This interface indicates that an object has remotely-invokable methods and can be used as the initial object served by a new Broker instance. It has an implements setting like:

@@ -517,7 +521,7 @@ implements(IPBRoot) -

Suppose you have your own class which implements your +

Suppose you have your own class which implements your IMyInterface interface:

1 @@ -537,7 +541,7 @@

Now if you want to make this class inherit from pb.Root, -the interfaces code will automatically determine that it also implements +the interfaces code will automatically determine that it also implements IPBRoot:

1 @@ -564,8 +568,7 @@ True

-

If you want MyThing to inherit from pb.Root but -not implement IPBRoot like pb.Root does, +

If you want MyThing to inherit from pb.Root but not implement IPBRoot like pb.Root does, use implementOnly:

1 @@ -595,6 +598,6 @@

Index

- Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/constants.html twisted-12.1.0/doc/howto/constants.html --- twisted-10.2.0/doc/howto/constants.html 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/constants.html 2012-06-04 08:46:19.000000000 +0000 @@ -0,0 +1,456 @@ + + +Twisted Documentation: Symbolic Constants + + + + +

Symbolic Constants

+ +
+ + +

Overview

+ +

It is often useful to define names which will be treated as + constants. twisted.python.constants provides APIs + for defining such symbolic constants with minimal overhead and some useful + features beyond those afforded by the common Python idioms for this task.

+ +

This document will explain how to use these APIs and what circumstances + they might be helpful in.

+ +

Constant Names

+ +

Constants which have no value apart from their name and identity can be + defined by subclassing Names. + Consider this example, in which some HTTP request method constants are defined.

+ +

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

from twisted.python.constants import NamedConstant, Names +class METHOD(Names): + """ + Constants representing various HTTP request methods. + """ + GET = NamedConstant() + PUT = NamedConstant() + POST = NamedConstant() + DELETE = NamedConstant() +
+ +

Only direct subclasses of Names are supported (i.e., you + cannot subclass METHOD to add new constants the collection).

+ +

Given this definition, constants can be looked up by name using attribute + access on the METHOD object:

+ +
+>>> METHOD.GET
+<METHOD=GET>
+>>> METHOD.PUT
+<METHOD=PUT>
+>>>
+  
+ +

If it's necessary to look up constants based on user input of some sort, a + safe way to do it is using lookupByName:

+ +
+>>> METHOD.lookupByName('GET')
+<METHOD=GET>
+>>> METHOD.lookupByName('__doc__')
+Traceback (most recent call last):
+  File "<stdin>", line 1, in <module>
+  File "twisted/python/constants.py", line 145, in lookupByName
+    raise ValueError(name)
+ValueError: __doc__
+>>>
+  
+ +

As demonstrated, it is safe because any name not associated with a constant + (even those special names initialized by Python itself) will result + in ValueError being raised, not some other object not intended to + be used the way the constants are used.

+ +

The constants can also be enumerated using the iterconstants + method.

+ +
+>>> list(METHOD.iterconstants())
+[<METHOD=GET>, <METHOD=PUT>, <METHOD=POST>, <METHOD=DELETE>]
+>>>
+  
+ +

And constants can also be compared, either for equality or identity:

+ +
+>>> METHOD.GET is METHOD.GET
+True
+>>> METHOD.GET == METHOD.GET
+True
+>>> METHOD.GET is METHOD.PUT
+False
+>>> METHOD.GET == METHOD.PUT
+False
+>>>
+  
+ +

Custom functionality can also be associated with constants defined this + way. A subclass of Names may define class methods to implement + such functionality. Consider this redefinition of METHOD:

+ +

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

from twisted.python.constants import NamedConstant, Names +class METHOD(Names): + """ + Constants representing various HTTP request methods. + """ + GET = NamedConstant() + PUT = NamedConstant() + POST = NamedConstant() + DELETE = NamedConstant() + + @classmethod + def isIdempotent(cls, method): + """ + Return True if the given method is side-effect free, False otherwise. + """ + return method is cls.GET +
+ +

This functionality can be used as any class methods are used:

+ +
+>>> METHOD.isIdempotent(METHOD.GET)
+True
+>>> METHOD.isIdempotent(METHOD.POST)
+False
+>>>
+  
+ +

Constants With Values

+ +

Constants with a particular associated value are supported by + the Values base + class. Consider this example, in which some HTTP status code constants are + defined. +

+ +

1 +2 +3 +4 +5 +6 +7 +8 +

from twisted.python.constants import ValueConstant, Values +class STATUS(Values): + """ + Constants representing various HTTP status codes. + """ + OK = ValueConstant("200") + FOUND = ValueConstant("302") + NOT_FOUND = ValueConstant("404") +
+ +

As with Names, constants are accessed as attributes of the + class object:

+ +
+>>> STATUS.OK
+<STATUS=OK>
+>>> STATUS.FOUND
+<STATUS=FOUND>
+>>>
+  
+ +

Additionally, the values of the constants can be accessed using + the value attribute of one these objects:

+ +
+>>> STATUS.OK.value
+'200'
+>>>
+  
+ +

And as with Names, constants can be looked up by name:

+ +
+>>> STATUS.lookupByName('NOT_FOUND')
+<STATUS=NOT_FOUND>
+>>>
+  
+ +

Constants on a Values subclass can also be looked up by + value:

+ +
+>>> STATUS.lookupByValue('404')
+<STATUS=NOT_FOUND>
+>>> STATUS.lookupByValue('500')
+Traceback (most recent call last):
+  File "<stdin>", line 1, in <module>
+  File "twisted/python/constants.py", line 244, in lookupByValue
+      raise ValueError(value)
+ValueError: 500
+>>>
+  
+ +

Multiple constants may have the same value. If they do, + lookupByValue will find the one which is defined first.

+ +

Iteration is also supported:

+ +
+>>> list(STATUS.iterconstants())
+[<STATUS=OK>, <STATUS=FOUND>, <STATUS=NOT_FOUND>]
+>>>
+  
+ +

And constants can be compared for equality and identity:

+ +
+>>> STATUS.OK == STATUS.OK
+True
+>>> STATUS.OK is STATUS.OK
+True
+>>> STATUS.OK == STATUS.OK
+True
+>>> STATUS.OK is STATUS.NOT_FOUND
+False
+>>> STATUS.OK == STATUS.NOT_FOUND
+False
+>>>
+  
+ +

And, as with Names, a subclass of Values can + define methods:

+ +

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

from twisted.python.constants import ValueConstant, Values +class STATUS(Values): + """ + Constants representing various HTTP status codes. + """ + OK = ValueConstant("200") + NO_CONTENT = ValueConstant("204") + NOT_MODIFIED = ValueConstant("304") + NOT_FOUND = ValueConstant("404") + + @classmethod + def hasBody(cls, status): + """ + Return True if the given status is associated with a response body, + False otherwise. + """ + return status in (cls.NO_CONTENT, cls.NOT_MODIFIED) +
+ +

This functionality can be used as any class methods are used:

+ +
+>>> STATUS.hasBody(STATUS.OK)
+True
+>>> STATUS.hasBody(STATUS.NO_CONTENT)
+False
+>>>
+  
+ +

Constants As Flags

+ +

Integers are often used as a simple set for constants. The values for + these constants are assigned as powers of two so that bits in the integer can + be set to represent them. Individual bits are often called flags. + Flags supports this + use-case, including allowing constants with particular bits to be set, for + interoperability with other tools.

+ +

POSIX filesystem access control is traditionally done using a bitvector + defining which users and groups may perform which operations on a file. This + state might be represented using Flags as follows:

+ +

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

from twisted.python.constants import FlagConstant, Flags +class Permission(Flags): + """ + Constants representing user, group, and other access bits for reading, + writing, and execution. + """ + OTHER_EXECUTE = FlagConstant() + OTHER_WRITE = FlagConstant() + OTHER_READ = FlagConstant() + GROUP_EXECUTE = FlagConstant() + GROUP_WRITE = FlagConstant() + GROUP_READ = FlagConstant() + USER_EXECUTE = FlagConstant() + USER_WRITE = FlagConstant() + USER_READ = FlagConstant() +
+ +

+ As for the previous types of constants, these can be accessed as attributes + of the class object: +

+ +
+>>> Permission.USER_READ
+<Permission=USER_READ>
+>>> Permission.USER_WRITE
+<Permission=USER_WRITE>
+>>> Permission.USER_EXECUTE
+<Permission=USER_EXECUTE>
+>>>
+  
+ +

These constant objects also have a value attribute giving + their integer value:

+ +
+>>> Permission.USER_READ.value
+256
+>>>
+  
+ +

And these constants can be looked up by name or value:

+ +
+>>> Permission.lookupByName('USER_READ') is Permission.USER_READ
+True
+>>> Permission.lookupByValue(256) is Permission.USER_READ
+True
+>>>
+  
+ +

Constants can also be combined using the logical operators & + (and), | (or), and ^ + (exclusive or). +

+ +
+>>> Permission.USER_READ | Permission.USER_WRITE
+<Permission={USER_READ,USER_WRITE}>
+>>> (Permission.USER_READ | Permission.USER_WRITE) & Permission.USER_WRITE
+<Permission=USER_WRITE>
+>>> (Permission.USER_READ | Permission.USER_WRITE) ^ Permission.USER_WRITE
+<Permission=USER_READ>
+>>>
+  
+ +

The unary operator ~ (not) is also defined:

+ +
+>>> ~Permission.USER_READ
+<Permission={GROUP_EXECUTE,GROUP_READ,GROUP_WRITE,OTHER_EXECUTE,OTHER_READ,OTHER_WRITE,USER_EXECUTE,USER_WRITE}>
+>>>
+  
+ +

Constants created using these operators also have a value + attribute.

+ +
+>>> (~Permission.USER_WRITE).value
+383
+>>>
+  
+ +

+ Note the care taken to ensure the ~ operator is applied first + and the valueattribute is looked up second. +

+ +

A Flags subclass can also define methods, just as + a Names or Values subclass may. For example, + Permission might benefit from a method to format a flag as a + string in the traditional style. Consider this addition to that class:

+ +

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

from twisted.python import filepath +from twisted.python.constants import FlagConstant, Flags +class Permission(Flags): + ... + + @classmethod + def format(cls, permissions): + """ + Format permissions flags in the traditional 'rwxr-xr-x' style. + """ + return filepath.Permissions(permissions.value).shorthand() +
+ +

Use this like any other class method:

+ +
+>>> Permission.format(Permission.USER_READ | Permission.USER_WRITE | Permission.GROUP_READ | Permission.OTHER_READ)
+'rw-r--r--'
+>>>
+  
+
+ +

Index

+ Version: 12.1.0 + + \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/cred.html twisted-12.1.0/doc/howto/cred.html --- twisted-10.2.0/doc/howto/cred.html 2010-11-30 03:13:16.000000000 +0000 +++ twisted-12.1.0/doc/howto/cred.html 2012-06-04 08:46:18.000000000 +0000 @@ -31,11 +31,11 @@

To sketch out how this works - a Realm corresponds to an application domain and is in charge of avatars, which are network-accessible business logic objects. To connect this to an authentication database, a top-level object -called a Portal stores a +called a Portal stores a realm, and a number of credential checkers. Something that wishes to log in, -such as a Protocol, +such as a Protocol, stores a reference to the portal. Login consists of passing credentials and a -request interface (e.g. POP3's IMailbox) to the portal. The portal passes +request interface (e.g. POP3's IMailbox) to the portal. The portal passes the credentials to the appropriate credential checker, which returns an avatar ID. The ID is passed to the realm, which returns the appropriate avatar. For a Portal that has a realm that creates mailbox objects and a credential checker @@ -55,7 +55,7 @@

This is the the core of login, the point of integration between all the objects in the cred system. There is one concrete implementation of Portal, and no interface - it does a very -simple task. A Portal +simple task. A Portal associates one (1) Realm with a collection of CredentialChecker instances. (More on those later.)

@@ -64,16 +64,16 @@ This has only 2 methods -

Visual Explanation

@@ -279,7 +280,7 @@
  • When the result is ready, give it to the Deferred object. .callback(result) if the operation succeeded, .errback(failure) if it failed. Note that - failure is typically an instance of a twisted.python.failure.Failure + failure is typically an instance of a twisted.python.failure.Failure instance.
  • Deferred object triggers previously-added (call/err)back @@ -301,7 +302,7 @@ statements.
  • If an errback doesn't raise an exception or return a - twisted.python.failure.Failure + twisted.python.failure.Failure instance, switch to callback.
  • @@ -314,7 +315,7 @@ callbacks run, one after the other, as described above.

    If the errback is called instead of the callback (e.g. because a DB query -raised an error), then a twisted.python.failure.Failure is passed into the first +raised an error), then a twisted.python.failure.Failure is passed into the first errback (you can add multiple errbacks, just like with callbacks). You can think of your errbacks as being like except blocks of ordinary Python code.

    @@ -333,7 +334,7 @@ so be careful. Make sure your errbacks return a Failure (probably the one that was passed to it), or a meaningful return value for the next callback.

    -

    Also, twisted.python.failure.Failure instances have +

    Also, twisted.python.failure.Failure instances have a useful method called trap, allowing you to effectively do the equivalent of:

    @@ -371,7 +372,7 @@ it re-raises the error.

    There's another potential gotcha here. There's a -method twisted.internet.defer.Deferred.addCallbacks +method twisted.internet.defer.Deferred.addCallbacks which is similar to, but not exactly the same as, addCallback followed by addErrback. In particular, consider these two cases:

    1 @@ -398,18 +399,18 @@ d.addCallbacks(callback2, errback2)

    -

    If an error occurs in callback1, then for Case 1 +

    If an error occurs in callback1, then for Case 1 errback1 will be called with the failure. For Case 2, errback2 will be called. Be careful with your callbacks and errbacks.

    -

    What this means in a practical sense is in Case 1, "A" will -handle a success condition from getDeferredFromSomewhere, and -"B" will handle any errors that occur from either the upstream -source, or that occur in 'A'. In Case 2, "C"'s errback1 -will only handle an error condition raised by -getDeferredFromSomewhere, it will not do any handling of -errors raised in callback1.

    +

    What this means in a practical sense is in Case 1, the callback in line +A will handle a success condition from getDeferredFromSomewhere, +and the errback in line B will handle any errors that occur from either the +upstream source, or that occur in A. In Case 2, the errback in line C will +only handle an error condition raised by getDeferredFromSomewhere, +it will not do any handling of errors +raised in callback1.

    Unhandled Errors

    @@ -504,18 +505,17 @@ 4 5 6 -

    from twisted.internet import reactor +

    from twisted.internet import reactor, defer -def asynchronousIsValidUser(d, user): - d = Deferred() +def asynchronousIsValidUser(user): + d = defer.Deferred() reactor.callLater(2, d.callback, user in ["Alice", "Angus", "Agnes"]) return d -

    Our original implementation of authenticateUser expected -isValidUser to be synchronous, but now we need to change it to handle both +

    Our original implementation of authenticateUser expected isValidUser to be synchronous, but now we need to change it to handle both synchronous and asynchronous implementations of isValidUser. For this, we -use maybeDeferred to +use maybeDeferred to call isValidUser, ensuring that the result of isValidUser is a Deferred, even if isValidUser is a synchronous function:

    @@ -545,19 +545,19 @@

    -Now isValidUser could be either synchronousIsValidUser or -asynchronousIsValidUser. +Now isValidUser could be either synchronousIsValidUser or asynchronousIsValidUser.

    It is also possible to modify synchronousIsValidUser to return a Deferred, see Generating Deferreds for more information.

    +

    DeferredList

    Sometimes you want to be notified after several different events have all happened, rather than waiting for each one individually. For example, you may -want to wait for all the connections in a list to close. twisted.internet.defer.DeferredList is the way to do +want to wait for all the connections in a list to close. twisted.internet.defer.DeferredList is the way to do this.

    To create a DeferredList from multiple Deferreds, you simply pass a list of @@ -568,8 +568,7 @@ dl = defer.DeferredList([deferred1, deferred2, deferred3]) -

    You can now treat the DeferredList like an ordinary Deferred; you can call -addCallbacks and so on. The DeferredList will call its callback +

    You can now treat the DeferredList like an ordinary Deferred; you can call addCallbacks and so on. The DeferredList will call its callback when all the deferreds have completed. The callback will be called with a list of the results of the Deferreds it contains, like so:

    @@ -592,20 +591,40 @@ 17 18 19 -

    def printResult(result): +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +

    # A callback that unpacks and prints the results of a DeferredList +def printResult(result): for (success, value) in result: if success: print 'Success:', value else: print 'Failure:', value.getErrorMessage() + +# Create three deferreds. deferred1 = defer.Deferred() deferred2 = defer.Deferred() deferred3 = defer.Deferred() + +# Pack them into a DeferredList dl = defer.DeferredList([deferred1, deferred2, deferred3], consumeErrors=True) + +# Add our callback dl.addCallback(printResult) + +# Fire our three deferreds with various values. deferred1.callback('one') deferred2.errback(Exception('bang!')) deferred3.callback('three') + # At this point, dl will fire its callback, printing: # Success: one # Failure: bang! @@ -692,7 +711,7 @@

    Other behaviours

    DeferredList accepts three keyword arguments that modify its behaviour: -fireOnOneCallback, fireOnOneErrback and +fireOnOneCallback, fireOnOneErrback and consumeErrors. If fireOnOneCallback is set, the DeferredList will immediately call its callback as soon as any of its Deferreds call their callback. Similarly, fireOnOneErrback will call errback @@ -711,22 +730,59 @@ callbacks and errbacks of their Deferreds). Stopping errors at the DeferredList with this option will prevent Unhandled error in Deferred warnings from the Deferreds it contains without needing to add extra errbacks1. Passing a true value -for the consumeErrors parameter will not change the behavior of -fireOnOneCallback or fireOnOneErrback.

    +for the consumeErrors parameter will not change the behavior of fireOnOneCallback or fireOnOneErrback.

    + +

    gatherResults

    + +

    A common use for DeferredList is to "join" a number of parallel asynchronous +operations, finishing successfully if all of the operations were successful, or +failing if any one of the operations fails. In this case, twisted.internet.defer.gatherResults is a useful +shortcut:

    + +

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

    from twisted.internet import defer +d1 = defer.Deferred() +d2 = defer.Deferred() +d = defer.gatherResults([d1, d2], consumeErrors=True) +def printResult(result): + print result +d.addCallback(printResult) +d1.callback("one") +# nothing is printed yet; d is still awaiting completion of d2 +d2.callback("two") +# printResult prints ["one", "two"] +
    + +

    The consumeErrors argument has the same meaning as it does +for DeferredList: if true, it causes +gatherResults to consume any errors in the passed-in Deferreds. +Always use this argument unless you are adding further callbacks or errbacks to +the passed-in Deferreds, or unless you know that they will not fail. +Otherwise, a failure will result in an unhandled error being logged by Twisted. +This argument is available since Twisted 11.1.0.

    -

    Class Overview

    +

    Class Overview

    This is an overview API reference for Deferred from the point of using a Deferred returned by a function. It is not meant to be a substitute for the docstrings in the Deferred class, but can provide guidelines for its use.

    -

    There is a parallel overview of functions used by the Deferred's -creator in Generating Deferreds.

    +

    There is a parallel overview of functions used by the Deferred's creator in Generating Deferreds.

    -

    Basic Callback Functions

    +

    Basic Callback Functions

    • @@ -796,7 +852,7 @@
    -

    Chaining Deferreds

    +

    Chaining Deferreds

    If you need one Deferred to wait on another, all you need to do is return a Deferred from a method added to addCallbacks. Specifically, if you return @@ -825,7 +881,7 @@ -

    See also

    +

    See also

    1. Generating Deferreds, an introduction to @@ -837,6 +893,6 @@ DeferredList is confusing and usually avoided.

    Index

    - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/deferredindepth.html twisted-12.1.0/doc/howto/deferredindepth.html --- twisted-10.2.0/doc/howto/deferredindepth.html 2010-11-30 03:13:15.000000000 +0000 +++ twisted-12.1.0/doc/howto/deferredindepth.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,2183 +0,0 @@ - - -Twisted Documentation: Deferreds are beautiful! (A Tutorial) - - - - -

    Deferreds are beautiful! (A Tutorial)

    - -
    - - -

    Introduction

    - -

    Deferreds are quite possibly the single most confusing topic that a -newcomer to Twisted has to deal with. I am going to forgo the normal talk -about what deferreds are, what they aren't, and why they're used in Twisted. -Instead, I'm going show you the logic behind what they -do.

    - - -

    A deferred allows you to encapsulate the logic that you'd normally use to -make a series of function calls after receiving a result into a single object. -In the examples that follow, I'll first show you what's going to go on behind -the scenes in the deferred chain, then show you the deferred API calls that set -up that chain. All of these examples are runnable code, so feel free to play -around with them.

    - - -

    A simple example

    - -First, a simple example so that we have something to talk about: - -

    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 -

    #!/usr/bin/env python - -# Copyright (c) 2009 Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure, util - -""" -Here we have the simplest case, a single callback and a single errback. -""" - -num = 0 - -def handleFailure(f): - print "errback" - print "we got an exception: %s" % (f.getTraceback(),) - f.trap(RuntimeError) - -def handleResult(result): - global num; num += 1 - print "callback %s" % (num,) - print "\tgot result: %s" % (result,) - return "yay! handleResult was successful!" - - -def behindTheScenes(result): - # equivalent to d.callback(result) - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = handleResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - if not isinstance(result, failure.Failure): # ---- callback - pass - else: # ---- errback - try: - result = handleFailure(result) - except: - result = failure.Failure() - - -def deferredExample(): - d = defer.Deferred() - d.addCallback(handleResult) - d.addErrback(handleFailure) - - d.callback("success") - - -if __name__ == '__main__': - behindTheScenes("success") - print "\n-------------------------------------------------\n" - global num; num = 0 - deferredExample() -
    - -

    And the output: (since both methods in the example produce the same output, -it will only be shown once.)

    - -
    -callback 1
    -        got result: success
    -
    - -

    Here we have the simplest case. A deferred with a single callback and a -single errback. Normally, a function would create a deferred and hand it back -to you when you request an operation that needs to wait for an event for -completion. The object you called then does d.callback(result) -when the results are in. -

    - -

    The thing to notice is that there is only one result that is passed from -method to method, and that the result returned from a method is the argument -to the next method in the chain. In case of an exception, result is set to an -instance of Failure -that describes the exception.

    - -

    Errbacks

    -

    Failure in requested operation

    -

    Things don't always go as planned, and sometimes the function that -returned the deferred needs to alert the callback chain that an error -has occurred.

    - -

    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 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -

    #!/usr/bin/env python - -# Copyright (c) 2009 Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure, util - -""" -This example is analogous to a function calling .errback(failure) -""" - - -class Counter(object): - num = 0 - -def handleFailure(f): - print "errback" - print "we got an exception: %s" % (f.getTraceback(),) - f.trap(RuntimeError) - -def handleResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - return "yay! handleResult was successful!" - -def failAtHandlingResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - print "\tabout to raise exception" - raise RuntimeError, "whoops! we encountered an error" - - -def behindTheScenes(result): - if not isinstance(result, failure.Failure): # ---- callback - try: - result = handleResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - if not isinstance(result, failure.Failure): # ---- callback - pass - else: # ---- errback - try: - result = handleFailure(result) - except: - result = failure.Failure() - - -def deferredExample(result): - d = defer.Deferred() - d.addCallback(handleResult) - d.addCallback(failAtHandlingResult) - d.addErrback(handleFailure) - - d.errback(result) - - -if __name__ == '__main__': - result = None - try: - raise RuntimeError, "*doh*! failure!" - except: - result = failure.Failure() - behindTheScenes(result) - print "\n-------------------------------------------------\n" - Counter.num = 0 - deferredExample(result) -
    - -
    -errback
    -we got an exception: Traceback (most recent call last):
    ---- exception caught here ---
    -  File "deferred_ex1a.py", line 73, in ?
    -    raise RuntimeError, "*doh*! failure!"
    -exceptions.RuntimeError: *doh*! failure!
    -
    - -

    The important thing to note (as it will come up again in later examples) -is that the callback isn't touched, the failure goes right to the errback. -Also note that the errback trap()s the expected exception type. If you don't -trap the exception, an error will be logged when the deferred is -garbage-collected. -

    - - -

    Exceptions raised in callbacks

    - -

    Now let's see what happens when our callback raises an -exception

    - -

    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 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -

    #!/usr/bin/env python - -# Copyright (c) 2009 Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure, util - -""" -Here we have a slightly more involved case. The deferred is called back with a -result. the first callback returns a value, the second callback, however -raises an exception, which is handled by the errback. -""" - - -class Counter(object): - num = 0 - -def handleFailure(f): - print "errback" - print "we got an exception: %s" % (f.getTraceback(),) - f.trap(RuntimeError) - -def handleResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - return "yay! handleResult was successful!" - -def failAtHandlingResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - print "\tabout to raise exception" - raise RuntimeError, "whoops! we encountered an error" - - -def behindTheScenes(result): - if not isinstance(result, failure.Failure): # ---- callback - try: - result = handleResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = failAtHandlingResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - if not isinstance(result, failure.Failure): # ---- callback - pass - else: # ---- errback - try: - result = handleFailure(result) - except: - result = failure.Failure() - - -def deferredExample(): - d = defer.Deferred() - d.addCallback(handleResult) - d.addCallback(failAtHandlingResult) - d.addErrback(handleFailure) - - d.callback("success") - - -if __name__ == '__main__': - behindTheScenes("success") - print "\n-------------------------------------------------\n" - Counter.num = 0 - deferredExample() -
    - -

    And the output: (note, tracebacks will be edited slightly to conserve -space)

    - -
    -callback 1
    -        got result: success
    -callback 2
    -        got result: yay! handleResult was successful!
    -        about to raise exception
    -errback
    -we got an exception: Traceback (most recent call last):
    ---- <exception caught here> ---
    -  File "/home/slyphon/Projects/Twisted/trunk/twisted/internet/defer.py", line
    -326, in _runCallbacks
    -    self.result = callback(self.result, *args, **kw)
    -  File "./deferred_ex1.py", line 32, in failAtHandlingResult
    -    raise RuntimeError, "whoops! we encountered an error"
    -exceptions.RuntimeError: whoops! we encountered an error
    -
    - -

    If your callback raises an exception, the next method to be called will be -the next errback in your chain.

    - - -

    Exceptions will only be handled by errbacks

    - -

    If a callback raises an exception the next method to be called will be next -errback in the chain. If the chain is started off with a failure, the first -method to be called will be the first errback.

    - -

    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 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -

    #!/usr/bin/env python - -# Copyright (c) 2009 Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure, util - -""" -This example shows an important concept that many deferred newbies -(myself included) have trouble understanding. - -when an error occurs in a callback, the first errback after the error -occurs will be the next method called. (in the next example we'll -see what happens in the 'chain' after an errback). -""" - -class Counter(object): - num = 0 - -def handleFailure(f): - print "errback" - print "we got an exception: %s" % (f.getTraceback(),) - f.trap(RuntimeError) - -def handleResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - return "yay! handleResult was successful!" - -def failAtHandlingResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - print "\tabout to raise exception" - raise RuntimeError, "whoops! we encountered an error" - - - -def behindTheScenes(result): - # equivalent to d.callback(result) - - # now, let's make the error happen in the first callback - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = failAtHandlingResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - # note: this callback will be skipped because - # result is a failure - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = handleResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - if not isinstance(result, failure.Failure): # ---- callback - pass - else: # ---- errback - try: - result = handleFailure(result) - except: - result = failure.Failure() - - - -def deferredExample(): - d = defer.Deferred() - d.addCallback(failAtHandlingResult) - d.addCallback(handleResult) - d.addErrback(handleFailure) - - d.callback("success") - - -if __name__ == '__main__': - behindTheScenes("success") - print "\n-------------------------------------------------\n" - Counter.num = 0 - deferredExample() -
    - -
    -callback 1
    -        got result: success
    -        about to raise exception
    -errback
    -we got an exception: Traceback (most recent call last):
    -  File "./deferred_ex2.py", line 85, in ?
    -    nonDeferredExample("success")
    ---- <exception caught here> ---
    -  File "./deferred_ex2.py", line 46, in nonDeferredExample
    -    result = failAtHandlingResult(result)
    -  File "./deferred_ex2.py", line 35, in failAtHandlingResult
    -    raise RuntimeError, "whoops! we encountered an error"
    -exceptions.RuntimeError: whoops! we encountered an error
    -
    - -

    You can see that our second callback, handleResult was not called because -failAtHandlingResult raised an exception

    - -

    Handling an exception and continuing on

    - -

    In this example, we see an errback handle an exception raised in the -preceeding callback. Take note that it could just as easily been an exception -from any other preceeding method. You'll see that after the -exception is handled in the errback (i.e. the errback does not return a -failure or raise an exception) the chain continues on with the next -callback.

    - -

    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 - 61 - 62 - 63 - 64 - 65 - 66 - 67 - 68 - 69 - 70 - 71 - 72 - 73 - 74 - 75 - 76 - 77 - 78 - 79 - 80 - 81 - 82 - 83 - 84 - 85 - 86 - 87 - 88 - 89 - 90 - 91 - 92 - 93 - 94 - 95 - 96 - 97 - 98 - 99 -100 -

    #!/usr/bin/env python - -# Copyright (c) 2009 Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure, util - -""" -Now we see how an errback can handle errors. if an errback -does not raise an exception, the next callback in the chain -will be called. -""" - -class Counter(object): - num = 0 - - -def handleFailure(f): - print "errback" - print "we got an exception: %s" % (f.getTraceback(),) - f.trap(RuntimeError) - return "okay, continue on" - -def handleResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - return "yay! handleResult was successful!" - -def failAtHandlingResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - print "\tabout to raise exception" - raise RuntimeError, "whoops! we encountered an error" - -def callbackAfterErrback(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - - - -def behindTheScenes(result): - # equivalent to d.callback(result) - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = handleResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = failAtHandlingResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - if not isinstance(result, failure.Failure): # ---- callback - pass - else: # ---- errback - try: - result = handleFailure(result) - except: - result = failure.Failure() - - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = callbackAfterErrback(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - -def deferredExample(): - d = defer.Deferred() - d.addCallback(handleResult) - d.addCallback(failAtHandlingResult) - d.addErrback(handleFailure) - d.addCallback(callbackAfterErrback) - - d.callback("success") - - -if __name__ == '__main__': - behindTheScenes("success") - print "\n-------------------------------------------------\n" - Counter.num = 0 - deferredExample() -
    - -
    -callback 1
    -        got result: success
    -callback 2
    -        got result: yay! handleResult was successful!
    -        about to raise exception
    -errback
    -we got an exception: Traceback (most recent call last):
    -  File "./deferred_ex3.py", line 97, in <module>
    -    deferredExample()
    -  File "./deferred_ex3.py", line 90, in deferredExample
    -    d.callback("success")
    -  File "/home/slyphon/Projects/Twisted/trunk/twisted/internet/defer.py", line 243, in callback
    -    self._startRunCallbacks(result)
    -  File "/home/slyphon/Projects/Twisted/trunk/twisted/internet/defer.py", line 312, in _startRunCallbacks
    -    self._runCallbacks()
    ---- <exception caught here> ---
    -  File "/home/slyphon/Projects/Twisted/trunk/twisted/internet/defer.py", line 328, in _runCallbacks
    -    self.result = callback(self.result, *args, **kw)
    -  File "./deferred_ex3.py", line 34, in failAtHandlingResult
    -    raise RuntimeError, "whoops! we encountered an error"
    -exceptions.RuntimeError: whoops! we encountered an error
    -
    -callback 3
    -        got result: okay, continue on
    -
    - -

    addBoth: the deferred version of finally

    - -

    Now we see how deferreds do finally, with .addBoth. The -callback that gets added as addBoth will be called if the result is a failure -or non-failure. We'll also see in this example, that our doThisNoMatterWhat() -method follows a common idiom in deferred callbacks by acting as a passthru, -returning the value that it received to allow processing the chain to -continue, but appearing transparent in terms of the result.

    - -

    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 - 61 - 62 - 63 - 64 - 65 - 66 - 67 - 68 - 69 - 70 - 71 - 72 - 73 - 74 - 75 - 76 - 77 - 78 - 79 - 80 - 81 - 82 - 83 - 84 - 85 - 86 - 87 - 88 - 89 - 90 - 91 - 92 - 93 - 94 - 95 - 96 - 97 - 98 - 99 -100 -101 -102 -103 -104 -

    #!/usr/bin/env python - -# Copyright (c) 2009 Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure, util - -""" -Now we'll see what happens when you use 'addBoth'. -""" - -class Counter(object): - num = 0 - - -def handleFailure(f): - print "errback" - print "we got an exception: %s" % (f.getTraceback(),) - f.trap(RuntimeError) - return "okay, continue on" - -def handleResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - return "yay! handleResult was successful!" - -def failAtHandlingResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - print "\tabout to raise exception" - raise RuntimeError, "whoops! we encountered an error" - -def doThisNoMatterWhat(arg): - Counter.num += 1 - print "both %s" % (Counter.num,) - print "\tgot argument %r" % (arg,) - print "\tdoing something very important" - # we pass the argument we received to the next phase here - return arg - - - -def behindTheScenes(result): - # equivalent to d.callback(result) - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = handleResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = failAtHandlingResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - # ---- this is equivalent to addBoth(doThisNoMatterWhat) - - if not isinstance(result, failure.Failure): - try: - result = doThisNoMatterWhat(result) - except: - result = failure.Failure() - else: - try: - result = doThisNoMatterWhat(result) - except: - result = failure.Failure() - - - if not isinstance(result, failure.Failure): # ---- callback - pass - else: # ---- errback - try: - result = handleFailure(result) - except: - result = failure.Failure() - - -def deferredExample(): - d = defer.Deferred() - d.addCallback(handleResult) - d.addCallback(failAtHandlingResult) - d.addBoth(doThisNoMatterWhat) - d.addErrback(handleFailure) - - d.callback("success") - - -if __name__ == '__main__': - behindTheScenes("success") - print "\n-------------------------------------------------\n" - Counter.num = 0 - deferredExample() -
    - -
    -callback 1
    -        got result: success
    -callback 2
    -        got result: yay! handleResult was successful!
    -        about to raise exception
    -both 3
    -        got argument <twisted.python.failure.Failure exceptions.RuntimeError>
    -        doing something very important
    -errback
    -we got an exception: Traceback (most recent call last):
    ---- <exception caught here> ---
    -  File "/home/slyphon/Projects/Twisted/trunk/twisted/internet/defer.py", line
    -326, in _runCallbacks
    -    self.result = callback(self.result, *args, **kw)
    -  File "./deferred_ex4.py", line 32, in failAtHandlingResult
    -    raise RuntimeError, "whoops! we encountered an error"
    -exceptions.RuntimeError: whoops! we encountered an error
    -
    - -

    You can see that the errback is called, (and consequently, the failure is -trapped). This is because doThisNoMatterWhat method returned the value it -received, a failure.

    - -

    addCallbacks: decision making based on previous success or failure

    - -

    As we've been seeing in the examples, the callback is a pair of -callback/errback. Using addCallback or addErrback is actually a special case -where one of the pair is a pass statement. If you want to make a decision -based on whether or not the previous result in the chain was a failure or not -(which is very rare, but included here for completeness), you use -addCallbacks. Note that this is not the same thing as an -addCallback followed by an addErrback.

    - - -

    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 - 61 - 62 - 63 - 64 - 65 - 66 - 67 - 68 - 69 - 70 - 71 - 72 - 73 - 74 - 75 - 76 - 77 - 78 - 79 - 80 - 81 - 82 - 83 - 84 - 85 - 86 - 87 - 88 - 89 - 90 - 91 - 92 - 93 - 94 - 95 - 96 - 97 - 98 - 99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -

    #!/usr/bin/env python - -# Copyright (c) 2009 Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure, util - -""" -Now comes the more nuanced addCallbacks, which allows us to make a -yes/no (branching) decision based on whether the result at a given point is -a failure or not. -""" - -class Counter(object): - num = 0 - - -def handleFailure(f): - print "errback" - print "we got an exception: %s" % (f.getTraceback(),) - f.trap(RuntimeError) - return "okay, continue on" - -def handleResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - return "yay! handleResult was successful!" - -def failAtHandlingResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - print "\tabout to raise exception" - raise RuntimeError, "whoops! we encountered an error" - -def yesDecision(result): - Counter.num += 1 - print "yes decision %s" % (Counter.num,) - print "\twasn't a failure, so we can plow ahead" - return "go ahead!" - -def noDecision(result): - Counter.num += 1 - result.trap(RuntimeError) - print "no decision %s" % (Counter.num,) - print "\t*doh*! a failure! quick! damage control!" - return "damage control successful!" - - - -def behindTheScenes(result): - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = failAtHandlingResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - # this is equivalent to addCallbacks(yesDecision, noDecision) - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = yesDecision(result) - except: - result = failure.Failure() - else: # ---- errback - try: - result = noDecision(result) - except: - result = failure.Failure() - - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = handleResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - # this is equivalent to addCallbacks(yesDecision, noDecision) - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = yesDecision(result) - except: - result = failure.Failure() - else: # ---- errback - try: - result = noDecision(result) - except: - result = failure.Failure() - - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = handleResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - if not isinstance(result, failure.Failure): # ---- callback - pass - else: # ---- errback - try: - result = handleFailure(result) - except: - result = failure.Failure() - - -def deferredExample(): - d = defer.Deferred() - d.addCallback(failAtHandlingResult) - d.addCallbacks(yesDecision, noDecision) # noDecision will be called - d.addCallback(handleResult) # - A - - d.addCallbacks(yesDecision, noDecision) # yesDecision will be called - d.addCallback(handleResult) - d.addErrback(handleFailure) - - d.callback("success") - - -if __name__ == '__main__': - behindTheScenes("success") - print "\n-------------------------------------------------\n" - Counter.num = 0 - deferredExample() -
    - -
    -callback 1
    -        got result: success
    -        about to raise exception
    -no decision 2
    -        *doh*! a failure! quick! damage control!
    -callback 3
    -        got result: damage control successful!
    -yes decision 4
    -        wasn't a failure, so we can plow ahead
    -callback 5
    -        got result: go ahead!
    -
    - -

    Notice that our errback is never called. The noDecision method returns a -non-failure so processing continues with the next callback. If we wanted to -skip the callback at "- A -" because of the error, but do some kind of -processing in response to the error, we would have used a passthru, and -returned the failure we received, as we see in this next example:

    - -

    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 - 61 - 62 - 63 - 64 - 65 - 66 - 67 - 68 - 69 - 70 - 71 - 72 - 73 - 74 - 75 - 76 - 77 - 78 - 79 - 80 - 81 - 82 - 83 - 84 - 85 - 86 - 87 - 88 - 89 - 90 - 91 - 92 - 93 - 94 - 95 - 96 - 97 - 98 - 99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -

    #!/usr/bin/env python - -# Copyright (c) 2009 Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure, util - -""" -Now comes the more nuanced addCallbacks, which allows us to make a -yes/no (branching) decision based on whether the result at a given point is -a failure or not. - -here, we return the failure from noDecisionPassthru, the errback argument to -the first addCallbacks method invocation, and see what happens. -""" - -class Counter(object): - num = 0 - - -def handleFailure(f): - print "errback" - print "we got an exception: %s" % (f.getTraceback(),) - f.trap(RuntimeError) - return "okay, continue on" - -def handleResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - return "yay! handleResult was successful!" - -def failAtHandlingResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - print "\tabout to raise exception" - raise RuntimeError, "whoops! we encountered an error" - -def yesDecision(result): - Counter.num += 1 - print "yes decision %s" % (Counter.num,) - print "\twasn't a failure, so we can plow ahead" - return "go ahead!" - -def noDecision(result): - Counter.num += 1 - result.trap(RuntimeError) - print "no decision %s" % (Counter.num,) - print "\t*doh*! a failure! quick! damage control!" - return "damage control successful!" - -def noDecisionPassthru(result): - Counter.num += 1 - print "no decision %s" % (Counter.num,) - print "\t*doh*! a failure! don't know what to do, returning failure!" - return result - - -def behindTheScenes(result): - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = failAtHandlingResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - # this is equivalent to addCallbacks(yesDecision, noDecision) - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = yesDecision(result) - except: - result = failure.Failure() - else: # ---- errback - try: - result = noDecisionPassthru(result) - except: - result = failure.Failure() - - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = handleResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - # this is equivalent to addCallbacks(yesDecision, noDecision) - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = yesDecision(result) - except: - result = failure.Failure() - else: # ---- errback - try: - result = noDecision(result) - except: - result = failure.Failure() - - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = handleResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - if not isinstance(result, failure.Failure): # ---- callback - pass - else: # ---- errback - try: - result = handleFailure(result) - except: - result = failure.Failure() - - -def deferredExample(): - d = defer.Deferred() - d.addCallback(failAtHandlingResult) - - # noDecisionPassthru will be called - d.addCallbacks(yesDecision, noDecisionPassthru) - d.addCallback(handleResult) # - A - - - # noDecision will be called - d.addCallbacks(yesDecision, noDecision) - d.addCallback(handleResult) # - B - - d.addErrback(handleFailure) - - d.callback("success") - - -if __name__ == '__main__': - behindTheScenes("success") - print "\n-------------------------------------------------\n" - Counter.num = 0 - deferredExample() -
    - -
    -callback 1
    -        got result: success
    -        about to raise exception
    -no decision 2
    -        *doh*! a failure! don't know what to do, returning failure!
    -no decision 3
    -        *doh*! a failure! quick! damage control!
    -callback 4
    -        got result: damage control successful!
    -
    - -

    Two things to note here. First, "- A -" was skipped, like we wanted it to, -and the second thing is that after "- A -", noDecision is called, because -it is the next errback that exists in the chain. It returns a -non-failure, so processing continues with the next callback at "- B -", and -the errback at the end of the chain is never called

    - -

    Hints, tips, common mistakes, and miscellaney

    - -

    The deferred callback chain is stateful

    - -

    A deferred that has been called back will call its addCallback and -addErrback methods as appropriate in the order they are added, when they are -added. So we see in the following example, deferredExample1 and -deferredExample2 are equivalent. The first sets up the processing chain -beforehand and then executes it, the other executes the chain as it is being -constructed. This is because deferreds are stateful.

    - -

    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 -61 -

    #!/usr/bin/env python - -# Copyright (c) 2009 Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure, util - -""" -The deferred callback chain is stateful, and can be executed before -or after all callbacks have been added to the chain -""" - -class Counter(object): - num = 0 - -def handleFailure(f): - print "errback" - print "we got an exception: %s" % (f.getTraceback(),) - f.trap(RuntimeError) - -def handleResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - return "yay! handleResult was successful!" - -def failAtHandlingResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - print "\tabout to raise exception" - raise RuntimeError, "whoops! we encountered an error" - -def deferredExample1(): - # this is another common idiom, since all add* methods - # return the deferred instance, you can just chain your - # calls to addCallback and addErrback - - d = defer.Deferred().addCallback(failAtHandlingResult - ).addCallback(handleResult - ).addErrback(handleFailure) - - d.callback("success") - -def deferredExample2(): - d = defer.Deferred() - - d.callback("success") - - d.addCallback(failAtHandlingResult) - d.addCallback(handleResult) - d.addErrback(handleFailure) - - -if __name__ == '__main__': - deferredExample1() - print "\n-------------------------------------------------\n" - Counter.num = 0 - deferredExample2() -
    - -
    -callback 1
    -        got result: success
    -        about to raise exception
    -errback
    -we got an exception: Traceback (most recent call last):
    ---- <exception caught here> ---
    -  File "/home/slyphon/Projects/Twisted/trunk/twisted/internet/defer.py", line
    -326, in _runCallbacks
    -    self.result = callback(self.result, *args, **kw)
    -  File "./deferred_ex7.py", line 35, in failAtHandlingResult
    -    raise RuntimeError, "whoops! we encountered an error"
    -exceptions.RuntimeError: whoops! we encountered an error
    -
    -
    --------------------------------------------------
    -
    -callback 1
    -        got result: success
    -        about to raise exception
    -errback
    -we got an exception: Traceback (most recent call last):
    ---- <exception caught here> ---
    -  File "/home/slyphon/Projects/Twisted/trunk/twisted/internet/defer.py", line
    -326, in _runCallbacks
    -    self.result = callback(self.result, *args, **kw)
    -  File "./deferred_ex7.py", line 35, in failAtHandlingResult
    -    raise RuntimeError, "whoops! we encountered an error"
    -exceptions.RuntimeError: whoops! we encountered an error
    -
    - -

    This example also shows you the common idiom of chaining calls to -addCallback and addErrback. -

    - -

    Don't call .callback() on deferreds you didn't create!

    - -

    It is an error to reinvoke deferreds callback or errback method, therefore -if you didn't create a deferred, do not under any -circumstances call its callback or errback. doing so will raise -an exception

    - -

    Callbacks can return deferreds

    - -

    If you need to call a method that returns a deferred within your callback -chain, just return that deferred, and the result of the secondary deferred's -processing chain will become the result that gets passed to the next callback -of the primary deferreds processing chain

    - -

    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 -61 -62 -63 -64 -65 -66 -

    #!/usr/bin/env python - -# Copyright (c) 2009 Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure, util - - -class Counter(object): - num = 0 - let = 'a' - - def incrLet(cls): - cls.let = chr(ord(cls.let) + 1) - incrLet = classmethod(incrLet) - - -def handleFailure(f): - print "errback" - print "we got an exception: %s" % (f.getTraceback(),) - return f - -def subCb_B(result): - print "sub-callback %s" % (Counter.let,) - Counter.incrLet() - s = " beautiful!" - print "\tadding %r to result" % (s,) - result += s - return result - -def subCb_A(result): - print "sub-callback %s" % (Counter.let,) - Counter.incrLet() - s = " are " - print "\tadding %r to result" % (s,) - result += s - return result - -def mainCb_1(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - result += " Deferreds " - - d = defer.Deferred().addCallback(subCb_A - ).addCallback(subCb_B) - d.callback(result) - return d - -def mainCb_2(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - - -def deferredExample(): - d = defer.Deferred().addCallback(mainCb_1 - ).addCallback(mainCb_2) - - d.callback("I hope you'll agree: ") - - -if __name__ == '__main__': - deferredExample() -
    - -
    -callback 1
    -        got result: I hope you'll agree: 
    -sub-callback a
    -        adding ' are ' to result
    -sub-callback b
    -        adding ' beautiful!' to result
    -callback 2
    -        got result: I hope you'll agree:  Deferreds  are  beautiful!
    -
    - -

    Conclusion

    - -

    Deferreds can be confusing, but only because they're so elegant and simple. -There is a lot of logical power that can expressed with a deferred's -processing chain, and once you see what's going on behind the curtain, it's a -lot easier to understand how to make use of what deferreds have to offer.

    - -
    - -

    Index

    - Version: 10.2.0 - - \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/design.html twisted-12.1.0/doc/howto/design.html --- twisted-10.2.0/doc/howto/design.html 2010-11-30 03:13:18.000000000 +0000 +++ twisted-12.1.0/doc/howto/design.html 2012-06-04 08:46:21.000000000 +0000 @@ -133,7 +133,7 @@ they also follow this approach. You can use them independently because they are not stuck to each other. They communicate in well-defined ways, and only when that -communication provides some additional feature. Thus, you can use twisted.web with twisted.enterprise, but neither requires the other, because +communication provides some additional feature. Thus, you can use twisted.web with twisted.enterprise, but neither requires the other, because they are integrated around the concept of Deferreds.

    Your Twisted applications should follow this style as much as possible. @@ -234,24 +234,21 @@

    The QOTDFactory's role is to specify to the Twisted framework how to create a Protocol instance -that will handle the connection. Twisted will not instantiate a QOTDFactory; you will do that yourself later, in a -twistd plug-in. +that will handle the connection. Twisted will not instantiate a QOTDFactory; you will do that yourself later, in a twistd plug-in.

    -

    Note: you can read more specifics of Protocol and -Factory in the Writing +

    Note: you can read more specifics of Protocol and Factory in the Writing Servers HOWTO.

    Once we have an abstraction -- a Quoter -- and we have a mechanism to connect it to the network -- the QOTD protocol -- the next thing to do is to put the last link in the chain of functionality between -abstraction and user. This last link will allow a user to choose a -Quoter and configure the protocol. Writing this configuration is +abstraction and user. This last link will allow a user to choose a Quoter and configure the protocol. Writing this configuration is covered in the Application HOWTO.

    Index

    - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/dirdbm.html twisted-12.1.0/doc/howto/dirdbm.html --- twisted-10.2.0/doc/howto/dirdbm.html 2010-11-30 03:13:14.000000000 +0000 +++ twisted-12.1.0/doc/howto/dirdbm.html 2012-06-04 08:46:20.000000000 +0000 @@ -12,14 +12,14 @@

    dirdbm.DirDBM

    -

    twisted.persisted.dirdbm.DirDBM is a DBM-like storage system. +

    twisted.persisted.dirdbm.DirDBM is a DBM-like storage system. That is, it stores mappings between keys and values, like a Python dictionary, except that it stores the values in files in a directory - each entry is a different file. The keys must always be strings, -as are the values. Other than that, DirDBM +as are the values. Other than that, DirDBM objects act just like Python dictionaries.

    -

    DirDBM is useful for cases +

    DirDBM is useful for cases when you want to store small amounts of data in an organized fashion, without having to deal with the complexity of a RDBMS or other sophisticated database. It is simple, easy to use, cross-platform, and doesn't require any external C libraries, unlike @@ -41,12 +41,11 @@

    dirdbm.Shelf

    Sometimes it is neccessary to persist more complicated objects than strings. -With some care, dirdbm.Shelf +With some care, dirdbm.Shelf can transparently persist them. Shelf works exactly like DirDBM, except that the values (but not the keys) can be arbitrary picklable objects. However, -notice that mutating an object after it has been stored in the -Shelf has no effect on the Shelf. +notice that mutating an object after it has been stored in the Shelf has no effect on the Shelf. When mutating objects, it is neccessary to explictly store them back in the Shelf afterwards:

    @@ -72,6 +71,6 @@

    Index

    - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/endpoints.html twisted-12.1.0/doc/howto/endpoints.html --- twisted-10.2.0/doc/howto/endpoints.html 2010-11-30 03:13:16.000000000 +0000 +++ twisted-12.1.0/doc/howto/endpoints.html 2012-06-04 08:46:20.000000000 +0000 @@ -6,7 +6,7 @@

    Getting Connected with Endpoints

    - +
    @@ -18,8 +18,8 @@ that is usually invisible to the application passing data across it. Twisted strives to make the nature of the "wire" as transparent as possible, with highly abstract interfaces for passing and receiving data, -such as ITransport -and IProtocol.

    +such as ITransport +and IProtocol.

    However, the application can't be completely ignorant of the wire. In particular, it must do something to start the connection, and @@ -30,7 +30,7 @@ connect to it, and the other side does the connecting.

    In Twisted 10.1, several new interfaces were introduced to describe -each of these roles for stream-oriented connections: IServerStreamEndpoint and IClientStreamEndpoint. +each of these roles for stream-oriented connections: IStreamServerEndpoint and IStreamClientEndpoint. The word "stream", in this case, refers to endpoints which treat a connection as a continuous stream of bytes, rather than a sequence of discrete datagrams: TCP is a "stream" protocol whereas UDP is a "datagram" @@ -47,7 +47,7 @@ endpoints directly. However, in most programs, you will want to allow the user to specify where to listen or connect, in a way which will allow the user to request different strategies, without having to adjust your -program. In order to allow this, you should use clientFromString or serverFromString.

    +program. In order to allow this, you should use clientFromString or serverFromString.

    There's Not Much To It

    @@ -65,9 +65,9 @@

    Servers and Stopping

    -

    IServerStreamEndpoint.listen -returns a Deferred -that fires with an IListeningPort. +

    IStreamServerEndpoint.listen +returns a Deferred +that fires with an IListeningPort. Note that this deferred may errback. The most common cause of such an error would be that another program is already using the requested port number, but the exact cause may vary depending on what type of endpoint you are @@ -81,7 +81,7 @@ response to anything other than a full server shutdown (reactor.stop and / or twistd will usually handle that case for you), make sure you keep a reference around to that listening port object so you can -call IListeningPort.stopListening +call IListeningPort.stopListening on it. Finally, keep in mind that stopListening itself returns a Deferred, and the port may not have fully stopped listening until that Deferred has fired.

    @@ -94,22 +94,22 @@

    Clients and Cancelling

    -

    IClientStreamEndpoint.connect +

    IStreamClientEndpoint.connect will connect your protocol factory to a new outgoing connection attempt. It returns a Deferred which fires with the IProtocol returned from the factory's buildProtocol method.

    -

    Connection attempts may fail, and so that Deferred may also errback. If it does so, +

    Connection attempts may fail, and so that Deferred may also errback. If it does so, you will have to try again; your protocol won't be constructed, and no further attempts will be made.

    Connection attempts may also take a long time, and your users may become bored and wander off. If this happens, and your code decides, for whatever reason, that you've been waiting for the connection too long, you -can call Deferred.cancel -on the Deferred returned from connect, and the +can call Deferred.cancel +on the Deferred returned from connect, and the underlying machinery should give up on the connection. This should cause the -Deferred to errback, usually with CancelledError; although you should +Deferred to errback, usually with CancelledError; although you should consult the documentation for your particular endpoint type to see if it may do something different.

    @@ -121,7 +121,7 @@

    1 2

    attempt = myEndpoint.connect(myFactory) -reactor.callback(30, attempt.cancel) +reactor.callLater(30, attempt.cancel)

    @@ -141,7 +141,7 @@

    If you are writing an application and you need to construct endpoints yourself, you can allow users to specify arbitrary endpoints -described by a string using the clientFromString and serverFromString +described by a string using the clientFromString and serverFromString APIs. Since these APIs just take a string, they provide flexibility: if Twisted adds support for new types of endpoints (for example, IPv6 endpoints, or WebSocket endpoints), your application will automatically be @@ -152,7 +152,7 @@

    For many use-cases, especially the common case of a twistd plugin which runs a long-running server that just binds a simple port, you might not want to use the endpoints APIs directly. Instead, you may want to -construct an IService, using strports.service , which will fit +construct an IService, using strports.service , which will fit neatly into the required structure of the twistd plugin API . This doesn't give your application much control - the port starts listening at startup and stops listening at shutdown - but it does @@ -160,13 +160,72 @@ application will support.

    It is, however, almost always preferable to use an endpoint rather -than calling a lower-level APIs like connectTCP, listenTCP, +than calling a lower-level APIs like connectTCP, listenTCP, etc, directly. By accepting an arbitrary endpoint rather than requiring a specific reactor interface, you leave your application open to lots of interesting transport-layer extensibility for the future.

    + +

    Endpoint Types Included With Twisted

    + +

    The parser used by clientFromString and +serverFromString is extensible via third-party plugins, so the +endpoints available on your system depend on what packages you have installed. +However, Twisted itself includes a set of basic endpoints that will always be +available.

    + +

    Clients

    + +
      +
    • TCP. Supported arguments: host, port, timeout. timeout is optional. For + example, tcp:host=twistedmatrix.com:port=80:timeout=15. +
    • +
    • SSL. All TCP arguments are supported, plus: certKey, privateKey, + caCertsDir. certKey (optional) gives a filesystem path to a certificate (PEM + format). privateKey (optional) gives a filesystem path to a a private key + (PEM format). caCertsDir (optional) gives a filesystem path to a directory + containing trusted CA certificates to use to verify the server certificate. + For example, + ssl:host=twistedmatrix.com:port=443:caCertsDir=/etc/ssl/certs. +
    • +
    • UNIX. Supported arguments: path, timeout, checkPID. path gives a + filesystem path to a listening UNIX domain socket server. checkPID (optional) + enables a check of the lock file Twisted-based UNIX domain socket servers use + to prove they are still running. For + example, unix:path=/var/run/web.sock. +
    • +
    + +

    Servers

    + +
      +
    • TCP. Supported arguments: port, interface, backlog. interface and + backlog are optional. interface is an IP address to bind to. For example, + tcp:port=80:interface=192.168.1.1. +
    • +
    • SSL. All TCP arguments are supported, plus: certKey, privateKey, and + sslmethod. certKey (optional, defaults to the value of privateKey) gives a + filesystem path to a certificate (PEM format). privateKey gives a filesystem + path to a a private key (PEM format). sslmethod indicates which SSL/TLS + version to use (a value like TLSv1_METHOD). For example, + ssl:port=443:privateKey=/etc/ssl/server.pem:sslmethod=SSLv3_METHOD. +
    • +
    • UNIX. Supported arguments: address, mode, backlog, lockfile. address + gives a filesystem path to listen on with a UNIX domain socket server. mode + (optional) gives the filesystem permission/mode (in octal) to apply to that + socket. lockfile enables use of a separate lock file to prove the server is + still running. For example, unix:address=/var/run/web.sock:lockfile=1. +
    • +
    • systemd. Supported arguments: domain, index. domain indicates which + socket domain the inherited file descriptor belongs to (eg INET, INET6). + index indicates an offset into the array of file descriptors which have been + inherited from systemd. For + example, systemd:domain=INET6:index=3. +
    • +
    +

    Index

    - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/gendefer.html twisted-12.1.0/doc/howto/gendefer.html --- twisted-10.2.0/doc/howto/gendefer.html 2010-11-30 03:13:18.000000000 +0000 +++ twisted-12.1.0/doc/howto/gendefer.html 2012-06-04 08:46:19.000000000 +0000 @@ -11,7 +11,7 @@ -

    Deferred objects are +

    Deferred objects are signals that a function you have called does not yet have the data you want available. When a function returns a Deferred object, your calling function attaches callbacks to it to handle the data when available.

    @@ -45,7 +45,7 @@

    Run success callbacks with the given result. This can only be run once. Later calls to this or - errback will raise twisted.internet.defer.AlreadyCalledError. + errback will raise twisted.internet.defer.AlreadyCalledError. If further callbacks or errbacks are added after this point, addCallbacks will run the callbacks immediately.

    @@ -55,7 +55,7 @@

    Run error callbacks with the given failure. This can only be run once. Later calls to this or - callback will raise twisted.internet.defer.AlreadyCalledError. + callback will raise twisted.internet.defer.AlreadyCalledError. If further callbacks or errbacks are added after this point, addCallbacks will run the callbacks immediately.

    @@ -161,8 +161,7 @@ d.addCallback(printNumber) -

    You will notice that despite creating a Deferred in the -largeFibonnaciNumber function, these things happened:

    +

    You will notice that despite creating a Deferred in the largeFibonnaciNumber function, these things happened:

    -
    Adapter
    +
    Adapter
    An object whose sole purpose is to implement an Interface for another object. See Interfaces and Adapters.
    -
    Application
    +
    Application
    - A twisted.application.service.Application. There are + A twisted.application.service.Application. There are HOWTOs on creating and manipulating them as a system-administrator, as well as using them in your code. @@ -34,19 +34,19 @@
    Avatar
    (from Twisted Cred) business logic for specific user. - For example, in PB these are perspectives, in pop3 these + For example, in PB these are perspectives, in POP3 these are mailboxes, and so on.
    -
    Banana
    +
    Banana
    The low-level data marshalling layer of Twisted Spread. - See twisted.spread.banana. + See twisted.spread.banana.
    -
    Broker
    +
    Broker
    - A twisted.spread.pb.Broker, the object request + A twisted.spread.pb.Broker, the object request broker for Twisted Spread.
    @@ -59,37 +59,37 @@
    component
    - A special kind of (persistent) Adapter that works with a twisted.python.components.Componentized. See also Interfaces and Adapters. + A special kind of (persistent) Adapter that works with a twisted.python.components.Componentized. See also Interfaces and Adapters.
    -
    Componentized
    +
    Componentized
    A Componentized object is a collection of information, separated into domain-specific or role-specific instances, that all stick together and refer to each other. - Each object is an Adapter, which, in the + Each object is an Adapter, which, in the context of Componentized, we call components. See also Interfaces and Adapters.
    -
    conch
    +
    conch
    Twisted's SSH implementation.
    Connector
    Object used to interface between client connections and protocols, usually - used with a twisted.internet.protocol.ClientFactory - to give you control over how a client connection reconnects. See twisted.internet.interfaces.IConnector and Writing Clients. + used with a twisted.internet.protocol.ClientFactory + to give you control over how a client connection reconnects. See twisted.internet.interfaces.IConnector and Writing Clients.
    Consumer
    An object that consumes data from a Producer. See - twisted.internet.interfaces.IConsumer. + twisted.internet.interfaces.IConsumer.
    Cred
    - Twisted's authentication API, twisted.cred. See + Twisted's authentication API, twisted.cred. See Introduction to Twisted Cred and Twisted Cred usage.
    @@ -103,7 +103,7 @@
    credential checker
    Where authentication actually happens. See - ICredentialChecker. + ICredentialsChecker.
    CVSToys
    @@ -113,12 +113,12 @@
    Daemon
    A background process that does a job or handles client requests. - Daemon is a Unix term; service is the NT equivalent. + Daemon is a Unix term; service is the Windows equivalent.
    -
    Deferred
    +
    Deferred
    - A instance of twisted.internet.defer.Deferred, an + A instance of twisted.internet.defer.Deferred, an abstraction for handling chains of callbacks and error handlers (errbacks). See the Deferring Execution HOWTO. @@ -126,11 +126,9 @@
    Enterprise
    - Twisted's RDBMS support. It contains twisted.enterprise.adbapi for asynchronous access to any - standard DB-API 2.0 module, and twisted.enterprise.row, a Relational - Object Wrapper. See Introduction to - Twisted Enterprise and Twisted Enterprise Row - Objects for more details. + Twisted's RDBMS support. It contains twisted.enterprise.adbapi for asynchronous access to any + standard DB-API 2.0 module. See Introduction to + Twisted Enterprise for more details.
    errback
    @@ -139,15 +137,15 @@ .addErrback to handle errors. -
    Factory
    +
    Factory
    In general, an object that constructs other objects. In Twisted, a Factory - usually refers to a twisted.internet.protocol.Factory, which constructs + usually refers to a twisted.internet.protocol.Factory, which constructs Protocol instances for incoming or outgoing connections. See Writing Servers and Writing Clients.
    -
    Failure
    +
    Failure
    Basically, an asynchronous exception that contains traceback information; these are used for passing errors through asynchronous callbacks. @@ -163,15 +161,15 @@
    Instance Messenger is a multi-protocol chat program that comes with Twisted. It can communicate via TOC with the AOL servers, via IRC, as well as - via PB with Twisted - Words. See twisted.im. + via PB with + Twisted Words. See twisted.words.im.
    -
    Interface
    +
    Interface
    A class that defines and documents methods that a class conforming to that - interface needs to have. A collection of core twisted.internet interfaces can - be found in twisted.internet.interfaces. See also Interfaces and Adapters. + interface needs to have. A collection of core twisted.internet interfaces can + be found in twisted.internet.interfaces. See also Interfaces and Adapters.
    Jelly
    @@ -179,7 +177,7 @@ The serialization layer for Twisted Spread, although it can be used seperately from Twisted Spread as well. It is similar in purpose to Python's standard pickle module, but is more - network-friendly, and depends on a separate marshaller (Banana, in most cases). See twisted.spread.jelly. + network-friendly, and depends on a separate marshaller (Banana, in most cases). See twisted.spread.jelly.
    Lore
    @@ -196,15 +194,14 @@
    Microdom
    A partial DOM implementation using SUX. It is simple and - pythonic, rather than strictly standards-compliant. See twisted.web.microdom. + pythonic, rather than strictly standards-compliant. See twisted.web.microdom.
    Names
    -
    Twisted's DNS server, found in twisted.names.
    +
    Twisted's DNS server, found in twisted.names.
    Nevow
    -
    The successor to Woven; available from -Divmod. +
    The successor to Woven; available from Divmod.
    PB
    @@ -217,7 +214,7 @@
    The high-level object layer of Twisted Spread, implementing semantics for method calling and object copying, caching, and - referencing. See twisted.spread.pb. + referencing. See twisted.spread.pb.
    Portal
    @@ -230,14 +227,14 @@
    An object that generates data a chunk at a time, usually to be processed by a Consumer. See - twisted.internet.interfaces.IProducer. + twisted.internet.interfaces.IProducer.
    -
    Protocol
    +
    Protocol
    In general each network connection has its own Protocol instance to manage connection-specific state. There is a collection of standard - protocol implementations in twisted.protocols. See + protocol implementations in twisted.protocols. See also Writing Servers and Writing Clients.
    @@ -257,31 +254,24 @@
    (in Twisted Cred) stores avatars and perhaps general business logic. See - IRealm. + IRealm.
    -
    Resource
    +
    Resource
    - A twisted.web.resource.Resource, which are served + A twisted.web.resource.Resource, which are served by Twisted Web. Resources can be as simple as a static file on disk, or they can have dynamically generated content.
    -
    ROW
    -
    - Relational Object Wrapper, an object-oriented - interface to a relational database. See Twisted Enterprise - Row Objects. -
    -
    Service
    - A twisted.application.service.Service. See Application howto for a description of how they + A twisted.application.service.Service. See Application howto for a description of how they relate to Applications.
    Spread
    -
    Twisted Spread is +
    Twisted Spread is Twisted's remote-object suite. It consists of three layers: Perspective Broker, Jelly and Banana. See Writing Applications @@ -289,8 +279,7 @@
    SUX
    Small Uncomplicated XML, Twisted's simple XML -parser written in pure Python. See -twisted.protocols.sux.
    +parser written in pure Python. See twisted.web.sux.
    TAC
    A Twisted Application Configuration is a Python @@ -298,15 +287,14 @@ configuration to make an application runnable using twistd.
    TAP
    -
    Twisted Application Pickle (deprecated), or simply just a +
    Twisted Application Pickle (no longer supported), or simply just a Twisted APplication. A serialised application that was created -with mktap and runnable by twistd. See +with mktap (no longer supported) and runnable by twistd. See Using the Utilities.
    Trial
    -
    twisted.trial, Twisted's unit-testing framework, -modelled after pyunit. See also -Writing tests for Twisted code.
    +
    twisted.trial, Twisted's unit-testing framework, +based on the unittest standard library module. See also Writing tests for Twisted code.
    Twisted Matrix Laboratories
    The team behind Twisted. @@ -317,24 +305,23 @@ In days of old, the Twisted Reality multiplayer text-based interactive-fiction system was the main focus of Twisted Matrix Labs; Twisted, the general networking framework, grew out of Reality's need for better network functionality. Twisted -Reality has been superseded by the -Imaginary project. +Reality has been superseded by the Imaginary project.
    -
    usage
    -
    The twisted.python.usage module, a replacement for +
    usage
    +
    The twisted.python.usage module, a replacement for the standard getopt module for parsing command-lines which is much easier to work with. See Parsing command-lines.
    Words
    Twisted Words is a multi-protocol chat server that uses the Perspective Broker protocol as its native -communication style. See twisted.words.
    +communication style. See twisted.words.
    Woven
    Web Object Visualization Environment. A templating system previously, but no longer, included with Twisted. Woven -has largely been superceded by +has largely been superceded by Divmod Nevow.
    @@ -342,6 +329,6 @@

    Index

    - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/index.html twisted-12.1.0/doc/howto/index.html --- twisted-10.2.0/doc/howto/index.html 2010-11-30 03:13:18.000000000 +0000 +++ twisted-12.1.0/doc/howto/index.html 2012-06-04 08:46:18.000000000 +0000 @@ -14,26 +14,23 @@
  • Introduction
  • -
  • Tutorials +
  • Getting Started
  • -
  • Low-Level Networking and Event Loop +
  • Networking and Other Event Sources
  • -
  • High-Level Twisted - +
  • High-Level Infrastructure +
  • + +
  • Deploying Twisted Applications + +
  • Utilities
  • -
  • Twisted RDBMS support +
  • Asynchronous Messaging Protocol (AMP)
  • Perspective Broker -
      -
    • Twisted Spread
    • +
    • Twisted Spread
      + A remote method invocation (RMI) protocol: call methods on remote objects.
    • Introduction to Perspective Broker
    • @@ -173,7 +207,7 @@
    • Using Perspective Broker
    • -
    • Managing Clients of +
    • Managing Clients of Perspectives
    • Passing Complex @@ -200,6 +234,6 @@

      Index

      - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/internet-overview.html twisted-12.1.0/doc/howto/internet-overview.html --- twisted-10.2.0/doc/howto/internet-overview.html 2010-11-30 03:13:18.000000000 +0000 +++ twisted-12.1.0/doc/howto/internet-overview.html 2012-06-04 08:46:18.000000000 +0000 @@ -20,29 +20,29 @@

      Twisted Internet contains the various interfaces to the reactor API, whose usage is documented in the low-level chapter. Those APIs -are IReactorCore, -IReactorTCP, -IReactorSSL, -IReactorUNIX, -IReactorUDP, -IReactorTime, -IReactorProcess, -IReactorMulticast -and IReactorThreads. +are IReactorCore, + IReactorTCP, + IReactorSSL, + IReactorUNIX, + IReactorUDP, + IReactorTime, + IReactorProcess, + IReactorMulticast +and IReactorThreads. The reactor APIs allow non-persistent calls to be made.

      Twisted Internet also covers the interfaces for the various transports, -in ITransport +in ITransport and friends. These interfaces allow Twisted network code to be written without regard to the underlying implementation of the transport.

      -

      The IProtocolFactory +

      The IProtocolFactory dictates how factories, which are usually a large part of third party code, are written.

      Index

      - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/listings/amp/basic_client.py twisted-12.1.0/doc/howto/listings/amp/basic_client.py --- twisted-10.2.0/doc/howto/listings/amp/basic_client.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/amp/basic_client.py 2011-08-30 12:39:33.000000000 +0000 @@ -0,0 +1,30 @@ + +if __name__ == '__main__': + import basic_client + raise SystemExit(basic_client.main()) + +from sys import stdout + +from twisted.python.log import startLogging, err +from twisted.protocols.amp import AMP +from twisted.internet import reactor +from twisted.internet.protocol import Factory +from twisted.internet.endpoints import TCP4ClientEndpoint + +def connect(): + endpoint = TCP4ClientEndpoint(reactor, "127.0.0.1", 8750) + factory = Factory() + factory.protocol = AMP + return endpoint.connect(factory) + + +def main(): + startLogging(stdout) + + d = connect() + d.addErrback(err, "Connection failed") + def done(ignored): + reactor.stop() + d.addCallback(done) + + reactor.run() diff -Nru twisted-10.2.0/doc/howto/listings/amp/basic_server.tac twisted-12.1.0/doc/howto/listings/amp/basic_server.tac --- twisted-10.2.0/doc/howto/listings/amp/basic_server.tac 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/amp/basic_server.tac 2011-08-29 01:58:08.000000000 +0000 @@ -0,0 +1,14 @@ +from twisted.protocols.amp import AMP +from twisted.internet import reactor +from twisted.internet.protocol import Factory +from twisted.internet.endpoints import TCP4ServerEndpoint +from twisted.application.service import Application +from twisted.application.internet import StreamServerEndpointService + +application = Application("basic AMP server") + +endpoint = TCP4ServerEndpoint(reactor, 8750) +factory = Factory() +factory.protocol = AMP +service = StreamServerEndpointService(endpoint, factory) +service.setServiceParent(application) diff -Nru twisted-10.2.0/doc/howto/listings/amp/command_client.py twisted-12.1.0/doc/howto/listings/amp/command_client.py --- twisted-10.2.0/doc/howto/listings/amp/command_client.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/amp/command_client.py 2011-08-30 12:39:33.000000000 +0000 @@ -0,0 +1,48 @@ + +if __name__ == '__main__': + import command_client + raise SystemExit(command_client.main()) + +from sys import stdout + +from twisted.python.log import startLogging, err +from twisted.protocols.amp import Integer, String, Unicode, Command +from twisted.internet import reactor + +from basic_client import connect + +class UsernameUnavailable(Exception): + pass + + +class RegisterUser(Command): + arguments = [('username', Unicode()), + ('publickey', String())] + + response = [('uid', Integer())] + + errors = {UsernameUnavailable: 'username-unavailable'} + + +def main(): + startLogging(stdout) + + d = connect() + def connected(protocol): + return protocol.callRemote( + RegisterUser, + username=u'alice', + publickey='ssh-rsa AAAAB3NzaC1yc2 alice@actinium') + d.addCallback(connected) + + def registered(result): + print 'Registration result:', result + d.addCallback(registered) + + d.addErrback(err, "Failed to register") + + def finished(ignored): + reactor.stop() + d.addCallback(finished) + + reactor.run() diff -Nru twisted-10.2.0/doc/howto/listings/deferred/deferred_ex1a.py twisted-12.1.0/doc/howto/listings/deferred/deferred_ex1a.py --- twisted-10.2.0/doc/howto/listings/deferred/deferred_ex1a.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/deferred/deferred_ex1a.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009 Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure, util - -""" -This example is analogous to a function calling .errback(failure) -""" - - -class Counter(object): - num = 0 - -def handleFailure(f): - print "errback" - print "we got an exception: %s" % (f.getTraceback(),) - f.trap(RuntimeError) - -def handleResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - return "yay! handleResult was successful!" - -def failAtHandlingResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - print "\tabout to raise exception" - raise RuntimeError, "whoops! we encountered an error" - - -def behindTheScenes(result): - if not isinstance(result, failure.Failure): # ---- callback - try: - result = handleResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - if not isinstance(result, failure.Failure): # ---- callback - pass - else: # ---- errback - try: - result = handleFailure(result) - except: - result = failure.Failure() - - -def deferredExample(result): - d = defer.Deferred() - d.addCallback(handleResult) - d.addCallback(failAtHandlingResult) - d.addErrback(handleFailure) - - d.errback(result) - - -if __name__ == '__main__': - result = None - try: - raise RuntimeError, "*doh*! failure!" - except: - result = failure.Failure() - behindTheScenes(result) - print "\n-------------------------------------------------\n" - Counter.num = 0 - deferredExample(result) diff -Nru twisted-10.2.0/doc/howto/listings/deferred/deferred_ex1b.py twisted-12.1.0/doc/howto/listings/deferred/deferred_ex1b.py --- twisted-10.2.0/doc/howto/listings/deferred/deferred_ex1b.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/deferred/deferred_ex1b.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009 Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure, util - -""" -Here we have a slightly more involved case. The deferred is called back with a -result. the first callback returns a value, the second callback, however -raises an exception, which is handled by the errback. -""" - - -class Counter(object): - num = 0 - -def handleFailure(f): - print "errback" - print "we got an exception: %s" % (f.getTraceback(),) - f.trap(RuntimeError) - -def handleResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - return "yay! handleResult was successful!" - -def failAtHandlingResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - print "\tabout to raise exception" - raise RuntimeError, "whoops! we encountered an error" - - -def behindTheScenes(result): - if not isinstance(result, failure.Failure): # ---- callback - try: - result = handleResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = failAtHandlingResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - if not isinstance(result, failure.Failure): # ---- callback - pass - else: # ---- errback - try: - result = handleFailure(result) - except: - result = failure.Failure() - - -def deferredExample(): - d = defer.Deferred() - d.addCallback(handleResult) - d.addCallback(failAtHandlingResult) - d.addErrback(handleFailure) - - d.callback("success") - - -if __name__ == '__main__': - behindTheScenes("success") - print "\n-------------------------------------------------\n" - Counter.num = 0 - deferredExample() diff -Nru twisted-10.2.0/doc/howto/listings/deferred/deferred_ex2.py twisted-12.1.0/doc/howto/listings/deferred/deferred_ex2.py --- twisted-10.2.0/doc/howto/listings/deferred/deferred_ex2.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/deferred/deferred_ex2.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009 Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure, util - -""" -This example shows an important concept that many deferred newbies -(myself included) have trouble understanding. - -when an error occurs in a callback, the first errback after the error -occurs will be the next method called. (in the next example we'll -see what happens in the 'chain' after an errback). -""" - -class Counter(object): - num = 0 - -def handleFailure(f): - print "errback" - print "we got an exception: %s" % (f.getTraceback(),) - f.trap(RuntimeError) - -def handleResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - return "yay! handleResult was successful!" - -def failAtHandlingResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - print "\tabout to raise exception" - raise RuntimeError, "whoops! we encountered an error" - - - -def behindTheScenes(result): - # equivalent to d.callback(result) - - # now, let's make the error happen in the first callback - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = failAtHandlingResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - # note: this callback will be skipped because - # result is a failure - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = handleResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - if not isinstance(result, failure.Failure): # ---- callback - pass - else: # ---- errback - try: - result = handleFailure(result) - except: - result = failure.Failure() - - - -def deferredExample(): - d = defer.Deferred() - d.addCallback(failAtHandlingResult) - d.addCallback(handleResult) - d.addErrback(handleFailure) - - d.callback("success") - - -if __name__ == '__main__': - behindTheScenes("success") - print "\n-------------------------------------------------\n" - Counter.num = 0 - deferredExample() - diff -Nru twisted-10.2.0/doc/howto/listings/deferred/deferred_ex3.py twisted-12.1.0/doc/howto/listings/deferred/deferred_ex3.py --- twisted-10.2.0/doc/howto/listings/deferred/deferred_ex3.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/deferred/deferred_ex3.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,100 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009 Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure, util - -""" -Now we see how an errback can handle errors. if an errback -does not raise an exception, the next callback in the chain -will be called. -""" - -class Counter(object): - num = 0 - - -def handleFailure(f): - print "errback" - print "we got an exception: %s" % (f.getTraceback(),) - f.trap(RuntimeError) - return "okay, continue on" - -def handleResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - return "yay! handleResult was successful!" - -def failAtHandlingResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - print "\tabout to raise exception" - raise RuntimeError, "whoops! we encountered an error" - -def callbackAfterErrback(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - - - -def behindTheScenes(result): - # equivalent to d.callback(result) - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = handleResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = failAtHandlingResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - if not isinstance(result, failure.Failure): # ---- callback - pass - else: # ---- errback - try: - result = handleFailure(result) - except: - result = failure.Failure() - - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = callbackAfterErrback(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - -def deferredExample(): - d = defer.Deferred() - d.addCallback(handleResult) - d.addCallback(failAtHandlingResult) - d.addErrback(handleFailure) - d.addCallback(callbackAfterErrback) - - d.callback("success") - - -if __name__ == '__main__': - behindTheScenes("success") - print "\n-------------------------------------------------\n" - Counter.num = 0 - deferredExample() - diff -Nru twisted-10.2.0/doc/howto/listings/deferred/deferred_ex4.py twisted-12.1.0/doc/howto/listings/deferred/deferred_ex4.py --- twisted-10.2.0/doc/howto/listings/deferred/deferred_ex4.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/deferred/deferred_ex4.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,104 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009 Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure, util - -""" -Now we'll see what happens when you use 'addBoth'. -""" - -class Counter(object): - num = 0 - - -def handleFailure(f): - print "errback" - print "we got an exception: %s" % (f.getTraceback(),) - f.trap(RuntimeError) - return "okay, continue on" - -def handleResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - return "yay! handleResult was successful!" - -def failAtHandlingResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - print "\tabout to raise exception" - raise RuntimeError, "whoops! we encountered an error" - -def doThisNoMatterWhat(arg): - Counter.num += 1 - print "both %s" % (Counter.num,) - print "\tgot argument %r" % (arg,) - print "\tdoing something very important" - # we pass the argument we received to the next phase here - return arg - - - -def behindTheScenes(result): - # equivalent to d.callback(result) - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = handleResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = failAtHandlingResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - # ---- this is equivalent to addBoth(doThisNoMatterWhat) - - if not isinstance(result, failure.Failure): - try: - result = doThisNoMatterWhat(result) - except: - result = failure.Failure() - else: - try: - result = doThisNoMatterWhat(result) - except: - result = failure.Failure() - - - if not isinstance(result, failure.Failure): # ---- callback - pass - else: # ---- errback - try: - result = handleFailure(result) - except: - result = failure.Failure() - - -def deferredExample(): - d = defer.Deferred() - d.addCallback(handleResult) - d.addCallback(failAtHandlingResult) - d.addBoth(doThisNoMatterWhat) - d.addErrback(handleFailure) - - d.callback("success") - - -if __name__ == '__main__': - behindTheScenes("success") - print "\n-------------------------------------------------\n" - Counter.num = 0 - deferredExample() diff -Nru twisted-10.2.0/doc/howto/listings/deferred/deferred_ex5.py twisted-12.1.0/doc/howto/listings/deferred/deferred_ex5.py --- twisted-10.2.0/doc/howto/listings/deferred/deferred_ex5.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/deferred/deferred_ex5.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,136 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009 Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure, util - -""" -Now comes the more nuanced addCallbacks, which allows us to make a -yes/no (branching) decision based on whether the result at a given point is -a failure or not. -""" - -class Counter(object): - num = 0 - - -def handleFailure(f): - print "errback" - print "we got an exception: %s" % (f.getTraceback(),) - f.trap(RuntimeError) - return "okay, continue on" - -def handleResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - return "yay! handleResult was successful!" - -def failAtHandlingResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - print "\tabout to raise exception" - raise RuntimeError, "whoops! we encountered an error" - -def yesDecision(result): - Counter.num += 1 - print "yes decision %s" % (Counter.num,) - print "\twasn't a failure, so we can plow ahead" - return "go ahead!" - -def noDecision(result): - Counter.num += 1 - result.trap(RuntimeError) - print "no decision %s" % (Counter.num,) - print "\t*doh*! a failure! quick! damage control!" - return "damage control successful!" - - - -def behindTheScenes(result): - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = failAtHandlingResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - # this is equivalent to addCallbacks(yesDecision, noDecision) - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = yesDecision(result) - except: - result = failure.Failure() - else: # ---- errback - try: - result = noDecision(result) - except: - result = failure.Failure() - - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = handleResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - # this is equivalent to addCallbacks(yesDecision, noDecision) - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = yesDecision(result) - except: - result = failure.Failure() - else: # ---- errback - try: - result = noDecision(result) - except: - result = failure.Failure() - - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = handleResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - if not isinstance(result, failure.Failure): # ---- callback - pass - else: # ---- errback - try: - result = handleFailure(result) - except: - result = failure.Failure() - - -def deferredExample(): - d = defer.Deferred() - d.addCallback(failAtHandlingResult) - d.addCallbacks(yesDecision, noDecision) # noDecision will be called - d.addCallback(handleResult) # - A - - d.addCallbacks(yesDecision, noDecision) # yesDecision will be called - d.addCallback(handleResult) - d.addErrback(handleFailure) - - d.callback("success") - - -if __name__ == '__main__': - behindTheScenes("success") - print "\n-------------------------------------------------\n" - Counter.num = 0 - deferredExample() - diff -Nru twisted-10.2.0/doc/howto/listings/deferred/deferred_ex6.py twisted-12.1.0/doc/howto/listings/deferred/deferred_ex6.py --- twisted-10.2.0/doc/howto/listings/deferred/deferred_ex6.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/deferred/deferred_ex6.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,148 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009 Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure, util - -""" -Now comes the more nuanced addCallbacks, which allows us to make a -yes/no (branching) decision based on whether the result at a given point is -a failure or not. - -here, we return the failure from noDecisionPassthru, the errback argument to -the first addCallbacks method invocation, and see what happens. -""" - -class Counter(object): - num = 0 - - -def handleFailure(f): - print "errback" - print "we got an exception: %s" % (f.getTraceback(),) - f.trap(RuntimeError) - return "okay, continue on" - -def handleResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - return "yay! handleResult was successful!" - -def failAtHandlingResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - print "\tabout to raise exception" - raise RuntimeError, "whoops! we encountered an error" - -def yesDecision(result): - Counter.num += 1 - print "yes decision %s" % (Counter.num,) - print "\twasn't a failure, so we can plow ahead" - return "go ahead!" - -def noDecision(result): - Counter.num += 1 - result.trap(RuntimeError) - print "no decision %s" % (Counter.num,) - print "\t*doh*! a failure! quick! damage control!" - return "damage control successful!" - -def noDecisionPassthru(result): - Counter.num += 1 - print "no decision %s" % (Counter.num,) - print "\t*doh*! a failure! don't know what to do, returning failure!" - return result - - -def behindTheScenes(result): - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = failAtHandlingResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - # this is equivalent to addCallbacks(yesDecision, noDecision) - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = yesDecision(result) - except: - result = failure.Failure() - else: # ---- errback - try: - result = noDecisionPassthru(result) - except: - result = failure.Failure() - - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = handleResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - # this is equivalent to addCallbacks(yesDecision, noDecision) - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = yesDecision(result) - except: - result = failure.Failure() - else: # ---- errback - try: - result = noDecision(result) - except: - result = failure.Failure() - - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = handleResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - if not isinstance(result, failure.Failure): # ---- callback - pass - else: # ---- errback - try: - result = handleFailure(result) - except: - result = failure.Failure() - - -def deferredExample(): - d = defer.Deferred() - d.addCallback(failAtHandlingResult) - - # noDecisionPassthru will be called - d.addCallbacks(yesDecision, noDecisionPassthru) - d.addCallback(handleResult) # - A - - - # noDecision will be called - d.addCallbacks(yesDecision, noDecision) - d.addCallback(handleResult) # - B - - d.addErrback(handleFailure) - - d.callback("success") - - -if __name__ == '__main__': - behindTheScenes("success") - print "\n-------------------------------------------------\n" - Counter.num = 0 - deferredExample() - diff -Nru twisted-10.2.0/doc/howto/listings/deferred/deferred_ex7.py twisted-12.1.0/doc/howto/listings/deferred/deferred_ex7.py --- twisted-10.2.0/doc/howto/listings/deferred/deferred_ex7.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/deferred/deferred_ex7.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009 Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure, util - -""" -The deferred callback chain is stateful, and can be executed before -or after all callbacks have been added to the chain -""" - -class Counter(object): - num = 0 - -def handleFailure(f): - print "errback" - print "we got an exception: %s" % (f.getTraceback(),) - f.trap(RuntimeError) - -def handleResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - return "yay! handleResult was successful!" - -def failAtHandlingResult(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - print "\tabout to raise exception" - raise RuntimeError, "whoops! we encountered an error" - -def deferredExample1(): - # this is another common idiom, since all add* methods - # return the deferred instance, you can just chain your - # calls to addCallback and addErrback - - d = defer.Deferred().addCallback(failAtHandlingResult - ).addCallback(handleResult - ).addErrback(handleFailure) - - d.callback("success") - -def deferredExample2(): - d = defer.Deferred() - - d.callback("success") - - d.addCallback(failAtHandlingResult) - d.addCallback(handleResult) - d.addErrback(handleFailure) - - -if __name__ == '__main__': - deferredExample1() - print "\n-------------------------------------------------\n" - Counter.num = 0 - deferredExample2() - diff -Nru twisted-10.2.0/doc/howto/listings/deferred/deferred_ex8.py twisted-12.1.0/doc/howto/listings/deferred/deferred_ex8.py --- twisted-10.2.0/doc/howto/listings/deferred/deferred_ex8.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/deferred/deferred_ex8.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009 Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure, util - - -class Counter(object): - num = 0 - let = 'a' - - def incrLet(cls): - cls.let = chr(ord(cls.let) + 1) - incrLet = classmethod(incrLet) - - -def handleFailure(f): - print "errback" - print "we got an exception: %s" % (f.getTraceback(),) - return f - -def subCb_B(result): - print "sub-callback %s" % (Counter.let,) - Counter.incrLet() - s = " beautiful!" - print "\tadding %r to result" % (s,) - result += s - return result - -def subCb_A(result): - print "sub-callback %s" % (Counter.let,) - Counter.incrLet() - s = " are " - print "\tadding %r to result" % (s,) - result += s - return result - -def mainCb_1(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - result += " Deferreds " - - d = defer.Deferred().addCallback(subCb_A - ).addCallback(subCb_B) - d.callback(result) - return d - -def mainCb_2(result): - Counter.num += 1 - print "callback %s" % (Counter.num,) - print "\tgot result: %s" % (result,) - - -def deferredExample(): - d = defer.Deferred().addCallback(mainCb_1 - ).addCallback(mainCb_2) - - d.callback("I hope you'll agree: ") - - -if __name__ == '__main__': - deferredExample() - diff -Nru twisted-10.2.0/doc/howto/listings/deferred/deferred_ex.py twisted-12.1.0/doc/howto/listings/deferred/deferred_ex.py --- twisted-10.2.0/doc/howto/listings/deferred/deferred_ex.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/deferred/deferred_ex.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009 Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure, util - -""" -Here we have the simplest case, a single callback and a single errback. -""" - -num = 0 - -def handleFailure(f): - print "errback" - print "we got an exception: %s" % (f.getTraceback(),) - f.trap(RuntimeError) - -def handleResult(result): - global num; num += 1 - print "callback %s" % (num,) - print "\tgot result: %s" % (result,) - return "yay! handleResult was successful!" - - -def behindTheScenes(result): - # equivalent to d.callback(result) - - if not isinstance(result, failure.Failure): # ---- callback - try: - result = handleResult(result) - except: - result = failure.Failure() - else: # ---- errback - pass - - - if not isinstance(result, failure.Failure): # ---- callback - pass - else: # ---- errback - try: - result = handleFailure(result) - except: - result = failure.Failure() - - -def deferredExample(): - d = defer.Deferred() - d.addCallback(handleResult) - d.addErrback(handleFailure) - - d.callback("success") - - -if __name__ == '__main__': - behindTheScenes("success") - print "\n-------------------------------------------------\n" - global num; num = 0 - deferredExample() diff -Nru twisted-10.2.0/doc/howto/listings/pb/cache_classes.py twisted-12.1.0/doc/howto/listings/pb/cache_classes.py --- twisted-10.2.0/doc/howto/listings/pb/cache_classes.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/cache_classes.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb diff -Nru twisted-10.2.0/doc/howto/listings/pb/cache_receiver.py twisted-12.1.0/doc/howto/listings/pb/cache_receiver.py --- twisted-10.2.0/doc/howto/listings/pb/cache_receiver.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/cache_receiver.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.application import service, internet diff -Nru twisted-10.2.0/doc/howto/listings/pb/cache_sender.py twisted-12.1.0/doc/howto/listings/pb/cache_sender.py --- twisted-10.2.0/doc/howto/listings/pb/cache_sender.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/cache_sender.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb, jelly diff -Nru twisted-10.2.0/doc/howto/listings/pb/chatclient.py twisted-12.1.0/doc/howto/listings/pb/chatclient.py --- twisted-10.2.0/doc/howto/listings/pb/chatclient.py 2010-06-04 21:28:31.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/chatclient.py 2011-03-14 08:15:50.000000000 +0000 @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2009-2010 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb @@ -20,12 +20,12 @@ reactor.run() def connected(self, perspective): - print "connected, joining group #lookingForFourth" + print "connected, joining group #NeedAFourth" # this perspective is a reference to our User object. Save a reference # to it here, otherwise it will get garbage collected after this call, # and the server will think we logged out. self.perspective = perspective - d = perspective.callRemote("joinGroup", "#lookingForFourth") + d = perspective.callRemote("joinGroup", "#NeedAFourth") d.addCallback(self.gotGroup) def gotGroup(self, group): diff -Nru twisted-10.2.0/doc/howto/listings/pb/chatserver.py twisted-12.1.0/doc/howto/listings/pb/chatserver.py --- twisted-10.2.0/doc/howto/listings/pb/chatserver.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/chatserver.py 2011-03-14 08:15:50.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from zope.interface import implements @@ -48,7 +48,7 @@ def addUser(self, user): self.users.append(user) def view_send(self, from_user, message): - if not self.allowMattress and message.find("mattress") != -1: + if not self.allowMattress and "mattress" in message: raise ValueError, "Don't say that word" for user in self.users: user.send("<%s> says: %s" % (from_user.name, message)) diff -Nru twisted-10.2.0/doc/howto/listings/pb/copy2_classes.py twisted-12.1.0/doc/howto/listings/pb/copy2_classes.py --- twisted-10.2.0/doc/howto/listings/pb/copy2_classes.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/copy2_classes.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb diff -Nru twisted-10.2.0/doc/howto/listings/pb/copy2_receiver.py twisted-12.1.0/doc/howto/listings/pb/copy2_receiver.py --- twisted-10.2.0/doc/howto/listings/pb/copy2_receiver.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/copy2_receiver.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.application import service, internet diff -Nru twisted-10.2.0/doc/howto/listings/pb/copy2_sender.py twisted-12.1.0/doc/howto/listings/pb/copy2_sender.py --- twisted-10.2.0/doc/howto/listings/pb/copy2_sender.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/copy2_sender.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb, jelly diff -Nru twisted-10.2.0/doc/howto/listings/pb/copy_receiver.tac twisted-12.1.0/doc/howto/listings/pb/copy_receiver.tac --- twisted-10.2.0/doc/howto/listings/pb/copy_receiver.tac 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/copy_receiver.tac 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ diff -Nru twisted-10.2.0/doc/howto/listings/pb/copy_sender.py twisted-12.1.0/doc/howto/listings/pb/copy_sender.py --- twisted-10.2.0/doc/howto/listings/pb/copy_sender.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/copy_sender.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb, jelly diff -Nru twisted-10.2.0/doc/howto/listings/pb/exc_client.py twisted-12.1.0/doc/howto/listings/pb/exc_client.py --- twisted-10.2.0/doc/howto/listings/pb/exc_client.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/exc_client.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb diff -Nru twisted-10.2.0/doc/howto/listings/pb/exc_server.py twisted-12.1.0/doc/howto/listings/pb/exc_server.py --- twisted-10.2.0/doc/howto/listings/pb/exc_server.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/exc_server.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb diff -Nru twisted-10.2.0/doc/howto/listings/pb/pb1client.py twisted-12.1.0/doc/howto/listings/pb/pb1client.py --- twisted-10.2.0/doc/howto/listings/pb/pb1client.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/pb1client.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb diff -Nru twisted-10.2.0/doc/howto/listings/pb/pb1server.py twisted-12.1.0/doc/howto/listings/pb/pb1server.py --- twisted-10.2.0/doc/howto/listings/pb/pb1server.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/pb1server.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb diff -Nru twisted-10.2.0/doc/howto/listings/pb/pb2client.py twisted-12.1.0/doc/howto/listings/pb/pb2client.py --- twisted-10.2.0/doc/howto/listings/pb/pb2client.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/pb2client.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb diff -Nru twisted-10.2.0/doc/howto/listings/pb/pb2server.py twisted-12.1.0/doc/howto/listings/pb/pb2server.py --- twisted-10.2.0/doc/howto/listings/pb/pb2server.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/pb2server.py 2011-03-14 08:15:50.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb @@ -15,12 +15,12 @@ #pb.Root.__init__(self) # pb.Root doesn't implement __init__ self.two = two def remote_getTwo(self): - print "One.getTwo(), returning my two called", two - return two + print "One.getTwo(), returning my two called", self.two + return self.two def remote_checkTwo(self, newtwo): print "One.checkTwo(): comparing my two", self.two print "One.checkTwo(): against your two", newtwo - if two == newtwo: + if self.two == newtwo: print "One.checkTwo(): our twos are the same" diff -Nru twisted-10.2.0/doc/howto/listings/pb/pb3client.py twisted-12.1.0/doc/howto/listings/pb/pb3client.py --- twisted-10.2.0/doc/howto/listings/pb/pb3client.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/pb3client.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb diff -Nru twisted-10.2.0/doc/howto/listings/pb/pb3server.py twisted-12.1.0/doc/howto/listings/pb/pb3server.py --- twisted-10.2.0/doc/howto/listings/pb/pb3server.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/pb3server.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb diff -Nru twisted-10.2.0/doc/howto/listings/pb/pb4client.py twisted-12.1.0/doc/howto/listings/pb/pb4client.py --- twisted-10.2.0/doc/howto/listings/pb/pb4client.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/pb4client.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb diff -Nru twisted-10.2.0/doc/howto/listings/pb/pb5client.py twisted-12.1.0/doc/howto/listings/pb/pb5client.py --- twisted-10.2.0/doc/howto/listings/pb/pb5client.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/pb5client.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb diff -Nru twisted-10.2.0/doc/howto/listings/pb/pb5server.py twisted-12.1.0/doc/howto/listings/pb/pb5server.py --- twisted-10.2.0/doc/howto/listings/pb/pb5server.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/pb5server.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from zope.interface import implements diff -Nru twisted-10.2.0/doc/howto/listings/pb/pb6client1.py twisted-12.1.0/doc/howto/listings/pb/pb6client1.py --- twisted-10.2.0/doc/howto/listings/pb/pb6client1.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/pb6client1.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb diff -Nru twisted-10.2.0/doc/howto/listings/pb/pb6client2.py twisted-12.1.0/doc/howto/listings/pb/pb6client2.py --- twisted-10.2.0/doc/howto/listings/pb/pb6client2.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/pb6client2.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb diff -Nru twisted-10.2.0/doc/howto/listings/pb/pb6server.py twisted-12.1.0/doc/howto/listings/pb/pb6server.py --- twisted-10.2.0/doc/howto/listings/pb/pb6server.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/pb6server.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from zope.interface import implements diff -Nru twisted-10.2.0/doc/howto/listings/pb/pb7client.py twisted-12.1.0/doc/howto/listings/pb/pb7client.py --- twisted-10.2.0/doc/howto/listings/pb/pb7client.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/pb7client.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb diff -Nru twisted-10.2.0/doc/howto/listings/pb/pbAnonClient.py twisted-12.1.0/doc/howto/listings/pb/pbAnonClient.py --- twisted-10.2.0/doc/howto/listings/pb/pbAnonClient.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/pbAnonClient.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2007-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ diff -Nru twisted-10.2.0/doc/howto/listings/pb/pbAnonServer.py twisted-12.1.0/doc/howto/listings/pb/pbAnonServer.py --- twisted-10.2.0/doc/howto/listings/pb/pbAnonServer.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/pbAnonServer.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2007-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ diff -Nru twisted-10.2.0/doc/howto/listings/pb/trap_client.py twisted-12.1.0/doc/howto/listings/pb/trap_client.py --- twisted-10.2.0/doc/howto/listings/pb/trap_client.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/trap_client.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb, jelly diff -Nru twisted-10.2.0/doc/howto/listings/pb/trap_server.py twisted-12.1.0/doc/howto/listings/pb/trap_server.py --- twisted-10.2.0/doc/howto/listings/pb/trap_server.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/pb/trap_server.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.internet import reactor diff -Nru twisted-10.2.0/doc/howto/listings/process/process.py twisted-12.1.0/doc/howto/listings/process/process.py --- twisted-10.2.0/doc/howto/listings/process/process.py 2010-02-12 15:34:01.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/process/process.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2009-2010 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.internet import protocol diff -Nru twisted-10.2.0/doc/howto/listings/sendmsg/copy_descriptor.py twisted-12.1.0/doc/howto/listings/sendmsg/copy_descriptor.py --- twisted-10.2.0/doc/howto/listings/sendmsg/copy_descriptor.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/sendmsg/copy_descriptor.py 2012-04-12 21:13:48.000000000 +0000 @@ -0,0 +1,35 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Demonstration of copying a file descriptor over an AF_UNIX connection using +sendmsg. +""" + +from os import pipe, read, write +from socket import SOL_SOCKET, socketpair +from struct import unpack, pack + +from twisted.python.sendmsg import SCM_RIGHTS, send1msg, recv1msg + +def main(): + foo, bar = socketpair() + reader, writer = pipe() + + # Send a copy of the descriptor. Notice that there must be at least one + # byte of normal data passed in. + sent = send1msg( + foo.fileno(), "\x00", 0, + [(SOL_SOCKET, SCM_RIGHTS, pack("i", reader))]) + + # Receive the copy, including that one byte of normal data. + data, flags, ancillary = recv1msg(bar.fileno(), 1024) + duplicate = unpack("i", ancillary[0][2])[0] + + # Demonstrate that the copy works just like the original + write(writer, "Hello, world") + print "Read from original (%d): %r" % (reader, read(reader, 6)) + print "Read from duplicate (%d): %r" % (duplicate, read(duplicate, 6)) + +if __name__ == '__main__': + main() diff -Nru twisted-10.2.0/doc/howto/listings/sendmsg/send_replacement.py twisted-12.1.0/doc/howto/listings/sendmsg/send_replacement.py --- twisted-10.2.0/doc/howto/listings/sendmsg/send_replacement.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/sendmsg/send_replacement.py 2012-04-12 21:13:48.000000000 +0000 @@ -0,0 +1,21 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Demonstration of sending bytes over a TCP connection using sendmsg. +""" + +from socket import socketpair + +from twisted.python.sendmsg import send1msg, recv1msg + +def main(): + foo, bar = socketpair() + sent = send1msg(foo.fileno(), "Hello, world") + print "Sent", sent, "bytes" + (received, flags, ancillary) = recv1msg(bar.fileno(), 1024) + print "Received", repr(received) + print "Extra stuff, boring in this case", flags, ancillary + +if __name__ == '__main__': + main() diff -Nru twisted-10.2.0/doc/howto/listings/servers/chat.py twisted-12.1.0/doc/howto/listings/servers/chat.py --- twisted-10.2.0/doc/howto/listings/servers/chat.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/servers/chat.py 2011-04-15 13:32:49.000000000 +0000 @@ -0,0 +1,51 @@ +from twisted.internet.protocol import Factory +from twisted.protocols.basic import LineReceiver +from twisted.internet import reactor + +class Chat(LineReceiver): + + def __init__(self, users): + self.users = users + self.name = None + self.state = "GETNAME" + + def connectionMade(self): + self.sendLine("What's your name?") + + def connectionLost(self, reason): + if self.users.has_key(self.name): + del self.users[self.name] + + def lineReceived(self, line): + if self.state == "GETNAME": + self.handle_GETNAME(line) + else: + self.handle_CHAT(line) + + def handle_GETNAME(self, name): + if self.users.has_key(name): + self.sendLine("Name taken, please choose another.") + return + self.sendLine("Welcome, %s!" % (name,)) + self.name = name + self.users[name] = self + self.state = "CHAT" + + def handle_CHAT(self, message): + message = "<%s> %s" % (self.name, message) + for name, protocol in self.users.iteritems(): + if protocol != self: + protocol.sendLine(message) + + +class ChatFactory(Factory): + + def __init__(self): + self.users = {} # maps user names to Chat instances + + def buildProtocol(self, addr): + return Chat(self.users) + + +reactor.listenTCP(8123, ChatFactory()) +reactor.run() diff -Nru twisted-10.2.0/doc/howto/listings/trial/calculus/base_1.py twisted-12.1.0/doc/howto/listings/trial/calculus/base_1.py --- twisted-10.2.0/doc/howto/listings/trial/calculus/base_1.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/trial/calculus/base_1.py 2008-04-25 14:32:48.000000000 +0000 @@ -0,0 +1,16 @@ +# -*- test-case-name: calculus.test.test_base_1 -*- + + + +class Calculation(object): + def add(self, a, b): + pass + + def subtract(self, a, b): + pass + + def multiply(self, a, b): + pass + + def divide(self, a, b): + pass diff -Nru twisted-10.2.0/doc/howto/listings/trial/calculus/base_2.py twisted-12.1.0/doc/howto/listings/trial/calculus/base_2.py --- twisted-10.2.0/doc/howto/listings/trial/calculus/base_2.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/trial/calculus/base_2.py 2008-04-25 14:32:48.000000000 +0000 @@ -0,0 +1,14 @@ +# -*- test-case-name: calculus.test.test_base_2 -*- + +class Calculation(object): + def add(self, a, b): + return a + b + + def subtract(self, a, b): + return a - b + + def multiply(self, a, b): + return a * b + + def divide(self, a, b): + return a / b diff -Nru twisted-10.2.0/doc/howto/listings/trial/calculus/base_3.py twisted-12.1.0/doc/howto/listings/trial/calculus/base_3.py --- twisted-10.2.0/doc/howto/listings/trial/calculus/base_3.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/trial/calculus/base_3.py 2012-03-13 23:49:05.000000000 +0000 @@ -0,0 +1,24 @@ +# -*- test-case-name: calculus.test.test_base_3 -*- + +class Calculation(object): + def _make_ints(self, *args): + try: + return map(int, args) + except ValueError: + raise TypeError("Couldn't coerce arguments to integers: %s" % args) + + def add(self, a, b): + a, b = self._make_ints(a, b) + return a + b + + def subtract(self, a, b): + a, b = self._make_ints(a, b) + return a - b + + def multiply(self, a, b): + a, b = self._make_ints(a, b) + return a * b + + def divide(self, a, b): + a, b = self._make_ints(a, b) + return a / b diff -Nru twisted-10.2.0/doc/howto/listings/trial/calculus/client_1.py twisted-12.1.0/doc/howto/listings/trial/calculus/client_1.py --- twisted-10.2.0/doc/howto/listings/trial/calculus/client_1.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/trial/calculus/client_1.py 2008-04-25 14:32:48.000000000 +0000 @@ -0,0 +1,39 @@ +# -*- test-case-name: calculus.test.test_client_1 -*- + +from twisted.protocols import basic +from twisted.internet import defer + + + +class RemoteCalculationClient(basic.LineReceiver): + def __init__(self): + self.results = [] + + + def lineReceived(self, line): + d = self.results.pop(0) + d.callback(int(line)) + + + def _sendOperation(self, op, a, b): + d = defer.Deferred() + self.results.append(d) + line = "%s %d %d" % (op, a, b) + self.sendLine(line) + return d + + + def add(self, a, b): + return self._sendOperation("add", a, b) + + + def subtract(self, a, b): + return self._sendOperation("subtract", a, b) + + + def multiply(self, a, b): + return self._sendOperation("multiply", a, b) + + + def divide(self, a, b): + return self._sendOperation("divide", a, b) diff -Nru twisted-10.2.0/doc/howto/listings/trial/calculus/client_2.py twisted-12.1.0/doc/howto/listings/trial/calculus/client_2.py --- twisted-10.2.0/doc/howto/listings/trial/calculus/client_2.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/trial/calculus/client_2.py 2008-04-25 14:32:48.000000000 +0000 @@ -0,0 +1,54 @@ +# -*- test-case-name: calculus.test.test_client_2 -*- + +from twisted.protocols import basic +from twisted.internet import defer, reactor + + + +class ClientTimeoutError(Exception): + pass + + + +class RemoteCalculationClient(basic.LineReceiver): + + callLater = reactor.callLater + timeOut = 60 + + def __init__(self): + self.results = [] + + + def lineReceived(self, line): + d, callID = self.results.pop(0) + callID.cancel() + d.callback(int(line)) + + + def _cancel(self, d): + d.errback(ClientTimeoutError()) + + + def _sendOperation(self, op, a, b): + d = defer.Deferred() + callID = self.callLater(self.timeOut, self._cancel, d) + self.results.append((d, callID)) + line = "%s %d %d" % (op, a, b) + self.sendLine(line) + return d + + + def add(self, a, b): + return self._sendOperation("add", a, b) + + + def subtract(self, a, b): + return self._sendOperation("subtract", a, b) + + + def multiply(self, a, b): + return self._sendOperation("multiply", a, b) + + + def divide(self, a, b): + return self._sendOperation("divide", a, b) diff -Nru twisted-10.2.0/doc/howto/listings/trial/calculus/client_3.py twisted-12.1.0/doc/howto/listings/trial/calculus/client_3.py --- twisted-10.2.0/doc/howto/listings/trial/calculus/client_3.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/trial/calculus/client_3.py 2011-03-24 13:26:04.000000000 +0000 @@ -0,0 +1,53 @@ +# -*- test-case-name: calculus.test.test_client -*- + +from twisted.protocols import basic, policies +from twisted.internet import defer + + + +class ClientTimeoutError(Exception): + pass + + + +class RemoteCalculationClient(object, basic.LineReceiver, policies.TimeoutMixin): + + def __init__(self): + self.results = [] + self._timeOut = 60 + + def lineReceived(self, line): + self.setTimeout(None) + d = self.results.pop(0) + d.callback(int(line)) + + + def timeoutConnection(self): + for d in self.results: + d.errback(ClientTimeoutError()) + self.transport.loseConnection() + + + def _sendOperation(self, op, a, b): + d = defer.Deferred() + self.results.append(d) + line = "%s %d %d" % (op, a, b) + self.sendLine(line) + self.setTimeout(self._timeOut) + return d + + + def add(self, a, b): + return self._sendOperation("add", a, b) + + + def subtract(self, a, b): + return self._sendOperation("subtract", a, b) + + + def multiply(self, a, b): + return self._sendOperation("multiply", a, b) + + + def divide(self, a, b): + return self._sendOperation("divide", a, b) diff -Nru twisted-10.2.0/doc/howto/listings/trial/calculus/remote_1.py twisted-12.1.0/doc/howto/listings/trial/calculus/remote_1.py --- twisted-10.2.0/doc/howto/listings/trial/calculus/remote_1.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/trial/calculus/remote_1.py 2008-04-25 14:32:48.000000000 +0000 @@ -0,0 +1,47 @@ +# -*- test-case-name: calculus.test.test_remote_1 -*- + +from twisted.protocols import basic +from twisted.internet import protocol +from calculus.base_3 import Calculation + + + +class CalculationProxy(object): + def __init__(self): + self.calc = Calculation() + for m in ['add', 'subtract', 'multiply', 'divide']: + setattr(self, 'remote_%s' % m, getattr(self.calc, m)) + + + +class RemoteCalculationProtocol(basic.LineReceiver): + def __init__(self): + self.proxy = CalculationProxy() + + + def lineReceived(self, line): + op, a, b = line.split() + a = int(a) + b = int(b) + op = getattr(self.proxy, 'remote_%s' % (op,)) + result = op(a, b) + self.sendLine(str(result)) + + + +class RemoteCalculationFactory(protocol.Factory): + protocol = RemoteCalculationProtocol + + + +def main(): + from twisted.internet import reactor + from twisted.python import log + import sys + log.startLogging(sys.stdout) + reactor.listenTCP(0, RemoteCalculationFactory()) + reactor.run() + + +if __name__ == "__main__": + main() diff -Nru twisted-10.2.0/doc/howto/listings/trial/calculus/remote_2.py twisted-12.1.0/doc/howto/listings/trial/calculus/remote_2.py --- twisted-10.2.0/doc/howto/listings/trial/calculus/remote_2.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/trial/calculus/remote_2.py 2008-04-25 14:32:48.000000000 +0000 @@ -0,0 +1,51 @@ +# -*- test-case-name: calculus.test.test_remote_1 -*- + +from twisted.protocols import basic +from twisted.internet import protocol +from twisted.python import log +from calculus.base_3 import Calculation + + + +class CalculationProxy(object): + def __init__(self): + self.calc = Calculation() + for m in ['add', 'subtract', 'multiply', 'divide']: + setattr(self, 'remote_%s' % m, getattr(self.calc, m)) + + + +class RemoteCalculationProtocol(basic.LineReceiver): + def __init__(self): + self.proxy = CalculationProxy() + + + def lineReceived(self, line): + op, a, b = line.split() + op = getattr(self.proxy, 'remote_%s' % (op,)) + try: + result = op(a, b) + except TypeError: + log.err() + self.sendLine("error") + else: + self.sendLine(str(result)) + + + +class RemoteCalculationFactory(protocol.Factory): + protocol = RemoteCalculationProtocol + + + +def main(): + from twisted.internet import reactor + from twisted.python import log + import sys + log.startLogging(sys.stdout) + reactor.listenTCP(0, RemoteCalculationFactory()) + reactor.run() + + +if __name__ == "__main__": + main() diff -Nru twisted-10.2.0/doc/howto/listings/trial/calculus/test/test_base_1.py twisted-12.1.0/doc/howto/listings/trial/calculus/test/test_base_1.py --- twisted-10.2.0/doc/howto/listings/trial/calculus/test/test_base_1.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/trial/calculus/test/test_base_1.py 2011-06-03 13:51:14.000000000 +0000 @@ -0,0 +1,23 @@ +from calculus.base_1 import Calculation +from twisted.trial import unittest + +class CalculationTestCase(unittest.TestCase): + def test_add(self): + calc = Calculation() + result = calc.add(3, 8) + self.assertEqual(result, 11) + + def test_subtract(self): + calc = Calculation() + result = calc.subtract(7, 3) + self.assertEqual(result, 4) + + def test_multiply(self): + calc = Calculation() + result = calc.multiply(12, 5) + self.assertEqual(result, 60) + + def test_divide(self): + calc = Calculation() + result = calc.divide(12, 5) + self.assertEqual(result, 2) diff -Nru twisted-10.2.0/doc/howto/listings/trial/calculus/test/test_base_2b.py twisted-12.1.0/doc/howto/listings/trial/calculus/test/test_base_2b.py --- twisted-10.2.0/doc/howto/listings/trial/calculus/test/test_base_2b.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/trial/calculus/test/test_base_2b.py 2011-06-03 13:51:14.000000000 +0000 @@ -0,0 +1,29 @@ +from calculus.base_2 import Calculation +from twisted.trial import unittest + + + +class CalculationTestCase(unittest.TestCase): + def setUp(self): + self.calc = Calculation() + + + def _test(self, operation, a, b, expected): + result = operation(a, b) + self.assertEqual(result, expected) + + + def test_add(self): + self._test(self.calc.add, 3, 8, 11) + + + def test_subtract(self): + self._test(self.calc.subtract, 7, 3, 4) + + + def test_multiply(self): + self._test(self.calc.multiply, 6, 9, 54) + + + def test_divide(self): + self._test(self.calc.divide, 12, 5, 2) diff -Nru twisted-10.2.0/doc/howto/listings/trial/calculus/test/test_base_2.py twisted-12.1.0/doc/howto/listings/trial/calculus/test/test_base_2.py --- twisted-10.2.0/doc/howto/listings/trial/calculus/test/test_base_2.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/trial/calculus/test/test_base_2.py 2011-06-03 13:51:14.000000000 +0000 @@ -0,0 +1,29 @@ +from calculus.base_2 import Calculation +from twisted.trial import unittest + + + +class CalculationTestCase(unittest.TestCase): + + def test_add(self): + calc = Calculation() + result = calc.add(3, 8) + self.assertEqual(result, 11) + + + def test_subtract(self): + calc = Calculation() + result = calc.subtract(7, 3) + self.assertEqual(result, 4) + + + def test_multiply(self): + calc = Calculation() + result = calc.multiply(12, 5) + self.assertEqual(result, 60) + + + def test_divide(self): + calc = Calculation() + result = calc.divide(12, 5) + self.assertEqual(result, 2) diff -Nru twisted-10.2.0/doc/howto/listings/trial/calculus/test/test_base_3.py twisted-12.1.0/doc/howto/listings/trial/calculus/test/test_base_3.py --- twisted-10.2.0/doc/howto/listings/trial/calculus/test/test_base_3.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/trial/calculus/test/test_base_3.py 2011-06-03 13:51:14.000000000 +0000 @@ -0,0 +1,52 @@ +from calculus.base_3 import Calculation +from twisted.trial import unittest + + + +class CalculationTestCase(unittest.TestCase): + def setUp(self): + self.calc = Calculation() + + + def _test(self, operation, a, b, expected): + result = operation(a, b) + self.assertEqual(result, expected) + + + def _test_error(self, operation): + self.assertRaises(TypeError, operation, "foo", 2) + self.assertRaises(TypeError, operation, "bar", "egg") + self.assertRaises(TypeError, operation, [3], [8, 2]) + self.assertRaises(TypeError, operation, {"e": 3}, {"r": "t"}) + + + def test_add(self): + self._test(self.calc.add, 3, 8, 11) + + + def test_subtract(self): + self._test(self.calc.subtract, 7, 3, 4) + + + def test_multiply(self): + self._test(self.calc.multiply, 6, 9, 54) + + + def test_divide(self): + self._test(self.calc.divide, 12, 5, 2) + + + def test_errorAdd(self): + self._test_error(self.calc.add) + + + def test_errorSubtract(self): + self._test_error(self.calc.subtract) + + + def test_errorMultiply(self): + self._test_error(self.calc.multiply) + + + def test_errorDivide(self): + self._test_error(self.calc.divide) diff -Nru twisted-10.2.0/doc/howto/listings/trial/calculus/test/test_client_1.py twisted-12.1.0/doc/howto/listings/trial/calculus/test/test_client_1.py --- twisted-10.2.0/doc/howto/listings/trial/calculus/test/test_client_1.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/trial/calculus/test/test_client_1.py 2011-06-03 13:51:14.000000000 +0000 @@ -0,0 +1,37 @@ +from calculus.client_1 import RemoteCalculationClient +from twisted.trial import unittest +from twisted.test import proto_helpers + + + +class ClientCalculationTestCase(unittest.TestCase): + def setUp(self): + self.tr = proto_helpers.StringTransport() + self.proto = RemoteCalculationClient() + self.proto.makeConnection(self.tr) + + + def _test(self, operation, a, b, expected): + d = getattr(self.proto, operation)(a, b) + self.assertEqual(self.tr.value(), '%s %d %d\r\n' % (operation, a, b)) + self.tr.clear() + d.addCallback(self.assertEqual, expected) + self.proto.dataReceived("%d\r\n" % (expected,)) + return d + + + def test_add(self): + return self._test('add', 7, 6, 13) + + + def test_subtract(self): + return self._test('subtract', 82, 78, 4) + + + def test_multiply(self): + return self._test('multiply', 2, 8, 16) + + + def test_divide(self): + return self._test('divide', 14, 3, 4) + diff -Nru twisted-10.2.0/doc/howto/listings/trial/calculus/test/test_client_2.py twisted-12.1.0/doc/howto/listings/trial/calculus/test/test_client_2.py --- twisted-10.2.0/doc/howto/listings/trial/calculus/test/test_client_2.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/trial/calculus/test/test_client_2.py 2011-06-03 13:51:14.000000000 +0000 @@ -0,0 +1,48 @@ +from calculus.client_2 import RemoteCalculationClient, ClientTimeoutError + +from twisted.internet import task +from twisted.trial import unittest +from twisted.test import proto_helpers + + + +class ClientCalculationTestCase(unittest.TestCase): + def setUp(self): + self.tr = proto_helpers.StringTransportWithDisconnection() + self.clock = task.Clock() + self.proto = RemoteCalculationClient() + self.tr.protocol = self.proto + self.proto.callLater = self.clock.callLater + self.proto.makeConnection(self.tr) + + + def _test(self, operation, a, b, expected): + d = getattr(self.proto, operation)(a, b) + self.assertEqual(self.tr.value(), '%s %d %d\r\n' % (operation, a, b)) + self.tr.clear() + d.addCallback(self.assertEqual, expected) + self.proto.dataReceived("%d\r\n" % (expected,)) + return d + + + def test_add(self): + return self._test('add', 7, 6, 13) + + + def test_subtract(self): + return self._test('subtract', 82, 78, 4) + + + def test_multiply(self): + return self._test('multiply', 2, 8, 16) + + + def test_divide(self): + return self._test('divide', 14, 3, 4) + + + def test_timeout(self): + d = self.proto.add(9, 4) + self.assertEqual(self.tr.value(), 'add 9 4\r\n') + self.clock.advance(self.proto.timeOut) + return self.assertFailure(d, ClientTimeoutError) diff -Nru twisted-10.2.0/doc/howto/listings/trial/calculus/test/test_client_3.py twisted-12.1.0/doc/howto/listings/trial/calculus/test/test_client_3.py --- twisted-10.2.0/doc/howto/listings/trial/calculus/test/test_client_3.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/trial/calculus/test/test_client_3.py 2011-06-03 13:51:14.000000000 +0000 @@ -0,0 +1,63 @@ +from calculus.client_3 import RemoteCalculationClient, ClientTimeoutError + +from twisted.internet import task +from twisted.trial import unittest +from twisted.test import proto_helpers + + + +class ClientCalculationTestCase(unittest.TestCase): + def setUp(self): + self.tr = proto_helpers.StringTransportWithDisconnection() + self.clock = task.Clock() + self.proto = RemoteCalculationClient() + self.tr.protocol = self.proto + self.proto.callLater = self.clock.callLater + self.proto.makeConnection(self.tr) + + + def _test(self, operation, a, b, expected): + d = getattr(self.proto, operation)(a, b) + self.assertEqual(self.tr.value(), '%s %d %d\r\n' % (operation, a, b)) + self.tr.clear() + d.addCallback(self.assertEqual, expected) + self.proto.dataReceived("%d\r\n" % (expected,)) + return d + + + def test_add(self): + return self._test('add', 7, 6, 13) + + + def test_subtract(self): + return self._test('subtract', 82, 78, 4) + + + def test_multiply(self): + return self._test('multiply', 2, 8, 16) + + + def test_divide(self): + return self._test('divide', 14, 3, 4) + + + def test_timeout(self): + d = self.proto.add(9, 4) + self.assertEqual(self.tr.value(), 'add 9 4\r\n') + self.clock.advance(self.proto.timeOut) + return self.assertFailure(d, ClientTimeoutError) + + + def test_timeoutConnectionLost(self): + called = [] + def lost(arg): + called.append(True) + self.proto.connectionLost = lost + + d = self.proto.add(9, 4) + self.assertEqual(self.tr.value(), 'add 9 4\r\n') + self.clock.advance(self.proto.timeOut) + + def check(ignore): + self.assertEqual(called, [True]) + return self.assertFailure(d, ClientTimeoutError).addCallback(check) diff -Nru twisted-10.2.0/doc/howto/listings/trial/calculus/test/test_remote_1.py twisted-12.1.0/doc/howto/listings/trial/calculus/test/test_remote_1.py --- twisted-10.2.0/doc/howto/listings/trial/calculus/test/test_remote_1.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/trial/calculus/test/test_remote_1.py 2011-06-03 13:51:14.000000000 +0000 @@ -0,0 +1,34 @@ +from calculus.remote_1 import RemoteCalculationFactory +from twisted.trial import unittest +from twisted.test import proto_helpers + + + +class RemoteCalculationTestCase(unittest.TestCase): + def setUp(self): + factory = RemoteCalculationFactory() + self.proto = factory.buildProtocol(('127.0.0.1', 0)) + self.tr = proto_helpers.StringTransport() + self.proto.makeConnection(self.tr) + + + def _test(self, operation, a, b, expected): + self.proto.dataReceived('%s %d %d\r\n' % (operation, a, b)) + self.assertEqual(int(self.tr.value()), expected) + + + def test_add(self): + return self._test('add', 7, 6, 13) + + + def test_subtract(self): + return self._test('subtract', 82, 78, 4) + + + def test_multiply(self): + return self._test('multiply', 2, 8, 16) + + + def test_divide(self): + return self._test('divide', 14, 3, 4) + diff -Nru twisted-10.2.0/doc/howto/listings/trial/calculus/test/test_remote_2.py twisted-12.1.0/doc/howto/listings/trial/calculus/test/test_remote_2.py --- twisted-10.2.0/doc/howto/listings/trial/calculus/test/test_remote_2.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/trial/calculus/test/test_remote_2.py 2011-06-03 13:51:14.000000000 +0000 @@ -0,0 +1,46 @@ +from calculus.remote_1 import RemoteCalculationFactory +from calculus.client_2 import RemoteCalculationClient + +from twisted.trial import unittest +from twisted.internet import reactor, protocol + + + +class RemoteRunCalculationTestCase(unittest.TestCase): + + def setUp(self): + factory = RemoteCalculationFactory() + self.port = reactor.listenTCP(0, factory, interface="127.0.0.1") + self.client = None + + + def tearDown(self): + if self.client is not None: + self.client.transport.loseConnection() + return self.port.stopListening() + + + def _test(self, op, a, b, expected): + creator = protocol.ClientCreator(reactor, RemoteCalculationClient) + def cb(client): + self.client = client + return getattr(self.client, op)(a, b + ).addCallback(self.assertEqual, expected) + return creator.connectTCP('127.0.0.1', self.port.getHost().port + ).addCallback(cb) + + + def test_add(self): + return self._test("add", 5, 9, 14) + + + def test_subtract(self): + return self._test("subtract", 47, 13, 34) + + + def test_multiply(self): + return self._test("multiply", 7, 3, 21) + + + def test_divide(self): + return self._test("divide", 84, 10, 8) diff -Nru twisted-10.2.0/doc/howto/listings/trial/calculus/test/test_remote_3.py twisted-12.1.0/doc/howto/listings/trial/calculus/test/test_remote_3.py --- twisted-10.2.0/doc/howto/listings/trial/calculus/test/test_remote_3.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/trial/calculus/test/test_remote_3.py 2011-06-03 13:51:14.000000000 +0000 @@ -0,0 +1,40 @@ +from calculus.remote_2 import RemoteCalculationFactory +from twisted.trial import unittest +from twisted.test import proto_helpers + + + +class RemoteCalculationTestCase(unittest.TestCase): + def setUp(self): + factory = RemoteCalculationFactory() + self.proto = factory.buildProtocol(('127.0.0.1', 0)) + self.tr = proto_helpers.StringTransport() + self.proto.makeConnection(self.tr) + + + def _test(self, operation, a, b, expected): + self.proto.dataReceived('%s %d %d\r\n' % (operation, a, b)) + self.assertEqual(int(self.tr.value()), expected) + + + def test_add(self): + return self._test('add', 7, 6, 13) + + + def test_subtract(self): + return self._test('subtract', 82, 78, 4) + + + def test_multiply(self): + return self._test('multiply', 2, 8, 16) + + + def test_divide(self): + return self._test('divide', 14, 3, 4) + + + def test_invalidParameters(self): + self.proto.dataReceived('add foo bar\r\n') + self.assertEqual(self.tr.value(), "error\r\n") + errors = self.flushLoggedErrors(TypeError) + self.assertEqual(len(errors), 1) diff -Nru twisted-10.2.0/doc/howto/listings/udp/MulticastClient.py twisted-12.1.0/doc/howto/listings/udp/MulticastClient.py --- twisted-10.2.0/doc/howto/listings/udp/MulticastClient.py 2005-08-21 07:38:26.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/udp/MulticastClient.py 2011-11-13 20:21:50.000000000 +0000 @@ -1,13 +1,19 @@ from twisted.internet.protocol import DatagramProtocol from twisted.internet import reactor -from twisted.application.internet import MulticastServer -class MulticastClientUDP(DatagramProtocol): + +class MulticastPingClient(DatagramProtocol): + + def startProtocol(self): + # Join the multicast address, so we can receive replies: + self.transport.joinGroup("228.0.0.5") + # Send to 228.0.0.5:8005 - all listeners on the multicast address + # (including us) will receive this message. + self.transport.write('Client: Ping', ("228.0.0.5", 8005)) def datagramReceived(self, datagram, address): - print "Received:" + repr(datagram) + print "Datagram %s received from %s" % (repr(datagram), repr(address)) + -# Send multicast on 224.0.0.1:8005, on our dynamically allocated port -reactor.listenUDP(0, MulticastClientUDP()).write('UniqueID', - ('224.0.0.1', 8005)) +reactor.listenMulticast(8005, MulticastPingClient(), listenMultiple=True) reactor.run() diff -Nru twisted-10.2.0/doc/howto/listings/udp/MulticastServer.py twisted-12.1.0/doc/howto/listings/udp/MulticastServer.py --- twisted-10.2.0/doc/howto/listings/udp/MulticastServer.py 2005-08-21 07:38:26.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/udp/MulticastServer.py 2011-11-13 20:21:50.000000000 +0000 @@ -1,25 +1,28 @@ from twisted.internet.protocol import DatagramProtocol from twisted.internet import reactor -from twisted.application.internet import MulticastServer -class MulticastServerUDP(DatagramProtocol): + +class MulticastPingPong(DatagramProtocol): + def startProtocol(self): - print 'Started Listening' - # Join a specific multicast group, which is the IP we will respond to - self.transport.joinGroup('224.0.0.1') + """ + Called after protocol has started listening. + """ + # Set the TTL>1 so multicast will cross router hops: + self.transport.setTTL(5) + # Join a specific multicast group: + self.transport.joinGroup("228.0.0.5") def datagramReceived(self, datagram, address): - # The uniqueID check is to ensure we only service requests from - # ourselves - if datagram == 'UniqueID': - print "Server Received:" + repr(datagram) - self.transport.write("data", address) - -# Note that the join function is picky about having a unique object -# on which to call join. To avoid using startProtocol, the following is -# sufficient: -#reactor.listenMulticast(8005, MulticastServerUDP()).join('224.0.0.1') + print "Datagram %s received from %s" % (repr(datagram), repr(address)) + if datagram == "Client: Ping": + # Rather than replying to the group multicast address, we send the + # reply directly (unicast) to the originating port: + self.transport.write("Server: Pong", address) + -# Listen for multicast on 224.0.0.1:8005 -reactor.listenMulticast(8005, MulticastServerUDP()) +# We use listenMultiple=True so that we can run MulticastServer.py and +# MulticastClient.py on same machine: +reactor.listenMulticast(8005, MulticastPingPong(), + listenMultiple=True) reactor.run() diff -Nru twisted-10.2.0/doc/howto/logging.html twisted-12.1.0/doc/howto/logging.html --- twisted-10.2.0/doc/howto/logging.html 2010-11-30 03:13:15.000000000 +0000 +++ twisted-12.1.0/doc/howto/logging.html 2012-06-04 08:46:20.000000000 +0000 @@ -12,11 +12,11 @@

      Basic usage

      -

      Twisted provides a simple and flexible logging system in the twisted.python.log module. It has three commonly used +

      Twisted provides a simple and flexible logging system in the twisted.python.log module. It has three commonly used functions:

      -
      msg
      +
      msg
      Logs a new message. For example:

      1 2 @@ -25,9 +25,9 @@

      -
      err
      +
      err
      Writes a failure to the log, including traceback information (if any). - You can pass it a Failure or Exception instance, or + You can pass it a Failure or Exception instance, or nothing. If you pass something else, it will be converted to a string with repr and logged. @@ -44,7 +44,7 @@
      -
      startLogging
      +
      startLogging
      Starts logging to a given file-like object. For example:

      1

      log.startLogging(open('/var/log/foo.log', 'w')) @@ -53,6 +53,14 @@

      1

      log.startLogging(sys.stdout)
      + or: +

      1 +2 +3 +

      from twisted.python.logfile import DailyLogFile + +log.startLogging(DailyLogFile.fromFullPath("/var/log/foo.log")) +
      By default, startLogging will also redirect anything written to sys.stdout and sys.stderr to the log. You @@ -74,18 +82,18 @@

      Log files

      -

      The twisted.python.logfile module provides +

      The twisted.python.logfile module provides some standard classes suitable for use with startLogging, such - as DailyLogFile, + as DailyLogFile, which will rotate the log to a new file once per day.

      Using the standard library logging module

      If your application uses the - standard library - logging module but don't want to lose twisted-produced messages, - the observer - PythonLoggingObserver + Python standard + library logging module or you want to use its easy configuration but + don't want to lose twisted-produced messages, the observer + PythonLoggingObserver should be useful to you.

      @@ -124,7 +132,7 @@ registered. There can be any number of observers, and each can treat the event in any way desired. An example of - a log observer in Twisted is the emit method of FileLogObserver. + a log observer in Twisted is the emit method of FileLogObserver. FileLogObserver, used by startLogging, writes events to a log file. A log observer is just a callable that accepts a dictionary as its only argument. You can @@ -175,15 +183,14 @@

      Customizing twistd logging

      - The behavior of the logging that twistd does can be customized - by setting the ILogObserver component on the application - object. See the Application document for - more information. + The behavior of the logging that twistd does can be + customized either with the --logger option or by setting the + ILogObserver component on the application object. See the Application document for more information.

      Index

      - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/options.html twisted-12.1.0/doc/howto/options.html --- twisted-10.2.0/doc/howto/options.html 2010-11-30 03:13:18.000000000 +0000 +++ twisted-12.1.0/doc/howto/options.html 2012-06-04 08:46:20.000000000 +0000 @@ -7,7 +7,7 @@

      Parsing command-lines with usage.Options

      + the Superclass
  • Parameters
  • Option Subcommands
  • Generic Code For Options
  • Parsing Arguments
  • Post Processing
  • Type enforcement
  • Shell tab-completion
  • @@ -16,12 +16,12 @@

    There is frequently a need for programs to parse a UNIX-like command line program: options preceded by - or --, sometimes followed by a parameter, followed by - a list of arguments. The twisted.python.usage provides a class, + a list of arguments. The twisted.python.usage provides a class, Options, to facilitate such parsing.

    While Python has the getopt module for doing this, it provides a very low level of abstraction for options. - Twisted has a higher level of abstraction, in the class twisted.python.usage.Options. It uses + Twisted has a higher level of abstraction, in the class twisted.python.usage.Options. It uses Python's reflection facilities to provide an easy to use yet flexible interface to the command line. While most command line processors either force the application writer to write her own @@ -32,7 +32,7 @@ programmer to decide how much control she wants.

    The Options class is used by subclassing. Since - a lot of time it will be used in the twisted.tap package, where the local + a lot of time it will be used in the twisted.tap package, where the local conventions require the specific options parsing class to also be called Options, it is usually imported with

    1 @@ -363,7 +363,7 @@ verbosity to -3.

    -

    The usage.Options +

    The usage.Options class knows that these are parameter-less options, since the methods do not receive an argument. Here is an example for a method with a parameter:

    @@ -477,11 +477,15 @@ 3 4 5 +6 +7

    from twisted.python import usage class Options(usage.Options): - optParameters = [["shiny_integer", "s", 1, None, int]] - optParameters = [["dummy_float", "d", 3.14159, None, float]] + optParameters = [ + ["shiny_integer", "s", 1, None, int], + ["dummy_float", "d", 3.14159, None, float], + ]

    Note that default values are not coerced, so you should either declare @@ -520,14 +524,58 @@

    -$ python myprogram.py --help
    +$ python myprogram.py --help
     Usage: myprogram [options] 
     Options:
       -o, --one_choice=           [default: 0]. Must be 1, 2 or 3.
     
    +

    Shell tab-completion

    + +

    The Options class may provide tab-completion to interactive + command shells. Only zsh is supported at present, but there is + some interest in supporting bash in the future.

    + +

    Support is automatic for all of the commands shipped with Twisted. Zsh + has shipped, for a number of years, a completion function which ties in to + the support provided by the Options class.

    + +

    If you are writing a twistd plugin, then tab-completion + for your twistd sub-command is also automatic.

    + +

    For other commands you may easily provide zsh tab-completion support. + Copy the file "twisted/python/twisted-completion.zsh" and name it something + like "_mycommand". A leading underscore with no extension is zsh's + convention for completion function files.

    + +

    Edit the new file and change the first line to refer only to your new + command(s), like so:

    + +
    +#compdef mycommand
    +
    + +

    Then ensure this file is made available to the shell by placing it in + one of the directories appearing in zsh's $fpath. Restart zsh, and ensure + advanced completion is enabled + (autoload -U compinit; compinit). You should then be able to + type the name of your command and press Tab to have your command-line + options completed.

    + +

    Completion metadata

    + +

    Optionally, a special attribute, compData, may be defined + on your Options subclass in order to provide more information + to the shell-completion system. The attribute should be an instance of + Completions. See that class + for further details.

    + +

    In addition, compData may be defined on parent classes in + your inheritance hiearchy. The information from each + Completions instance will be + aggregated when producing the final tab-completion results.

    Index

    - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/overview.html twisted-12.1.0/doc/howto/overview.html --- twisted-10.2.0/doc/howto/overview.html 2010-11-30 03:13:17.000000000 +0000 +++ twisted-12.1.0/doc/howto/overview.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ - - -Twisted Documentation: High-Level Overview of Twisted - - - - -

    High-Level Overview of Twisted

    -
      -
      - - -
      - -

      Index

      - Version: 10.2.0 - - \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/pb-clients.html twisted-12.1.0/doc/howto/pb-clients.html --- twisted-10.2.0/doc/howto/pb-clients.html 2010-11-30 03:13:14.000000000 +0000 +++ twisted-12.1.0/doc/howto/pb-clients.html 2012-06-04 08:46:19.000000000 +0000 @@ -12,19 +12,19 @@

      Overview

      -

      In all the IPerspective +

      In all the IPerspective uses we have shown so far, we ignored the mind argument and created a new Avatar for every connection. This is usually an easy design choice, and it works well for simple cases.

      In more complicated cases, for example an Avatar that represents a player object which is persistent in the game universe, -we will want connections from the same player to use the same +we will want connections from the same player to use the same Avatar.

      Another thing which is necessary in more complicated scenarios is notifying a player asynchronously. While it is possible, of -course, to allow a player to call +course, to allow a player to call perspective_remoteListener(referencable) that would mean both duplication of code and a higher latency in logging in, both bad.

      @@ -126,7 +126,6 @@ 26 27 28 -29

      from zope.interface import implements class Greeter: @@ -136,7 +135,6 @@ return "<%d>hello" % (self.greetings, self.name) class SimpleAvatar(pb.Avatar): - greetings = 0 def __init__(self, name, greeter): self.name = name self.greeter = greeter @@ -359,6 +357,6 @@

      Index

      - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/pb-copyable.html twisted-12.1.0/doc/howto/pb-copyable.html --- twisted-10.2.0/doc/howto/pb-copyable.html 2010-11-30 03:13:18.000000000 +0000 +++ twisted-12.1.0/doc/howto/pb-copyable.html 2012-06-04 08:46:20.000000000 +0000 @@ -14,17 +14,17 @@

      This chapter focuses on how to use PB to pass complex types (specifically class instances) to and from a remote process. The first section is on -simply copying the contents of an object to a remote process (pb.Copyable). The second covers how -to copy those contents once, then update them later when they change (Cacheable).

      +simply copying the contents of an object to a remote process (pb.Copyable). The second covers how +to copy those contents once, then update them later when they change (Cacheable).

      Motivation

      From the previous chapter, you've seen how to pass basic types to a remote process, by using them in the arguments or -return values of a callRemote function. However, +return values of a callRemote function. However, if you've experimented with it, you may have discovered problems when trying to pass anything more complicated than a primitive int/list/dict/string -type, or another pb.Referenceable object. At some point you want +type, or another pb.Referenceable object. At some point you want to pass entire objects between processes, instead of having to reduce them down to dictionaries on one end and then re-instantiating them on the other.

      @@ -52,7 +52,7 @@

      If you try to run this, you might hope that a suitable remote end which implements the remote_sendPond method would see that method get invoked with an instance from the LilyPond class. But instead, -you'll encounter the dreaded InsecureJelly exception. This is +you'll encounter the dreaded InsecureJelly exception. This is Twisted's way of telling you that you've violated a security restriction, and that the receiving end refuses to accept your object.

      @@ -77,14 +77,14 @@ create arbitrary objects in your namespace or on your computer. Imagine a protocol that involved sending a file-like object with a read() method that was supposed to used later to retrieve a document. Then imagine -what if that object were created with -os.fdopen("~/.gnupg/secring.gpg"). Or an instance of -telnetlib.Telnet("localhost", "chargen").

      +what if that object were created with + os.fdopen("~/.gnupg/secring.gpg"). Or an instance of + telnetlib.Telnet("localhost", "chargen").

      Classes you've written for your own program are likely to have far more power. They may run code during __init__, or even have special -meaning simply because of their existence. A program might have -User objects to represent user accounts, and have a rule that +meaning simply because of their existence. A program might have + User objects to represent user accounts, and have a rule that says all User objects in the system are referenced when authorizing a login session. (In this system, User.__init__ would probably add the object to a global list of known users). The simple @@ -98,7 +98,7 @@ events is the receipt of an object through a PB remote procedure call, which is a request to create an object in your inside namespace. The question is what to do in response to it. For this reason, you must -explicitly specific what remote classes will be accepted, and how their +explicitly specify what remote classes will be accepted, and how their local representatives are to be created.

      What class to use?

      @@ -117,7 +117,8 @@

      PB lets you specify the mapping from remote class names to local classes -with the setUnjellyableForClass function1. +with the setUnjellyableForClass function +1. This function takes a remote/sender class reference (either the @@ -126,8 +127,8 @@ create the local representation for incoming serialized objects). Whenever the remote end sends an object, the class name that they transmit is looked up in the table controlled by this function. If a matching class is found, -it is used to create the local object. If not, you get the -InsecureJelly exception.

      +it is used to create the local object. If not, you get the + InsecureJelly exception.

      In general you expect both ends to share the same codebase: either you control the program that is running on both ends of the wire, or both @@ -135,8 +136,8 @@ which exists on both ends. You wouldn't expect them to send you an object of the MyFooziWhatZit class unless you also had a definition for that class. So it is reasonable for the Jelly layer to reject all incoming classes except -the ones that you have explicitly marked with -setUnjellyableForClass. But keep in mind that the sender's idea +the ones that you have explicitly marked with + setUnjellyableForClass. But keep in mind that the sender's idea of a User object might differ from the recipient's, either through namespace collisions between unrelated packages, version skew between nodes that haven't been updated at the same rate, or a malicious @@ -208,7 +209,7 @@ 57

      #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb, jelly @@ -305,7 +306,7 @@ 39 40 41 -

      # Copyright (c) 2009 Twisted Matrix Laboratories. +

      # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ @@ -351,20 +352,20 @@

      The sending side has a class called LilyPond. To make this eligble for transport through callRemote (either as an argument, a return value, or something referenced by either of those [like a -dictionary value]), it must inherit from one of the four Serializable classes. In this section, -we focus on Copyable. -The copyable subclass of LilyPond is called -CopyPond. We create an instance of it and send it through -callRemote as an argument to the receiver's -remote_takePond method. The Jelly layer will serialize +dictionary value]), it must inherit from one of the four Serializable classes. In this section, +we focus on Copyable. +The copyable subclass of LilyPond is called + CopyPond. We create an instance of it and send it through + callRemote as an argument to the receiver's + remote_takePond method. The Jelly layer will serialize (jelly) that object as an instance with a class name of copy_sender.CopyPond and some chunk of data that represents the -object's state. pond.__class__.__module__ and -pond.__class__.__name__ are used to derive the class name -string. The object's getStateToCopy method is -used to get the state: this is provided by pb.Copyable, and the default just retrieves -self.__dict__. This works just like the optional -__getstate__ method used by pickle. The pair of +object's state. pond.__class__.__module__ and + pond.__class__.__name__ are used to derive the class name +string. The object's getStateToCopy method is +used to get the state: this is provided by pb.Copyable, and the default just retrieves + self.__dict__. This works just like the optional + __getstate__ method used by pickle. The pair of name and state are sent over the wire to the receiver.

      The receiving end defines a local class named ReceiverPond @@ -373,10 +374,10 @@ of copy_sender.LilyPond), which specifies how we expect it to behave. We trust that this is the same LilyPond class as the sender used. (At the very least, we hope ours will be able to accept a state -created by theirs). It also inherits from pb.RemoteCopy, which is a requirement for all +created by theirs). It also inherits from pb.RemoteCopy, which is a requirement for all classes that act in this local-representative role (those which are given to -the second argument of setUnjellyableForClass). -RemoteCopy provides the methods that tell the Jelly layer how +the second argument of setUnjellyableForClass). + RemoteCopy provides the methods that tell the Jelly layer how to create the local object from the incoming serialized state.

      Then setUnjellyableForClass is used to register the two @@ -387,12 +388,12 @@

      When the receiver unserializes (unjellies) the object, it will create an instance of the local ReceiverPond class, and hand -the transmitted state (usually in the form of a dictionary) to that object's -setCopyableState method. -This acts just like the __setstate__ method that -pickle uses when unserializing an object. -getStateToCopy/setCopyableState are distinct from -__getstate__/__setstate__ to allow objects to be +the transmitted state (usually in the form of a dictionary) to that object's + setCopyableState method. +This acts just like the __setstate__ method that + pickle uses when unserializing an object. + getStateToCopy/setCopyableState are distinct from + __getstate__/__setstate__ to allow objects to be persisted (across time) differently than they are transmitted (across [memory]space).

      @@ -408,20 +409,20 @@
      -% ./copy_sender.py
      +$ ./copy_sender.py
       7 frogs
       copy_sender.CopyPond
       pond arrived safe and sound
       Main loop terminated.
      -%
      +$
       

      Controlling the Copied State

      -

      By overriding getStateToCopy and -setCopyableState, you can control how the object is transmitted +

      By overriding getStateToCopy and + setCopyableState, you can control how the object is transmitted over the wire. For example, you might want perform some data-reduction: pre-compute some results instead of sending all the raw data over the wire. Or you could replace references to a local object on the sender's side with @@ -429,14 +430,14 @@ references to a receiver-side proxy that could perform the same operations against a local cache of data.

      -

      Another good use for getStateToCopy is to implement +

      Another good use for getStateToCopy is to implement local-only attributes: data that is only accessible by the local process, not to any remote users. For example, a .password attribute could be removed from the object state before sending to a remote system. Combined with the fact that Copyable objects return unchanged from a round trip, this could be used to build a -challenge-response system (in fact PB does this with -pb.Referenceable objects to implement authorization as +challenge-response system (in fact PB does this with + pb.Referenceable objects to implement authorization as described here).

      Whatever getStateToCopy returns from the sending object will @@ -476,7 +477,7 @@ 29

      #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb @@ -550,7 +551,7 @@ 44

      #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb, jelly @@ -615,7 +616,7 @@ 21

      #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.application import service, internet @@ -637,7 +638,7 @@

      In this example, the classes are defined in a separate source file, which -also sets up the binding between them. The SenderPond and +also sets up the binding between them. The SenderPond and ReceiverPond are unrelated save for this binding: they happen to implement the same methods, but use different internal instance variables to accomplish them.

      @@ -652,7 +653,7 @@

      When run, the copy2 example emits the following:

      -% twistd -n -y copy2_receiver.py
      +$ twistd -n -y copy2_receiver.py
       [-] twisted.spread.pb.PBServerFactory starting on 8800
       [-] Starting factory <twisted.spread.pb.PBServerFactory instance at
       0x40604b4c>
      @@ -662,11 +663,10 @@
       
      -% ./copy2_sender.py
      +$ ./copy2_sender.py
       count 7
       pond arrived safe and sound
       Main loop terminated.
      -%
       
      @@ -686,11 +686,8 @@ defined together, with the setUnjellyableForClass immediately following them. - - - -
    1. The class that is sent must inherit from pb.Copyable. The class that is registered to - receive it must inherit from pb.RemoteCopy2.
    2. +
    3. The class that is sent must inherit from pb.Copyable. The class that is registered to + receive it must inherit from pb.RemoteCopy2.
    4. The same class can be used to send and receive. Just have it inherit from both pb.Copyable and pb.RemoteCopy. This @@ -699,16 +696,16 @@ using setCopyableState) versus when it is going (using getStateToCopy).
    5. -
    6. InsecureJelly +
    7. InsecureJelly exceptions are raised by the receiving end. They will be delivered asynchronously to an errback handler. If you do not add one to the Deferred returned by callRemote, then you will never receive notification of the problem.
    8. -
    9. The class that is derived from pb.RemoteCopy will be created using a +
    10. The class that is derived from pb.RemoteCopy will be created using a constructor __init__ method that takes no arguments. All setup must be performed in the setCopyableState method. As - the docstring on RemoteCopy says, don't implement a + the docstring on RemoteCopy says, don't implement a constructor that requires arguments in a subclass of RemoteCopy.
    11. @@ -726,11 +723,11 @@ in twisted.spread.flavors, and the docstrings there are the best source of additional information. -
    12. Copyable is also used in twisted.web.distrib to deliver HTTP requests to other +
    13. Copyable is also used in twisted.web.distrib to deliver HTTP requests to other programs for rendering, allowing subtrees of URL space to be delegated to multiple programs (on multiple machines).
    14. -
    15. twisted.manhole.explorer also uses +
    16. twisted.manhole.explorer also uses Copyable to distribute debugging information from the program under test to the debugging tool.
    17. @@ -744,41 +741,39 @@ processing) to represent its state. slow means that state doesn't change very frequently. It may be more efficient to send the full state only once, the first time it is needed, then afterwards only send the differences -or changes in state whenever it is modified. The pb.Cacheable class provides a framework to +or changes in state whenever it is modified. The pb.Cacheable class provides a framework to implement this.

      -

      pb.Cacheable is derived -from pb.Copyable, so it is +

      pb.Cacheable is derived +from pb.Copyable, so it is based upon the idea of an object's state being captured on the sending side, and then turned into a new object on the receiving side. This is extended to -have an object publishing on the sending side (derived from pb.Cacheable), matched with one -observing on the receiving side (derived from pb.RemoteCache).

      +have an object publishing on the sending side (derived from pb.Cacheable), matched with one +observing on the receiving side (derived from pb.RemoteCache).

      To effectively use pb.Cacheable, you need to isolate changes to your object into accessor functions (specifically setter functions). Your object needs to get control every single time some -attribute is changed3.

      +attribute is changed3.

      You derive your sender-side class from pb.Cacheable, and you -add two methods: getStateToCacheAndObserveFor -and stoppedObserving. The first +add two methods: getStateToCacheAndObserveFor +and stoppedObserving. The first is called when a remote caching reference is first created, and retrieves the data with which the cache is first filled. It also provides an -object called the observer4 - -that points at that receiver-side cache. Every time the state of the object +object called the observer 4 that points at that receiver-side cache. Every time the state of the object is changed, you give a message to the observer, informing them of the change. The other method, stoppedObserving, is called when the remote cache goes away, so that you can stop sending updates.

      -

      On the receiver end, you make your cache class inherit from pb.RemoteCache, and implement the -setCopyableState as you would for a pb.RemoteCopy +

      On the receiver end, you make your cache class inherit from pb.RemoteCache, and implement the + setCopyableState as you would for a pb.RemoteCopy object. In addition, you must implement methods to receive the updates sent to the observer by the pb.Cacheable: these methods should have -names that start with observe_, and match the -callRemote invocations from the sender side just as the usual -remote_* and perspective_* methods match normal -callRemote calls.

      +names that start with observe_, and match the + callRemote invocations from the sender side just as the usual + remote_* and perspective_* methods match normal + callRemote calls.

      The first time a reference to the pb.Cacheable object is sent to any particular recipient, a sender-side Observer will be created for @@ -788,8 +783,8 @@ using setCopyableState just like pb.RemoteCopy, described above (in fact it inherits from that class).

      -

      After that, your setter functions on the sender side should call -callRemote on the Observer, which causes observe_* +

      After that, your setter functions on the sender side should call + callRemote on the Observer, which causes observe_* methods to run on the receiver, which are then supposed to update the receiver-local (cached) state.

      @@ -798,13 +793,13 @@ Just before it dies, it tells the sender side it no longer cares about the original object. When that reference count goes to zero, the Observer goes away and the pb.Cacheable object can stop -announcing every change that takes place. The stoppedObserving method is +announcing every change that takes place. The stoppedObserving method is used to tell the pb.Cacheable that the Observer has gone away.

      With the pb.Cacheable and pb.RemoteCache -classes in place, bound together by a call to -pb.setUnjellyableForClass, all that remains is to pass a +classes in place, bound together by a call to + pb.setUnjellyableForClass, all that remains is to pass a reference to your pb.Cacheable over the wire to the remote end. The corresponding pb.RemoteCache object will automatically be created, and the matching methods will be used to keep the receiver-side @@ -861,7 +856,7 @@ 43

      #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb @@ -955,7 +950,7 @@ 50

      #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb, jelly @@ -1034,7 +1029,7 @@ 28

      #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.application import service, internet @@ -1064,7 +1059,7 @@

      When run, this example emits the following:

      -% twistd -n -y cache_receiver.py
      +$ twistd -n -y cache_receiver.py
       [-] twisted.spread.pb.PBServerFactory starting on 8800
       [-] Starting factory <twisted.spread.pb.PBServerFactory instance at
       0x40615acc>
      @@ -1077,16 +1072,14 @@
       [Broker,0,127.0.0.1]  cache - removeDuck
       [Broker,0,127.0.0.1] [2] ducks:  ['two duck', 'ugly duckling']
       [Broker,0,127.0.0.1] dropping pond
      -%
       
      -% ./cache_sender.py
      +$ ./cache_sender.py
       I have [2] ducks
       I have [3] ducks
       I have [2] ducks
       Main loop terminated.
      -%
       
      @@ -1096,7 +1089,7 @@
    18. There is one Observer for each remote program that holds an active reference. Multiple references inside the same program don't matter: the serialization layer notices the duplicates and does the - appropriate reference counting5. + appropriate reference counting5.
    19. Multiple Observers need to be kept in a list, and all of them need to @@ -1141,22 +1134,20 @@ -

      Footnotes

      1. Note that, in this context, unjelly is +

        Footnotes

        1. Note that, in this context, unjelly is a verb with the opposite meaning of jelly. The verb to jelly means to serialize an object or data structure into a sequence of bytes (or other primitive transmittable/storable representation), while to @@ -1166,30 +1157,29 @@ recipient of the unjellying process. A is unjellyable into B means that a serialized representation A (of some remote object) can be unserialized into a local object of type B. It is these objects B -that are the Unjellyable second argument of the -setUnjellyableForClass function.

          - -

          In particular, unjellyable does not mean cannot be -jellied. Unpersistable means not +that are the Unjellyable second argument of the +setUnjellyableForClass function. +In particular, unjellyable does not mean cannot be +jellied. Unpersistable means not persistable, but unjelly, unserialize, and unpickle mean to reverse the operations of jellying, serializing, and -pickling.

        2. pb.RemoteCopy is actually defined - as pb.RemoteCopy, but - pb.RemoteCopy is the preferred way to access it
        3. of course you could be clever and +pickling.
        4. pb.RemoteCopy is actually defined + in twisted.spread.flavors, but + pb.RemoteCopy is the preferred way to access it
        5. Of course you could be clever and add a hook to __setattr__, along with magical change-announcing subclasses of the usual builtin types, to detect changes that result from normal = set operations. The semi-magical property attributes -that were introduced in Python-2.2 could be useful too. The result might be -hard to maintain or extend, though.
        6. this is actually a RemoteCacheObserver, but it isn't very +that were introduced in Python 2.2 could be useful too. The result might be +hard to maintain or extend, though.
        7. This is actually a RemoteCacheObserver, but it isn't very useful to subclass or modify, so simply treat it as a little demon that sits in your pb.Cacheable class and helps you distribute change -notifications. The only useful thing to do with it is to run its -callRemote method, which acts just like a normal -pb.Referenceable's method of the same name.
        8. this applies to - multiple references through the same Broker. If you've managed to make multiple +notifications. The only useful thing to do with it is to run its +callRemote method, which acts just like a normal +pb.Referenceable's method of the same name.
        9. This applies to + multiple references through the same Broker. If you've managed to make multiple TCP connections to the same program, you deserve whatever you get.

        Index

        - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/pb-cred.html twisted-12.1.0/doc/howto/pb-cred.html --- twisted-10.2.0/doc/howto/pb-cred.html 2010-11-30 03:13:17.000000000 +0000 +++ twisted-12.1.0/doc/howto/pb-cred.html 2012-06-04 08:46:21.000000000 +0000 @@ -20,7 +20,7 @@

        As soon as you have a program which offers services to multiple users, where those users should not be allowed to interfere with each other, you -need to think about authentication. Many services use the idea of an +need to think about authentication. Many services use the idea of an account, and rely upon fact that each user has access to only one account. Twisted uses a system called cred to handle authentication issues, and Perspective Broker has code to make it @@ -29,8 +29,8 @@

        Compartmentalizing Services

        Imagine how you would write a chat server using PB. The first step might -be a ChatServer object which had a bunch of -pb.RemoteReferences that point at user clients. Pretend that +be a ChatServer object which had a bunch of + pb.RemoteReferences that point at user clients. Pretend that those clients offered a remote_print method which lets the server print a message on the user's console. In that case, the server might look something like this:

        @@ -71,8 +71,8 @@ message)) -

        For now, assume that all clients have somehow acquired a -pb.RemoteReference to this ChatServer object, +

        For now, assume that all clients have somehow acquired a + pb.RemoteReference to this ChatServer object, perhaps using pb.Root and getRootObject as described in the previous chapter. In this scheme, when a user sends a message to the group, their client runs @@ -87,7 +87,7 @@

        You've probably seen the first problem: users can trivially spoof each other. We depend upon the user to pass a correct value in their -username argument, and have no way to tell if they're lying or not. + username argument, and have no way to tell if they're lying or not. There is nothing to prevent Alice from modifying her client to do:

        1 @@ -102,8 +102,8 @@

        The best way to fix this is to keep track of the user's name locally, rather than asking them to send it to the server with each message. The best place to keep state is in an object, so this suggests we need a per-user -object. Rather than choosing an obvious name2, let's call this the -User class. +object. Rather than choosing an obvious name2, let's call this the + User class.

        1 @@ -158,8 +158,8 @@ user.send("<%s> says: %s" % (from_username, message))

        -

        Again, assume that each remote client gets access to a single -User object, which is created with the proper username.

        +

        Again, assume that each remote client gets access to a single + User object, which is created with the proper username.

        Note how the ChatServer object has no remote access: it isn't even pb.Referenceable anymore. This means that all access @@ -167,16 +167,16 @@ control.

        As long as Alice only has access to her own User object, she -can no longer spoof Bob. The only way for her to invoke -ChatServer.sendMessage is to call her User +can no longer spoof Bob. The only way for her to invoke + ChatServer.sendMessage is to call her User object's remote_sendMessage method, and that method uses its own state to provide the from_username argument. It doesn't give her any way to change that state.

        This restriction is important. The User object is able to maintain its own integrity because there is a wall between the object and -the client: the client cannot inspect or modify internal state, like the -.name attribute. The only way through this wall is via remote +the client: the client cannot inspect or modify internal state, like the + .name attribute. The only way through this wall is via remote method invocations, and the only control Alice has over those invocations is when they get invoked and what arguments they are given.

        @@ -193,9 +193,9 @@

        Now suppose you wanted to implement group parameters, for example a mode in which nobody was allowed to talk about mattresses because some users were sensitive and calming them down after someone said mattress is a -hassle that were best avoided altogether. Again, per-group state implies a -per-group object. We'll go out on a limb and call this the -Group object:

        +hassle that's best avoided altogether. Again, per-group state implies a +per-group object. We'll go out on a limb and call this the + Group object:

        1 2 @@ -234,7 +234,7 @@ self.server = server self.remote = clientref def remote_joinGroup(self, groupname, allowMattress=True): - return self.server.joinGroup(groupname, self) + return self.server.joinGroup(groupname, self, allowMattress) def send(self, message): self.remote.callRemote("print", message) @@ -244,7 +244,7 @@ self.allowMattress = allowMattress self.users = [] def remote_send(self, from_user, message): - if not self.allowMattress and message.find("mattress") != -1: + if not self.allowMattress and "mattress" in message: raise ValueError, "Don't say that word" for user in self.users: user.send("<%s> says: %s" % (from_user.name, message)) @@ -255,15 +255,15 @@ def __init__(self): self.groups = {} # indexed by name def joinGroup(self, groupname, user, allowMattress): - if not self.groups.has_key(groupname): + if groupname not in self.groups: self.groups[groupname] = Group(groupname, allowMattress) self.groups[groupname].addUser(user) return self.groups[groupname]

        -

        This example takes advantage of the fact that -pb.Referenceable objects sent over a wire can be returned to +

        This example takes advantage of the fact that + pb.Referenceable objects sent over a wire can be returned to you, and they will be turned into references to the same object that you originally sent. The client cannot modify the object in any way: all they can do is point at it and invoke its remote_* methods. Thus, @@ -294,18 +294,18 @@

        The User object is sent from the server side, and is turned into a pb.RemoteReference when it arrives at the client. The client sends it back to Group.remote_send, and PB turns it back -into a reference to the original User when it gets there. -Group.remote_send can then use its .name attribute +into a reference to the original User when it gets there. + Group.remote_send can then use its .name attribute as the sender of the message.

        Note:

        Third party references (there aren't any)

        -

        This technique also relies upon the fact that the -pb.Referenceable reference can only come from someone +

        This technique also relies upon the fact that the + pb.Referenceable reference can only come from someone who holds a corresponding pb.RemoteReference. The design of the -serialization mechanism (implemented in twisted.spread.jelly: pb, jelly, spread.. get it? Look for +serialization mechanism (implemented in twisted.spread.jelly: pb, jelly, spread.. get it? Look for banana, too. What other networking framework can claim API names based on sandwich ingredients?) makes it impossible for a client to obtain a reference that they weren't explicitly given. @@ -315,8 +315,8 @@ will give them anything else. The dict goes away when the connection is dropped, further limiting the scope of those references.

        -

        Futhermore, it is not possible for Bob to send his -User reference to Alice (perhaps over some other PB channel +

        Futhermore, it is not possible for Bob to send his + User reference to Alice (perhaps over some other PB channel just between the two of them). Outside the context of Bob's connection to the server, that reference is just a meaningless number. To prevent confusion, PB will tell you if you try to give it away: when you try to hand @@ -348,8 +348,8 @@

        -

        But again, note the vulnerability. If Alice holds a -RemoteReference to any object on the server side that +

        But again, note the vulnerability. If Alice holds a + RemoteReference to any object on the server side that has a .name attribute, she can use that name as a spoofed from parameter. As a simple example, what if her client code looked like:

        @@ -368,7 +368,7 @@ group.callRemote("send", from_user=group, "hi everybody")
        -

        This would let her send a message that appeared to come from +

        This would let her send a message that appeared to come from #twisted rather than Alice. If she joined a group that happened to be named bob (perhaps it is the How To Be Bob channel, populated by Alice and countless others, a place where they can @@ -380,8 +380,8 @@

        Argument Typechecking

        There are two techniques to close this hole. The first is to have your -remotely-invokable methods do type-checking on their arguments: if -Group.remote_send asserted isinstance(from_user, +remotely-invokable methods do type-checking on their arguments: if + Group.remote_send asserted isinstance(from_user, User) then Alice couldn't use non-User objects to do her spoofing, and hopefully the rest of the system is designed well enough to prevent her from obtaining access to somebody else's User object.

        @@ -391,9 +391,9 @@

        The second technique is to avoid having the client send you the objects altogether. If they don't send you anything, there is nothing to verify. In -this case, you would have to have a per-user-per-group object, in which the -remote_send method would only take a single -message argument. The UserGroup object is created +this case, you would have to have a per-user-per-group object, in which the + remote_send method would only take a single + message argument. The UserGroup object is created with references to the only User and Group objects that it will ever use, so no lookups are needed:

        @@ -429,7 +429,7 @@ self.allowMattress = allowMattress self.users = [] def send(self, from_user, message): - if not self.allowMattress and message.find("mattress") != -1: + if not self.allowMattress and "mattress" in message: raise ValueError, "Don't say that word" for user in self.users: user.send("<%s> says: %s" % (from_user.name, message)) @@ -437,16 +437,16 @@ self.users.append(user) -

        The only message-sending method Alice has left is -UserGroup.remote_send, and it only accepts a message: there are +

        The only message-sending method Alice has left is + UserGroup.remote_send, and it only accepts a message: there are no remaining ways to influence the from name.

        In this model, each remotely-accessible object represents a very small set of capabilities. Security is achieved by only granting a minimal set of abilities to each remote user.

        -

        PB provides a shortcut which makes this technique easier to use. The -Viewable class will be discussed below.

        +

        PB provides a shortcut which makes this technique easier to use. The + Viewable class will be discussed below.

        Avatars and Perspectives

        @@ -460,17 +460,17 @@ to run some code. The avatar object may enforce some security checks, and provide additional data, then call other methods which get things done.

        -

        The two pieces in the cred puzzle (for any protocol, not just PB) are: +

        The two pieces in the cred puzzle (for any protocol, not just PB) are: what serves as the Avatar?, and how does the user get access to it?.

        For PB, the first question is easy. The Avatar is a remotely-accessible -object which can run code: this is a perfect description of -pb.Referenceable and its subclasses. We shall defer the second +object which can run code: this is a perfect description of + pb.Referenceable and its subclasses. We shall defer the second question until the next section.

        -

        In the example above, you can think of the ChatServer and -Group objects as a service. The User object is the +

        In the example above, you can think of the ChatServer and + Group objects as a service. The User object is the user's server-side representative: everything the user is capable of doing is done by running one of its methods. Anything that the server wants to do to the user (change their group membership, change their name, delete their @@ -484,28 +484,28 @@ origin of the term Perspective in Perspective Broker: PB provides and controls (i.e. brokers) access to Perspectives.

        -

        Once upon a time, these local-representative objects were actually called -pb.Perspective. But this has changed with the advent of the +

        Once upon a time, these local-representative objects were actually called + pb.Perspective. But this has changed with the advent of the rewritten cred system, and now the more generic term for a local representative object is an Avatar. But you will still see reference to -Perspective in the code, the docs, and the module names3. Just remember + Perspective in the code, the docs, and the module names3. Just remember that perspectives and avatars are basically the same thing.

        Despite all we've been telling you about how Avatars are more of a concept than an actual class, the base class from -which you can create your server-side avatar-ish objects is, in fact, named -pb.Avatar4. These objects behave very much like -pb.Referenceable. The only difference is that instead of +which you can create your server-side avatar-ish objects is, in fact, named + pb.Avatar4. These objects behave very much like + pb.Referenceable. The only difference is that instead of offering remote_FOO methods, they offer perspective_FOO methods.

        -

        The other way in which pb.Avatar differs from -pb.Referenceable is that the avatar objects are designed to be -the first thing retrieved by a cred-using remote client. Just as -PBClientFactory.getRootObject gives the client access to a -pb.Root object (which can then provide access to all kinds of -other objects), PBClientFactory.login gives client access to a -pb.Avatar object (which can return other references).

        +

        The other way in which pb.Avatar differs from + pb.Referenceable is that the avatar objects are designed to be +the first thing retrieved by a cred-using remote client. Just as + PBClientFactory.getRootObject gives the client access to a + pb.Root object (which can then provide access to all kinds of +other objects), PBClientFactory.login gives client access to a + pb.Avatar object (which can return other references).

        So, the first half of using cred in your PB application is to create an Avatar object which implements perspective_ methods and is @@ -581,7 +581,7 @@ 29

        #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from zope.interface import implements @@ -633,7 +633,7 @@ 22

        #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb @@ -664,8 +664,8 @@

        When the client runs login to request the Perspective, they can provide it with an optional client argument (which must be a pb.Referenceable object). If they do, then a -reference to that object will be handed to the realm's -requestAvatar in the mind argument.

        +reference to that object will be handed to the realm's + requestAvatar in the mind argument.

        The server-side Perspective can use it to invoke remote methods on something in the client, so that the client doesn't always have to drive the @@ -710,7 +710,7 @@ 30

        #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from zope.interface import implements @@ -763,7 +763,7 @@ 22

        #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb @@ -811,7 +811,7 @@ 25

        #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb @@ -850,8 +850,8 @@ our server-side Avatar. It implements a perspective_foo method that is exposed to the remote client.

        -

        Second, we created a realm (an object which implements -IRealm, and therefore implements requestAvatar). +

        Second, we created a realm (an object which implements + IRealm, and therefore implements requestAvatar). This realm manufactures MyPerspective objects. It makes as many as we want, and names each one with the avatarID (a username) that comes out of the checkers. This MyRealm object returns two other objects as well, @@ -861,11 +861,11 @@ dispatch incoming clients to the credential checkers, and then to request Avatars for any which survive the authentication process.

        -

        Fourth, we made a simple checker (an object which implements -IChecker) to hold valid user/password pairs. The checker +

        Fourth, we made a simple checker (an object which implements + IChecker) to hold valid user/password pairs. The checker gets registered with the portal, so it knows who to ask when new -clients connect. We use a checker named -InMemoryUsernamePasswordDatabaseDontUse, which suggests +clients connect. We use a checker named + InMemoryUsernamePasswordDatabaseDontUse, which suggests that 1: all the username/password pairs are kept in memory instead of being saved to a database or something, and 2: you shouldn't use it. The admonition against using it is because there are better @@ -884,19 +884,19 @@

        On the client side, a pb.PBClientFactory is created (as before) and attached to a TCP connection. When the connection completes, the factory will be asked to produce a Protocol, and -it will create a PB object. Unlike the previous chapter, where we used -.getRootObject, here we use factory.login to -initiate the cred authentication process. We provide a -credentials object, which is the client-side agent for doing +it will create a PB object. Unlike the previous chapter, where we used + .getRootObject, here we use factory.login to + initiate the cred authentication process. We provide a + credentials object, which is the client-side agent for doing our half of the authentication process. This process may involve several messages: challenges, responses, encrypted passwords, secure hashes, etc. We give our credentials object everything it will need to respond correctly (in this case, a username and password, but you could write a credential that used public-key encryption or even fancier techniques).

        -

        login returns a Deferred which, when it fires, will return a -pb.RemoteReference to the remote avatar. We can then do -callRemote to invoke a perspective_foo method on +

        login returns a Deferred which, when it fires, will return a + pb.RemoteReference to the remote avatar. We can then do + callRemote to invoke a perspective_foo method on that Avatar.

        @@ -995,7 +995,7 @@ 91

        #!/usr/bin/env python -# Copyright (c) 2007-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ @@ -1157,7 +1157,7 @@ 70

        #!/usr/bin/env python -# Copyright (c) 2007-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ @@ -1228,20 +1228,18 @@

        pbAnonServer.py implements a server based on pb6server.py, extending it to -permit anonymous logins in addition to authenticated logins. A -AllowAnonymousAccess -checker and a -InMemoryUsernamePasswordDatabaseDontUse checker are registered and the +permit anonymous logins in addition to authenticated logins. An + AllowAnonymousAccess +checker and an InMemoryUsernamePasswordDatabaseDontUse +checker are registered and the client's choice of credentials object determines which is used to authenticate the login. In either case, the realm will be called on to create an avatar for the login. AllowAnonymousAccess always produces an avatarId - of ANONYMOUS.

        +
        of twisted.cred.checkers.ANONYMOUS.

        -

        On the client side, the only change is the use of an instance of -Anonymous when calling -PBClientFactory.login.

        +

        On the client side, the only change is the use of an instance of + Anonymous when calling + PBClientFactory.login.

        Using Avatars

        @@ -1270,8 +1268,8 @@

        Making Avatars

        -

        In the example above, we create Avatars upon request, during -requestAvatar. Depending upon the service, these Avatars might +

        In the example above, we create Avatars upon request, during + requestAvatar. Depending upon the service, these Avatars might already exist before the connection is received, and might outlive the connection. The Avatars might also accept multiple connections.

        @@ -1282,8 +1280,8 @@ case, it would probably return a Deferred so it could provide the real Avatar later, once the lookup had completed.

        -

        Here are some possible implementations of -MyRealm.requestAvatar:

        +

        Here are some possible implementations of + MyRealm.requestAvatar:

        1 2 @@ -1380,8 +1378,8 @@

        One common idiom which accomplishes this is to have the Realm tell the avatar that a remote client has just attached. The Realm can also ask the protocol to let it know when the connection goes away, so it can then inform -the Avatar that the client has detached. The third member of the -requestAvatar return tuple is a callable which will be invoked +the Avatar that the client has detached. The third member of the + requestAvatar return tuple is a callable which will be invoked when the connection is lost.

        1 @@ -1428,12 +1426,11 @@

        Viewable

        Once you have IPerspective objects (i.e. the Avatar) to -represent users, the Viewable class can come into play. This -class behaves a lot like Referenceable: it turns into a -RemoteReference when sent over the wire, and certain methods +represent users, the Viewable class can come into play. This +class behaves a lot like Referenceable: it turns into a + RemoteReference when sent over the wire, and certain methods can be invoked by the holder of that reference. However, the methods that -can be called have names that start with view_ instead of -remote_, and those methods are always called with an extra +can be called have names that start with view_ instead of remote_, and those methods are always called with an extra perspective argument that points to the Avatar through which the reference was sent:

        @@ -1447,7 +1444,7 @@

        This is useful if you want to let multiple clients share a reference to the same object. The view_ methods can use the -perspective argument to figure out which client is calling them. This + perspective argument to figure out which client is calling them. This gives them a way to do additional permission checks, do per-user accounting, etc.

        @@ -1456,7 +1453,7 @@ just have per-group objects which inherit from pb.Viewable, and give the user references to them. The local pb.Avatar object will automatically show up as the perspective argument in the -view_* method calls, give you a chance to involve the Avatar in + view_* method calls, give you a chance to involve the Avatar in the process.

        @@ -1535,7 +1532,7 @@ 65

        #!/usr/bin/env python -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from zope.interface import implements @@ -1583,7 +1580,7 @@ def addUser(self, user): self.users.append(user) def view_send(self, from_user, message): - if not self.allowMattress and message.find("mattress") != -1: + if not self.allowMattress and "mattress" in message: raise ValueError, "Don't say that word" for user in self.users: user.send("<%s> says: %s" % (from_user.name, message)) @@ -1602,9 +1599,9 @@

        Notice that the client uses perspective_joinGroup to both join a group and retrieve a RemoteReference to the -Group object. However, the reference they get is actually to a + Group object. However, the reference they get is actually to a special intermediate object called a pb.ViewPoint. When they do -group.callRemote("send", "message"), their avatar is inserted + group.callRemote("send", "message"), their avatar is inserted into the argument list that Group.view_send actually sees. This lets the group get their username out of the Avatar without giving the client an opportunity to spoof someone else.

        @@ -1655,7 +1652,7 @@ 41 42

        #!/usr/bin/env python -# Copyright (c) 2009-2010 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.spread import pb @@ -1676,12 +1673,12 @@ reactor.run() def connected(self, perspective): - print "connected, joining group #lookingForFourth" + print "connected, joining group #NeedAFourth" # this perspective is a reference to our User object. Save a reference # to it here, otherwise it will get garbage collected after this call, # and the server will think we logged out. self.perspective = perspective - d = perspective.callRemote("joinGroup", "#lookingForFourth") + d = perspective.callRemote("joinGroup", "#NeedAFourth") d.addCallback(self.gotGroup) def gotGroup(self, group): @@ -1704,17 +1701,17 @@ client code entirely to accomplish this juvenile prank. Given this adversarial relationship, one must wonder why she and Bob seem to spend so much time together: their adventures are clearly documented by the -cryptographic literature.
      2. the -obvious name is clearly +cryptographic literature.
      3. The +obvious name is clearly ServerSidePerUserObjectWhichNobodyElseHasAccessTo, but because -python makes everything else so easy to read, it only seems fair to make -your audience work for something
      4. We could just go ahead and rename Perspective Broker to be -Avatar Broker, but 1) that would cause massive compatibility problems, and 2) +Python makes everything else so easy to read, it only seems fair to make +your audience work for something.
      5. We could just go ahead and rename Perspective Broker to be +Avatar Broker, but 1) that would cause massive compatibility problems, and 2) AB doesn't fit into the whole sandwich-themed naming scheme nearly as well as PB does. If we changed it to AB, we'd probably have to change Banana to be CD (CoderDecoder), and Jelly to be EF (EncapsulatorFragmentor). twisted.spread would then have to be renamed twisted.alphabetsoup, and then -the whole food-pun thing would start all over again.
      6. The avatar-ish class is named +the whole food-pun thing would start all over again.
      7. The avatar-ish class is named pb.Avatar because pb.Perspective was already taken, by the (now obsolete) oldcred perspective-ish class. It is a pity, but it simply wasn't possible both replace pb.Perspective @@ -1722,6 +1719,6 @@ backwards-compatibility.

      Index

      - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/pb.html twisted-12.1.0/doc/howto/pb.html --- twisted-10.2.0/doc/howto/pb.html 2010-11-30 03:13:15.000000000 +0000 +++ twisted-12.1.0/doc/howto/pb.html 2012-06-04 08:46:20.000000000 +0000 @@ -11,7 +11,7 @@

      Perspective Broker (affectionately known as PB) is an -asynchronous, symmetric1 network protocol for secure, +asynchronous, symmetric1 network protocol for secure, remote method calls and transferring of objects. PB is translucent, not transparent, meaning that it is very visible and obvious to see the difference between local method calls and potentially remote method calls, @@ -23,7 +23,7 @@ either copied each time the value is returned, or cached: only copied once and updated by notifications.

      -

      PB gets its name from the fact that access to objects is through a +

      PB gets its name from the fact that access to objects is through a perspective. This means that when you are responding to a remote method call, you can establish who is making the call.

      @@ -42,11 +42,11 @@ without restarting the server or client.

      Footnotes

      1. There is a negotiation phase -for banana with particular roles for listener and initiator, so it's not +for the banana serialization protocol with particular roles for listener and initiator, so it's not completely symmetric, but after the connection is fully established, the protocol is completely symmetrical.

      Index

      - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/pb-intro.html twisted-12.1.0/doc/howto/pb-intro.html --- twisted-10.2.0/doc/howto/pb-intro.html 2010-11-30 03:13:18.000000000 +0000 +++ twisted-12.1.0/doc/howto/pb-intro.html 2012-06-04 08:46:18.000000000 +0000 @@ -16,9 +16,9 @@ have two programs that need to talk to each other, and you get to use any protocol you want. If you can think of your problem in terms of objects that need to make method calls on each other, then chances are good that you can -use twisted's Perspective Broker protocol rather than trying to shoehorn +use Twisted's Perspective Broker protocol rather than trying to shoehorn your needs into something like HTTP, or implementing yet another RPC -mechanism1.

      +mechanism1.

      The Perspective Broker system (abbreviated PB, spawning numerous sandwich-related puns) is based upon a few central concepts:

      @@ -33,7 +33,7 @@
    20. remote method calls: doing something to a local object and causing a method to get run on a distant one. The local object is called a - RemoteReference, and you + RemoteReference, and you do something by running its .callRemote method.
    21. @@ -54,13 +54,13 @@ @@ -69,15 +69,15 @@
        -
      • RemoteReference +
      • RemoteReference : spread/pb.py
      • -
      • pb.Root +
      • pb.Root : spread/pb.py, actually defined as twisted.spread.flavors.Root in spread/flavors.py
      • -
      • pb.Referenceable +
      • pb.Referenceable : spread/pb.py, actually defined as twisted.spread.flavors.Referenceable in spread/flavors.py
      • @@ -88,15 +88,15 @@ about authorization and security:

        Subclassing and Implementing

        @@ -110,17 +110,17 @@
          -
        • pb.Root, pb.Referenceable: you'll +
        • pb.Root, pb.Referenceable: you'll subclass these to make remotely-referenceable objects (i.e., objects which you can call methods on remotely) using PB. You don't need to change any of the existing behavior, just inherit all of it and add the remotely-accessible methods that you want to export.
        • -
        • pb.Avatar: You'll +
        • pb.Avatar: You'll be subclassing this when you get into PB programming with authorization. This is an implementor of IPerspective.
        • -
        • ICredentialsChecker: Implement this if +
        • ICredentialsChecker: Implement this if you want to authenticate your users against some sort of data store: i.e., an LDAP database, an RDBMS, etc. There are already a few implementations of this for various back-ends in @@ -133,14 +133,14 @@

          Things you can Call Remotely

          At this writing, there are three flavors of objects that can -be accessed remotely through RemoteReference objects. Each of these +be accessed remotely through RemoteReference objects. Each of these flavors has a rule for how the callRemote message is transformed into a local method call on the server. In order to use one of these flavors, subclass them and name your published methods with the appropriate prefix.

            -
          • twisted.spread.pb.IPerspective implementors +
          • twisted.spread.pb.IPerspective implementors

            This is the first interface we deal with. It is a perspective onto your PB application. Perspectives are slightly special because @@ -165,7 +165,7 @@

          • -
          • twisted.spread.pb.Referenceable +
          • twisted.spread.pb.Referenceable

            Referenceable objects are the simplest kind of PB object. You can call methods on them and return them from methods to provide access to other @@ -179,7 +179,7 @@

          • -
          • twisted.spread.pb.Viewable +
          • twisted.spread.pb.Viewable

            Viewable objects are remotely referenceable objects which have the additional requirement that it must be possible to tell who is calling them. @@ -202,19 +202,19 @@

            There are 2 basic flavors that allow for copying objects remotely. Again, you can use these by subclassing them. In order to specify what state you want -to have copied when these are serialized, you can either use the Python default -__getstate__ or specialized method calls for that +to have copied when these are serialized, you can either use the Python default + __getstate__ or specialized method calls for that flavor.

            -

            Factories

            +

            Factories

            -

            As mentioned before, usually the class twisted.internet.protocol.Factory works, - and there is no need to subclass it. However, sometimes there - can be factory-specific configuration of the protocols, or - other considerations. In those cases, there is a need to - subclass Factory.

            +

            Simpler Protocol Creation

            For a factory which simply instantiates instances of a - specific protocol class, simply instantiate - Factory, and sets its protocol attribute:

            -

            1 -2 -3 -4 -5 -

            from twisted.internet.protocol import Factory -from twisted.protocols.wire import Echo - -myFactory = Factory() -myFactory.protocol = Echo -
            + specific protocol class, there is a simpler way to implement the factory. + The default implementation of the buildProtocol method calls + the protocol attribute of the factory to create + a Protocol instance, and then sets an attribute on it + called factory which points to the factory + itself. This lets every Protocol access, and possibly + modify, the persistent configuration. Here is an example that uses these + features instead of overriding buildProtocol:

            -

            If there is a need to easily construct factories for a - specific configuration, a factory function is often useful:

            1 2 3 @@ -295,22 +314,42 @@ 12 13 14 +15 +16 +17 +18 +19 +20 +21 +22 +23

            from twisted.internet.protocol import Factory, Protocol +from twisted.internet.endpoints import TCP4ServerEndpoint +from twisted.internet import reactor class QOTD(Protocol): def connectionMade(self): - self.transport.write(self.factory.quote+'\r\n') + # self.factory was set by the factory's default buildProtocol: + self.transport.write(self.factory.quote + '\r\n') self.transport.loseConnection() -def makeQOTDFactory(quote=None): - factory = Factory() - factory.protocol = QOTD - factory.quote = quote or 'An apple a day keeps the doctor away' - return factory +class QOTDFactory(Factory): + + # This will be used by the default buildProtocol to create new protocols: + protocol = QOTD + + def __init__(self, quote=None): + self.quote = quote or 'An apple a day keeps the doctor away' + +endpoint = TCP4ServerEndpoint(reactor, 8007) +endpoint.listen(QOTDFactory("configurable quote")) +reactor.run()
            +

            Factory Startup and Shutdown

            +

            A Factory has two methods to perform application-specific building up and tearing down (since a Factory is frequently persisted, it is often not appropriate to do them in __init__ @@ -364,13 +403,15 @@ self.fp.close() -

            Putting it All Together

            +

            Putting it All Together

            -

            So, you know what factories are, and want to run the QOTD - with configurable quote server, do you? No problems, here is an - example.

            +

            As a final example, here's a simple chat server that allows + users to choose a username and then communicate with other + users. It demonstrates the use of shared state in the factory, a + state machine for each individual protocol, and communication + between different protocols.

            -

            1 +

            1 2 3 4 @@ -389,40 +430,119 @@ 17 18 19 -

            from twisted.internet.protocol import Factory, Protocol +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 +

            from twisted.internet.protocol import Factory +from twisted.protocols.basic import LineReceiver from twisted.internet import reactor -class QOTD(Protocol): +class Chat(LineReceiver): + + def __init__(self, users): + self.users = users + self.name = None + self.state = "GETNAME" def connectionMade(self): - self.transport.write(self.factory.quote+'\r\n') - self.transport.loseConnection() + self.sendLine("What's your name?") + def connectionLost(self, reason): + if self.users.has_key(self.name): + del self.users[self.name] -class QOTDFactory(Factory): + def lineReceived(self, line): + if self.state == "GETNAME": + self.handle_GETNAME(line) + else: + self.handle_CHAT(line) - protocol = QOTD + def handle_GETNAME(self, name): + if self.users.has_key(name): + self.sendLine("Name taken, please choose another.") + return + self.sendLine("Welcome, %s!" % (name,)) + self.name = name + self.users[name] = self + self.state = "CHAT" - def __init__(self, quote=None): - self.quote = quote or 'An apple a day keeps the doctor away' + def handle_CHAT(self, message): + message = "<%s> %s" % (self.name, message) + for name, protocol in self.users.iteritems(): + if protocol != self: + protocol.sendLine(message) -reactor.listenTCP(8007, QOTDFactory("configurable quote")) -reactor.run() -
            -

            The only lines you might not understand are the last two.

            +class ChatFactory(Factory): + + def __init__(self): + self.users = {} # maps user names to Chat instances -

            listenTCP is -the method which connects a Factory to the network. -It uses the reactor interface, which lets many different loops handle -the networking code, without modifying end-user code, like this. -As mentioned above, if you want to write your code to be a production-grade -Twisted server, and not a mere 20-line hack, you will want to -use the Application object.

            + def buildProtocol(self, addr): + return Chat(self.users) + + +reactor.listenTCP(8123, ChatFactory()) +reactor.run() +
            Source listing - listings/servers/chat.py
            + +

            The only API you might not be familiar with + is listenTCP. listenTCP is + the method which connects a Factory to the network. + This is the lower-level API + that endpoints wraps for you.

            + +

            Here's a sample transcript of a chat session (this is text entered by the user):

            + +
            +$ telnet 127.0.0.1 8123
            +Trying 127.0.0.1...
            +Connected to 127.0.0.1.
            +Escape character is '^]'.
            +What's your name?
            +test
            +Name taken, please choose another.
            +bob
            +Welcome, bob!
            +hello
            +<alice> hi bob
            +twisted makes writing servers so easy!
            +<alice> I couldn't agree more
            +<carrol> yeah, it's great
            +

            Index

            - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/ssl.html twisted-12.1.0/doc/howto/ssl.html --- twisted-10.2.0/doc/howto/ssl.html 2010-11-30 03:13:15.000000000 +0000 +++ twisted-12.1.0/doc/howto/ssl.html 2012-06-04 08:46:20.000000000 +0000 @@ -32,21 +32,21 @@ key file name, and certificate file name.

            Instead of using listenTCP and connectTCP to create a connection, use - listenSSL and - connectSSL for a + listenSSL and + connectSSL for a server and client respectively. These methods take a contextFactory as an additional argument.

            The basic server context factory is - twisted.internet.ssl.ContextFactory, and the basic + twisted.internet.ssl.ContextFactory, and the basic client context factory is - twisted.internet.ssl.ClientContextFactory. They can + twisted.internet.ssl.ClientContextFactory. They can be used as-is or subclassed. - twisted.internet.ssl.DefaultOpenSSLContextFactory + twisted.internet.ssl.DefaultOpenSSLContextFactory is a convenience server class that subclasses ContextFactory and adds default parameters to the SSL handshake and connection. Another useful class is - twisted.internet.ssl.CertificateOptions; it is a + twisted.internet.ssl.CertificateOptions; it is a factory for SSL context objects that lets you specify many of the common verification and session options so it can do the proper pyOpenSSL initialization for you.

            @@ -168,12 +168,12 @@ is explicitly disallowed in both DefaultOpenSSLContextFactory and ClientContextFactory for being insecure by calling set_options(SSL.OP_NO_SSLv2) on their contexts. See - twisted.internet.ssl for additional comments.

            + twisted.internet.ssl for additional comments.

            Using startTLS

            If you want to switch from unencrypted to encrypted traffic - mid-connection, you'll need to turn on SSL with startTLS on both + mid-connection, you'll need to turn on SSL with startTLS on both ends of the connection at the same time via some agreed-upon signal like the reception of a particular message. You can readily verify the switch to an encrypted channel by examining the packet payloads with a tool like @@ -526,10 +526,10 @@

            Other facilities

            -

            twisted.protocols.amp supports encrypted +

            twisted.protocols.amp supports encrypted connections and exposes a startTLS method one can use or - subclass. twisted.web has built-in SSL support in - its client, http, and xmlrpc modules.

            + subclass. twisted.web has built-in SSL support in + its client, http, and xmlrpc modules.

            Conclusion

            @@ -545,6 +545,6 @@

            Index

            - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/tap.html twisted-12.1.0/doc/howto/tap.html --- twisted-10.2.0/doc/howto/tap.html 2010-11-30 03:13:18.000000000 +0000 +++ twisted-12.1.0/doc/howto/tap.html 2012-06-04 08:46:20.000000000 +0000 @@ -6,7 +6,7 @@

            Writing a twistd Plugin

            - +
            @@ -21,7 +21,7 @@

            There are a few prerequisites to understanding this document:

            Index

            - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/telnet.html twisted-12.1.0/doc/howto/telnet.html --- twisted-10.2.0/doc/howto/telnet.html 2010-11-30 03:13:18.000000000 +0000 +++ twisted-12.1.0/doc/howto/telnet.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,83 +0,0 @@ - - -Twisted Documentation: Using telnet to manipulate a twisted server - - - - -

            Using telnet to manipulate a twisted server

            -
              -
              - - -

              To start things off, we're going to create a simple server that just -gives you remote access to a Python interpreter. We will use a telnet client -to access this server.

              - -

              Run twistd telnet -p 4040 -u admin -w admin at -your shell prompt. The Application has a telnet server that you specified to -be on port 4040, and it will start listening for connections on this port. Try -connecting with your favorite telnet utility to 127.0.0.1 port 4040.

              - -
              -$ telnet localhost 4040
              -Trying 127.0.0.1...
              -Connected to localhost.
              -Escape character is '^]'.
              -
              -twisted.manhole.telnet.ShellFactory
              -Twisted 1.1.0
              -username: admin
              -password: admin
              ->>>
              -
              - -

              Now, you should see a Python prompt -- ->>>. You can type any valid Python code -here. Let's try looking around.

              - -
              ->>> dir()
              -['__builtins__']
              -
              - -

              Ok, not much. let's play a little more:

              -
              ->>> import __main__
              ->>> dir(__main__)
              -['__builtins__', '__doc__', '__name__', 'os', 'run', 'string', 'sys']
              -
              ->>> service
              -<twisted.application.internet.TCPServer instance at 0x10270f48>
              ->>> service._port
              -<twisted.manhole.telnet.ShellFactory on 4040>
              ->>> service.parent
              -<twisted.application.service.MultiService instance at 0x1024d7a8>
              -
              - -

              The service object is the service used to serve the telnet shell, -and that it is listening on port 4040 with something called a -ShellFactory. -Its parent is a twisted.application.service.MultiService, -a collection of services. We can keep getting the parent attribute -of services until we hit the root of all services.

              - -

              As you can see, this is quite useful - we can introspect a -running process, see the internal objects, and even change -their attributes. The telnet server can of course be used from straight -Python code; you can see how to do this by reading the code for -twisted.tap.telnet.

              - -

              A final note - if you want access to be more secure, you can even -have the telnet server use SSL. Assuming you have the appropriate -certificate and private key files, you can twistd -telnet -p ssl:443:privateKey=mykey.pem:certKey=cert.pem -u admin -w -admin. See twisted.application.strports for more examples of -options for listening on a port.

              - -
              - -

              Index

              - Version: 10.2.0 - - \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/testing.html twisted-12.1.0/doc/howto/testing.html --- twisted-10.2.0/doc/howto/testing.html 2010-11-30 03:13:14.000000000 +0000 +++ twisted-12.1.0/doc/howto/testing.html 2012-06-04 08:46:18.000000000 +0000 @@ -39,7 +39,7 @@ created if two instances of Trial are run in parallel from the same directory, so as to avoid giving two different test-runs the same temporary directory.

              -

              The twisted.python.lockfile utility is used to lock +

              The twisted.python.lockfile utility is used to lock the _trial_temp directories. On Linux, this results in symlinks to pids. On Windows, directories are created with a single file with a pid as the contents. These lock files will be cleaned up if Trial exits normally @@ -70,10 +70,10 @@

              If your test leaves event sources in the reactor, Trial will fail the test. The tearDown method is a good place to put cleanup code: it is -always run regardless of whether your test passes or fails (like a bare -except clause in a try-except construct). Exceptions in tearDown - are flagged as errors and flunk the test. -TestCase.addCleanup is +always run regardless of whether your test passes or fails (like a finally +clause in a try-except-finally construct). Exceptions in tearDown +are flagged as errors and flunk the test. + TestCase.addCleanup is another useful tool for cleaning up. With it, you can register callables to clean up resources as the test allocates them. Generally, code should be written so that only resources allocated in the tests need to be cleaned up in @@ -83,25 +83,24 @@

              If your code uses Deferreds or depends on the reactor running, you can return a Deferred from your test method, setUp, or tearDown and Trial will do the right thing. That is, it will run the reactor for you until the -Deferred has triggered and its callbacks have been run. Don't use -reactor.run(), reactor.stop(), reactor.crash() -or reactor.iterate() in your tests.

              +Deferred has triggered and its callbacks have been run. Don't use + reactor.run(), reactor.stop(), reactor.crash() or reactor.iterate() in your tests.

              -

              Calls to reactor.callLater create IDelayedCalls. These need to be run +

              Calls to reactor.callLater create IDelayedCalls. These need to be run or cancelled during a test, otherwise they will outlive the test. This would be bad, because they could interfere with a later test, causing confusing failures in unrelated tests! For this reason, Trial checks the reactor to make -sure there are no leftover IDelayedCalls in the reactor after a +sure there are no leftover IDelayedCalls in the reactor after a test, and will fail the test if there are. The cleanest and simplest way to make sure this all works is to return a Deferred from your test.

              Similarly, sockets created during a test should be closed by the end of the test. This applies to both listening ports and client connections. So, calls to reactor.listenTCP (and listenUNIX, and so on) -return IListeningPorts, and these should be -cleaned up before a test ends by calling their stopListening method. -Calls to reactor.connectTCP return IConnectors, which should be cleaned -up by calling their disconnect method. Trial +return IListeningPorts, and these should be +cleaned up before a test ends by calling their stopListening method. +Calls to reactor.connectTCP return IConnectors, which should be cleaned +up by calling their disconnect method. Trial will warn about unclosed sockets.

              The golden rule is: If your tests call a function which returns a Deferred, @@ -126,43 +125,43 @@

              Interacting with warnings in tests

              -

              Trial includes specific support for interacting with Python's -warnings module. This support allows warning-emitting code to +

              Trial includes specific support for interacting with Python's + warnings module. This support allows warning-emitting code to be written test-driven, just as any other code would be. It also improves the way in which warnings reporting when a test suite is running.

              -

              TestCase.assertWarns and TestCase.flushWarnings -allow tests to be written which make assertions about what warnings have -been emitted during a particular test method. flushWarnings is -the new method and has a simpler and more flexible API and should be -preferred when writing new code. In order to test a warning with -flushWarnings, write a test which first invokes the code which +

              TestCase.flushWarnings +allows tests to be written which make assertions about what warnings have +been emitted during a particular test method. In order to test a warning with + flushWarnings, write a test which first invokes the code which will emit a warning and then calls flushWarnings and makes assertions about the result. For example:

              1 2 3 -

              def test_warning(self): - warnings.warn("foo is bad") - self.assertEqual(len(self.flushWarnings()), 1) +4 +

              class SomeWarningsTests(TestCase): + def test_warning(self): + warnings.warn("foo is bad") + self.assertEqual(len(self.flushWarnings()), 1)

              Warnings emitted in tests which are not flushed will be included by the default reporter in its output after the result of the test. If Python's -warnings filter system (see the -W command -line option to Python) is configured to treat a warning as an error, +warnings filter system (see the +-W command option to Python) is configured to treat a warning as an error, then unflushed warnings will causes tests to fail and will be included in the summary section of the default reporter. Note that unlike usual operation, when warnings.warn is called as part of a test method, it will not raise an exception when warnings have been configured as errors. However, if called outside of a test method (for example, at module -scope in a test module or a module imported by a test module) then it -will raise an exception.

              +scope in a test module or a module imported by a test module) then it + will raise an exception.

              Index

              - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/threading.html twisted-12.1.0/doc/howto/threading.html --- twisted-10.2.0/doc/howto/threading.html 2010-11-30 03:13:14.000000000 +0000 +++ twisted-12.1.0/doc/howto/threading.html 2012-06-04 08:46:18.000000000 +0000 @@ -15,7 +15,7 @@

              Most code in Twisted is not thread-safe. For example, writing data to a transport from a protocol is not thread-safe. Therefore, we want a way to schedule methods to be run in the - main event loop. This can be done using the function twisted.internet.interfaces.IReactorThreads.callFromThread:

              + main event loop. This can be done using the function twisted.internet.interfaces.IReactorThreads.callFromThread:

              1 2 3 @@ -44,8 +44,8 @@

              Sometimes we may want to run methods in threads - for example, in order to access blocking APIs. Twisted provides - methods for doing so using the IReactorThreads API (twisted.internet.interfaces.IReactorThreads). - Additional utility functions are provided in twisted.internet.threads. Basically, these + methods for doing so using the IReactorThreads API (twisted.internet.interfaces.IReactorThreads). + Additional utility functions are provided in twisted.internet.threads. Basically, these methods allow us to queue methods to be run by a thread pool.

              @@ -74,8 +74,8 @@

              Utility Methods

              -

              The utility methods are not part of the twisted.internet.reactor APIs, but are implemented - in twisted.internet.threads.

              +

              The utility methods are not part of the twisted.internet.reactor APIs, but are implemented + in twisted.internet.threads.

              If we have multiple methods to run sequentially within a thread, we can do:

              @@ -143,7 +143,7 @@

              If you wish to call a method in the reactor thread and get its result, - you can use blockingCallFromThread:

              + you can use blockingCallFromThread:

              1 2 @@ -187,7 +187,7 @@

              Managing the Thread Pool

              -

              The thread pool is implemented by twisted.python.threadpool.ThreadPool.

              +

              The thread pool is implemented by twisted.python.threadpool.ThreadPool.

              We may want to modify the size of the threadpool, increasing or decreasing the number of threads in use. We can do this @@ -208,6 +208,6 @@

              Index

              - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/time.html twisted-12.1.0/doc/howto/time.html --- twisted-10.2.0/doc/howto/time.html 2010-11-30 03:13:14.000000000 +0000 +++ twisted-12.1.0/doc/howto/time.html 2012-06-04 08:46:20.000000000 +0000 @@ -11,7 +11,7 @@

              Let's say we want to run a task X seconds in the future. - The way to do that is defined in the reactor interface twisted.internet.interfaces.IReactorTime:

              + The way to do that is defined in the reactor interface twisted.internet.interfaces.IReactorTime:

              1 2 3 @@ -33,8 +33,8 @@

              If the result of the function is important or if it may be necessary - to handle exceptions it raises, then the twisted.internet.task.deferLater utility conveniently - takes care of creating a Deferred and setting up a delayed + to handle exceptions it raises, then the twisted.internet.task.deferLater utility conveniently + takes care of creating a Deferred and setting up a delayed call:

              1 2 @@ -65,7 +65,7 @@

              If we want a task to run every X seconds repeatedly, we can - use twisted.internet.task.LoopingCall:

              + use twisted.internet.task.LoopingCall:

              1 2 3 @@ -113,6 +113,6 @@

              Index

              - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/trial.html twisted-12.1.0/doc/howto/trial.html --- twisted-10.2.0/doc/howto/trial.html 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/trial.html 2012-06-04 08:46:19.000000000 +0000 @@ -0,0 +1,2042 @@ + + +Twisted Documentation: Test-driven development with Twisted + + + + +

              Test-driven development with Twisted

              + +
              + + + +

              Writing good code is hard, or at least it can be. A major challenge is +to ensure that your code remains correct as you add new functionality.

              + +

              Unit testing is a +modern, light-weight testing methodology in widespread use in many +programming languages. Development that relies on unit tests is often +referred to as Test-Driven Development +(TDD). +Most Twisted code is tested using TDD.

              + +

              To gain a solid understanding of unit testing in Python, you should read +the unittest -- +Unit testing framework chapter of the Python Library +Reference. There is also a ton of information available online and in +books.

              + +

              Introductory example of Python unit testing

              + +

              This document is principally a guide to Trial, Twisted's unit testing +framework. Trial is based on Python's unit testing framework. While we do not +aim to give a comprehensive guide to general Python unit testing, it will be +helpful to consider a simple non-networked example before expanding to cover a +networking code that requires the special capabilities of Trial. If you are +already familiar with unit test in Python, jump straight to the section +specific to testing Twisted code.

              + +

              Note: In what follows we will make a series of refinements +to some simple classes. In order to keep the examples and source code links +complete and to allow you to run Trial on the intermediate results at every +stage, I add _N (where the N are successive +integers) to file names to keep them separate. This is a minor visual +distraction that should be ignored.

              + +

              Creating an API and writing tests

              + +

              We'll create a library for arithmetic calculation. First, create a +project structure with a directory called calculus containing an empty __init__.py file.

              + +

              Then put the following simple class definition API into calculus/base_1.py:

              + +
              + +

              (Ignore the test-case-name comment for +now. You'll see why that's useful below.)

              + +

              We've written the interface, but not the code. Now we'll write a set of +tests. At this point of development, we'll be expecting all tests to +fail. Don't worry, that's part of the point. Once we have a test framework +functioning, and we have some decent tests written (and failing!), we'll go +and do the actual development of our calculation API. This is the preferred +way to work for many people using TDD - write tests first, make sure they +fail, then do development. Others are not so strict and write tests after +doing the development.

              + +

              Create a test directory beneath calculus, with an empty __init__.py file. In a calculus/test/test_base_1.py, put the +following:

              + +

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

              from calculus.base_1 import Calculation +from twisted.trial import unittest + +class CalculationTestCase(unittest.TestCase): + def test_add(self): + calc = Calculation() + result = calc.add(3, 8) + self.assertEqual(result, 11) + + def test_subtract(self): + calc = Calculation() + result = calc.subtract(7, 3) + self.assertEqual(result, 4) + + def test_multiply(self): + calc = Calculation() + result = calc.multiply(12, 5) + self.assertEqual(result, 60) + + def test_divide(self): + calc = Calculation() + result = calc.divide(12, 5) + self.assertEqual(result, 2) +
              + +

              You should now have the following 4 files: + +

              +    calculus/__init__.py
              +    calculus/base_1.py
              +    calculus/test/__init__.py
              +    calculus/test/test_base_1.py
              +
              +

              + +

              To run the tests, there are two things you must get set up. Make sure +you get these both done - nothing below will work unless you do.

              + +

              First, make sure that the directory that contains your + calculus directory is in your Python load path. If you're +using the Bash shell on some form of unix (e.g., Linux, Mac OS X), run + PYTHONPATH="$PYTHONPATH:`pwd`/.." at +the command line in the calculus directory. Once you have your +Python path set up correctly, you should be able to run Python from the +command line and import calculus without seeing +an import error.

              + +

              Second, make sure you can run the trial +command. That is, make sure the directory containing the trial +program on you system is in your shell's PATH. The easiest way to check if you have this is to +try running trial --help at the command line. If +you see a list of invocation options, you're in business. If your shell +reports something like trial: command not found, +make sure you have Twisted installed properly, and that the Twisted + bin directory is in your PATH. If +you don't know how to do this, get some local help, or figure it out by +searching online for information on setting and changing environment +variables for you operating system.

              + +

              With those (one-time) preliminary steps out of the way, let's perform +the tests. Run trial calculus.test.test_base_1 from the +command line from the calculus directory. + +You should see the following output (though your files are probably not in + /tmp:

              + +
              +$ trial calculus.test.test_base_1
              +calculus.test.test_base_1
              +  CalculationTestCase
              +    test_add ...                                                         [FAIL]
              +    test_divide ...                                                      [FAIL]
              +    test_multiply ...                                                    [FAIL]
              +    test_subtract ...                                                    [FAIL]
              +
              +===============================================================================
              +[FAIL]
              +Traceback (most recent call last):
              +  File "/tmp/calculus/test/test_base_1.py", line 8, in test_add
              +    self.assertEqual(result, 11)
              +twisted.trial.unittest.FailTest: not equal:
              +a = None
              +b = 11
              +
              +
              +calculus.test.test_base_1.CalculationTestCase.test_add
              +===============================================================================
              +[FAIL]
              +Traceback (most recent call last):
              +  File "/tmp/calculus/test/test_base_1.py", line 23, in test_divide
              +    self.assertEqual(result, 2)
              +twisted.trial.unittest.FailTest: not equal:
              +a = None
              +b = 2
              +
              +
              +calculus.test.test_base_1.CalculationTestCase.test_divide
              +===============================================================================
              +[FAIL]
              +Traceback (most recent call last):
              +  File "/tmp/calculus/test/test_base_1.py", line 18, in test_multiply
              +    self.assertEqual(result, 60)
              +twisted.trial.unittest.FailTest: not equal:
              +a = None
              +b = 60
              +
              +
              +calculus.test.test_base_1.CalculationTestCase.test_multiply
              +===============================================================================
              +[FAIL]
              +Traceback (most recent call last):
              +  File "/tmp/calculus/test/test_base_1.py", line 13, in test_subtract
              +    self.assertEqual(result, 4)
              +twisted.trial.unittest.FailTest: not equal:
              +a = None
              +b = 4
              +
              +
              +calculus.test.test_base_1.CalculationTestCase.test_subtract
              +-------------------------------------------------------------------------------
              +Ran 4 tests in 0.042s
              +
              +FAILED (failures=4)
              +
              + +

              How to interpret this output? You get a list of the individual tests, each +followed by its result. By default, failures are printed at the end, but this +can be changed with the -e (or --rterrors) option.

              + +

              One very useful thing in this output is the fully-qualified name of the +failed tests. This appears at the bottom of each =-delimited area of the +output. This allows you to copy and paste it to just run a single test you're +interested in. In our example, you could run trial +calculus.test.test_base_1.CalculationTestCase.test_subtract from the +shell.

              + +

              Note that trial can use different reporters to modify its output. Run + trial --help-reporters to see a list of +reporters.

              + +

              +The tests can be run by trial in multiple ways: +

              + +The first 3 versions using full qualified names are strongly encouraged: they +are much more reliable and they allow you to easily be more selective in your +test runs. +

              + +

              You'll notice that Trial create a _trial_temp directory in +the directory where you run the tests. This has a file called + test.log which contains the log output of the tests (created +using log.msg or log.err functions). Examine this file if you add +logging to your tests.

              + +

              Making the tests pass

              + +

              Now that we have a working test framework in place, and our tests are +failing (as expected) we can go and try to implement the correct API. We'll do +that in a new version of the above base_1 +module, calculus/base_2.py:

              + +
              + +

              We'll also create a new version of test_base_1 which imports and tests this +new implementation, +in calculus/test_base_2.py:

              + +

              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 +

              from calculus.base_2 import Calculation +from twisted.trial import unittest + + + +class CalculationTestCase(unittest.TestCase): + + def test_add(self): + calc = Calculation() + result = calc.add(3, 8) + self.assertEqual(result, 11) + + + def test_subtract(self): + calc = Calculation() + result = calc.subtract(7, 3) + self.assertEqual(result, 4) + + + def test_multiply(self): + calc = Calculation() + result = calc.multiply(12, 5) + self.assertEqual(result, 60) + + + def test_divide(self): + calc = Calculation() + result = calc.divide(12, 5) + self.assertEqual(result, 2) +
              is a copy of test_base_1, but with the import changed. Run trial again as above, and your tests should now pass:

              + +
              +$ trial calculus.test.test_base_2
              +
              +Running 4 tests.
              +calculus.test.test_base
              +  CalculationTestCase
              +    test_add ...                                                           [OK]
              +    test_divide ...                                                        [OK]
              +    test_multiply ...                                                      [OK]
              +    test_subtract ...                                                      [OK]
              +
              +-------------------------------------------------------------------------------
              +Ran 4 tests in 0.067s
              +
              +PASSED (successes=4)
              +
              + +

              Factoring out common test logic

              + +

              You'll notice that our test file contains redundant code. Let's get rid +of that. Python's unit testing framework allows your test class to define a + setUp method that is called before + each test method in the class. This allows you to add attributes +to self that can be used in tests +methods. We'll also add a parameterized test method to further simplify the +code.

              + +

              Note that a test class may also provide the counterpart of setUp, named tearDown, +which will be called after each test (whether successful or +not). tearDown is mainly used for post-test +cleanup purposes. We will not use tearDown +until later.

              + +

              Create calculus/test/test_base_2b.py as +follows:

              + +
              + +

              Much cleaner, no?

              + +

              We'll now add some additional error tests. Testing just for successful +use of the API is generally not enough, especially if you expect your code +to be used by others. Let's make sure the Calculation class raises exceptions if someone tries +to call its methods with arguments that cannot be converted to +integers.

              + +

              We arrive at calculus/test/test_base_3.py:

              + +

              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 +

              from calculus.base_3 import Calculation +from twisted.trial import unittest + + + +class CalculationTestCase(unittest.TestCase): + def setUp(self): + self.calc = Calculation() + + + def _test(self, operation, a, b, expected): + result = operation(a, b) + self.assertEqual(result, expected) + + + def _test_error(self, operation): + self.assertRaises(TypeError, operation, "foo", 2) + self.assertRaises(TypeError, operation, "bar", "egg") + self.assertRaises(TypeError, operation, [3], [8, 2]) + self.assertRaises(TypeError, operation, {"e": 3}, {"r": "t"}) + + + def test_add(self): + self._test(self.calc.add, 3, 8, 11) + + + def test_subtract(self): + self._test(self.calc.subtract, 7, 3, 4) + + + def test_multiply(self): + self._test(self.calc.multiply, 6, 9, 54) + + + def test_divide(self): + self._test(self.calc.divide, 12, 5, 2) + + + def test_errorAdd(self): + self._test_error(self.calc.add) + + + def test_errorSubtract(self): + self._test_error(self.calc.subtract) + + + def test_errorMultiply(self): + self._test_error(self.calc.multiply) + + + def test_errorDivide(self): + self._test_error(self.calc.divide) +
              + +

              We've added four new tests and one general-purpose function, _test_error. This function uses the assertRaises method, which takes an exception class, +a function to run and its arguments, and checks that calling the function +on the arguments does indeed raise the given exception.

              + +

              If you run the above, you'll see that not all tests fail. In Python it's +often valid to add and multiply objects of different and even differing +types, so the code in the add and mutiply tests does not raise an exception +and those tests therefore fail. So let's add explicit type conversion to +our API class. This brings us to calculus/base_3.py:

              + +

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

              # -*- test-case-name: calculus.test.test_base_3 -*- + +class Calculation(object): + def _make_ints(self, *args): + try: + return map(int, args) + except ValueError: + raise TypeError("Couldn't coerce arguments to integers: %s" % args) + + def add(self, a, b): + a, b = self._make_ints(a, b) + return a + b + + def subtract(self, a, b): + a, b = self._make_ints(a, b) + return a - b + + def multiply(self, a, b): + a, b = self._make_ints(a, b) + return a * b + + def divide(self, a, b): + a, b = self._make_ints(a, b) + return a / b +
              + +

              Here the _make_ints helper function tries to +convert a list into a list of equivalent integers, and raises a TypeError in case the conversion goes wrong. + +

              Note: The int conversion can also +raise a TypeError if passed something of the +wrong type, such as a list. We'll just let that exception go by as TypeError is already what we want in case something +goes wrong.

              + + + +

              Twisted specific testing

              + +

              Up to this point we've been doing fairly standard Python unit testing. +With only a few cosmetic changes (most importantly, directly importing + unittest instead of using Twisted's unittest version) we could make the +above tests run using Python's standard library unit testing framework.

              + +

              Here we will assume a basic familiarity with Twisted's network I/O, timing, +and Deferred APIs. If you haven't already read them, you should read the +documentation on Writing +Servers, Writing Clients, +and Deferreds.

              + +

              Now we'll get to the real point of this tutorial and take advantage of +Trial to test Twisted code.

              + +

              Testing a protocol

              + +

              We'll now create a custom protocol to invoke our class from within a +telnet-like session. We'll remotely call commands with arguments and read back +the response. The goal will be to test our network code without creating +sockets.

              + +

              Creating and testing the server

              + +

              First we'll write the tests, and then explain what they do. The first +version of the remote test code is:

              + +
              + +

              To fully understand this client, it helps a lot to be comfortable with +the Factory/Protocol/Transport pattern used in Twisted.

              + +

              We first create a protocol factory object. Note that we have yet to see +the RemoteCalculationFactory class. It is in + calculus/remote_1.py below. We +call buildProtocol to ask the factory to build us a +protocol object that knows how to talk to our server. We then make a fake +network transport, an instance of twisted.test.proto_helpers.StringTransport +class (note that test packages are generally not part of Twisted's public API; +twisted.test.proto_helpers is an exception). This fake +transport is the key to the communications. It is used to emulate a network +connection without a network. The address and port passed to buildProtocol +are typically used by the factory to choose to immediately deny remote connections; since we're using a fake transport, we can choose any value that will be acceptable to the factory. In this case the factory just ignores the address, so we don't need to pick anything in particular.

              + +

              Testing protocols without the use of real network connections is both simple and recommended when testing Twisted +code. Even though there are many tests in Twisted that use the network, +most good tests don't. The problem with unit tests and networking is that +networks aren't reliable. We cannot know that they will exhibit reasonable +behavior all the time. This creates intermittent test failures due to +network vagaries. Right now we're trying to test our Twisted code, not +network reliability. By setting up and using a fake transport, we can +write 100% reliable tests. We can also test network failures in a deterministic manner, another important part of your complete test suite.

              + +

              The final key to understanding this client code is the _test method. The call to dataReceived simulates data arriving on the network +transport. But where does it arrive? It's handed to the lineReceived method of the protocol instance (in + calculus/remote_1.py below). So the client +is essentially tricking the server into thinking it has received the +operation and the arguments over the network. The server (once again, see +below) hands the work off to its CalculationProxy object which in turn hands it to its + Calculation instance. The result is written +back via sendLine (into the fake string +transport object), and is then immediately available to the client, who +fetches it with tr.value() and checks that it +has the expected value. So there's quite a lot going on behind the scenes +in the two-line _test method above.

              + +

              Finally, let's see the implementation of this protocol. Put the +following into calculus/remote_1.py:

              + +

              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 +

              # -*- test-case-name: calculus.test.test_remote_1 -*- + +from twisted.protocols import basic +from twisted.internet import protocol +from calculus.base_3 import Calculation + + + +class CalculationProxy(object): + def __init__(self): + self.calc = Calculation() + for m in ['add', 'subtract', 'multiply', 'divide']: + setattr(self, 'remote_%s' % m, getattr(self.calc, m)) + + + +class RemoteCalculationProtocol(basic.LineReceiver): + def __init__(self): + self.proxy = CalculationProxy() + + + def lineReceived(self, line): + op, a, b = line.split() + a = int(a) + b = int(b) + op = getattr(self.proxy, 'remote_%s' % (op,)) + result = op(a, b) + self.sendLine(str(result)) + + + +class RemoteCalculationFactory(protocol.Factory): + protocol = RemoteCalculationProtocol + + + +def main(): + from twisted.internet import reactor + from twisted.python import log + import sys + log.startLogging(sys.stdout) + reactor.listenTCP(0, RemoteCalculationFactory()) + reactor.run() + + +if __name__ == "__main__": + main() +
              + +

              As mentioned, this server creates a protocol that inherits from basic.LineReceiver, and then a +factory that uses it as protocol. The only trick is the CalculationProxy object, which calls Calculation methods through remote_* methods. This pattern is used frequently in +Twisted, because it is very explicit about what methods you are making +accessible.

              + +

              If you run this test (trial +calculus.test.test_remote_1), everything should be fine. You can also +run a server to test it with a telnet client. To do that, call python calculus/remote_1.py. You should have the following output:

              + +
              +2008-04-25 10:53:27+0200 [-] Log opened.
              +2008-04-25 10:53:27+0200 [-] __main__.RemoteCalculationFactory starting on 46194
              +2008-04-25 10:53:27+0200 [-] Starting factory <__main__.RemoteCalculationFactory instance at 0x846a0cc>
              +
              + +

              46194 is replaced by a random port. You can then call telnet on it:

              +
              +$ telnet localhost 46194
              +Trying 127.0.0.1...
              +Connected to localhost.
              +Escape character is '^]'.
              +add 4123 9423
              +13546
              +
              + +

              It works!

              + +

              Creating and testing the client

              + +

              Of course, what we build is not particulary useful for now : we'll now build +a client to our server, to be able to use it inside a Python program. And it +will serve our next purpose.

              + +

              Create calculus/test/test_client_1.py:

              + +
              + +

              It's really symmetric to the server test cases. The only tricky part is +that we don't use a client factory. We're lazy, and it's not very useful in +the client part, so we instantiate the protocol directly.

              + +

              Incidentally, we have introduced a very important concept here: the tests +now return a Deferred object, and the assertion is done in a callback. The +important thing to do here is to not forget to return the +Deferred. If you do, your tests will pass even if nothing is asserted. +That's also why it's important to make tests fail first: if your tests pass +whereas you know they shouldn't, there is a problem in your tests.

              + +

              We'll now add the remote client class to produce calculus/client_1.py:

              + +

              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 +

              # -*- test-case-name: calculus.test.test_client_1 -*- + +from twisted.protocols import basic +from twisted.internet import defer + + + +class RemoteCalculationClient(basic.LineReceiver): + def __init__(self): + self.results = [] + + + def lineReceived(self, line): + d = self.results.pop(0) + d.callback(int(line)) + + + def _sendOperation(self, op, a, b): + d = defer.Deferred() + self.results.append(d) + line = "%s %d %d" % (op, a, b) + self.sendLine(line) + return d + + + def add(self, a, b): + return self._sendOperation("add", a, b) + + + def subtract(self, a, b): + return self._sendOperation("subtract", a, b) + + + def multiply(self, a, b): + return self._sendOperation("multiply", a, b) + + + def divide(self, a, b): + return self._sendOperation("divide", a, b) +
              + + +

              More good practices

              + +

              Testing scheduling

              + +

              When testing code that involves the passage of time, waiting e.g. for a two hour timeout to occur in a test is not very realistic. Twisted provides a solution to this, the Clock class that allows one to simulate the passage of time.

              + +

              As an example we'll test the code for client request timeout: since our client +uses TCP it can hang for a long time (firewall, connectivity problems, etc...). +So generally we need to implement timeouts on the client side. Basically it's +just that we send a request, don't receive a response and expect a timeout error +to be triggered after a certain duration. +

              + +

              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 +

              from calculus.client_2 import RemoteCalculationClient, ClientTimeoutError + +from twisted.internet import task +from twisted.trial import unittest +from twisted.test import proto_helpers + + + +class ClientCalculationTestCase(unittest.TestCase): + def setUp(self): + self.tr = proto_helpers.StringTransportWithDisconnection() + self.clock = task.Clock() + self.proto = RemoteCalculationClient() + self.tr.protocol = self.proto + self.proto.callLater = self.clock.callLater + self.proto.makeConnection(self.tr) + + + def _test(self, operation, a, b, expected): + d = getattr(self.proto, operation)(a, b) + self.assertEqual(self.tr.value(), '%s %d %d\r\n' % (operation, a, b)) + self.tr.clear() + d.addCallback(self.assertEqual, expected) + self.proto.dataReceived("%d\r\n" % (expected,)) + return d + + + def test_add(self): + return self._test('add', 7, 6, 13) + + + def test_subtract(self): + return self._test('subtract', 82, 78, 4) + + + def test_multiply(self): + return self._test('multiply', 2, 8, 16) + + + def test_divide(self): + return self._test('divide', 14, 3, 4) + + + def test_timeout(self): + d = self.proto.add(9, 4) + self.assertEqual(self.tr.value(), 'add 9 4\r\n') + self.clock.advance(self.proto.timeOut) + return self.assertFailure(d, ClientTimeoutError) +
              + +

              What happens here? We instantiate our protocol as usual, the only trick +is to create the clock, and assign proto.callLater to + clock.callLater. Thus, every callLater calls in the protocol +will finish before clock.advance() returns.

              + +

              In the new test (test_timeout), we call clock.advance, that simulates and advance in time +(logically it's similar to a time.sleep call). And +we just have to verify that our Deferred got a timeout error.

              + +

              Let's implement that in our code.

              + +

              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 +

              # -*- test-case-name: calculus.test.test_client_2 -*- + +from twisted.protocols import basic +from twisted.internet import defer, reactor + + + +class ClientTimeoutError(Exception): + pass + + + +class RemoteCalculationClient(basic.LineReceiver): + + callLater = reactor.callLater + timeOut = 60 + + def __init__(self): + self.results = [] + + + def lineReceived(self, line): + d, callID = self.results.pop(0) + callID.cancel() + d.callback(int(line)) + + + def _cancel(self, d): + d.errback(ClientTimeoutError()) + + + def _sendOperation(self, op, a, b): + d = defer.Deferred() + callID = self.callLater(self.timeOut, self._cancel, d) + self.results.append((d, callID)) + line = "%s %d %d" % (op, a, b) + self.sendLine(line) + return d + + + def add(self, a, b): + return self._sendOperation("add", a, b) + + + def subtract(self, a, b): + return self._sendOperation("subtract", a, b) + + + def multiply(self, a, b): + return self._sendOperation("multiply", a, b) + + + def divide(self, a, b): + return self._sendOperation("divide", a, b) +
              + +

              The only important thing here is to not forget to cancel our callLater +when everything went fine.

              + +

              Cleaning up after tests

              + +

              This chapter is mainly intended for people that want to have sockets or +processes created in their tests. If it's still not obvious, you must try to +avoid that like the plague, because it ends up with a lot of problems, one of +them being intermittent failures. And intermittent failures are the plague +of automated tests.

              + +

              To actually test that, we'll launch a server with our protocol.

              + +
              + +

              Recent versions of trial will fail loudly if you remove the + stopListening call, which is good.

              + +

              Also, you should be aware that tearDown will +called in any case, after success or failure. So don't expect that every +objects you created in the test method are present, because your tests may +have failed in the middle.

              + +

              Trial also has a addCleanup method, which makes +these kind of cleanups easy and removes the need for tearDown +. For example, you could remove the code in _test +this way:

              + +

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

              def setUp(self): + factory = RemoteCalculationFactory() + self.port = reactor.listenTCP(0, factory, interface="127.0.0.1") + self.addCleanup(self.port.stopListening) + +def _test(self, op, a, b, expected): + creator = protocol.ClientCreator(reactor, RemoteCalculationClient) + def cb(client): + self.addCleanup(self.client.transport.loseConnection) + return getattr(client, op)(a, b).addCallback(self.assertEqual, expected) + return creator.connectTCP('127.0.0.1', self.port.getHost().port).addCallback(cb) +
              + +

              This remove the need of a tearDown method, and you don't have to check for +the value of self.client: you only call addCleanup when the client is +created.

              + +

              Handling logged errors

              + +

              Currently, if you send an invalid command or invalid arguments to our +server, it logs an exception and closes the connection. This is a perfectly +valid behavior, but for the sake of this tutorial, we want to return an error +to the user if he sends invalid operators, and log any errors on server side. +So we'll want a test like this:

              + +

              1 +2 +3 +

              def test_invalidParameters(self): + self.proto.dataReceived('add foo bar\r\n') + self.assertEqual(self.tr.value(), "error\r\n") +
              + +
              + +

              If you try something like that, it will not work. Here is the output you should have:

              + +
              +trial calculus.test.test_remote_3.RemoteCalculationTestCase.test_invalidParameters
              +calculus.test.test_remote_3
              +  RemoteCalculationTestCase
              +    test_invalidParameters ...                                          [ERROR]
              +
              +===============================================================================
              +[ERROR]: calculus.test.test_remote_3.RemoteCalculationTestCase.test_invalidParameters
              +
              +Traceback (most recent call last):
              +  File "/tmp/calculus/remote_2.py", line 27, in lineReceived
              +    result = op(a, b)
              +  File "/tmp/calculus/base_3.py", line 11, in add
              +    a, b = self._make_ints(a, b)
              +  File "/tmp/calculus/base_3.py", line 8, in _make_ints
              +    raise TypeError
              +exceptions.TypeError:
              +-------------------------------------------------------------------------------
              +Ran 1 tests in 0.004s
              +
              +FAILED (errors=1)
              +
              + +

              At first, you could think there is a problem, because you catch this +exception. But in fact trial doesn't let you do that without controlling it: +you must expect logged errors and clean them. To do that, you have to use the + flushLoggedErrors method. You call it with the +exception you expect, and it returns the list of exceptions logged since the +start of the test. Generally, you'll want to check that this list has the +expected length, or possibly that each exception has an expected message. We do +the former in our test:

              + +

              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 +

              from calculus.remote_2 import RemoteCalculationFactory +from twisted.trial import unittest +from twisted.test import proto_helpers + + + +class RemoteCalculationTestCase(unittest.TestCase): + def setUp(self): + factory = RemoteCalculationFactory() + self.proto = factory.buildProtocol(('127.0.0.1', 0)) + self.tr = proto_helpers.StringTransport() + self.proto.makeConnection(self.tr) + + + def _test(self, operation, a, b, expected): + self.proto.dataReceived('%s %d %d\r\n' % (operation, a, b)) + self.assertEqual(int(self.tr.value()), expected) + + + def test_add(self): + return self._test('add', 7, 6, 13) + + + def test_subtract(self): + return self._test('subtract', 82, 78, 4) + + + def test_multiply(self): + return self._test('multiply', 2, 8, 16) + + + def test_divide(self): + return self._test('divide', 14, 3, 4) + + + def test_invalidParameters(self): + self.proto.dataReceived('add foo bar\r\n') + self.assertEqual(self.tr.value(), "error\r\n") + errors = self.flushLoggedErrors(TypeError) + self.assertEqual(len(errors), 1) +
              + +

              Resolve a bug

              + +

              A bug was left over during the development of the timeout (probably several +bugs, but that's not the point), concerning the reuse of the protocol when you +got a timeout: the connection is not dropped, so you can get timeout forever. +Generally an user will come to you saying "I have this strange problem on +my crappy network environment. It seems you could solve it with doing XXX at +YYY."

              + +

              Actually, this bug can be corrected several ways. But if you correct it +without adding tests, one day you'll face a big problem: regression. +So the first step is adding a failing test.

              + +

              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 +61 +62 +63 +

              from calculus.client_3 import RemoteCalculationClient, ClientTimeoutError + +from twisted.internet import task +from twisted.trial import unittest +from twisted.test import proto_helpers + + + +class ClientCalculationTestCase(unittest.TestCase): + def setUp(self): + self.tr = proto_helpers.StringTransportWithDisconnection() + self.clock = task.Clock() + self.proto = RemoteCalculationClient() + self.tr.protocol = self.proto + self.proto.callLater = self.clock.callLater + self.proto.makeConnection(self.tr) + + + def _test(self, operation, a, b, expected): + d = getattr(self.proto, operation)(a, b) + self.assertEqual(self.tr.value(), '%s %d %d\r\n' % (operation, a, b)) + self.tr.clear() + d.addCallback(self.assertEqual, expected) + self.proto.dataReceived("%d\r\n" % (expected,)) + return d + + + def test_add(self): + return self._test('add', 7, 6, 13) + + + def test_subtract(self): + return self._test('subtract', 82, 78, 4) + + + def test_multiply(self): + return self._test('multiply', 2, 8, 16) + + + def test_divide(self): + return self._test('divide', 14, 3, 4) + + + def test_timeout(self): + d = self.proto.add(9, 4) + self.assertEqual(self.tr.value(), 'add 9 4\r\n') + self.clock.advance(self.proto.timeOut) + return self.assertFailure(d, ClientTimeoutError) + + + def test_timeoutConnectionLost(self): + called = [] + def lost(arg): + called.append(True) + self.proto.connectionLost = lost + + d = self.proto.add(9, 4) + self.assertEqual(self.tr.value(), 'add 9 4\r\n') + self.clock.advance(self.proto.timeOut) + + def check(ignore): + self.assertEqual(called, [True]) + return self.assertFailure(d, ClientTimeoutError).addCallback(check) +
              +

              What have we done here ? +

                +
              • We switched to StringTransportWithDisconnection. This transport manages + loseConnection and forwards it to its protocol.
              • +
              • We assign the protocol to the transport via the protocol + attribute.
              • +
              • We check that after a timeout our connection has closed.
              • +
              +

              + +

              For doing that, we then use the TimeoutMixin +class, that does almost everything we want. The great thing is that it almost +changes nothing to our class.

              + +

              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 +

              # -*- test-case-name: calculus.test.test_client -*- + +from twisted.protocols import basic, policies +from twisted.internet import defer + + + +class ClientTimeoutError(Exception): + pass + + + +class RemoteCalculationClient(object, basic.LineReceiver, policies.TimeoutMixin): + + def __init__(self): + self.results = [] + self._timeOut = 60 + + def lineReceived(self, line): + self.setTimeout(None) + d = self.results.pop(0) + d.callback(int(line)) + + + def timeoutConnection(self): + for d in self.results: + d.errback(ClientTimeoutError()) + self.transport.loseConnection() + + + def _sendOperation(self, op, a, b): + d = defer.Deferred() + self.results.append(d) + line = "%s %d %d" % (op, a, b) + self.sendLine(line) + self.setTimeout(self._timeOut) + return d + + + def add(self, a, b): + return self._sendOperation("add", a, b) + + + def subtract(self, a, b): + return self._sendOperation("subtract", a, b) + + + def multiply(self, a, b): + return self._sendOperation("multiply", a, b) + + + def divide(self, a, b): + return self._sendOperation("divide", a, b) +
              + +

              Code coverage

              + +

              Code coverage is one of the aspects of software testing that shows how much +your tests cross (cover) the code of your program. There are different kind of +measures: path coverage, condition coverage, statement coverage... We'll only +consider statement coverage here, whether a line has been executed or not. +

              + +

              Trial has an option to generate the statement coverage of your tests. +This option is --coverage. It creates a coverage directory in _trial_temp, +with a file .cover for every modules used during the tests. The ones +interesting for us are calculus.base.cover and calculus.remote.cover. In +front of each line is the number of times you went through during the +tests, or the marker '>>>>>>' if the line was not +covered. If you went through all the tutorial to this point, you should +have complete coverage :).

              + +

              Again, this is only another useful pointer, but it doesn't mean your +code is perfect: your tests should consider every possibile input and +output, to get full coverage (condition, path, etc.) as well +.

              + +

              Conclusion

              + +

              So what did you learn in this document? +

                +
              • How to use the trial command-line tool to run your tests
              • +
              • How to use string transports to test individual clients and servers + without creating sockets
              • +
              • If you really want to create sockets, how to cleanly do it so that it + doesn't have bad side effects
              • +
              • And some small tips you can't live without.
              • +
              +If one of the topics still looks cloudy to you, please give us your feedback! +You can file tickets to improve this document +
              on the Twisted web site. +

              + +
              + +

              Index

              + Version: 12.1.0 + + \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/tutorial/backends.html twisted-12.1.0/doc/howto/tutorial/backends.html --- twisted-10.2.0/doc/howto/tutorial/backends.html 2010-11-30 03:13:20.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/backends.html 2012-06-04 08:46:22.000000000 +0000 @@ -321,6 +321,41 @@ 255 256 257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292

              # Do everything properly, and componentize from twisted.application import internet, service from twisted.internet import protocol, reactor, defer, utils @@ -335,24 +370,36 @@ class IFingerService(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def getUsers(): - """Return a deferred returning a list of strings""" + """ + Return a deferred returning a list of strings. + """ + class IFingerSetterService(Interface): def setUser(user, status): - """Set the user's status to something""" + """ + Set the user's status to something. + """ + class IFingerSetterService(Interface): def setUser(user, status): - """Set the user's status to something""" + """ + Set the user's status to something. + """ + def catchError(err): return "Internal error in server" + class FingerProtocol(basic.LineReceiver): def lineReceived(self, user): @@ -367,10 +414,14 @@ class IFingerFactory(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerFactoryFromService(protocol.ServerFactory): @@ -389,6 +440,7 @@ IFingerService, IFingerFactory) + class FingerSetterProtocol(basic.LineReceiver): def connectionMade(self): @@ -405,10 +457,14 @@ class IFingerSetterFactory(Interface): def setUser(user, status): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerSetterFactoryFromService(protocol.ServerFactory): @@ -450,10 +506,14 @@ """ def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol""" + """ + Return a protocol. + """ class IRCClientFactoryFromService(protocol.ClientFactory): @@ -473,6 +533,7 @@ IFingerService, IIRCClientFactory) + class UserStatusTree(resource.Resource): implements(resource.IResource) @@ -502,6 +563,7 @@ components.registerAdapter(UserStatusTree, IFingerService, resource.IResource) + class UserStatus(resource.Resource): def __init__(self, user, service): @@ -536,7 +598,6 @@ def __init__(self, filename): self.filename = filename self.users = {} - self._read() def _read(self): self.users.clear() @@ -553,6 +614,15 @@ def getUsers(self): return defer.succeed(self.users.keys()) + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + + # Another back-end class LocalFingerService(service.Service): @@ -922,6 +992,42 @@ 267 268 269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305

              # Do everything properly, and componentize from twisted.application import internet, service from twisted.internet import protocol, reactor, defer, utils @@ -937,24 +1043,36 @@ class IFingerService(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def getUsers(): - """Return a deferred returning a list of strings""" + """ + Return a deferred returning a list of strings. + """ + class IFingerSetterService(Interface): def setUser(user, status): - """Set the user's status to something""" + """ + Set the user's status to something. + """ + class IFingerSetterService(Interface): def setUser(user, status): - """Set the user's status to something""" + """ + Set the user's status to something. + """ + def catchError(err): return "Internal error in server" + class FingerProtocol(basic.LineReceiver): def lineReceived(self, user): @@ -969,10 +1087,14 @@ class IFingerFactory(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerFactoryFromService(protocol.ServerFactory): @@ -991,6 +1113,7 @@ IFingerService, IFingerFactory) + class FingerSetterProtocol(basic.LineReceiver): def connectionMade(self): @@ -1007,10 +1130,14 @@ class IFingerSetterFactory(Interface): def setUser(user, status): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerSetterFactoryFromService(protocol.ServerFactory): @@ -1030,6 +1157,7 @@ IFingerSetterService, IFingerSetterFactory) + class IRCReplyBot(irc.IRCClient): def connectionMade(): @@ -1052,10 +1180,14 @@ """ def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol""" + """ + Return a protocol. + """ class IRCClientFactoryFromService(protocol.ClientFactory): @@ -1075,6 +1207,7 @@ IFingerService, IIRCClientFactory) + class UserStatusTree(resource.Resource): implements(resource.IResource) @@ -1104,6 +1237,7 @@ components.registerAdapter(UserStatusTree, IFingerService, resource.IResource) + class UserStatus(resource.Resource): def __init__(self, user, service): @@ -1138,7 +1272,6 @@ def __init__(self, filename): self.filename = filename self.users = {} - self._read() def _read(self): self.users.clear() @@ -1155,6 +1288,15 @@ def getUsers(self): return defer.succeed(self.users.keys()) + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + + # Yet another back-end class LocalFingerService(service.Service): @@ -1201,6 +1343,6 @@

              Index

              - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/tutorial/client.html twisted-12.1.0/doc/howto/tutorial/client.html --- twisted-10.2.0/doc/howto/tutorial/client.html 2010-11-30 03:13:21.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/client.html 2012-06-04 08:46:21.000000000 +0000 @@ -255,6 +255,6 @@

              Index

              - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/tutorial/components.html twisted-12.1.0/doc/howto/tutorial/components.html --- twisted-10.2.0/doc/howto/tutorial/components.html 2010-11-30 03:13:21.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/components.html 2012-06-04 08:46:21.000000000 +0000 @@ -280,6 +280,38 @@ 236 237 238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270

              # Do everything properly, and componentize from twisted.application import internet, service from twisted.internet import protocol, reactor, defer @@ -293,19 +325,28 @@ class IFingerService(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def getUsers(): - """Return a deferred returning a list of strings""" + """ + Return a deferred returning a list of strings. + """ + class IFingerSetterService(Interface): def setUser(user, status): - """Set the user's status to something""" + """ + Set the user's status to something. + """ + def catchError(err): return "Internal error in server" + class FingerProtocol(basic.LineReceiver): def lineReceived(self, user): @@ -320,10 +361,14 @@ class IFingerFactory(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerFactoryFromService(protocol.ServerFactory): @@ -342,6 +387,7 @@ IFingerService, IFingerFactory) + class FingerSetterProtocol(basic.LineReceiver): def connectionMade(self): @@ -358,10 +404,14 @@ class IFingerSetterFactory(Interface): def setUser(user, status): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerSetterFactoryFromService(protocol.ServerFactory): @@ -381,6 +431,7 @@ IFingerSetterService, IFingerSetterFactory) + class IRCReplyBot(irc.IRCClient): def connectionMade(self): @@ -397,16 +448,19 @@ class IIRCClientFactory(Interface): - """ @ivar nickname """ def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol""" + """ + Return a protocol. + """ class IRCClientFactoryFromService(protocol.ClientFactory): @@ -426,6 +480,7 @@ IFingerService, IIRCClientFactory) + class UserStatusTree(resource.Resource): implements(resource.IResource) @@ -455,6 +510,7 @@ components.registerAdapter(UserStatusTree, IFingerService, resource.IResource) + class UserStatus(resource.Resource): def __init__(self, user, service): @@ -489,7 +545,6 @@ def __init__(self, filename): self.filename = filename self.users = {} - self._read() def _read(self): self.users.clear() @@ -506,10 +561,19 @@ def getUsers(self): return defer.succeed(self.users.keys()) + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + application = service.Application('finger', uid=1, gid=1) f = FingerService('/etc/users') serviceCollection = service.IServiceCollection(application) +f.setServiceParent(serviceCollection) internet.TCPServer(79, IFingerFactory(f) ).setServiceParent(serviceCollection) internet.TCPServer(8000, server.Site(resource.IResource(f)) @@ -1063,6 +1127,6 @@

              Index

              - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/tutorial/configuration.html twisted-12.1.0/doc/howto/tutorial/configuration.html --- twisted-10.2.0/doc/howto/tutorial/configuration.html 2010-11-30 03:13:19.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/configuration.html 2012-06-04 08:46:21.000000000 +0000 @@ -358,6 +358,43 @@ 329 330 331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368

              # finger.py module from zope.interface import Interface, implements @@ -375,19 +412,28 @@ class IFingerService(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def getUsers(): - """Return a deferred returning a list of strings""" + """ + Return a deferred returning a list of strings. + """ + class IFingerSetterService(Interface): def setUser(user, status): - """Set the user's status to something""" + """ + Set the user's status to something. + """ + def catchError(err): return "Internal error in server" + class FingerProtocol(basic.LineReceiver): def lineReceived(self, user): @@ -402,10 +448,14 @@ class IFingerFactory(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerFactoryFromService(protocol.ServerFactory): @@ -423,6 +473,7 @@ IFingerService, IFingerFactory) + class FingerSetterProtocol(basic.LineReceiver): def connectionMade(self): @@ -439,10 +490,14 @@ class IFingerSetterFactory(Interface): def setUser(user, status): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerSetterFactoryFromService(protocol.ServerFactory): @@ -462,6 +517,7 @@ IFingerSetterService, IFingerSetterFactory) + class IRCReplyBot(irc.IRCClient): def connectionMade(self): @@ -484,10 +540,14 @@ """ def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol""" + """ + Return a protocol. + """ class IRCClientFactoryFromService(protocol.ClientFactory): @@ -507,6 +567,7 @@ IFingerService, IIRCClientFactory) + class UserStatusTree(resource.Resource): template = """<html><head><title>Users</title></head><body> @@ -589,10 +650,15 @@ class IPerspectiveFinger(Interface): def remote_getUser(username): - """return a user's status""" + """ + Return a user's status. + """ def remote_getUsers(): - """return a user's status""" + """ + Return a user's status. + """ + class PerspectiveFingerFromService(pb.Root): @@ -618,7 +684,6 @@ def __init__(self, filename): self.filename = filename - self._read() def _read(self): self.users = {} @@ -635,14 +700,24 @@ def getUsers(self): return defer.succeed(self.users.keys()) + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + class ServerContextFactory: def getContext(self): - """Create an SSL context. + """ + Create an SSL context. This is a sample implementation that loads a certificate from a file - called 'server.pem'.""" + called 'server.pem'. + """ ctx = SSL.Context(SSL.SSLv23_METHOD) ctx.use_certificate_file('server.pem') ctx.use_privatekey_file('server.pem') @@ -650,7 +725,6 @@ - # Easy configuration def makeService(config): @@ -749,7 +823,7 @@ twisted/plugins/finger_tutorial.py - listings/finger/twisted/plugins/finger_tutorial.py -

              Note that the second argument to ServiceMaker, +

              Note that the second argument to ServiceMaker, finger.tap, is a reference to a module (finger/tap.py), not to a filename.

              @@ -791,6 +865,6 @@

              Index

              - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/tutorial/factory.html twisted-12.1.0/doc/howto/tutorial/factory.html --- twisted-10.2.0/doc/howto/tutorial/factory.html 2010-11-30 03:13:20.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/factory.html 2012-06-04 08:46:21.000000000 +0000 @@ -325,6 +325,46 @@ 295 296 297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337

              # Do everything properly, and componentize from twisted.application import internet, service from twisted.internet import protocol, reactor, defer @@ -340,19 +380,28 @@ class IFingerService(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def getUsers(): - """Return a deferred returning a list of strings""" + """ + Return a deferred returning a list of strings. + """ + class IFingerSetterService(Interface): def setUser(user, status): - """Set the user's status to something""" + """ + Set the user's status to something. + """ + def catchError(err): return "Internal error in server" + class FingerProtocol(basic.LineReceiver): def lineReceived(self, user): @@ -367,10 +416,14 @@ class IFingerFactory(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerFactoryFromService(protocol.ServerFactory): @@ -389,6 +442,7 @@ IFingerService, IFingerFactory) + class FingerSetterProtocol(basic.LineReceiver): def connectionMade(self): @@ -405,10 +459,14 @@ class IFingerSetterFactory(Interface): def setUser(user, status): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerSetterFactoryFromService(protocol.ServerFactory): @@ -428,6 +486,7 @@ IFingerSetterService, IFingerSetterFactory) + class IRCReplyBot(irc.IRCClient): def connectionMade(self): @@ -450,10 +509,14 @@ """
              def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol""" + """ + Return a protocol. + """ class IRCClientFactoryFromService(protocol.ClientFactory): @@ -473,6 +536,7 @@ IFingerService, IIRCClientFactory) + class UserStatusTree(resource.Resource): def __init__(self, service): @@ -508,6 +572,7 @@ components.registerAdapter(UserStatusTree, IFingerService, resource.IResource) + class UserStatus(resource.Resource): def __init__(self, user, service): @@ -529,6 +594,7 @@ # signal that the rendering is not complete return server.NOT_DONE_YET + class UserStatusXR(xmlrpc.XMLRPC): def __init__(self, service): @@ -545,10 +611,14 @@ class IPerspectiveFinger(Interface): def remote_getUser(username): - """return a user's status""" + """ + Return a user's status. + """ def remote_getUsers(): - """return a user's status""" + """ + Return a user's status. + """ class PerspectiveFingerFromService(pb.Root): @@ -575,7 +645,6 @@ def __init__(self, filename): self.filename = filename self.users = {} - self._read() def _read(self): self.users.clear() @@ -592,14 +661,24 @@ def getUsers(self): return defer.succeed(self.users.keys()) + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + class ServerContextFactory: def getContext(self): - """Create an SSL context. + """ + Create an SSL context. This is a sample implementation that loads a certificate from a file - called 'server.pem'.""" + called 'server.pem'. + """ ctx = SSL.Context(SSL.SSLv23_METHOD) ctx.use_certificate_file('server.pem') ctx.use_privatekey_file('server.pem') @@ -609,6 +688,7 @@ application = service.Application('finger', uid=1, gid=1) f = FingerService('/etc/users') serviceCollection = service.IServiceCollection(application) +f.setServiceParent(serviceCollection) internet.TCPServer(79, IFingerFactory(f) ).setServiceParent(serviceCollection) site = server.Site(resource.IResource(f)) @@ -628,6 +708,6 @@

              Index

              - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/tutorial/index.html twisted-12.1.0/doc/howto/tutorial/index.html --- twisted-10.2.0/doc/howto/tutorial/index.html 2010-11-30 03:13:21.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/index.html 2012-06-04 08:46:21.000000000 +0000 @@ -78,6 +78,6 @@

              Index

              - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/tutorial/intro.html twisted-12.1.0/doc/howto/tutorial/intro.html --- twisted-10.2.0/doc/howto/tutorial/intro.html 2010-11-30 03:13:20.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/intro.html 2012-06-04 08:46:21.000000000 +0000 @@ -75,7 +75,7 @@

              The Reactor

              -

              You don't call Twisted, Twisted calls you. The reactor is Twisted's main event loop, similar to +

              You don't call Twisted, Twisted calls you. The reactor is Twisted's main event loop, similar to the main loop in other toolkits available in Python (Qt, wx, and Gtk). There is exactly one reactor in any running Twisted application. Once started it loops over and over again, responding to network events and making scheduled calls to @@ -189,7 +189,7 @@ reactor.run()

              -

              Here we make FingerProtocol inherit from LineReceiver, so that we get data-based +

              Here we make FingerProtocol inherit from LineReceiver, so that we get data-based events on a line-by-line basis. We respond to the event of receiving the line with shutting down the connection.

              @@ -708,8 +708,8 @@ the protocol or the factory. Any services (such as TCPServer) which have the application as their parent will be started when the application is started by twistd. The application object is more -useful for returning an object that supports the IService, IServiceCollection, IProcess, -and sob.IPersistable +useful for returning an object that supports the IService, IServiceCollection, IProcess, +and sob.IPersistable interfaces with the given parameters; we'll be seeing these in the next part of the tutorial. As the parent of the TCPServer we opened, the application lets us manage the TCPServer.

              @@ -720,6 +720,6 @@

              Index

              - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/tutorial/library.html twisted-12.1.0/doc/howto/tutorial/library.html --- twisted-10.2.0/doc/howto/tutorial/library.html 2010-11-30 03:13:20.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/library.html 2012-06-04 08:46:21.000000000 +0000 @@ -266,6 +266,6 @@

              Index

              - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/tutorial/listings/finger/finger/finger.py twisted-12.1.0/doc/howto/tutorial/listings/finger/finger/finger.py --- twisted-10.2.0/doc/howto/tutorial/listings/finger/finger/finger.py 2009-01-09 17:01:53.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/listings/finger/finger/finger.py 2011-01-22 14:10:51.000000000 +0000 @@ -15,19 +15,28 @@ class IFingerService(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def getUsers(): - """Return a deferred returning a list of strings""" + """ + Return a deferred returning a list of strings. + """ + class IFingerSetterService(Interface): def setUser(user, status): - """Set the user's status to something""" + """ + Set the user's status to something. + """ + def catchError(err): return "Internal error in server" + class FingerProtocol(basic.LineReceiver): def lineReceived(self, user): @@ -42,10 +51,14 @@ class IFingerFactory(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerFactoryFromService(protocol.ServerFactory): @@ -63,6 +76,7 @@ IFingerService, IFingerFactory) + class FingerSetterProtocol(basic.LineReceiver): def connectionMade(self): @@ -79,10 +93,14 @@ class IFingerSetterFactory(Interface): def setUser(user, status): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerSetterFactoryFromService(protocol.ServerFactory): @@ -102,6 +120,7 @@ IFingerSetterService, IFingerSetterFactory) + class IRCReplyBot(irc.IRCClient): def connectionMade(self): @@ -124,10 +143,14 @@ """ def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol""" + """ + Return a protocol. + """ class IRCClientFactoryFromService(protocol.ClientFactory): @@ -147,6 +170,7 @@ IFingerService, IIRCClientFactory) + class UserStatusTree(resource.Resource): template = """Users @@ -229,10 +253,15 @@ class IPerspectiveFinger(Interface): def remote_getUser(username): - """return a user's status""" + """ + Return a user's status. + """ def remote_getUsers(): - """return a user's status""" + """ + Return a user's status. + """ + class PerspectiveFingerFromService(pb.Root): @@ -258,7 +287,6 @@ def __init__(self, filename): self.filename = filename - self._read() def _read(self): self.users = {} @@ -275,14 +303,24 @@ def getUsers(self): return defer.succeed(self.users.keys()) + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + class ServerContextFactory: def getContext(self): - """Create an SSL context. + """ + Create an SSL context. This is a sample implementation that loads a certificate from a file - called 'server.pem'.""" + called 'server.pem'. + """ ctx = SSL.Context(SSL.SSLv23_METHOD) ctx.use_certificate_file('server.pem') ctx.use_privatekey_file('server.pem') @@ -290,7 +328,6 @@ - # Easy configuration def makeService(config): diff -Nru twisted-10.2.0/doc/howto/tutorial/listings/finger/finger14.tac twisted-12.1.0/doc/howto/tutorial/listings/finger/finger14.tac --- twisted-10.2.0/doc/howto/tutorial/listings/finger/finger14.tac 2010-05-31 02:07:39.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/listings/finger/finger14.tac 2011-01-22 14:10:51.000000000 +0000 @@ -16,6 +16,7 @@ self.transport.loseConnection() d.addCallback(writeResponse) + class FingerService(service.Service): def __init__(self, filename): self.users = {} @@ -46,6 +47,7 @@ f.getUser = self.getUser return f + application = service.Application('finger', uid=1, gid=1) f = FingerService('/etc/users') finger = internet.TCPServer(79, f.getFingerFactory()) diff -Nru twisted-10.2.0/doc/howto/tutorial/listings/finger/finger15.tac twisted-12.1.0/doc/howto/tutorial/listings/finger/finger15.tac --- twisted-10.2.0/doc/howto/tutorial/listings/finger/finger15.tac 2009-04-15 22:58:22.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/listings/finger/finger15.tac 2011-09-21 23:23:38.000000000 +0000 @@ -18,6 +18,7 @@ self.transport.loseConnection() d.addCallback(writeResponse) + class FingerResource(resource.Resource): def __init__(self, users): @@ -39,11 +40,11 @@ text = '

              %s

              No such user

              ' % username return static.Data(text, 'text/html') + class FingerService(service.Service): def __init__(self, filename): self.filename = filename self.users = {} - self._read() def _read(self): self.users.clear() @@ -67,9 +68,19 @@ r = FingerResource(self.users) return r + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + + application = service.Application('finger', uid=1, gid=1) f = FingerService('/etc/users') serviceCollection = service.IServiceCollection(application) +f.setServiceParent(serviceCollection) internet.TCPServer(79, f.getFingerFactory() ).setServiceParent(serviceCollection) internet.TCPServer(8000, server.Site(f.getResource()) diff -Nru twisted-10.2.0/doc/howto/tutorial/listings/finger/finger16.tac twisted-12.1.0/doc/howto/tutorial/listings/finger/finger16.tac --- twisted-10.2.0/doc/howto/tutorial/listings/finger/finger16.tac 2009-04-15 22:58:22.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/listings/finger/finger16.tac 2011-09-21 23:23:38.000000000 +0000 @@ -39,11 +39,11 @@ irc.IRCClient.msg(self, user, msg+': '+message) d.addCallback(writeResponse) + class FingerService(service.Service): def __init__(self, filename): self.filename = filename self.users = {} - self._read() def _read(self): self.users.clear() @@ -80,9 +80,19 @@ f.getUser = self.getUser return f + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + + application = service.Application('finger', uid=1, gid=1) f = FingerService('/etc/users') serviceCollection = service.IServiceCollection(application) +f.setServiceParent(serviceCollection) internet.TCPServer(79, f.getFingerFactory() ).setServiceParent(serviceCollection) internet.TCPServer(8000, server.Site(f.getResource()) diff -Nru twisted-10.2.0/doc/howto/tutorial/listings/finger/finger17.tac twisted-12.1.0/doc/howto/tutorial/listings/finger/finger17.tac --- twisted-10.2.0/doc/howto/tutorial/listings/finger/finger17.tac 2009-04-15 22:58:22.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/listings/finger/finger17.tac 2011-09-21 23:23:38.000000000 +0000 @@ -19,6 +19,7 @@ self.transport.loseConnection() d.addCallback(writeResponse) + class IRCReplyBot(irc.IRCClient): def connectionMade(self): self.nickname = self.factory.nickname @@ -37,11 +38,11 @@ irc.IRCClient.msg(self, user, msg+': '+message) d.addCallback(writeResponse) + class FingerService(service.Service): def __init__(self, filename): self.filename = filename self.users = {} - self._read() def _read(self): self.users.clear() @@ -80,9 +81,19 @@ f.getUser = self.getUser return f + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + + application = service.Application('finger', uid=1, gid=1) f = FingerService('/etc/users') serviceCollection = service.IServiceCollection(application) +f.setServiceParent(serviceCollection) internet.TCPServer(79, f.getFingerFactory() ).setServiceParent(serviceCollection) internet.TCPServer(8000, server.Site(f.getResource()) diff -Nru twisted-10.2.0/doc/howto/tutorial/listings/finger/finger18.tac twisted-12.1.0/doc/howto/tutorial/listings/finger/finger18.tac --- twisted-10.2.0/doc/howto/tutorial/listings/finger/finger18.tac 2009-04-15 22:58:22.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/listings/finger/finger18.tac 2011-09-21 23:23:38.000000000 +0000 @@ -9,6 +9,7 @@ def catchError(err): return "Internal error in server" + class FingerProtocol(basic.LineReceiver): def lineReceived(self, user): @@ -57,6 +58,7 @@ else: return UserStatus(path, self.service) + class UserStatus(resource.Resource): def __init__(self, user, service): @@ -89,7 +91,6 @@ def __init__(self, filename): self.filename = filename self.users = {} - self._read() def _read(self): self.users.clear() @@ -125,10 +126,19 @@ f.getUser = self.getUser return f + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + application = service.Application('finger', uid=1, gid=1) f = FingerService('/etc/users') serviceCollection = service.IServiceCollection(application) +f.setServiceParent(serviceCollection) internet.TCPServer(79, f.getFingerFactory() ).setServiceParent(serviceCollection) internet.TCPServer(8000, server.Site(f.getResource()) diff -Nru twisted-10.2.0/doc/howto/tutorial/listings/finger/finger19b.tac twisted-12.1.0/doc/howto/tutorial/listings/finger/finger19b.tac --- twisted-10.2.0/doc/howto/tutorial/listings/finger/finger19b.tac 2009-04-15 22:58:22.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/listings/finger/finger19b.tac 2011-01-22 14:10:51.000000000 +0000 @@ -12,24 +12,36 @@ class IFingerService(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def getUsers(): - """Return a deferred returning a list of strings""" + """ + Return a deferred returning a list of strings. + """ + class IFingerSetterService(Interface): def setUser(user, status): - """Set the user's status to something""" + """ + Set the user's status to something. + """ + class IFingerSetterService(Interface): def setUser(user, status): - """Set the user's status to something""" + """ + Set the user's status to something. + """ + def catchError(err): return "Internal error in server" + class FingerProtocol(basic.LineReceiver): def lineReceived(self, user): @@ -44,10 +56,14 @@ class IFingerFactory(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerFactoryFromService(protocol.ServerFactory): @@ -66,6 +82,7 @@ IFingerService, IFingerFactory) + class FingerSetterProtocol(basic.LineReceiver): def connectionMade(self): @@ -82,10 +99,14 @@ class IFingerSetterFactory(Interface): def setUser(user, status): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerSetterFactoryFromService(protocol.ServerFactory): @@ -127,10 +148,14 @@ """ def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol""" + """ + Return a protocol. + """ class IRCClientFactoryFromService(protocol.ClientFactory): @@ -150,6 +175,7 @@ IFingerService, IIRCClientFactory) + class UserStatusTree(resource.Resource): implements(resource.IResource) @@ -179,6 +205,7 @@ components.registerAdapter(UserStatusTree, IFingerService, resource.IResource) + class UserStatus(resource.Resource): def __init__(self, user, service): @@ -213,7 +240,6 @@ def __init__(self, filename): self.filename = filename self.users = {} - self._read() def _read(self): self.users.clear() @@ -230,6 +256,15 @@ def getUsers(self): return defer.succeed(self.users.keys()) + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + + # Another back-end class LocalFingerService(service.Service): diff -Nru twisted-10.2.0/doc/howto/tutorial/listings/finger/finger19c.tac twisted-12.1.0/doc/howto/tutorial/listings/finger/finger19c.tac --- twisted-10.2.0/doc/howto/tutorial/listings/finger/finger19c.tac 2009-04-15 22:58:22.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/listings/finger/finger19c.tac 2011-01-22 14:10:51.000000000 +0000 @@ -13,24 +13,36 @@ class IFingerService(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def getUsers(): - """Return a deferred returning a list of strings""" + """ + Return a deferred returning a list of strings. + """ + class IFingerSetterService(Interface): def setUser(user, status): - """Set the user's status to something""" + """ + Set the user's status to something. + """ + class IFingerSetterService(Interface): def setUser(user, status): - """Set the user's status to something""" + """ + Set the user's status to something. + """ + def catchError(err): return "Internal error in server" + class FingerProtocol(basic.LineReceiver): def lineReceived(self, user): @@ -45,10 +57,14 @@ class IFingerFactory(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerFactoryFromService(protocol.ServerFactory): @@ -67,6 +83,7 @@ IFingerService, IFingerFactory) + class FingerSetterProtocol(basic.LineReceiver): def connectionMade(self): @@ -83,10 +100,14 @@ class IFingerSetterFactory(Interface): def setUser(user, status): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerSetterFactoryFromService(protocol.ServerFactory): @@ -106,6 +127,7 @@ IFingerSetterService, IFingerSetterFactory) + class IRCReplyBot(irc.IRCClient): def connectionMade(): @@ -128,10 +150,14 @@ """ def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol""" + """ + Return a protocol. + """ class IRCClientFactoryFromService(protocol.ClientFactory): @@ -151,6 +177,7 @@ IFingerService, IIRCClientFactory) + class UserStatusTree(resource.Resource): implements(resource.IResource) @@ -180,6 +207,7 @@ components.registerAdapter(UserStatusTree, IFingerService, resource.IResource) + class UserStatus(resource.Resource): def __init__(self, user, service): @@ -214,7 +242,6 @@ def __init__(self, filename): self.filename = filename self.users = {} - self._read() def _read(self): self.users.clear() @@ -231,6 +258,15 @@ def getUsers(self): return defer.succeed(self.users.keys()) + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + + # Yet another back-end class LocalFingerService(service.Service): diff -Nru twisted-10.2.0/doc/howto/tutorial/listings/finger/finger19.tac twisted-12.1.0/doc/howto/tutorial/listings/finger/finger19.tac --- twisted-10.2.0/doc/howto/tutorial/listings/finger/finger19.tac 2009-04-15 22:58:22.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/listings/finger/finger19.tac 2011-09-21 23:23:38.000000000 +0000 @@ -11,19 +11,28 @@ class IFingerService(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def getUsers(): - """Return a deferred returning a list of strings""" + """ + Return a deferred returning a list of strings. + """ + class IFingerSetterService(Interface): def setUser(user, status): - """Set the user's status to something""" + """ + Set the user's status to something. + """ + def catchError(err): return "Internal error in server" + class FingerProtocol(basic.LineReceiver): def lineReceived(self, user): @@ -38,10 +47,14 @@ class IFingerFactory(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerFactoryFromService(protocol.ServerFactory): @@ -60,6 +73,7 @@ IFingerService, IFingerFactory) + class FingerSetterProtocol(basic.LineReceiver): def connectionMade(self): @@ -76,10 +90,14 @@ class IFingerSetterFactory(Interface): def setUser(user, status): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerSetterFactoryFromService(protocol.ServerFactory): @@ -99,6 +117,7 @@ IFingerSetterService, IFingerSetterFactory) + class IRCReplyBot(irc.IRCClient): def connectionMade(self): @@ -115,16 +134,19 @@ class IIRCClientFactory(Interface): - """ @ivar nickname """ def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol""" + """ + Return a protocol. + """ class IRCClientFactoryFromService(protocol.ClientFactory): @@ -144,6 +166,7 @@ IFingerService, IIRCClientFactory) + class UserStatusTree(resource.Resource): implements(resource.IResource) @@ -173,6 +196,7 @@ components.registerAdapter(UserStatusTree, IFingerService, resource.IResource) + class UserStatus(resource.Resource): def __init__(self, user, service): @@ -207,7 +231,6 @@ def __init__(self, filename): self.filename = filename self.users = {} - self._read() def _read(self): self.users.clear() @@ -224,10 +247,19 @@ def getUsers(self): return defer.succeed(self.users.keys()) + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + application = service.Application('finger', uid=1, gid=1) f = FingerService('/etc/users') serviceCollection = service.IServiceCollection(application) +f.setServiceParent(serviceCollection) internet.TCPServer(79, IFingerFactory(f) ).setServiceParent(serviceCollection) internet.TCPServer(8000, server.Site(resource.IResource(f)) diff -Nru twisted-10.2.0/doc/howto/tutorial/listings/finger/finger20.tac twisted-12.1.0/doc/howto/tutorial/listings/finger/finger20.tac --- twisted-10.2.0/doc/howto/tutorial/listings/finger/finger20.tac 2009-04-15 22:58:22.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/listings/finger/finger20.tac 2011-09-21 23:23:38.000000000 +0000 @@ -11,19 +11,28 @@ class IFingerService(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def getUsers(): - """Return a deferred returning a list of strings""" + """ + Return a deferred returning a list of strings. + """ + class IFingerSetterService(Interface): def setUser(user, status): - """Set the user's status to something""" + """ + Set the user's status to something. + """ + def catchError(err): return "Internal error in server" + class FingerProtocol(basic.LineReceiver): def lineReceived(self, user): @@ -38,10 +47,14 @@ class IFingerFactory(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerFactoryFromService(protocol.ServerFactory): @@ -60,6 +73,7 @@ IFingerService, IFingerFactory) + class FingerSetterProtocol(basic.LineReceiver): def connectionMade(self): @@ -76,10 +90,14 @@ class IFingerSetterFactory(Interface): def setUser(user, status): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerSetterFactoryFromService(protocol.ServerFactory): @@ -99,6 +117,7 @@ IFingerSetterService, IFingerSetterFactory) + class IRCReplyBot(irc.IRCClient): def connectionMade(self): @@ -121,10 +140,14 @@ """ def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol""" + """ + Return a protocol. + """ class IRCClientFactoryFromService(protocol.ClientFactory): @@ -144,6 +167,7 @@ IFingerService, IIRCClientFactory) + class UserStatusTree(resource.Resource): def __init__(self, service): @@ -179,6 +203,7 @@ components.registerAdapter(UserStatusTree, IFingerService, resource.IResource) + class UserStatus(resource.Resource): def __init__(self, user, service): @@ -200,6 +225,7 @@ # signal that the rendering is not complete return server.NOT_DONE_YET + class UserStatusXR(xmlrpc.XMLRPC): def __init__(self, service): @@ -220,7 +246,6 @@ def __init__(self, filename): self.filename = filename self.users = {} - self._read() def _read(self): self.users.clear() @@ -237,10 +262,19 @@ def getUsers(self): return defer.succeed(self.users.keys()) + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + application = service.Application('finger', uid=1, gid=1) f = FingerService('/etc/users') serviceCollection = service.IServiceCollection(application) +f.setServiceParent(serviceCollection) internet.TCPServer(79, IFingerFactory(f) ).setServiceParent(serviceCollection) internet.TCPServer(8000, server.Site(resource.IResource(f)) diff -Nru twisted-10.2.0/doc/howto/tutorial/listings/finger/finger21.tac twisted-12.1.0/doc/howto/tutorial/listings/finger/finger21.tac --- twisted-10.2.0/doc/howto/tutorial/listings/finger/finger21.tac 2009-04-15 22:58:22.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/listings/finger/finger21.tac 2011-09-21 23:23:38.000000000 +0000 @@ -12,19 +12,28 @@ class IFingerService(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def getUsers(): - """Return a deferred returning a list of strings""" + """ + Return a deferred returning a list of strings. + """ + class IFingerSetterService(Interface): def setUser(user, status): - """Set the user's status to something""" + """ + Set the user's status to something. + """ + def catchError(err): return "Internal error in server" + class FingerProtocol(basic.LineReceiver): def lineReceived(self, user): @@ -39,10 +48,14 @@ class IFingerFactory(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerFactoryFromService(protocol.ServerFactory): @@ -61,6 +74,7 @@ IFingerService, IFingerFactory) + class FingerSetterProtocol(basic.LineReceiver): def connectionMade(self): @@ -77,10 +91,14 @@ class IFingerSetterFactory(Interface): def setUser(user, status): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerSetterFactoryFromService(protocol.ServerFactory): @@ -100,6 +118,7 @@ IFingerSetterService, IFingerSetterFactory) + class IRCReplyBot(irc.IRCClient): def connectionMade(self): @@ -122,10 +141,14 @@ """ def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol""" + """ + Return a protocol. + """ class IRCClientFactoryFromService(protocol.ClientFactory): @@ -145,6 +168,7 @@ IFingerService, IIRCClientFactory) + class UserStatusTree(resource.Resource): def __init__(self, service): @@ -180,6 +204,7 @@ components.registerAdapter(UserStatusTree, IFingerService, resource.IResource) + class UserStatus(resource.Resource): def __init__(self, user, service): @@ -201,6 +226,7 @@ # signal that the rendering is not complete return server.NOT_DONE_YET + class UserStatusXR(xmlrpc.XMLRPC): def __init__(self, service): @@ -217,10 +243,15 @@ class IPerspectiveFinger(Interface): def remote_getUser(username): - """return a user's status""" + """ + Return a user's status. + """ def remote_getUsers(): - """return a user's status""" + """ + Return a user's status. + """ + class PerspectiveFingerFromService(pb.Root): @@ -247,7 +278,6 @@ def __init__(self, filename): self.filename = filename self.users = {} - self._read() def _read(self): self.users.clear() @@ -264,10 +294,19 @@ def getUsers(self): return defer.succeed(self.users.keys()) + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + application = service.Application('finger', uid=1, gid=1) f = FingerService('/etc/users') serviceCollection = service.IServiceCollection(application) +f.setServiceParent(serviceCollection) internet.TCPServer(79, IFingerFactory(f) ).setServiceParent(serviceCollection) internet.TCPServer(8000, server.Site(resource.IResource(f)) diff -Nru twisted-10.2.0/doc/howto/tutorial/listings/finger/finger22.py twisted-12.1.0/doc/howto/tutorial/listings/finger/finger22.py --- twisted-10.2.0/doc/howto/tutorial/listings/finger/finger22.py 2009-04-15 22:58:22.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/listings/finger/finger22.py 2011-09-21 23:23:38.000000000 +0000 @@ -13,19 +13,28 @@ class IFingerService(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def getUsers(): - """Return a deferred returning a list of strings""" + """ + Return a deferred returning a list of strings. + """ + class IFingerSetterService(Interface): def setUser(user, status): - """Set the user's status to something""" + """ + Set the user's status to something. + """ + def catchError(err): return "Internal error in server" + class FingerProtocol(basic.LineReceiver): def lineReceived(self, user): @@ -40,10 +49,14 @@ class IFingerFactory(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerFactoryFromService(protocol.ServerFactory): @@ -62,6 +75,7 @@ IFingerService, IFingerFactory) + class FingerSetterProtocol(basic.LineReceiver): def connectionMade(self): @@ -78,10 +92,14 @@ class IFingerSetterFactory(Interface): def setUser(user, status): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerSetterFactoryFromService(protocol.ServerFactory): @@ -101,6 +119,7 @@ IFingerSetterService, IFingerSetterFactory) + class IRCReplyBot(irc.IRCClient): def connectionMade(self): @@ -123,10 +142,14 @@ """ def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol""" + """ + Return a protocol. + """ class IRCClientFactoryFromService(protocol.ClientFactory): @@ -146,6 +169,7 @@ IFingerService, IIRCClientFactory) + class UserStatusTree(resource.Resource): def __init__(self, service): @@ -181,6 +205,7 @@ components.registerAdapter(UserStatusTree, IFingerService, resource.IResource) + class UserStatus(resource.Resource): def __init__(self, user, service): @@ -202,6 +227,7 @@ # signal that the rendering is not complete return server.NOT_DONE_YET + class UserStatusXR(xmlrpc.XMLRPC): def __init__(self, service): @@ -218,10 +244,14 @@ class IPerspectiveFinger(Interface): def remote_getUser(username): - """return a user's status""" + """ + Return a user's status. + """ def remote_getUsers(): - """return a user's status""" + """ + Return a user's status. + """ class PerspectiveFingerFromService(pb.Root): @@ -248,7 +278,6 @@ def __init__(self, filename): self.filename = filename self.users = {} - self._read() def _read(self): self.users.clear() @@ -265,14 +294,24 @@ def getUsers(self): return defer.succeed(self.users.keys()) + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + class ServerContextFactory: def getContext(self): - """Create an SSL context. + """ + Create an SSL context. This is a sample implementation that loads a certificate from a file - called 'server.pem'.""" + called 'server.pem'. + """ ctx = SSL.Context(SSL.SSLv23_METHOD) ctx.use_certificate_file('server.pem') ctx.use_privatekey_file('server.pem') @@ -282,6 +321,7 @@ application = service.Application('finger', uid=1, gid=1) f = FingerService('/etc/users') serviceCollection = service.IServiceCollection(application) +f.setServiceParent(serviceCollection) internet.TCPServer(79, IFingerFactory(f) ).setServiceParent(serviceCollection) site = server.Site(resource.IResource(f)) diff -Nru twisted-10.2.0/doc/howto/tutorial/pb.html twisted-12.1.0/doc/howto/tutorial/pb.html --- twisted-10.2.0/doc/howto/tutorial/pb.html 2010-11-30 03:13:20.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/pb.html 2012-06-04 08:46:22.000000000 +0000 @@ -306,6 +306,45 @@ 278 279 280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319

              # Do everything properly, and componentize from twisted.application import internet, service from twisted.internet import protocol, reactor, defer @@ -320,19 +359,28 @@ class IFingerService(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def getUsers(): - """Return a deferred returning a list of strings""" + """ + Return a deferred returning a list of strings. + """ + class IFingerSetterService(Interface): def setUser(user, status): - """Set the user's status to something""" + """ + Set the user's status to something. + """ + def catchError(err): return "Internal error in server" + class FingerProtocol(basic.LineReceiver): def lineReceived(self, user): @@ -347,10 +395,14 @@ class IFingerFactory(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerFactoryFromService(protocol.ServerFactory): @@ -369,6 +421,7 @@ IFingerService, IFingerFactory) + class FingerSetterProtocol(basic.LineReceiver): def connectionMade(self): @@ -385,10 +438,14 @@ class IFingerSetterFactory(Interface): def setUser(user, status): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerSetterFactoryFromService(protocol.ServerFactory): @@ -408,6 +465,7 @@ IFingerSetterService, IFingerSetterFactory) + class IRCReplyBot(irc.IRCClient): def connectionMade(self): @@ -430,10 +488,14 @@ """
              def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol""" + """ + Return a protocol. + """ class IRCClientFactoryFromService(protocol.ClientFactory): @@ -453,6 +515,7 @@ IFingerService, IIRCClientFactory) + class UserStatusTree(resource.Resource): def __init__(self, service): @@ -488,6 +551,7 @@ components.registerAdapter(UserStatusTree, IFingerService, resource.IResource) + class UserStatus(resource.Resource): def __init__(self, user, service): @@ -509,6 +573,7 @@ # signal that the rendering is not complete return server.NOT_DONE_YET + class UserStatusXR(xmlrpc.XMLRPC): def __init__(self, service): @@ -525,10 +590,15 @@ class IPerspectiveFinger(Interface): def remote_getUser(username): - """return a user's status""" + """ + Return a user's status. + """ def remote_getUsers(): - """return a user's status""" + """ + Return a user's status. + """ + class PerspectiveFingerFromService(pb.Root): @@ -555,7 +625,6 @@ def __init__(self, filename): self.filename = filename self.users = {} - self._read() def _read(self): self.users.clear() @@ -572,10 +641,19 @@ def getUsers(self): return defer.succeed(self.users.keys()) + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + application = service.Application('finger', uid=1, gid=1) f = FingerService('/etc/users') serviceCollection = service.IServiceCollection(application) +f.setServiceParent(serviceCollection) internet.TCPServer(79, IFingerFactory(f) ).setServiceParent(serviceCollection) internet.TCPServer(8000, server.Site(resource.IResource(f)) @@ -645,6 +723,6 @@

              Index

              - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/tutorial/protocol.html twisted-12.1.0/doc/howto/tutorial/protocol.html --- twisted-10.2.0/doc/howto/tutorial/protocol.html 2010-11-30 03:13:21.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/protocol.html 2012-06-04 08:46:22.000000000 +0000 @@ -20,7 +20,7 @@ service to send those announcements on the web, on IRC and over XML-RPC. Resources and XML-RPC are introduced in the Web Applications portion of the Twisted Web howto. More examples -using twisted.words.protocols.irc can be found +using twisted.words.protocols.irc can be found in Writing a TCP Client and the Twisted Words examples.

              @@ -154,9 +154,9 @@

              This program has two protocol-factory-TCPServer pairs, which are both child services of the application. Specifically, -the setServiceParent +the setServiceParent method is used to define the two TCPServer services as children -of application, which implements IServiceCollection. Both +of application, which implements IServiceCollection. Both services are thus started with the application.

              @@ -196,7 +196,7 @@ none of our protocol classes had to be changed, and neither will have to change until the end of the tutorial.

              -

              As an application service, this new finger service implements the IService interface and +

              As an application service, this new finger service implements the IService interface and can be started and stopped in a standardized manner. We'll make use of this in the next example.

              @@ -320,7 +320,7 @@ ).setServiceParent(serviceCollection)
              -

              Most application services will want to use the Service base class, which implements +

              Most application services will want to use the Service base class, which implements all the generic IService behavior.

              Read Status File

              @@ -389,6 +389,8 @@ 52 53 54 +55 +56

              # Read from file from twisted.application import internet, service from twisted.internet import protocol, reactor, defer @@ -407,6 +409,7 @@ self.transport.loseConnection() d.addCallback(writeResponse) + class FingerService(service.Service): def __init__(self, filename): self.users = {} @@ -437,6 +440,7 @@ f.getUser = self.getUser return f + application = service.Application('finger', uid=1, gid=1) f = FingerService('/etc/users') finger = internet.TCPServer(79, f.getFingerFactory()) @@ -449,8 +453,8 @@ every 30 seconds), there is no FingerSetterFactory and thus nothing listening on port 1079.

              -

              Here we override the standard startService -and stopService hooks in +

              Here we override the standard startService +and stopService hooks in the Finger service, which is set up as a child service of the application in the last line of the code. startService calls _read, the function responsible for reading the @@ -551,6 +555,17 @@ 74 75 76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87

              # Read from file, announce on the web! from twisted.application import internet, service from twisted.internet import protocol, reactor, defer @@ -571,6 +586,7 @@ self.transport.loseConnection() d.addCallback(writeResponse) + class FingerResource(resource.Resource): def __init__(self, users): @@ -592,11 +608,11 @@ text = '<h1>%s</h1><p>No such user</p>' % username return static.Data(text, 'text/html') + class FingerService(service.Service): def __init__(self, filename): self.filename = filename self.users = {} - self._read() def _read(self): self.users.clear() @@ -620,9 +636,19 @@ r = FingerResource(self.users) return r + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + + application = service.Application('finger', uid=1, gid=1) f = FingerService('/etc/users') serviceCollection = service.IServiceCollection(application) +f.setServiceParent(serviceCollection) internet.TCPServer(79, f.getFingerFactory() ).setServiceParent(serviceCollection) internet.TCPServer(8000, server.Site(f.getResource()) @@ -639,97 +665,107 @@ only real hack is getting the nickname from the factory in connectionMade.

              -

              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 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 +

              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 + 61 + 62 + 63 + 64 + 65 + 66 + 67 + 68 + 69 + 70 + 71 + 72 + 73 + 74 + 75 + 76 + 77 + 78 + 79 + 80 + 81 + 82 + 83 + 84 + 85 + 86 + 87 + 88 + 89 + 90 + 91 + 92 + 93 + 94 + 95 + 96 + 97 + 98 + 99 +100 +101

              # Read from file, announce on the web, irc from twisted.application import internet, service from twisted.internet import protocol, reactor, defer @@ -771,11 +807,11 @@ irc.IRCClient.msg(self, user, msg+': '+message) d.addCallback(writeResponse) + class FingerService(service.Service): def __init__(self, filename): self.filename = filename self.users = {} - self._read() def _read(self): self.users.clear() @@ -812,9 +848,19 @@ f.getUser = self.getUser return f + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + + application = service.Application('finger', uid=1, gid=1) f = FingerService('/etc/users') serviceCollection = service.IServiceCollection(application) +f.setServiceParent(serviceCollection) internet.TCPServer(79, f.getFingerFactory() ).setServiceParent(serviceCollection) internet.TCPServer(8000, server.Site(f.getResource()) @@ -845,97 +891,108 @@ The client, of course, will not get the answer until the deferred is triggered.

              -

              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 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 +

              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 + 61 + 62 + 63 + 64 + 65 + 66 + 67 + 68 + 69 + 70 + 71 + 72 + 73 + 74 + 75 + 76 + 77 + 78 + 79 + 80 + 81 + 82 + 83 + 84 + 85 + 86 + 87 + 88 + 89 + 90 + 91 + 92 + 93 + 94 + 95 + 96 + 97 + 98 + 99 +100 +101 +102

              # Read from file, announce on the web, irc, xml-rpc from twisted.application import internet, service from twisted.internet import protocol, reactor, defer @@ -957,6 +1014,7 @@ self.transport.loseConnection() d.addCallback(writeResponse) + class IRCReplyBot(irc.IRCClient): def connectionMade(self): self.nickname = self.factory.nickname @@ -975,11 +1033,11 @@ irc.IRCClient.msg(self, user, msg+': '+message) d.addCallback(writeResponse) + class FingerService(service.Service): def __init__(self, filename): self.filename = filename self.users = {} - self._read() def _read(self): self.users.clear() @@ -1018,9 +1076,19 @@ f.getUser = self.getUser return f + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + + application = service.Application('finger', uid=1, gid=1) f = FingerService('/etc/users') serviceCollection = service.IServiceCollection(application) +f.setServiceParent(serviceCollection) internet.TCPServer(79, f.getFingerFactory() ).setServiceParent(serviceCollection) internet.TCPServer(8000, server.Site(f.getResource()) @@ -1048,6 +1116,6 @@

              Index

              - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/tutorial/style.html twisted-12.1.0/doc/howto/tutorial/style.html --- twisted-10.2.0/doc/howto/tutorial/style.html 2010-11-30 03:13:22.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/style.html 2012-06-04 08:46:22.000000000 +0000 @@ -166,6 +166,16 @@ 135 136 137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147

              # Do everything properly from twisted.application import internet, service from twisted.internet import protocol, reactor, defer @@ -177,6 +187,7 @@ def catchError(err): return "Internal error in server" + class FingerProtocol(basic.LineReceiver): def lineReceived(self, user): @@ -225,6 +236,7 @@ else: return UserStatus(path, self.service) + class UserStatus(resource.Resource): def __init__(self, user, service): @@ -257,7 +269,6 @@ def __init__(self, filename): self.filename = filename self.users = {} - self._read() def _read(self): self.users.clear() @@ -293,10 +304,19 @@ f.getUser = self.getUser return f + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + application = service.Application('finger', uid=1, gid=1) f = FingerService('/etc/users') serviceCollection = service.IServiceCollection(application) +f.setServiceParent(serviceCollection) internet.TCPServer(79, f.getFingerFactory() ).setServiceParent(serviceCollection) internet.TCPServer(8000, server.Site(f.getResource()) @@ -308,6 +328,6 @@

              Index

              - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/tutorial/web.html twisted-12.1.0/doc/howto/tutorial/web.html --- twisted-10.2.0/doc/howto/tutorial/web.html 2010-11-30 03:13:22.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/web.html 2012-06-04 08:46:22.000000000 +0000 @@ -16,7 +16,7 @@

              This is the sixth part of the Twisted tutorial Twisted from Scratch, or The Evolution of Finger.

              In this part, we demonstrate adding a web frontend using -simple twisted.web.resource.Resource +simple twisted.web.resource.Resource objects: UserStatusTree, which will produce a listing of all users at the base URL (/) of our site; UserStatus, which gives the status @@ -281,6 +281,40 @@ 249 250 251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285

              # Do everything properly, and componentize from twisted.application import internet, service from twisted.internet import protocol, reactor, defer @@ -294,19 +328,28 @@ class IFingerService(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def getUsers(): - """Return a deferred returning a list of strings""" + """ + Return a deferred returning a list of strings. + """ + class IFingerSetterService(Interface): def setUser(user, status): - """Set the user's status to something""" + """ + Set the user's status to something. + """ + def catchError(err): return "Internal error in server" + class FingerProtocol(basic.LineReceiver): def lineReceived(self, user): @@ -321,10 +364,14 @@ class IFingerFactory(Interface): def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerFactoryFromService(protocol.ServerFactory): @@ -343,6 +390,7 @@ IFingerService, IFingerFactory) + class FingerSetterProtocol(basic.LineReceiver): def connectionMade(self): @@ -359,10 +407,14 @@ class IFingerSetterFactory(Interface): def setUser(user, status): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol returning a string""" + """ + Return a protocol returning a string. + """ class FingerSetterFactoryFromService(protocol.ServerFactory): @@ -382,6 +434,7 @@ IFingerSetterService, IFingerSetterFactory) + class IRCReplyBot(irc.IRCClient): def connectionMade(self): @@ -404,10 +457,14 @@ """ def getUser(user): - """Return a deferred returning a string""" + """ + Return a deferred returning a string. + """ def buildProtocol(addr): - """Return a protocol""" + """ + Return a protocol. + """ class IRCClientFactoryFromService(protocol.ClientFactory): @@ -427,6 +484,7 @@ IFingerService, IIRCClientFactory) + class UserStatusTree(resource.Resource): def __init__(self, service): @@ -462,6 +520,7 @@ components.registerAdapter(UserStatusTree, IFingerService, resource.IResource) + class UserStatus(resource.Resource): def __init__(self, user, service): @@ -483,6 +542,7 @@ # signal that the rendering is not complete return server.NOT_DONE_YET + class UserStatusXR(xmlrpc.XMLRPC): def __init__(self, service): @@ -503,7 +563,6 @@ def __init__(self, filename): self.filename = filename self.users = {} - self._read() def _read(self): self.users.clear() @@ -520,10 +579,19 @@ def getUsers(self): return defer.succeed(self.users.keys()) + def startService(self): + self._read() + service.Service.startService(self) + + def stopService(self): + service.Service.stopService(self) + self.call.cancel() + application = service.Application('finger', uid=1, gid=1) f = FingerService('/etc/users') serviceCollection = service.IServiceCollection(application) +f.setServiceParent(serviceCollection) internet.TCPServer(79, IFingerFactory(f) ).setServiceParent(serviceCollection) internet.TCPServer(8000, server.Site(resource.IResource(f)) @@ -537,6 +605,6 @@

              Index

              - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/udp.html twisted-12.1.0/doc/howto/udp.html --- twisted-10.2.0/doc/howto/udp.html 2010-11-30 03:13:18.000000000 +0000 +++ twisted-12.1.0/doc/howto/udp.html 2012-06-04 08:46:20.000000000 +0000 @@ -6,7 +6,7 @@

              UDP Networking

              - +
              @@ -20,14 +20,14 @@

              Since there are no connections, we only use a single object, a protocol, for each UDP socket. We then use the reactor to connect this protocol to a UDP transport, using the - twisted.internet.interfaces.IReactorUDP + twisted.internet.interfaces.IReactorUDP reactor API.

              DatagramProtocol

              The class where you actually implement the protocol parsing and handling will usually be descended - from twisted.internet.protocol.DatagramProtocol or + from twisted.internet.protocol.DatagramProtocol or from one of its convenience children. The DatagramProtocol class receives datagrams and can send them out over the network. Received datagrams include the address they were sent from. When sending datagrams @@ -60,15 +60,15 @@

              As you can see, the protocol is registered with the reactor. This means it may be persisted if it's added to an application, and thus it has - startProtocol - and stopProtocol + startProtocol + and stopProtocol methods that will get called when the protocol is connected and disconnected from a UDP socket.

              The protocol's transport attribute will - implement the twisted.internet.interfaces.IUDPTransport interface. + implement the twisted.internet.interfaces.IUDPTransport interface. Notice that the host argument should be an - IP address, not a hostname. If you only have the hostname use reactor.resolve() to resolve the address (see twisted.internet.interfaces.IReactorCore.resolve).

              + IP address, not a hostname. If you only have the hostname use reactor.resolve() to resolve the address (see twisted.internet.interfaces.IReactorCore.resolve).

              Connected UDP

              @@ -108,14 +108,20 @@ 19 20 21 +22 +23 +24

              from twisted.internet.protocol import DatagramProtocol from twisted.internet import reactor class Helloer(DatagramProtocol): def startProtocol(self): - self.transport.connect("192.168.1.1", 1234) - print "we can only send to %s now" % str((host, port)) + host = "192.168.1.1" + port = 1234 + + self.transport.connect(host, port) + print "now we can only send to host %s port %d" % (host, port) self.transport.write("hello") # no need for address def datagramReceived(self, data, (host, port)): @@ -142,12 +148,16 @@ 4 5 6 +7 +8

              from twisted.internet import reactor def gotIP(ip): print "IP of 'example.com' is", ip + reactor.callLater(3, reactor.stop) reactor.resolve('example.com').addCallback(gotIP) +reactor.run()

              Connecting to a new address after a previous connection or making a @@ -156,10 +166,14 @@

              Multicast UDP

              -

              A multicast UDP socket can send and receive datagrams from multiple - clients. The interesting and useful feature of multicast is that a client - can contact multiple servers with a single packet, without knowing the - specific IP address of any of the hosts.

              +

              Multicast allows a process to contact multiple hosts with a single + packet, without knowing the specific IP address of any of the hosts. This + is in contrast to normal, or unicast, UDP, where each datagram has a single + IP as its destination. Multicast datagrams are sent to special multicast + group addresses (in the IPv4 range 224.0.0.0 to 239.255.255.255), along with + a corresponding port. In order to receive multicast datagrams, you must + join that specific group address. However, any UDP socket can send to + multicast addresses.

              1 2 @@ -186,44 +200,50 @@ 23 24 25 +26 +27 +28

              from twisted.internet.protocol import DatagramProtocol from twisted.internet import reactor -from twisted.application.internet import MulticastServer -class MulticastServerUDP(DatagramProtocol): + +class MulticastPingPong(DatagramProtocol): + def startProtocol(self): - print 'Started Listening' - # Join a specific multicast group, which is the IP we will respond to - self.transport.joinGroup('224.0.0.1') + """ + Called after protocol has started listening. + """ + # Set the TTL>1 so multicast will cross router hops: + self.transport.setTTL(5) + # Join a specific multicast group: + self.transport.joinGroup("228.0.0.5") def datagramReceived(self, datagram, address): - # The uniqueID check is to ensure we only service requests from - # ourselves - if datagram == 'UniqueID': - print "Server Received:" + repr(datagram) - self.transport.write("data", address) - -# Note that the join function is picky about having a unique object -# on which to call join. To avoid using startProtocol, the following is -# sufficient: -#reactor.listenMulticast(8005, MulticastServerUDP()).join('224.0.0.1') + print "Datagram %s received from %s" % (repr(datagram), repr(address)) + if datagram == "Client: Ping": + # Rather than replying to the group multicast address, we send the + # reply directly (unicast) to the originating port: + self.transport.write("Server: Pong", address) + -# Listen for multicast on 224.0.0.1:8005 -reactor.listenMulticast(8005, MulticastServerUDP()) +# We use listenMultiple=True so that we can run MulticastServer.py and +# MulticastClient.py on same machine: +reactor.listenMulticast(8005, MulticastPingPong(), + listenMultiple=True) reactor.run()
              -

              The server protocol is very simple and closely resembles a - normal listenUDP - implementation. The main difference is that instead - of listenUDP, listenMulticast - is called with a specified port number. The server must also - call joinGroup to - specify on which multicast IP address it will service requests. Another - item of interest is the contents of the datagram. Many different - applications use multicast as a way of device discovery, which leads to an - abundance of packets flying around. Checking the payload can ensure that we - only service requests from our specific clients. +

              As with UDP, with multicast there is no server/client differentiation + at the protocol level. Our server example is very simple and closely + resembles a normal listenUDP + protocol implementation. The main difference is that instead + of listenUDP, listenMulticast + is called with the port number. The server calls joinGroup to + join a multicast group. A DatagramProtocol + that is listening with multicast and has joined a group can receive + multicast datagrams, but also unicast datagrams sent directly to its + address. The server in the example above sends such a unicast message in + reply to the multicast message it receives from the client.

              1 @@ -239,43 +259,46 @@ 11 12 13 +14 +15 +16 +17 +18 +19

              from twisted.internet.protocol import DatagramProtocol from twisted.internet import reactor -from twisted.application.internet import MulticastServer -class MulticastClientUDP(DatagramProtocol): - def datagramReceived(self, datagram, address): - print "Received:" + repr(datagram) +class MulticastPingClient(DatagramProtocol): -# Send multicast on 224.0.0.1:8005, on our dynamically allocated port -reactor.listenUDP(0, MulticastClientUDP()).write('UniqueID', - ('224.0.0.1', 8005)) -reactor.run() -
              + def startProtocol(self): + # Join the multicast address, so we can receive replies: + self.transport.joinGroup("228.0.0.5") + # Send to 228.0.0.5:8005 - all listeners on the multicast address + # (including us) will receive this message. + self.transport.write('Client: Ping', ("228.0.0.5", 8005)) -

              This is a mirror implementation of a standard UDP client. The only - difference is that the destination IP is the multicast address. This - datagram will be distributed to every server listening on - 224.0.0.1 (a special address for all hosts on the local - network segment, defined by - RFC 1112) and port - 8005. Note that the client port is specified as - 0, as we have no need to keep track of what port the client - is listening on. -

              + def datagramReceived(self, datagram, address): + print "Datagram %s received from %s" % (repr(datagram), repr(address)) -

              Acknowledgments

              -

              Thank you to all contributors to this document, including:

              +reactor.listenMulticast(8005, MulticastPingClient(), listenMultiple=True) +reactor.run() +
              -
                -
              • Kyle Robertson, author of the explanation and examples of multicast
              • -
              +

              Note that a multicast socket will have a default TTL (time to live) of + 1. That is, datagrams won't traverse more than one router hop, unless a + higher TTL is set with + setTTL. Other + functionality provided by the multicast transport + includes setOutgoingInterface + and setLoopbackMode + -- see IMulticastTransport for more + information.

              Index

              - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/upgrading.html twisted-12.1.0/doc/howto/upgrading.html --- twisted-10.2.0/doc/howto/upgrading.html 2010-11-30 03:13:14.000000000 +0000 +++ twisted-12.1.0/doc/howto/upgrading.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,331 +0,0 @@ - - -Twisted Documentation: Upgrading Applications - - - - -

              Upgrading Applications

              - -
              - - -

              Applications must frequently deal with data that lives longer than the -programs that create it. Sometimes the structure of that data changes over -time, but new versions of a program must be able to accomodate data created -by an older version. These versions may change very quickly, especially -during development of new code. Sometimes different versions of the same -program are running at the same time, sharing data across a network -connection. These situations all result in a need for a way to upgrade data -structures.

              - -

              Basic Persistence: Application and .tap files

              - -

              Simple object persistence (using pickle or -jelly) provides the fundamental save the object to disk -functionality at application shutdown. If you use the Application object, every object -referenced by your Application will be saved into the --shutdown.tap file when the program terminates. When you use -twistd to launch that new .tap file, the Application object -will be restored along with all of its referenced data.

              - -

              This provides a simple way to have data outlive any particular invocation -of your program: simply store it as an attribute of the Application. Note -that all Services are referenced by the Application, so their attributes -will be stored as well. Ports that have been bound with listenTCP (and the -like) are also remembered, and the sockets are created at startup time (when -Application.run is called).

              - -

              To influence the way that the Application is persisted, you can adapt -it to twisted.persisted.sob.IPersistable and use -the setStyle(style) method with -a string like pickle or source. These use different serializers (and different -extensions: .tap and .tas respectively) for the -saved Application.

              - -

              You can manually cause the application to be saved by calling its -.save method (on the twisted.persisted.sob.IPersistable -adapted object).

              - - -

              Versioned: New Code Meets Old Data

              - -

              So suppose you're running version 1 of some application, and you want to -upgrade to version 2. You shut down the program, giving you a .tap file that -you could restore with twistd to get back to the same state that you had -before. The upgrade process is to then install the new version of the -application, and then use twistd to launch the saved .tap file. The old data -will be loaded into classes created with the new code, and now you'll have a -program running with the new behavior but the old data.

              - -

              But what about the data structures that have changed? Since these -structures are really just pickled class instances, the real question is -what about the class definitions that have changed? Changes to class methods -are easy: nothing about them is saved in the .tap file. The issue is when -the data attributes of a instance are added, removed, or their format is -changed.

              - -

              Twisted provides a mechanism called Versioned to ease these upgrades. -Each version of the data structure (i.e. each version of the class) gets a -version number. This number must change every time you add or remove a data -attribute to the class. It must also change every time you modify one of -those data attributes: for example, if you use a string in one version and -an integer in another, those versions must have different version numbers. -

              - -

              The version number is defined in a class attribute named -persistenceVersion. This is an integer which will be stored in -the .tap file along with the rest of the instance state. When the object is -unserialized, the saved persistenceVersion is compared against the current -class's value, and if they differ, special upgrade methods are called. These -methods are named upgradeToVersionNN, and there must be one for -each intermediate version. These methods are expected to manipulate the -instance's state from the previous version's format into that of the new -version.

              - -

              To use this, simply have your class inherit from Versioned. You don't have to do this -from the very beginning of time: all objects have an implicit version number -of 0 when they don't inherit from Versioned. So when you first make -an incompatible data-format change to your class, add Versioned to the -inheritance list, and add an upgradeToVersion1 method.

              - -

              For example, suppose the first version of our class saves an integer -which measures the size of a line. We release this as version 1.0 of our -neat application:

              - -

              1 -2 -3 -

              class Thing: - def __init__(self, length): - self.length = length -
              - -

              Then we fix some bugs elsewhere, and release versions 1.1 and 1.2 of the -application. Later, we decide that we should add some units to the length, -so that people can refer to it in inches or meters. Version 1.3 is shipped -with the following code:

              - -

              1 -2 -3 -4 -5 -6 -

              class Thing(Versioned): - persistenceVersion = 1 - def __init__(self, length, units): - self.length = "%d %s" % (length, units) - def upgradeToVersion1(self): - self.length = "%d inches" % self.length -
              - -

              Note that we must make an assumption about what the previous value meant: -in this case, we assume the number was in inches.

              - -

              1.4 and 1.5 are shipped with other changes. Then in version 1.6 we decide -that saving the two values as a string was foolish and that it would be -better to save the number and the string separately, using a tuple. We ship -1.6 with the following:

              - -

              1 -2 -3 -4 -5 -6 -7 -8 -9 -

              class Thing(Versioned): - persistenceVersion = 2 - def __init__(self, length, units): - self.length = (length, units) - def upgradeToVersion1(self): - self.length = "%d inches" % self.length - def upgradeToVersion2(self): - (length, units) = self.length.split() - self.length = (length, units) -
              - -

              Note that we must provide both upgradeToVersion1 -and upgradeToVersion2. We have to assume that the -saved .tap files which will be provided to this class come from a random -assortment of old versions: we must be prepared to accept anything ever -saved by a released version of our application.

              - -

              Finally, version 2.0 adds multiple dimensions. Instead of merely -recording the length of a line, it records the size of an N-dimensional -rectangular solid. For backwards compatiblity, all 1.X version of the -program are assumed to be dealing with a 1-dimensional line. We change the -name of the attribute from .length to .size to -reflect the new meaning.

              - -

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

              class Thing(Versioned): - persistenceVersion = 3 - def __init__(self, dimensions): - # dimensions is a list of tuples, each is (length, units) - self.size = dimensions - self.name = ["line", "square", "cube", "hypercube"][len(dimensions)] - def upgradeToVersion1(self): - self.length = "%d inches" % self.length - def upgradeToVersion2(self): - (length, units) = self.length.split() - self.length = (length, units) - def upgradeToVersion3(self): - self.size = [self.length] - del self.length - self.name = "line" -
              - -

              If a .tap file from the earliest version of our program were to be loaded -by the latest code, the following sequence would occur for each Thing -instance contained inside:

              - -
                - -
              1. An instance of Thing would be created, with a __dict__ that contained - a single attribute .size, which was an integer, like - 5.
              2. - -
              3. self.upgradeToVersion1() would be called, - changing self.size into a string, like 5 inches.
              4. - -
              5. self.upgradeToVersion2() would be called, - changing self.size into a tuple, like (5, - inches).
              6. - -
              7. Finally, self.upgradeToVersion3() would be - called, creating self.size as a list holding a single - dimension, like [(5, inches)]. The old .length - attribute is deleted, and a new .name is created with the - type of shape this instance represents (line).
              8. - -
              - -

              Some hints for the upgradeVersion methods:

              - -
                - -
              • They must do everything the __init__ method would have - done, as well as any methods that might have been called during the - lifetime of the object.
              • - -
              • If the class has (or used to have) methods which can add attributes - that weren't created in __init__, then the saved object may - have a haphazard subset of those attributes, depending upon which methods - were called. The upgradeVersion methods must be prepared to deal with - this. hasattr and .get may be useful.
              • - -
              • Once you have released a class with a given - upgradeVersion method, you should never change that method. - (assuming you care about infinite backwards compatibility).
              • - -
              • You must add a new upgradeVersion method (and bump the - persistenceVersion value) for each and every release that has a different - set of data attributes than the previous release.
              • - -
              • Versioned works by providing __setstate__ - and __getstate__ methods. You probably don't want to override - these methods without being very careful to call the Versioned versions at - exactly the right time. It also requires a doUpgrade function - to be called after all the objects are loaded. This is done automatically - by Application.run.
              • - -
              • Depending upon how they are serialized, Versioned objects - can probably be sent across a network connection, and the upgrade process - can be made to occur upon receipt. (You'll want to look at the requireUpgrade - function). This might be useful in providing compability with an older - peer. Note, however, that Versioned does not let you go - backwards in time; there is no downgradeVersionNN method. - This means it is probably only useful for compatibility in one direction: - the newer-to-older direction must still be explicitly handled by the - application.
              • - -
              • In general, backwards compatibility is handled by pretending that the - old code was restricting itself to a narrow subset of the capabilities of - the new code. The job of the upgrade routines is then to translate the old - representation into a new one.
              • - -
              - -

              For more information, look at the doc strings for styles.Versioned, as well as the app.Application class and the Application HOWTO.

              - - -

              Rebuild: Loading New Code Without Restarting

              - -

              Versioned is good for handling changes between -released versions of your program, where the application state is saved on -disk during the upgrade. But while you are developing that code, you often -want to change the behavior of the running program, without the -slowdown of saving everything out to disk, shutting down, and restarting. -Sometimes it will be difficult or time-consuming to get back to the previous -state: the running program could include ephemeral objects (like open -sockets) which cannot be persisted.

              - -

              twisted.python.rebuild provides a function -called rebuild which helps smooth this cycle. It allows objects -in a running program to be upgraded to a new version of the code without -shutting down.

              - -

              To use it, simply call rebuild on the module -that holds the classes you want to be upgraded. Through deep gc magic, all instances of classes in that module will -be located and upgraded.

              - -

              Typically, this is done in response to a privileged command sent over a -network connection. The usual development cycle is to start the server, get -it into an interesting state, see a problem, edit the class definition, then -push the rebuild yourself button. That button could be a magic -web page which, when requested, runs rebuild(mymodule), or a special IRC command, or -perhaps just a socket that listens for connections and accepts a password to -trigger the rebuild. (You want this to be a privileged operation to prevent -someone from making your server do a rebuild while you're in the middle of -editing the code).

              - -

              A few useful notes about the rebuild process:

              - -
                -
              • If the module has a top-level attribute named - ALLOW_TWISTED_REBUILD, this attribute must evaluate to True. - Should it be false, the rebuild attempt will raise an exception.
              • - -
              • Adapters (from twisted.python.components) use - top-level registration function calls. These are handled correctly during - rebuilds, and the usual duplicate registration errors are not raised.
              • - -
              • Rebuilds may be slow: every single object known to the interpreter - must be examined to see if it is one of the classes being changed.
              • -
              - -

              Finally, note that rebuild cannot currently be -mixed with Versioned. rebuild does -not run any of the classes' methods, whereas Versioned works by -running __setstate__ during the load process and -doUpgrade afterwards. This means rebuild can only -be used to process upgrades that do not change the data attributes of any of -the involved classes. Any time attributes are added or removed, the program -must be shut down, persisted, and restarted, with upgradeToVersionNN methods -used to handle the attributes. (this may change in the future, but for now -the implementation is easier and more reliable with this restriction).

              - -
              - -

              Index

              - Version: 10.2.0 - - \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/vision.html twisted-12.1.0/doc/howto/vision.html --- twisted-10.2.0/doc/howto/vision.html 2010-11-30 03:13:16.000000000 +0000 +++ twisted-12.1.0/doc/howto/vision.html 2012-06-04 08:46:21.000000000 +0000 @@ -20,7 +20,7 @@ interactive and entertaining experience for the end-user.

              Twisted is a platform for developing internet applications. - While python, by itself, is a very powerful language, there are + While Python by itself is a very powerful language, there are many facilities it lacks which other languages have spent great attention to adding. It can do this now; Twisted is a good (if somewhat idiosyncratic) pure-python framework or library, @@ -38,6 +38,6 @@

              Index

              - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/howto/website-template.tpl twisted-12.1.0/doc/howto/website-template.tpl --- twisted-10.2.0/doc/howto/website-template.tpl 2003-01-15 20:12:37.000000000 +0000 +++ twisted-12.1.0/doc/howto/website-template.tpl 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ - - - - - -Twisted Documentation: - - - - -

              -
              -
              - -
              - -

              Index

              - - - Binary files /tmp/KgQjYJ5bY6/twisted-10.2.0/doc/img/twisted-overview.dia and /tmp/3jKMiOphL2/twisted-12.1.0/doc/img/twisted-overview.dia differ Binary files /tmp/KgQjYJ5bY6/twisted-10.2.0/doc/img/twisted-overview.png and /tmp/3jKMiOphL2/twisted-12.1.0/doc/img/twisted-overview.png differ diff -Nru twisted-10.2.0/doc/index.html twisted-12.1.0/doc/index.html --- twisted-10.2.0/doc/index.html 2010-11-30 03:13:14.000000000 +0000 +++ twisted-12.1.0/doc/index.html 2012-06-04 08:46:17.000000000 +0000 @@ -13,8 +13,6 @@
              • Developer guides: documentation on using Twisted Core to develop your own applications
              • -
              • Upgrades between versions: -documentation specific to upgrading between versions of Twisted core
              • Examples: short code examples using Twisted Core
              • Specifications: specification @@ -28,6 +26,6 @@

                Index

                - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/man/manhole-man.html twisted-12.1.0/doc/man/manhole-man.html --- twisted-10.2.0/doc/man/manhole-man.html 2010-11-30 03:13:23.000000000 +0000 +++ twisted-12.1.0/doc/man/manhole-man.html 2012-06-04 08:46:17.000000000 +0000 @@ -45,6 +45,6 @@

                Index

                - Version: 10.2.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-10.2.0/doc/man/mktap.1 twisted-12.1.0/doc/man/mktap.1 --- twisted-10.2.0/doc/man/mktap.1 2008-12-14 23:09:07.000000000 +0000 +++ twisted-12.1.0/doc/man/mktap.1 1970-01-01 00:00:00.000000000 +0000 @@ -1,219 +0,0 @@ -.TH MKTAP "1" "July 2001" "" "" -.SH NAME -mktap \- create twisted.servers -.SH SYNOPSIS -.B mktap -[\fIoptions\fR] \fIapptype\fR [\fIapplication_option\fR]... -.PP -.B mktap -\fIapptype\fR --help -.SH DESCRIPTION -.PP -The \fB\--help\fR prints out a usage message to standard output. -.TP -\fB\--debug\fR, \fB\-d\fR -Show debug information for plugin loading. -.TP -\fB\--progress\fR, \fB\-p\fR -Show progress information for plugin loading. -.TP -\fB\--encrypted\fR, \fB\-e\fR -Encrypt file before writing (will make the extension of the resultant file begin with 'e'). -.TP -\fB\--uid\fR, \fB\-u\fR \fI\fR -Application belongs to this uid, and should run with its permissions. -.TP -\fB\--gid\fR, \fB\-d\fR \fI\fR -Application belongs to this gid, and should run with its permissions. -.TP -\fB\--append\fR, \fB\-a\fR \fI\fR -Append given servers to given file, instead of creating a new one. -File should be be a tap file. -.TP -\fB\--appname\fR, \fB\-n\fR \fI\fR -Use the specified name as the process name when the application is run with -\fItwistd(1)\fR. This option also causes some initialization code to be -duplicated when \fItwistd(1)\fR is run. -.TP -\fB\--type\fR, \fB\-t\fR \fI\fR -Specify the output file type. Available types are: -.IP -pickle - (default) Output as a python pickle file. -.br -source - Output as a .tas (AOT Python source) file. -.P -\fIapptype\fR -Can be 'web', 'portforward', 'toc', 'coil', 'words', \ -'manhole', 'im', 'news', 'socks', 'telnet', 'parent', 'sibling', \ -'ftp', and 'mail'. Each of those support different options. -.PP -.SH \fBportforward\fR options -.TP -\fB\-h\fR, \fB\--host\fR \fI\fR -Proxy connections to \fI\fR -.TP -\fB\-d\fR, \fB\--dest_port\fR \fI\fR -Proxy connections to \fI\fR on remote host. -.TP -\fB\-p\fR, \fB\--port\fR \fI\fR -Listen locally on \fI\fR -.PP -.SH \fBweb\fR options -.TP -\fB\-u\fR, \fB\--user\fR -Makes a server with ~/public_html and -~/.twistd-web-pb support for users. -.TP -\fB\--personal\fR -Instead of generating a webserver, generate a -ResourcePublisher which listens on ~/.twistd-web-pb -.TP -\fB\--path\fR \fI\fR - is either a specific file or a directory to be -set as the root of the web server. Use this if you -have a directory full of HTML, cgi, php3, epy, or rpy files or -any other files that you want to be served up raw. -.TP -\fB\-p\fR, \fB\--port\fR \fI\fR - is a number representing which port you want to -start the server on. -.TP -\fB\-m\fR, \fB\--mime_type\fR \fI\fR - is the default MIME type to use for -files in a --path web server when none can be determined -for a particular extension. The default is 'text/html'. -.TP -\fB\--allow_ignore_ext\fR -Specify whether or not a request for 'foo' should return 'foo.ext'. -Default is off. -.TP -\fB\--ignore-ext\fR \fI.\fR -Specify that a request for 'foo' should return 'foo.\fI\fR'. -.TP -\fB\-t\fR, \fB\--telnet\fR \fI\fR -Run a telnet server on , for additional -configuration later. -.TP -\fB\-i\fR, \fB\--index\fR \fI\fR -Use an index name other than "index.html" -.TP -\fB--https\fR \fI\fR -Port to listen on for Secure HTTP. -.TP -\fB-c\fR, \fB--certificate\fR \fI\fR -SSL certificate to use for HTTPS. [default: server.pem] -.TP -\fB-k\fR, \fB--privkey\fR \fI\fR -SSL certificate to use for HTTPS. [default: server.pem] -.TP -\fB--processor\fR \fI=\fR -Adds a processor to those file names. (Only usable if after -.B --path) -.TP -\fB--resource-script\fR \fI