diff -Nru twisted-11.1.0/debian/changelog twisted-12.1.0/debian/changelog --- twisted-11.1.0/debian/changelog 2012-03-09 15:08:00.000000000 +0000 +++ twisted-12.1.0/debian/changelog 2012-06-21 13:26:37.000000000 +0000 @@ -1,17 +1,15 @@ -twisted (11.1.0-1ubuntu2) precise; urgency=low +twisted (12.1.0-1~ppa1~precise1) precise; urgency=low - * debian/patches/01_posix_wakeups.patch: - - Backport wakeup change from trunk gtk2refactoring (LP: #935756) + * New upstream version. + * Rebuild package for use in PPA. - -- Rodney Dawes Thu, 08 Mar 2012 11:25:48 -0500 + -- Jessica McKellar Thu, 21 Jun 2012 09:26:05 -0400 -twisted (11.1.0-1ubuntu1) precise; urgency=low +twisted (12.0.0-1~ppa1~precise1) precise; urgency=low - * debian/patches/00_gi_gtk3reactor.patch: - - Backport gireactor/gtk3reactor and gtk2reactor refactor from svn - (LP: #571648, LP: #851187) + * Rebuild package for use in PPA. - -- Rodney Dawes Wed, 15 Feb 2012 21:39:07 -0500 + -- Jessica McKellar Fri, 25 May 2012 09:50:42 -0400 twisted (11.1.0-1) unstable; urgency=low diff -Nru twisted-11.1.0/debian/compat twisted-12.1.0/debian/compat --- twisted-11.1.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-11.1.0/debian/control twisted-12.1.0/debian/control --- twisted-11.1.0/debian/control 2012-02-16 14:52:56.000000000 +0000 +++ twisted-12.1.0/debian/control 2012-06-19 02:16:58.000000000 +0000 @@ -1,23 +1,21 @@ Source: twisted Section: python Priority: optional -Maintainer: Ubuntu Developers -XSBC-Original-Maintainer: Matthias Klose +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.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} +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 @@ -30,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 @@ -53,7 +50,7 @@ Priority: extra Architecture: all Depends: ${misc:Depends} -Suggests: python-twisted, twisted-doc-api +Suggests: python-twisted Recommends: www-browser | postscript-viewer | pdf-viewer Description: Official documentation of Twisted This contains various HOWTOs and overviews in various formats @@ -63,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: 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 (>= 11.0), python-twisted-conch (>= 1:11.0), python-twisted-mail (>= 11.0), python-twisted-lore (>= 11.0), python-twisted-names (>= 11.0), python-twisted-news (>= 11.0), python-twisted-runner (>= 11.0), python-twisted-web (>= 11.0), python-twisted-words (>= 11.0), ${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 (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-11.1.0/debian/patches/00_gi_gtk3reactor.patch twisted-12.1.0/debian/patches/00_gi_gtk3reactor.patch --- twisted-11.1.0/debian/patches/00_gi_gtk3reactor.patch 2012-02-16 14:52:33.000000000 +0000 +++ twisted-12.1.0/debian/patches/00_gi_gtk3reactor.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,981 +0,0 @@ -=== added file 'twisted/internet/_glibbase.py' ---- old/twisted/internet/_glibbase.py 1970-01-01 00:00:00 +0000 -+++ new/twisted/internet/_glibbase.py 2012-02-16 02:35:00 +0000 -@@ -0,0 +1,368 @@ -+# -*- test-case-name: twisted.internet.test -*- -+# Copyright (c) Twisted Matrix Laboratories. -+# See LICENSE for details. -+ -+""" -+This module provides base support for Twisted to interact with the glib/gtk -+mainloops. -+ -+The classes in this module should not be used directly, but rather you should -+import gireactor or gtk3reactor for GObject Introspection based applications, -+or glib2reactor or gtk2reactor for applications using legacy static bindings. -+""" -+ -+import signal -+ -+from twisted.internet import base, posixbase, selectreactor -+from twisted.internet.interfaces import IReactorFDSet -+from twisted.python import log, runtime -+from twisted.python.compat import set -+from zope.interface import implements -+ -+ -+class GlibSignalMixin(object): -+ -+ if runtime.platformType == 'posix': -+ -+ def _handleSignals(self): -+ # Let the base class do its thing, but pygtk is probably -+ # going to stomp on us so go beyond that and set up some -+ # signal handling which pygtk won't mess with. This would -+ # be better done by letting this reactor select a -+ # different implementation of installHandler for -+ # _SIGCHLDWaker to use. Then, at least, we could fall -+ # back to our extension module. See #4286. -+ from twisted.internet.process import ( -+ reapAllProcesses as _reapAllProcesses) -+ base._SignalReactorMixin._handleSignals(self) -+ signal.signal(signal.SIGCHLD, -+ lambda *a: self.callFromThread(_reapAllProcesses)) -+ if getattr(signal, "siginterrupt", None) is not None: -+ signal.siginterrupt(signal.SIGCHLD, False) -+ # Like the base, reap processes now in case a process -+ # exited before the handlers above were installed. -+ _reapAllProcesses() -+ -+ -+ -+class GlibWaker(posixbase._UnixWaker): -+ """ -+ Run scheduled events after waking up. -+ """ -+ -+ def doRead(self): -+ posixbase._UnixWaker.doRead(self) -+ self.reactor._simulate() -+ -+ -+ -+class GlibReactorBase(GlibSignalMixin, -+ posixbase.PosixReactorBase, posixbase._PollLikeMixin): -+ """ -+ Base class for GObject event loop reactors. -+ -+ Notification for I/O events (reads and writes on file descriptors) is done -+ by the the gobject-based event loop. File descriptors are registered with -+ gobject with the appropriate flags for read/write/disconnect notification. -+ -+ Time-based events, the results of C{callLater} and C{callFromThread}, are -+ handled differently. Rather than registering each event with gobject, a -+ single gobject timeout is registered for the earliest scheduled event, the -+ output of C{reactor.timeout()}. For example, if there are timeouts in 1, 2 -+ and 3.4 seconds, a single timeout is registered for 1 second in the -+ future. When this timeout is hit, C{_simulate} is called, which calls the -+ appropriate Twisted-level handlers, and a new timeout is added to gobject -+ by the C{_reschedule} method. -+ -+ To handle C{callFromThread} events, we use a custom waker that calls -+ C{_simulate} whenever it wakes up. -+ -+ @ivar _sources: A dictionary mapping L{FileDescriptor} instances to -+ GSource handles. -+ -+ @ivar _reads: A set of L{FileDescriptor} instances currently monitored for -+ reading. -+ -+ @ivar _writes: A set of L{FileDescriptor} instances currently monitored for -+ writing. -+ -+ @ivar _simtag: A GSource handle for the next L{simulate} call. -+ """ -+ implements(IReactorFDSet) -+ -+ # Install a waker that knows it needs to call C{_simulate} in order to run -+ # callbacks queued from a thread: -+ _wakerFactory = GlibWaker -+ -+ def __init__(self, glib_module, gtk_module, useGtk=False): -+ self._simtag = None -+ self._reads = set() -+ self._writes = set() -+ self._sources = {} -+ self._glib = glib_module -+ self._gtk = gtk_module -+ posixbase.PosixReactorBase.__init__(self) -+ -+ self._source_remove = self._glib.source_remove -+ self._timeout_add = self._glib.timeout_add -+ -+ def _mainquit(): -+ if self._gtk.main_level(): -+ self._gtk.main_quit() -+ -+ if useGtk: -+ self._pending = self._gtk.events_pending -+ self._iteration = self._gtk.main_iteration_do -+ self._crash = _mainquit -+ self._run = self._gtk.main -+ else: -+ self.context = self._glib.main_context_default() -+ self._pending = self.context.pending -+ self._iteration = self.context.iteration -+ self.loop = self._glib.MainLoop() -+ self._crash = lambda: self._glib.idle_add(self.loop.quit) -+ self._run = self.loop.run -+ -+ -+ # The input_add function in pygtk1 checks for objects with a -+ # 'fileno' method and, if present, uses the result of that method -+ # as the input source. The pygtk2 input_add does not do this. The -+ # function below replicates the pygtk1 functionality. -+ -+ # In addition, pygtk maps gtk.input_add to _gobject.io_add_watch, and -+ # g_io_add_watch() takes different condition bitfields than -+ # gtk_input_add(). We use g_io_add_watch() here in case pygtk fixes this -+ # bug. -+ def input_add(self, source, condition, callback): -+ if hasattr(source, 'fileno'): -+ # handle python objects -+ def wrapper(source, condition, real_s=source, real_cb=callback): -+ return real_cb(real_s, condition) -+ return self._glib.io_add_watch(source.fileno(), condition, wrapper) -+ else: -+ return self._glib.io_add_watch(source, condition, callback) -+ -+ -+ def _ioEventCallback(self, source, condition): -+ """ -+ Called by event loop when an I/O event occurs. -+ """ -+ log.callWithLogger( -+ source, self._doReadOrWrite, source, source, condition) -+ return True # True = don't auto-remove the source -+ -+ -+ def _add(self, source, primary, other, primaryFlag, otherFlag): -+ """ -+ Add the given L{FileDescriptor} for monitoring either for reading or -+ writing. If the file is already monitored for the other operation, we -+ delete the previous registration and re-register it for both reading -+ and writing. -+ """ -+ if source in primary: -+ return -+ flags = primaryFlag -+ if source in other: -+ self._source_remove(self._sources[source]) -+ flags |= otherFlag -+ self._sources[source] = self.input_add( -+ source, flags, self._ioEventCallback) -+ primary.add(source) -+ -+ -+ def addReader(self, reader): -+ """ -+ Add a L{FileDescriptor} for monitoring of data available to read. -+ """ -+ self._add(reader, self._reads, self._writes, -+ self.INFLAGS, self.OUTFLAGS) -+ -+ -+ def addWriter(self, writer): -+ """ -+ Add a L{FileDescriptor} for monitoring ability to write data. -+ """ -+ self._add(writer, self._writes, self._reads, -+ self.OUTFLAGS, self.INFLAGS) -+ -+ -+ def getReaders(self): -+ """ -+ Retrieve the list of current L{FileDescriptor} monitored for reading. -+ """ -+ return list(self._reads) -+ -+ -+ def getWriters(self): -+ """ -+ Retrieve the list of current L{FileDescriptor} monitored for writing. -+ """ -+ return list(self._writes) -+ -+ -+ def removeAll(self): -+ """ -+ Remove monitoring for all registered L{FileDescriptor}s. -+ """ -+ return self._removeAll(self._reads, self._writes) -+ -+ -+ def _remove(self, source, primary, other, flags): -+ """ -+ Remove monitoring the given L{FileDescriptor} for either reading or -+ writing. If it's still monitored for the other operation, we -+ re-register the L{FileDescriptor} for only that operation. -+ """ -+ if source not in primary: -+ return -+ self._source_remove(self._sources[source]) -+ primary.remove(source) -+ if source in other: -+ self._sources[source] = self.input_add( -+ source, flags, self._ioEventCallback) -+ else: -+ self._sources.pop(source) -+ -+ -+ def removeReader(self, reader): -+ """ -+ Stop monitoring the given L{FileDescriptor} for reading. -+ """ -+ self._remove(reader, self._reads, self._writes, self.OUTFLAGS) -+ -+ -+ def removeWriter(self, writer): -+ """ -+ Stop monitoring the given L{FileDescriptor} for writing. -+ """ -+ self._remove(writer, self._writes, self._reads, self.INFLAGS) -+ -+ -+ def iterate(self, delay=0): -+ """ -+ One iteration of the event loop, for trial's use. -+ -+ This is not used for actual reactor runs. -+ """ -+ self.runUntilCurrent() -+ while self._pending(): -+ self._iteration(0) -+ -+ -+ def crash(self): -+ """ -+ Crash the reactor. -+ """ -+ posixbase.PosixReactorBase.crash(self) -+ self._crash() -+ -+ -+ def stop(self): -+ """ -+ Stop the reactor. -+ """ -+ posixbase.PosixReactorBase.stop(self) -+ # The base implementation only sets a flag, to ensure shutting down is -+ # not reentrant. Unfortunately, this flag is not meaningful to the -+ # gobject event loop. We therefore call wakeUp() to ensure the event -+ # loop will call back into Twisted once this iteration is done. This -+ # will result in self.runUntilCurrent() being called, where the stop -+ # flag will trigger the actual shutdown process, eventually calling -+ # crash() which will do the actual gobject event loop shutdown. -+ self.wakeUp() -+ -+ -+ def run(self, installSignalHandlers=True): -+ """ -+ Run the reactor. -+ """ -+ self.callWhenRunning(self._reschedule) -+ self.startRunning(installSignalHandlers=installSignalHandlers) -+ if self._started: -+ self._run() -+ -+ -+ def callLater(self, *args, **kwargs): -+ """ -+ Schedule a C{DelayedCall}. -+ """ -+ result = posixbase.PosixReactorBase.callLater(self, *args, **kwargs) -+ # Make sure we'll get woken up at correct time to handle this new -+ # scheduled call: -+ self._reschedule() -+ return result -+ -+ -+ def _reschedule(self): -+ """ -+ Schedule a glib timeout for C{_simulate}. -+ """ -+ if self._simtag is not None: -+ self._source_remove(self._simtag) -+ self._simtag = None -+ timeout = self.timeout() -+ if timeout is not None: -+ self._simtag = self._timeout_add(int(timeout * 1000), -+ self._simulate) -+ -+ -+ def _simulate(self): -+ """ -+ Run timers, and then reschedule glib timeout for next scheduled event. -+ """ -+ self.runUntilCurrent() -+ self._reschedule() -+ -+ -+ -+class PortableGlibReactorBase(GlibSignalMixin, selectreactor.SelectReactor): -+ """ -+ Base class for GObject event loop reactors that works on Windows. -+ -+ Sockets aren't supported by GObject's input_add on Win32. -+ """ -+ def __init__(self, glib_module, gtk_module, useGtk=False): -+ self._simtag = None -+ self._glib = glib_module -+ self._gtk = gtk_module -+ selectreactor.SelectReactor.__init__(self) -+ -+ self._source_remove = self._glib.source_remove -+ self._timeout_add = self._glib.timeout_add -+ -+ def _mainquit(): -+ if self._gtk.main_level(): -+ self._gtk.main_quit() -+ -+ if useGtk: -+ self._crash = _mainquit -+ self._run = self._gtk.main -+ else: -+ self.loop = self._glib.MainLoop() -+ self._crash = lambda: self._glib.idle_add(self.loop.quit) -+ self._run = self.loop.run -+ -+ -+ def crash(self): -+ selectreactor.SelectReactor.crash(self) -+ self._crash() -+ -+ -+ def run(self, installSignalHandlers=True): -+ self.startRunning(installSignalHandlers=installSignalHandlers) -+ self._timeout_add(0, self.simulate) -+ if self._started: -+ self._run() -+ -+ -+ def simulate(self): -+ """ -+ Run simulation loops and reschedule callbacks. -+ """ -+ if self._simtag is not None: -+ self._source_remove(self._simtag) -+ self.iterate() -+ timeout = min(self.timeout(), 0.01) -+ if timeout is None: -+ timeout = 0.01 -+ self._simtag = self._timeout_add(int(timeout * 1000), self.simulate) - -=== added file 'twisted/internet/gireactor.py' ---- old/twisted/internet/gireactor.py 1970-01-01 00:00:00 +0000 -+++ new/twisted/internet/gireactor.py 2012-02-16 02:35:00 +0000 -@@ -0,0 +1,93 @@ -+# Copyright (c) Twisted Matrix Laboratories. -+# See LICENSE for details. -+ -+""" -+This module provides support for Twisted to interact with the glib -+mainloop via GObject Introspection. -+ -+In order to use this support, simply do the following:: -+ -+ from twisted.internet import gireactor -+ gireactor.install() -+ -+Then use twisted.internet APIs as usual. The other methods here are not -+intended to be called directly. -+""" -+ -+import sys -+ -+if 'gobject' in sys.modules: -+ raise ImportError( -+ "Introspected and static glib/gtk bindings must not be mixed; can't " -+ "import gireactor since pygtk2 module is already imported.") -+ -+from gi.repository import GLib -+GLib.threads_init() -+ -+from twisted.internet import _glibbase -+from twisted.python import runtime -+ -+# We need to override sys.modules with these to prevent imports. -+# This is required, as importing these can result in SEGFAULTs. -+sys.modules['glib'] = None -+sys.modules['gobject'] = None -+sys.modules['gio'] = None -+sys.modules['gtk'] = None -+ -+ -+ -+class GIReactor(_glibbase.GlibReactorBase): -+ """ -+ GObject-introspection event loop reactor. -+ """ -+ _POLL_DISCONNECTED = (GLib.IOCondition.HUP | GLib.IOCondition.ERR | -+ GLib.IOCondition.NVAL) -+ _POLL_IN = GLib.IOCondition.IN -+ _POLL_OUT = GLib.IOCondition.OUT -+ -+ # glib's iochannel sources won't tell us about any events that we haven't -+ # asked for, even if those events aren't sensible inputs to the poll() -+ # call. -+ INFLAGS = _POLL_IN | _POLL_DISCONNECTED -+ OUTFLAGS = _POLL_OUT | _POLL_DISCONNECTED -+ -+ def __init__(self, useGtk=False): -+ _gtk = None -+ if useGtk is True: -+ from gi.repository import Gtk as _gtk -+ -+ _glibbase.GlibReactorBase.__init__(self, GLib, _gtk, useGtk=useGtk) -+ -+ -+ -+class PortableGIReactor(_glibbase.PortableGlibReactorBase): -+ """ -+ Portable GObject Introspection event loop reactor. -+ """ -+ def __init__(self, useGtk=False): -+ _gtk = None -+ if useGtk is True: -+ from gi.repository import Gtk as _gtk -+ -+ _glibbase.PortableGlibReactorBase.__init__(self, GLib, _gtk, -+ useGtk=useGtk) -+ -+ -+def install(useGtk=False): -+ """ -+ Configure the twisted mainloop to be run inside the glib mainloop. -+ -+ @param useGtk: should GTK+ rather than glib event loop be -+ used (this will be slightly slower but does support GUI). -+ """ -+ if runtime.platform.getType() == 'posix': -+ reactor = GIReactor(useGtk=useGtk) -+ else: -+ reactor = PortableGIReactor(useGtk=useGtk) -+ -+ from twisted.internet.main import installReactor -+ installReactor(reactor) -+ return reactor -+ -+ -+__all__ = ['install'] - -=== modified file 'twisted/internet/gtk2reactor.py' ---- old/twisted/internet/gtk2reactor.py 2011-12-21 12:29:38 +0000 -+++ new/twisted/internet/gtk2reactor.py 2012-02-16 02:35:00 +0000 -@@ -9,21 +9,23 @@ mainloop. - - In order to use this support, simply do the following:: - -- | from twisted.internet import gtk2reactor -- | gtk2reactor.install() -+ from twisted.internet import gtk2reactor -+ gtk2reactor.install() - - Then use twisted.internet APIs as usual. The other methods here are not - intended to be called directly. -- --When installing the reactor, you can choose whether to use the glib --event loop or the GTK+ event loop which is based on it but adds GUI --integration. - """ - - # System Imports --import sys, signal -+import sys -+ -+if 'gi' in sys.modules: -+ raise ImportError( -+ "Introspected and static glib/gtk bindings must not be mixed; can't " -+ "import gtk2reactor since gi module is already imported.") - --from zope.interface import implements -+# Disable gi imports to avoid potential problems. -+sys.modules['gi'] = None - - try: - if not hasattr(sys, 'frozen'): -@@ -32,6 +34,7 @@ try: - pygtk.require('2.0') - except (ImportError, AttributeError): - pass # maybe we're using pygtk before this hack existed. -+ - import gobject - if hasattr(gobject, "threads_init"): - # recent versions of python-gtk expose this. python-gtk=2.4.1 -@@ -40,309 +43,46 @@ if hasattr(gobject, "threads_init"): - gobject.threads_init() - - # Twisted Imports --from twisted.python import log, runtime --from twisted.python.compat import set --from twisted.internet.interfaces import IReactorFDSet --from twisted.internet import base, posixbase, selectreactor -- --POLL_DISCONNECTED = gobject.IO_HUP | gobject.IO_ERR | gobject.IO_NVAL -- --# glib's iochannel sources won't tell us about any events that we haven't --# asked for, even if those events aren't sensible inputs to the poll() --# call. --INFLAGS = gobject.IO_IN | POLL_DISCONNECTED --OUTFLAGS = gobject.IO_OUT | POLL_DISCONNECTED -- -- -- --def _our_mainquit(): -- # XXX: gtk.main_quit() (which is used for crash()) raises an exception if -- # gtk.main_level() == 0; however, all the tests freeze if we use this -- # function to stop the reactor. what gives? (I believe this may have been -- # a stupid mistake where I forgot to import gtk here... I will remove this -- # comment if the tests pass) -- import gtk -- if gtk.main_level(): -- gtk.main_quit() -+from twisted.internet import _glibbase -+from twisted.python import runtime - - -- --class _Gtk2SignalMixin(object): -- if runtime.platformType == 'posix': -- def _handleSignals(self): -- # Let the base class do its thing, but pygtk is probably -- # going to stomp on us so go beyond that and set up some -- # signal handling which pygtk won't mess with. This would -- # be better done by letting this reactor select a -- # different implementation of installHandler for -- # _SIGCHLDWaker to use. Then, at least, we could fall -- # back to our extension module. See #4286. -- from twisted.internet.process import reapAllProcesses as _reapAllProcesses -- base._SignalReactorMixin._handleSignals(self) -- signal.signal(signal.SIGCHLD, lambda *a: self.callFromThread(_reapAllProcesses)) -- if getattr(signal, "siginterrupt", None) is not None: -- signal.siginterrupt(signal.SIGCHLD, False) -- # Like the base, reap processes now in case a process -- # exited before the handlers above were installed. -- _reapAllProcesses() -- -- -- --class Gtk2Reactor(_Gtk2SignalMixin, posixbase.PosixReactorBase, posixbase._PollLikeMixin): -+class Gtk2Reactor(_glibbase.GlibReactorBase): - """ -- GTK+-2 event loop reactor. -- -- @ivar _sources: A dictionary mapping L{FileDescriptor} instances to gtk -- watch handles. -- -- @ivar _reads: A set of L{FileDescriptor} instances currently monitored for -- reading. -- -- @ivar _writes: A set of L{FileDescriptor} instances currently monitored for -- writing. -- -- @ivar _simtag: A gtk timeout handle for the next L{simulate} call. -+ PyGTK+ 2 event loop reactor. - """ -- implements(IReactorFDSet) -- -- _POLL_DISCONNECTED = POLL_DISCONNECTED -+ _POLL_DISCONNECTED = gobject.IO_HUP | gobject.IO_ERR | gobject.IO_NVAL - _POLL_IN = gobject.IO_IN - _POLL_OUT = gobject.IO_OUT - -+ # glib's iochannel sources won't tell us about any events that we haven't -+ # asked for, even if those events aren't sensible inputs to the poll() -+ # call. -+ INFLAGS = _POLL_IN | _POLL_DISCONNECTED -+ OUTFLAGS = _POLL_OUT | _POLL_DISCONNECTED -+ - def __init__(self, useGtk=True): -- self._simtag = None -- self._reads = set() -- self._writes = set() -- self._sources = {} -- posixbase.PosixReactorBase.__init__(self) -- # pre 2.3.91 the glib iteration and mainloop functions didn't release -- # global interpreter lock, thus breaking thread and signal support. -- if getattr(gobject, "pygtk_version", ()) >= (2, 3, 91) and not useGtk: -- self.context = gobject.main_context_default() -- self.__pending = self.context.pending -- self.__iteration = self.context.iteration -- self.loop = gobject.MainLoop() -- self.__crash = self.loop.quit -- self.__run = self.loop.run -- else: -- import gtk -- self.__pending = gtk.events_pending -- self.__iteration = gtk.main_iteration -- self.__crash = _our_mainquit -- self.__run = gtk.main -- -- -- # The input_add function in pygtk1 checks for objects with a -- # 'fileno' method and, if present, uses the result of that method -- # as the input source. The pygtk2 input_add does not do this. The -- # function below replicates the pygtk1 functionality. -- -- # In addition, pygtk maps gtk.input_add to _gobject.io_add_watch, and -- # g_io_add_watch() takes different condition bitfields than -- # gtk_input_add(). We use g_io_add_watch() here in case pygtk fixes this -- # bug. -- def input_add(self, source, condition, callback): -- if hasattr(source, 'fileno'): -- # handle python objects -- def wrapper(source, condition, real_s=source, real_cb=callback): -- return real_cb(real_s, condition) -- return gobject.io_add_watch(source.fileno(), condition, wrapper) -- else: -- return gobject.io_add_watch(source, condition, callback) -- -- -- def _add(self, source, primary, other, primaryFlag, otherFlag): -- """ -- Add the given L{FileDescriptor} for monitoring either for reading or -- writing. If the file is already monitored for the other operation, we -- delete the previous registration and re-register it for both reading -- and writing. -- """ -- if source in primary: -- return -- flags = primaryFlag -- if source in other: -- gobject.source_remove(self._sources[source]) -- flags |= otherFlag -- self._sources[source] = self.input_add(source, flags, self.callback) -- primary.add(source) -- -- -- def addReader(self, reader): -- """ -- Add a L{FileDescriptor} for monitoring of data available to read. -- """ -- self._add(reader, self._reads, self._writes, INFLAGS, OUTFLAGS) -- -- -- def addWriter(self, writer): -- """ -- Add a L{FileDescriptor} for monitoring ability to write data. -- """ -- self._add(writer, self._writes, self._reads, OUTFLAGS, INFLAGS) -- -- -- def getReaders(self): -- """ -- Retrieve the list of current L{FileDescriptor} monitored for reading. -- """ -- return list(self._reads) -- -- -- def getWriters(self): -- """ -- Retrieve the list of current L{FileDescriptor} monitored for writing. -- """ -- return list(self._writes) -- -- -- def removeAll(self): -- """ -- Remove monitoring for all registered L{FileDescriptor}s. -- """ -- return self._removeAll(self._reads, self._writes) -- -- -- def _remove(self, source, primary, other, flags): -- """ -- Remove monitoring the given L{FileDescriptor} for either reading or -- writing. If it's still monitored for the other operation, we -- re-register the L{FileDescriptor} for only that operation. -- """ -- if source not in primary: -- return -- gobject.source_remove(self._sources[source]) -- primary.remove(source) -- if source in other: -- self._sources[source] = self.input_add( -- source, flags, self.callback) -- else: -- self._sources.pop(source) -- -- -- def removeReader(self, reader): -- """ -- Stop monitoring the given L{FileDescriptor} for reading. -- """ -- self._remove(reader, self._reads, self._writes, OUTFLAGS) -- -- -- def removeWriter(self, writer): -- """ -- Stop monitoring the given L{FileDescriptor} for writing. -- """ -- self._remove(writer, self._writes, self._reads, INFLAGS) -- -- -- doIterationTimer = None -- -- def doIterationTimeout(self, *args): -- self.doIterationTimer = None -- return 0 # auto-remove -- -- -- def doIteration(self, delay): -- # flush some pending events, return if there was something to do -- # don't use the usual "while self.context.pending(): self.context.iteration()" -- # idiom because lots of IO (in particular test_tcp's -- # ProperlyCloseFilesTestCase) can keep us from ever exiting. -- log.msg(channel='system', event='iteration', reactor=self) -- if self.__pending(): -- self.__iteration(0) -- return -- # nothing to do, must delay -- if delay == 0: -- return # shouldn't delay, so just return -- self.doIterationTimer = gobject.timeout_add(int(delay * 1000), -- self.doIterationTimeout) -- # This will either wake up from IO or from a timeout. -- self.__iteration(1) # block -- # note: with the .simulate timer below, delays > 0.1 will always be -- # woken up by the .simulate timer -- if self.doIterationTimer: -- # if woken by IO, need to cancel the timer -- gobject.source_remove(self.doIterationTimer) -- self.doIterationTimer = None -- -- -- def crash(self): -- posixbase.PosixReactorBase.crash(self) -- self.__crash() -- -- -- def run(self, installSignalHandlers=1): -- self.startRunning(installSignalHandlers=installSignalHandlers) -- gobject.timeout_add(0, self.simulate) -- if self._started: -- self.__run() -- -- -- def callback(self, source, condition): -- log.callWithLogger( -- source, self._doReadOrWrite, source, source, condition) -- self.simulate() # fire Twisted timers -- return 1 # 1=don't auto-remove the source -- -- -- def simulate(self): -- """ -- Run simulation loops and reschedule callbacks. -- """ -- if self._simtag is not None: -- gobject.source_remove(self._simtag) -- self.runUntilCurrent() -- timeout = min(self.timeout(), 0.1) -- if timeout is None: -- timeout = 0.1 -- # grumble -- self._simtag = gobject.timeout_add(int(timeout * 1010), self.simulate) -+ _gtk = None -+ if useGtk is True: -+ import gtk as _gtk -+ -+ _glibbase.GlibReactorBase.__init__(self, gobject, _gtk, useGtk=useGtk) - - - --class PortableGtkReactor(_Gtk2SignalMixin, selectreactor.SelectReactor): -+class PortableGtkReactor(_glibbase.PortableGlibReactorBase): - """ - Reactor that works on Windows. - - Sockets aren't supported by GTK+'s input_add on Win32. - """ -- _simtag = None -- -- def crash(self): -- selectreactor.SelectReactor.crash(self) -- import gtk -- # mainquit is deprecated in newer versions -- if gtk.main_level(): -- if hasattr(gtk, 'main_quit'): -- gtk.main_quit() -- else: -- gtk.mainquit() -- -- -- def run(self, installSignalHandlers=1): -- import gtk -- self.startRunning(installSignalHandlers=installSignalHandlers) -- gobject.timeout_add(0, self.simulate) -- # mainloop is deprecated in newer versions -- if self._started: -- if hasattr(gtk, 'main'): -- gtk.main() -- else: -- gtk.mainloop() -- -- -- def simulate(self): -- """ -- Run simulation loops and reschedule callbacks. -- """ -- if self._simtag is not None: -- gobject.source_remove(self._simtag) -- self.iterate() -- timeout = min(self.timeout(), 0.1) -- if timeout is None: -- timeout = 0.1 -- # grumble -- self._simtag = gobject.timeout_add(int(timeout * 1010), self.simulate) -+ def __init__(self, useGtk=True): -+ _gtk = None -+ if useGtk is True: -+ import gtk as _gtk - -+ _glibbase.PortableGlibReactorBase.__init__(self, gobject, _gtk, -+ useGtk=useGtk) - - - def install(useGtk=True): -@@ -358,7 +98,6 @@ def install(useGtk=True): - return reactor - - -- - def portableInstall(useGtk=True): - """ - Configure the twisted mainloop to be run inside the gtk mainloop. -@@ -369,10 +108,8 @@ def portableInstall(useGtk=True): - return reactor - - -- - if runtime.platform.getType() != 'posix': - install = portableInstall - - -- - __all__ = ['install'] - -=== added file 'twisted/internet/gtk3reactor.py' ---- old/twisted/internet/gtk3reactor.py 1970-01-01 00:00:00 +0000 -+++ new/twisted/internet/gtk3reactor.py 2012-02-16 02:35:00 +0000 -@@ -0,0 +1,60 @@ -+# Copyright (c) Twisted Matrix Laboratories. -+# See LICENSE for details. -+ -+""" -+This module provides support for Twisted to interact with the gtk3 mainloop -+via Gobject introspection. This is like gi, but slightly slower and requires a -+working $DISPLAY. -+ -+In order to use this support, simply do the following:: -+ -+ from twisted.internet import gtk3reactor -+ gtk3reactor.install() -+ -+Then use twisted.internet APIs as usual. -+""" -+ -+from twisted.internet import gireactor -+from twisted.python import runtime -+ -+ -+class Gtk3Reactor(gireactor.GIReactor): -+ """ -+ A reactor using the gtk3+ event loop. -+ """ -+ -+ def __init__(self): -+ """ -+ Override init to set the C{useGtk} flag. -+ """ -+ gireactor.GIReactor.__init__(self, useGtk=True) -+ -+ -+ -+class PortableGtk3Reactor(gireactor.PortableGIReactor): -+ """ -+ Portable GTK+ 3.x reactor. -+ """ -+ def __init__(self): -+ """ -+ Override init to set the C{useGtk} flag. -+ """ -+ gireactor.PortableGIReactor.__init__(self, useGtk=True) -+ -+ -+ -+def install(): -+ """ -+ Configure the Twisted mainloop to be run inside the gtk3+ mainloop. -+ """ -+ if runtime.platform.getType() == 'posix': -+ reactor = Gtk3Reactor() -+ else: -+ reactor = PortableGtk3Reactor() -+ -+ from twisted.internet.main import installReactor -+ installReactor(reactor) -+ return reactor -+ -+ -+__all__ = ['install'] - -=== modified file 'twisted/internet/test/reactormixins.py' ---- old/twisted/internet/test/reactormixins.py 2011-12-21 12:29:38 +0000 -+++ new/twisted/internet/test/reactormixins.py 2012-02-16 02:36:29 +0000 -@@ -56,20 +56,26 @@ class ReactorBuilder: - # it's not _really_ worth it to support on other platforms, - # since no one really wants to use it on other platforms. - _reactors.extend([ -+ "twisted.internet.gireactor.PortableGIReactor", -+ "twisted.internet.gtk3reactor.PortableGtk3Reactor", - "twisted.internet.gtk2reactor.PortableGtkReactor", - "twisted.internet.win32eventreactor.Win32Reactor", - "twisted.internet.iocpreactor.reactor.IOCPReactor"]) - else: - _reactors.extend([ -+ "twisted.internet.gireactor.GIReactor", -+ "twisted.internet.gtk3reactor.Gtk3Reactor", - "twisted.internet.glib2reactor.Glib2Reactor", -- "twisted.internet.gtk2reactor.Gtk2Reactor", -- "twisted.internet.kqreactor.KQueueReactor"]) -+ "twisted.internet.gtk2reactor.Gtk2Reactor"]) - if platform.isMacOSX(): - _reactors.append("twisted.internet.cfreactor.CFReactor") - else: - _reactors.extend([ - "twisted.internet.pollreactor.PollReactor", -- "twisted.internet.epollreactor.EPollReactor"]) -+ "twisted.internet.epollreactor.EPollReactor", -+ # Support KQueue on non-OS-X POSIX platforms for now. -+ "twisted.internet.kqreactor.KQueueReactor", -+ ]) - - reactorFactory = None - originalHandler = None - -=== modified file 'twisted/plugins/twisted_reactors.py' ---- old/twisted/plugins/twisted_reactors.py 2011-12-21 12:29:38 +0000 -+++ new/twisted/plugins/twisted_reactors.py 2012-02-16 02:35:28 +0000 -@@ -11,6 +11,10 @@ select = Reactor( - 'select', 'twisted.internet.selectreactor', 'select(2)-based reactor.') - wx = Reactor( - 'wx', 'twisted.internet.wxreactor', 'wxPython integration reactor.') -+gi = Reactor( -+ 'gi', 'twisted.internet.gireactor', 'GObject Introspection integration reactor.') -+gtk3 = Reactor( -+ 'gtk3', 'twisted.internet.gtk3reactor', 'Gtk3 integration reactor.') - gtk = Reactor( - 'gtk', 'twisted.internet.gtkreactor', 'Gtk1 integration reactor.') - gtk2 = Reactor( - diff -Nru twisted-11.1.0/debian/patches/01_posix_wakeups.patch twisted-12.1.0/debian/patches/01_posix_wakeups.patch --- twisted-11.1.0/debian/patches/01_posix_wakeups.patch 2012-03-09 15:08:00.000000000 +0000 +++ twisted-12.1.0/debian/patches/01_posix_wakeups.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,114 +0,0 @@ -=== modified file 'twisted/internet/posixbase.py' ---- old/twisted/internet/posixbase.py 2011-10-16 19:13:26 +0000 -+++ new/twisted/internet/posixbase.py 2011-12-08 03:37:41 +0000 -@@ -265,6 +265,11 @@ class PosixReactorBase(_SignalReactorMix - self.removeWriter(selectable) - selectable.connectionLost(failure.Failure(why)) - -+ -+ # Callable that creates a waker, overrideable so that subclasses can -+ # substitute their own implementation: -+ _wakerFactory = _Waker -+ - def installWaker(self): - """ - Install a `waker' to allow threads and signals to wake up the IO thread. -@@ -273,7 +278,7 @@ class PosixReactorBase(_SignalReactorMix - the reactor. On Windows we use a pair of sockets. - """ - if not self.waker: -- self.waker = _Waker(self) -+ self.waker = self._wakerFactory(self) - self._internalReaders.add(self.waker) - self.addReader(self.waker) - - -=== modified file 'twisted/internet/test/test_threads.py' ---- old/twisted/internet/test/test_threads.py 2011-06-13 22:20:22 +0000 -+++ new/twisted/internet/test/test_threads.py 2011-12-08 03:37:41 +0000 -@@ -8,7 +8,7 @@ Tests for implementations of L{IReactorT - __metaclass__ = type - - from weakref import ref --import gc -+import gc, threading - - from twisted.python.threadable import isInIOThread - from twisted.internet.test.reactormixins import ReactorBuilder -@@ -104,6 +104,24 @@ class ThreadTestsBuilder(ReactorBuilder) - self.assertTrue(after - before < 30) - - -+ def test_callFromThread(self): -+ """ -+ A function scheduled with L{IReactorThreads.callFromThread} invoked -+ from another thread is run in the reactor thread. -+ """ -+ reactor = self.buildReactor() -+ result = [] -+ -+ def threadCall(): -+ result.append(threading.currentThread()) -+ reactor.stop() -+ reactor.callLater(0, reactor.callInThread, -+ reactor.callFromThread, threadCall) -+ self.runReactor(reactor, 5) -+ -+ self.assertEquals(result, [threading.currentThread()]) -+ -+ - def test_stopThreadPool(self): - """ - When the reactor stops, L{ReactorBase._stopThreadPool} drops the - -=== modified file 'twisted/internet/test/test_time.py' ---- old/twisted/internet/test/test_time.py 2011-02-14 04:45:15 +0000 -+++ new/twisted/internet/test/test_time.py 2011-12-08 03:37:41 +0000 -@@ -7,6 +7,7 @@ Tests for implementations of L{IReactorT - - __metaclass__ = type - -+from twisted.python.runtime import platform - from twisted.internet.test.reactormixins import ReactorBuilder - - -@@ -23,4 +24,38 @@ class TimeTestsBuilder(ReactorBuilder): - reactor.run() - - -+ -+class GlibTimeTestsBuilder(ReactorBuilder): -+ """ -+ Builder for defining tests relating to L{IReactorTime} for reactors based -+ off glib. -+ """ -+ if platform.isWindows(): -+ _reactors = ["twisted.internet.gtk2reactor.PortableGtkReactor"] -+ else: -+ _reactors = ["twisted.internet.glib2reactor.Glib2Reactor", -+ "twisted.internet.gtk2reactor.Gtk2Reactor"] -+ -+ def test_timeout_add(self): -+ """ -+ A C{reactor.callLater} call scheduled from a C{gobject.timeout_add} -+ call is run on time. -+ """ -+ import gobject -+ reactor = self.buildReactor() -+ -+ result = [] -+ def gschedule(): -+ reactor.callLater(0, callback) -+ return 0 -+ def callback(): -+ result.append(True) -+ reactor.stop() -+ -+ reactor.callWhenRunning(gobject.timeout_add, 10, gschedule) -+ self.runReactor(reactor, 5) -+ self.assertEqual(result, [True]) -+ -+ - globals().update(TimeTestsBuilder.makeTestCaseClasses()) -+globals().update(GlibTimeTestsBuilder.makeTestCaseClasses()) - diff -Nru twisted-11.1.0/debian/patches/series twisted-12.1.0/debian/patches/series --- twisted-11.1.0/debian/patches/series 2012-03-09 15:08:00.000000000 +0000 +++ twisted-12.1.0/debian/patches/series 2012-06-20 13:55:27.000000000 +0000 @@ -1,3 +1 @@ -00_gi_gtk3reactor.patch -01_posix_wakeups.patch tap2deb.diff diff -Nru twisted-11.1.0/debian/rules twisted-12.1.0/debian/rules --- twisted-11.1.0/debian/rules 2011-12-21 11:33:38.000000000 +0000 +++ twisted-12.1.0/debian/rules 2012-06-19 02:26:52.000000000 +0000 @@ -36,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; \ @@ -58,12 +50,14 @@ : # 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/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 \ @@ -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-11.1.0/debian/twisted-api twisted-12.1.0/debian/twisted-api --- twisted-11.1.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-11.1.0/debian/watch twisted-12.1.0/debian/watch --- twisted-11.1.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-11.1.0/doc/development/index.html twisted-12.1.0/doc/development/index.html --- twisted-11.1.0/doc/development/index.html 2011-11-17 10:51:11.000000000 +0000 +++ twisted-12.1.0/doc/development/index.html 2012-06-04 08:46:17.000000000 +0000 @@ -21,6 +21,6 @@

Index

- Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/development/naming.html twisted-12.1.0/doc/development/naming.html --- twisted-11.1.0/doc/development/naming.html 2011-11-17 10:51:11.000000000 +0000 +++ twisted-12.1.0/doc/development/naming.html 2012-06-04 08:46:17.000000000 +0000 @@ -33,6 +33,6 @@

Index

- Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/development/philosophy.html twisted-12.1.0/doc/development/philosophy.html --- twisted-11.1.0/doc/development/philosophy.html 2011-11-17 10:51:11.000000000 +0000 +++ twisted-12.1.0/doc/development/philosophy.html 2012-06-04 08:46:17.000000000 +0000 @@ -53,6 +53,6 @@

Index

- Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/development/policy/coding-standard.html twisted-12.1.0/doc/development/policy/coding-standard.html --- twisted-11.1.0/doc/development/policy/coding-standard.html 2011-11-17 10:51:11.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, @@ -64,7 +64,7 @@ example of what you should write). The names of test modules should 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.

@@ -398,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 @@ -507,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 @@ -586,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 @@ -596,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 @@ -813,6 +813,6 @@

    Index

    - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/development/policy/doc-standard.html twisted-12.1.0/doc/development/policy/doc-standard.html --- twisted-11.1.0/doc/development/policy/doc-standard.html 2011-11-17 10:51:11.000000000 +0000 +++ twisted-12.1.0/doc/development/policy/doc-standard.html 2012-06-04 08:46:18.000000000 +0000 @@ -141,8 +141,8 @@

    Rendered result:

    - To add a twisted.web.static.File - instance to a Resource + To add a twisted.web.static.File + instance to a Resource instance, do myResource.putChild("resourcePath", File("/tmp")).

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

    Index

    - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/development/policy/index.html twisted-12.1.0/doc/development/policy/index.html --- twisted-11.1.0/doc/development/policy/index.html 2011-11-17 10:51:11.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: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/development/policy/svn-dev.html twisted-12.1.0/doc/development/policy/svn-dev.html --- twisted-11.1.0/doc/development/policy/svn-dev.html 2011-11-17 10:51:11.000000000 +0000 +++ twisted-12.1.0/doc/development/policy/svn-dev.html 2012-06-04 08:46:18.000000000 +0000 @@ -58,12 +58,12 @@

    Combinator

    In order to simplify the use of Subversion, we typically use -Divmod Combinator. +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 - + UQDS page.

    Compiling C extensions

    @@ -225,6 +225,6 @@

    Index

    - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/development/policy/test-standard.html twisted-12.1.0/doc/development/policy/test-standard.html --- twisted-11.1.0/doc/development/policy/test-standard.html 2011-11-17 10:51:11.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

    - +
    @@ -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 @@ -202,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:

    @@ -270,7 +305,7 @@ 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 @@ -278,7 +313,7 @@ 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 @@ -323,7 +358,7 @@ twisted-dev.el's F9 command) use this to automatically run the right tests.

    -
    +
    • A chapter on Unit Testing @@ -359,6 +394,6 @@

      Index

      - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/development/policy/writing-standard.html twisted-12.1.0/doc/development/policy/writing-standard.html --- twisted-11.1.0/doc/development/policy/writing-standard.html 2011-11-17 10:51:11.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: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/development/security.html twisted-12.1.0/doc/development/security.html --- twisted-11.1.0/doc/development/security.html 2011-11-17 10:51:11.000000000 +0000 +++ twisted-12.1.0/doc/development/security.html 2012-06-04 08:46:17.000000000 +0000 @@ -38,6 +38,6 @@

      Index

      - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/examples/index.html twisted-12.1.0/doc/examples/index.html --- twisted-11.1.0/doc/examples/index.html 2011-11-17 10:51:11.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
      • @@ -111,7 +108,7 @@
      • stdin.py - reading a line at a time from standard input without blocking the reactor
      • streaming.py - example of a push producer/consumer system
      • -
      • filewatch.py - write the content of a file to standard out +
      • 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 @@ -119,10 +116,10 @@
      • wxacceptance.py - acceptance tests for wxreactor
      • postfix.py - test application for PostfixTCPMapServer
      - +

      Index

      - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/examples/ptyserv.py twisted-12.1.0/doc/examples/ptyserv.py --- twisted-11.1.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-11.1.0/doc/examples/pyuidemo.py twisted-12.1.0/doc/examples/pyuidemo.py --- twisted-11.1.0/doc/examples/pyuidemo.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/doc/examples/pyuidemo.py 2012-04-14 00:36:38.000000000 +0000 @@ -3,6 +3,14 @@ # 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-11.1.0/doc/examples/recvfd.py twisted-12.1.0/doc/examples/recvfd.py --- twisted-11.1.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-11.1.0/doc/examples/row_example.py twisted-12.1.0/doc/examples/row_example.py --- twisted-11.1.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-11.1.0/doc/examples/row_schema.sql twisted-12.1.0/doc/examples/row_schema.sql --- twisted-11.1.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-11.1.0/doc/examples/row_util.py twisted-12.1.0/doc/examples/row_util.py --- twisted-11.1.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-11.1.0/doc/examples/sendfd.py twisted-12.1.0/doc/examples/sendfd.py --- twisted-11.1.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-11.1.0/doc/examples/tkinterdemo.py twisted-12.1.0/doc/examples/tkinterdemo.py --- twisted-11.1.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-11.1.0/doc/howto/amp.html twisted-12.1.0/doc/howto/amp.html --- twisted-11.1.0/doc/howto/amp.html 2011-11-17 10:51:08.000000000 +0000 +++ twisted-12.1.0/doc/howto/amp.html 2012-06-04 08:46:18.000000000 +0000 @@ -10,13 +10,13 @@
      -

      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.

      +

      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:

      +

      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 @@ -113,7 +113,7 @@

      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.

      +

      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 @@ -344,6 +344,6 @@

      Index

      - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/application.html twisted-12.1.0/doc/howto/application.html --- twisted-11.1.0/doc/howto/application.html 2011-11-17 10:51:10.000000000 +0000 +++ twisted-12.1.0/doc/howto/application.html 2012-06-04 08:46:20.000000000 +0000 @@ -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.

      @@ -103,7 +103,7 @@

      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 +.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:

      @@ -217,13 +217,13 @@

      Alternatively, the logging behavior can be customized through an API -accessible from .tac files. The ILogObserver component can be +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.

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

      See also the UDP documentation.

      @@ -316,8 +316,8 @@
      Services which send and receive data over UNIX datagram sockets.
      @@ -326,11 +326,11 @@
      A server for UDP socket methods that support multicast.
      -
      TimerService
      +
      TimerService
      A service to periodically call a function. @@ -340,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.

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

      Index

      - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/basics.html twisted-12.1.0/doc/howto/basics.html --- twisted-11.1.0/doc/howto/basics.html 2011-11-17 10:51:08.000000000 +0000 +++ twisted-12.1.0/doc/howto/basics.html 2012-06-04 08:46:19.000000000 +0000 @@ -13,11 +13,11 @@

      Application

      Twisted programs usually work -with twisted.application.service.Application. +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.

      +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 @@ -95,6 +95,6 @@

      Index

      - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/book.tex twisted-12.1.0/doc/howto/book.tex --- twisted-11.1.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-11.1.0/doc/howto/choosing-reactor.html twisted-12.1.0/doc/howto/choosing-reactor.html --- twisted-11.1.0/doc/howto/choosing-reactor.html 2011-11-17 10:51:08.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 @@
      -

      PyUI

      +

      PyUI

      As with Tkinter, the support for integrating Twisted with a PyUI @@ -341,6 +390,6 @@

      Index

      - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/clients.html twisted-12.1.0/doc/howto/clients.html --- twisted-11.1.0/doc/howto/clients.html 2011-11-17 10:51:09.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 @@ -143,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 @@ -160,9 +160,9 @@ 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:

      @@ -196,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 @@ -257,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

      @@ -287,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.

      @@ -717,17 +717,17 @@

      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 @@ -736,6 +736,6 @@

      Index

      - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/components.html twisted-12.1.0/doc/howto/components.html --- twisted-11.1.0/doc/howto/components.html 2011-11-17 10:51:07.000000000 +0000 +++ twisted-12.1.0/doc/howto/components.html 2012-06-04 08:46:18.000000000 +0000 @@ -253,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. @@ -505,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:

      @@ -598,6 +598,6 @@

      Index

      - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/constants.html twisted-12.1.0/doc/howto/constants.html --- twisted-11.1.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-11.1.0/doc/howto/cred.html twisted-12.1.0/doc/howto/cred.html --- twisted-11.1.0/doc/howto/cred.html 2011-11-17 10:51:09.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,9 +64,9 @@ This has only 2 methods -

        -
      • login(credentials, mind, *interfaces) +
      • login(credentials, mind, *interfaces) -

        The docstring is quite expansive (see twisted.cred.portal), but in +

        The docstring is quite expansive (see twisted.cred.portal), but in brief, this is what you call when you need to call in order to connect a user to the system. Typically you only pass in one interface, and the mind is None. The interfaces are the possible interfaces the returned @@ -82,7 +82,7 @@

        The logout method has to be called when the avatar is logged out. For POP3 this means when the protocol is disconnected or logged out, etc..

      • -
      • registerChecker(checker, *credentialInterfaces) +
      • registerChecker(checker, *credentialInterfaces)

        which adds a CredentialChecker to the portal. The optional list of interfaces are interfaces of credentials that the checker is able to check.

        @@ -90,7 +90,7 @@

        The CredentialChecker

        -

        This is an object implementing ICredentialsChecker which resolves some +

        This is an object implementing ICredentialsChecker which resolves some credentials to an avatar ID. Whether the credentials are stored in an in-memory data structure, an @@ -122,18 +122,18 @@ several method calls in order to determine a result.

        Twisted comes with a number of credentials interfaces and implementations -in the twisted.cred.credentials module, -such as IUsernamePassword -and IUsernameHashedPassword.

        +in the twisted.cred.credentials module, +such as IUsernamePassword +and IUsernameHashedPassword.

        The Realm

        A realm is an interface which connects your universe of business objects to the authentication system.

        -

        IRealm is another one-method interface:

        +

        IRealm is another one-method interface:

          -
        • requestAvatar(avatarId, mind, *interfaces) +
        • requestAvatar(avatarId, mind, *interfaces)

          This method will typically be called from 'Portal.login'. The avatarId is the one returned by a CredentialChecker.

          @@ -432,7 +432,7 @@

          To build a plugin for cred, you should first define an authType, a short one-word string that defines your plugin to the command-line. Once you have this, the convention is to create a file named myapp_plugins.py in the -twisted.plugins module path.

          +twisted.plugins module path.

          Below is an example file structure for an application that defines such a plugin:

          @@ -464,7 +464,7 @@

          Once you have created this structure within your application, you can create the code for your cred plugin by building a factory class which -implements ICheckerFactory. +implements ICheckerFactory. These factory classes should not consist of a tremendous amount of code. Most of the real application logic should reside in the cred checker itself. (For help on building those, scroll up.) @@ -561,6 +561,6 @@

          Index

          - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/debug-with-emacs.html twisted-12.1.0/doc/howto/debug-with-emacs.html --- twisted-11.1.0/doc/howto/debug-with-emacs.html 2011-11-17 10:51:08.000000000 +0000 +++ twisted-12.1.0/doc/howto/debug-with-emacs.html 2012-06-04 08:46:21.000000000 +0000 @@ -60,6 +60,6 @@ THE AUTHORS

Index

- Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/defer.html twisted-12.1.0/doc/howto/defer.html --- twisted-11.1.0/doc/howto/defer.html 2011-11-17 10:51:09.000000000 +0000 +++ twisted-12.1.0/doc/howto/defer.html 2012-06-04 08:46:19.000000000 +0000 @@ -11,7 +11,7 @@ -

This document is a guide to the behaviour of the twisted.internet.defer.Deferred object, and to various +

This document is a guide to the behaviour of the twisted.internet.defer.Deferred object, and to various ways you can use them when they are returned by functions.

This document assumes that you are familiar with the basic principle that @@ -36,7 +36,7 @@

Deferreds

-

Twisted uses the Deferred object to manage the callback +

Twisted uses the Deferred object to manage the callback sequence. The client application attaches a series of functions to the deferred to be called in order when the results of the asychronous request are available (this series of functions is known as a series of @@ -49,7 +49,7 @@

Callbacks

-

A twisted.internet.defer.Deferred is a promise that +

A twisted.internet.defer.Deferred is a promise that a function will at some point have a result. We can attach callback functions to a Deferred, and once it gets a result these callbacks will be called. In addition Deferreds allow the developer to register a callback for an error, @@ -280,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 @@ -302,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.
  • @@ -315,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.

    @@ -334,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:

    @@ -372,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 @@ -515,7 +515,7 @@

    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:

    @@ -557,7 +557,7 @@

    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 @@ -736,7 +736,7 @@

    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 +failing if any one of the operations fails. In this case, twisted.internet.defer.gatherResults is a useful shortcut:

    1 @@ -893,6 +893,6 @@ DeferredList is confusing and usually avoided.

    Index

    - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/deferredindepth.html twisted-12.1.0/doc/howto/deferredindepth.html --- twisted-11.1.0/doc/howto/deferredindepth.html 2011-11-17 10:51:09.000000000 +0000 +++ twisted-12.1.0/doc/howto/deferredindepth.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,2185 +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) 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) 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) 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 -

    #!/usr/bin/env python -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure - -""" -This example shows an important concept that many deferred newbies 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 90, in <module>
    -    deferredExample()
    -  File "deferred_ex2.py", line 83, in deferredExample
    -    d.callback("success")
    -  File "twisted/internet/defer.py", line 361, in callback
    -    self._startRunCallbacks(result)
    -  File "twisted/internet/defer.py", line 455, in _startRunCallbacks
    -    self._runCallbacks()
    ---- <exception caught here> ---
    -  File "twisted/internet/defer.py", line 542, in _runCallbacks
    -    current.result = callback(current.result, *args, **kw)
    -  File "deferred_ex2.py", line 37, 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) 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) 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) 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) 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) 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) 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: 11.1.0 - - \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/design.html twisted-12.1.0/doc/howto/design.html --- twisted-11.1.0/doc/howto/design.html 2011-11-17 10:51:09.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. @@ -249,6 +249,6 @@

    Index

    - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/dirdbm.html twisted-12.1.0/doc/howto/dirdbm.html --- twisted-11.1.0/doc/howto/dirdbm.html 2011-11-17 10:51:07.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,7 +41,7 @@

    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, @@ -71,6 +71,6 @@

    Index

    - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/endpoints.html twisted-12.1.0/doc/howto/endpoints.html --- twisted-11.1.0/doc/howto/endpoints.html 2011-11-17 10:51:08.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: IStreamServerEndpoint and IStreamClientEndpoint. +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

    -

    IStreamServerEndpoint.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

    -

    IStreamClientEndpoint.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: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/gendefer.html twisted-12.1.0/doc/howto/gendefer.html --- twisted-11.1.0/doc/howto/gendefer.html 2011-11-17 10:51:07.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.

    @@ -229,8 +229,8 @@

    While we can require that callers of our function wrap our synchronous -result in a Deferred using maybeDeferred, for the sake of API -compatibility it is better to return a Deferred ourselves using defer.succeed:

    +result in a Deferred using maybeDeferred, for the sake of API +compatibility it is better to return a Deferred ourselves using defer.succeed:

    1 2 @@ -258,7 +258,7 @@ return defer.succeed(result)

    -

    There is an equivalent defer.fail method to return a Deferred with the +

    There is an equivalent defer.fail method to return a Deferred with the errback chain already fired.

    Integrating blocking code with Twisted

    @@ -271,7 +271,7 @@ other than rewriting them.

    In this case, Twisted provides the ability to run the blocking code in a -separate thread rather than letting it block your application. The twisted.internet.threads.deferToThread function will set up +separate thread rather than letting it block your application. The twisted.internet.threads.deferToThread function will set up a thread to run your blocking function, return a Deferred and later fire that Deferred when the thread completes.

    @@ -406,6 +406,6 @@

    Index

    - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/glossary.html twisted-12.1.0/doc/howto/glossary.html --- twisted-11.1.0/doc/howto/glossary.html 2011-11-17 10:51:08.000000000 +0000 +++ twisted-12.1.0/doc/howto/glossary.html 2012-06-04 08:46:21.000000000 +0000 @@ -17,15 +17,15 @@ An object that has been adapted, also called original. See Adapter. -
    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. @@ -38,15 +38,15 @@ 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 - ICredentialsChecker. + ICredentialsChecker.
    CVSToys
    @@ -116,9 +116,9 @@ 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. @@ -164,14 +162,14 @@ 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.words.im. + Twisted Words. See twisted.words.im.
    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,11 +194,11 @@
    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. @@ -216,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
    @@ -229,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.
    @@ -256,26 +254,19 @@
    (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.
    @@ -288,7 +279,7 @@
    SUX
    Small Uncomplicated XML, Twisted's simple XML -parser written in pure Python. See twisted.web.sux.
    +parser written in pure Python. See twisted.web.sux.
    TAC
    A Twisted Application Configuration is a Python @@ -302,7 +293,7 @@ Using the Utilities.
    Trial
    -
    twisted.trial, Twisted's unit-testing framework, +
    twisted.trial, Twisted's unit-testing framework, based on the unittest standard library module. See also Writing tests for Twisted code.
    Twisted Matrix Laboratories
    @@ -317,15 +308,15 @@ 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. @@ -338,6 +329,6 @@

    Index

    - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/index.html twisted-12.1.0/doc/howto/index.html --- twisted-11.1.0/doc/howto/index.html 2011-11-17 10:51:10.000000000 +0000 +++ twisted-12.1.0/doc/howto/index.html 2012-06-04 08:46:18.000000000 +0000 @@ -14,28 +14,23 @@
  • Introduction
  • -
  • Tutorials +
  • Getting Started
  • -
  • Low-Level Networking and Event Loop +
  • Networking and Other Event Sources
  • -
  • High-Level Twisted - +
  • High-Level Infrastructure
  • -
  • Utilities +
  • Deploying Twisted Applications
  • -
  • Twisted RDBMS support +
  • Utilities
  • 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
    • @@ -211,6 +234,6 @@

      Index

      - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/internet-overview.html twisted-12.1.0/doc/howto/internet-overview.html --- twisted-11.1.0/doc/howto/internet-overview.html 2011-11-17 10:51:07.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: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/listings/deferred/deferred_ex1a.py twisted-12.1.0/doc/howto/listings/deferred/deferred_ex1a.py --- twisted-11.1.0/doc/howto/listings/deferred/deferred_ex1a.py 2011-02-14 04:45:15.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) 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-11.1.0/doc/howto/listings/deferred/deferred_ex1b.py twisted-12.1.0/doc/howto/listings/deferred/deferred_ex1b.py --- twisted-11.1.0/doc/howto/listings/deferred/deferred_ex1b.py 2011-02-14 04:45:15.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) 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-11.1.0/doc/howto/listings/deferred/deferred_ex2.py twisted-12.1.0/doc/howto/listings/deferred/deferred_ex2.py --- twisted-11.1.0/doc/howto/listings/deferred/deferred_ex2.py 2011-04-14 02:24:55.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/deferred/deferred_ex2.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,90 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -from twisted.internet import defer -from twisted.python import failure - -""" -This example shows an important concept that many deferred newbies 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-11.1.0/doc/howto/listings/deferred/deferred_ex3.py twisted-12.1.0/doc/howto/listings/deferred/deferred_ex3.py --- twisted-11.1.0/doc/howto/listings/deferred/deferred_ex3.py 2011-02-14 04:45:15.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) 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-11.1.0/doc/howto/listings/deferred/deferred_ex4.py twisted-12.1.0/doc/howto/listings/deferred/deferred_ex4.py --- twisted-11.1.0/doc/howto/listings/deferred/deferred_ex4.py 2011-02-14 04:45:15.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) 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-11.1.0/doc/howto/listings/deferred/deferred_ex5.py twisted-12.1.0/doc/howto/listings/deferred/deferred_ex5.py --- twisted-11.1.0/doc/howto/listings/deferred/deferred_ex5.py 2011-02-14 04:45:15.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) 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-11.1.0/doc/howto/listings/deferred/deferred_ex6.py twisted-12.1.0/doc/howto/listings/deferred/deferred_ex6.py --- twisted-11.1.0/doc/howto/listings/deferred/deferred_ex6.py 2011-02-14 04:45:15.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) 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-11.1.0/doc/howto/listings/deferred/deferred_ex7.py twisted-12.1.0/doc/howto/listings/deferred/deferred_ex7.py --- twisted-11.1.0/doc/howto/listings/deferred/deferred_ex7.py 2011-02-14 04:45:15.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) 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-11.1.0/doc/howto/listings/deferred/deferred_ex8.py twisted-12.1.0/doc/howto/listings/deferred/deferred_ex8.py --- twisted-11.1.0/doc/howto/listings/deferred/deferred_ex8.py 2011-02-14 04:45:15.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) 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-11.1.0/doc/howto/listings/deferred/deferred_ex.py twisted-12.1.0/doc/howto/listings/deferred/deferred_ex.py --- twisted-11.1.0/doc/howto/listings/deferred/deferred_ex.py 2011-02-14 04:45:15.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) 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-11.1.0/doc/howto/listings/sendmsg/copy_descriptor.py twisted-12.1.0/doc/howto/listings/sendmsg/copy_descriptor.py --- twisted-11.1.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-11.1.0/doc/howto/listings/sendmsg/send_replacement.py twisted-12.1.0/doc/howto/listings/sendmsg/send_replacement.py --- twisted-11.1.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-11.1.0/doc/howto/listings/trial/calculus/base_3.py twisted-12.1.0/doc/howto/listings/trial/calculus/base_3.py --- twisted-11.1.0/doc/howto/listings/trial/calculus/base_3.py 2009-06-08 18:39:34.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/trial/calculus/base_3.py 2012-03-13 23:49:05.000000000 +0000 @@ -5,7 +5,7 @@ try: return map(int, args) except ValueError: - raise TypeError("Coudln't coerce arguments to integers: %s" % args) + raise TypeError("Couldn't coerce arguments to integers: %s" % args) def add(self, a, b): a, b = self._make_ints(a, b) diff -Nru twisted-11.1.0/doc/howto/listings/udp/MulticastClient.py twisted-12.1.0/doc/howto/listings/udp/MulticastClient.py --- twisted-11.1.0/doc/howto/listings/udp/MulticastClient.py 2011-06-05 17:53:27.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/udp/MulticastClient.py 2011-11-13 20:21:50.000000000 +0000 @@ -1,12 +1,19 @@ from twisted.internet.protocol import DatagramProtocol from twisted.internet import reactor -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 -port = reactor.listenUDP(0, MulticastClientUDP()) -port.write('UniqueID', ('224.0.0.1', 8005)) +reactor.listenMulticast(8005, MulticastPingClient(), listenMultiple=True) reactor.run() diff -Nru twisted-11.1.0/doc/howto/listings/udp/MulticastServer.py twisted-12.1.0/doc/howto/listings/udp/MulticastServer.py --- twisted-11.1.0/doc/howto/listings/udp/MulticastServer.py 2011-06-05 17:53:27.000000000 +0000 +++ twisted-12.1.0/doc/howto/listings/udp/MulticastServer.py 2011-11-13 20:21:50.000000000 +0000 @@ -1,24 +1,28 @@ from twisted.internet.protocol import DatagramProtocol from twisted.internet import reactor -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-11.1.0/doc/howto/logging.html twisted-12.1.0/doc/howto/logging.html --- twisted-11.1.0/doc/howto/logging.html 2011-11-17 10:51:09.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')) @@ -82,9 +82,9 @@

    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

    @@ -93,7 +93,7 @@ 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 + PythonLoggingObserver should be useful to you.

    @@ -132,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 @@ -191,6 +191,6 @@

    Index

    - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/options.html twisted-12.1.0/doc/howto/options.html --- twisted-11.1.0/doc/howto/options.html 2011-11-17 10:51:08.000000000 +0000 +++ twisted-12.1.0/doc/howto/options.html 2012-06-04 08:46:20.000000000 +0000 @@ -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:

    @@ -566,16 +566,16 @@

    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 + 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 + Completions instance will be aggregated when producing the final tab-completion results.

    Index

    - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/overview.html twisted-12.1.0/doc/howto/overview.html --- twisted-11.1.0/doc/howto/overview.html 2011-11-17 10:51:10.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: 11.1.0 - - \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/pb-clients.html twisted-12.1.0/doc/howto/pb-clients.html --- twisted-11.1.0/doc/howto/pb-clients.html 2011-11-17 10:51:07.000000000 +0000 +++ twisted-12.1.0/doc/howto/pb-clients.html 2012-06-04 08:46:19.000000000 +0000 @@ -12,7 +12,7 @@

      Overview

      -

      In all the IPerspective uses +

      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.

      @@ -357,6 +357,6 @@

      Index

      - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/pb-copyable.html twisted-12.1.0/doc/howto/pb-copyable.html --- twisted-11.1.0/doc/howto/pb-copyable.html 2011-11-17 10:51:09.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.

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

      PB lets you specify the mapping from remote class names to local classes -with the setUnjellyableForClass function +with the setUnjellyableForClass function 1. @@ -352,8 +352,8 @@

      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. +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 @@ -362,8 +362,8 @@ 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 +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.

      @@ -374,7 +374,7 @@ 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 @@ -389,7 +389,7 @@

      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. + setCopyableState method. This acts just like the __setstate__ method that pickle uses when unserializing an object. getStateToCopy/setCopyableState are distinct from @@ -686,8 +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 @@ -696,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. @@ -723,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. @@ -741,15 +741,15 @@ 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 @@ -757,8 +757,8 @@ 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 observer 4 that points at that receiver-side cache. Every time the state of the object @@ -766,7 +766,7 @@ 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 +

      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 @@ -793,7 +793,7 @@ 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.

      @@ -1134,13 +1134,13 @@ @@ -1160,26 +1160,26 @@ that are the Unjellyable second argument of the setUnjellyableForClass function. In particular, unjellyable does not mean cannot be -jellied. Unpersistable means not +jellied. Unpersistable means not persistable, but unjelly, unserialize, and unpickle mean to reverse the operations of jellying, serializing, and -pickling.
    18. pb.RemoteCopy is actually defined - in twisted.spread.flavors, but +pickling.
    19. pb.RemoteCopy is actually defined + in twisted.spread.flavors, but pb.RemoteCopy is the preferred way to access it
    20. 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.
    21. This is actually a RemoteCacheObserver, but it isn't very +hard to maintain or extend, though.
    22. 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.
    23. This applies to - multiple references through the same Broker. If you've managed to make multiple + multiple references through the same Broker. If you've managed to make multiple TCP connections to the same program, you deserve whatever you get.
    24. Index

      - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/pb-cred.html twisted-12.1.0/doc/howto/pb-cred.html --- twisted-11.1.0/doc/howto/pb-cred.html 2011-11-17 10:51:08.000000000 +0000 +++ twisted-12.1.0/doc/howto/pb-cred.html 2012-06-04 08:46:21.000000000 +0000 @@ -305,7 +305,7 @@

      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. @@ -1229,8 +1229,8 @@

      pbAnonServer.py implements a server based on pb6server.py, extending it to permit anonymous logins in addition to authenticated logins. An - AllowAnonymousAccess -checker and an InMemoryUsernamePasswordDatabaseDontUse + 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 @@ -1238,8 +1238,8 @@ of twisted.cred.checkers.ANONYMOUS.

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

      + Anonymous when calling + PBClientFactory.login.

      Using Avatars

      @@ -1426,7 +1426,7 @@

      Viewable

      Once you have IPerspective objects (i.e. the Avatar) to -represent users, the Viewable class can come into play. This +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 @@ -1719,6 +1719,6 @@ backwards-compatibility.

      Index

      - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/pb.html twisted-12.1.0/doc/howto/pb.html --- twisted-11.1.0/doc/howto/pb.html 2011-11-17 10:51:08.000000000 +0000 +++ twisted-12.1.0/doc/howto/pb.html 2012-06-04 08:46:20.000000000 +0000 @@ -47,6 +47,6 @@ the protocol is completely symmetrical.

      Index

      - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/pb-intro.html twisted-12.1.0/doc/howto/pb-intro.html --- twisted-11.1.0/doc/howto/pb-intro.html 2011-11-17 10:51:08.000000000 +0000 +++ twisted-12.1.0/doc/howto/pb-intro.html 2012-06-04 08:46:18.000000000 +0000 @@ -33,7 +33,7 @@
    25. 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.
    26. @@ -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. @@ -208,13 +208,13 @@

              -
            • twisted.spread.pb.Copyable +
            • twisted.spread.pb.Copyable

              This is the simpler kind of object that can be copied. Every time this object is returned from a method or passed as an argument, it is serialized and unserialized.

              -

              Copyable +

              Copyable provides a method you can override, getStateToCopyFor(perspective), which allows you to decide what an object will look like for the perspective who is requesting it. The perspective argument will be the perspective @@ -249,7 +249,7 @@

            • -
            • twisted.spread.pb.Cacheable +
            • twisted.spread.pb.Cacheable

              Let me preface this with a warning: Cacheable may be hard to understand. The motivation for it may be unclear if you don't have some experience with @@ -279,13 +279,13 @@ perspective. It also gets passed an observer, which is a remote reference to a secret fourth referenceable flavor: - RemoteCache.

              + RemoteCache.

              -

              A RemoteCache is simply +

              A RemoteCache is simply the object that represents your - Cacheable on the other side + Cacheable on the other side of the connection. It is registered using the same method as - RemoteCopy, above. + RemoteCopy, above. RemoteCache is different, however, in that it will be referenced by its peer. It acts as a Referenceable, where all methods prefixed with observe_ will be callable remotely. It is @@ -295,11 +295,11 @@ that should be noticeable to its clients.

              Finally, when all references to a - Cacheable from a given + Cacheable from a given perspective are lost, stoppedObserving(perspective, observer) will be called on the - Cacheable, with the same + Cacheable, with the same perspective/observer pair that getStateToCacheAndObserveFor was originally called with. Any cleanup remote calls can be made there, as well as removing the observer object from any lists which it was previously in. @@ -315,6 +315,6 @@ now.

            • Index

              - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/pb-limits.html twisted-12.1.0/doc/howto/pb-limits.html --- twisted-11.1.0/doc/howto/pb-limits.html 2011-11-17 10:51:08.000000000 +0000 +++ twisted-12.1.0/doc/howto/pb-limits.html 2012-06-04 08:46:18.000000000 +0000 @@ -33,7 +33,7 @@ the size of long integers. The purpose of this limit is the same as the SIZE_LIMIT. By default, only integers between -2 ** 448 and 2 ** 448 (exclusive) can be transferred. This limit can be changed using - twisted.spread.banana.setPrefixLimit.

              + twisted.spread.banana.setPrefixLimit.

              Perspective Broker Limits

              @@ -46,6 +46,6 @@

              Index

              - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/pb-usage.html twisted-12.1.0/doc/howto/pb-usage.html --- twisted-11.1.0/doc/howto/pb-usage.html 2011-11-17 10:51:07.000000000 +0000 +++ twisted-12.1.0/doc/howto/pb-usage.html 2012-06-04 08:46:20.000000000 +0000 @@ -68,20 +68,20 @@

      First we look at the server. This defines an Echoer class (derived from - pb.Root), with a method called + pb.Root), with a method called remote_echo(). - pb.Root objects (because of + pb.Root objects (because of their inheritance of - pb.Referenceable, described + pb.Referenceable, described later) can define methods with names of the form remote_*; a client which obtains a remote reference to that - pb.Root object will be able to + pb.Root object will be able to invoke those methods.

      -

      The pb.Root-ish object is -given to a pb.PBServerFactory(). This is a - Factory object like -any other: the Protocol objects it creates for new +

      The pb.Root-ish object is +given to a pb.PBServerFactory(). This is a + Factory object like +any other: the Protocol objects it creates for new connections know how to speak the PB protocol. The object you give to pb.PBServerFactory() becomes the root object, which simply makes it available for the client to retrieve. The client may only @@ -89,11 +89,11 @@ implement your security model. Because it is so common to export just a single object (and because a remote_* method on that one can return a reference to any other object you might want to give out), the -simplest example is one where the PBServerFactory is given the root object, and +simplest example is one where the PBServerFactory is given the root object, and the client retrieves it.

      The client side uses - pb.PBClientFactory to make a + pb.PBClientFactory to make a connection to a given port. This is a two-step process involving opening a TCP connection to a given host and port and requesting the root object using .getRootObject().

      @@ -102,7 +102,7 @@ connection has been made and exchange some data, it may take a while, so it returns a Deferred, to which the gotObject() callback is attached. (See the documentation on Deferring -Execution for a complete explanation of Deferreds). If and when the +Execution for a complete explanation of Deferreds). If and when the connection succeeds and a reference to the remote root object is obtained, this callback is run. The first argument passed to the callback is a remote reference to the distant root object. (you can @@ -119,10 +119,10 @@ (running .callRemote("boom") would cause .remote_boom() to be run, etc). Again because of the delay involved, callRemote() returns a - Deferred. Assuming the + Deferred. Assuming the remote method was run without causing an exception (including an attempt to invoke an unknown method), the callback attached to that - Deferred will be + Deferred will be invoked with any objects that were returned by the remote method call.

      In this example, the server's Echoer object has a method @@ -135,8 +135,8 @@

      and from the definition of remote_echo() we see that this just returns the same string it was given: hello network.

      -

      From the client's point of view, the remote call gets another Deferred object instead of -that string. callRemote() always returns a Deferred. This is why PB is +

      From the client's point of view, the remote call gets another Deferred object instead of +that string. callRemote() always returns a Deferred. This is why PB is described as a system for translucent remote method calls instead of transparent ones: you cannot pretend that the remote object is really local. Trying to do so (as some other RPC mechanisms do, coughCORBAcough) @@ -144,17 +144,17 @@ Deferreds turns out to be a very clean way to deal with the whole thing.

      The remote reference object (the one given to - getRootObject()'s success callback) is an instance the RemoteReference class. This means + getRootObject()'s success callback) is an instance the RemoteReference class. This means you can use it to invoke methods on the remote object that it refers to. Only -instances of RemoteReference are eligible for - .callRemote(). The RemoteReference object is the one that lives +instances of RemoteReference are eligible for + .callRemote(). The RemoteReference object is the one that lives on the remote side (the client, in this case), not the local side (where the actual object is defined).

      In our example, the local object is that Echoer() instance, -which inherits from pb.Root, +which inherits from pb.Root, which inherits from - pb.Referenceable. It is that + pb.Referenceable. It is that Referenceable class that makes the object eligible to be available for remote method calls1. If you have an object that is Referenceable, then any client that manages to get a @@ -167,31 +167,31 @@ remote_* methods can do.

      Also note: the other classes like - Referenceable allow access to + Referenceable allow access to other methods, in particular perspective_* and view_* may be accessed. Don't write local-only methods with these names, because then remote callers will be able to do more than you intended.

      Also also note: the other classes like - pb.Copyable do allow + pb.Copyable do allow access to attributes, but you control which ones they can see.

      You don't have to be a - pb.Root to be remotely callable, + pb.Root to be remotely callable, but you do have to be - pb.Referenceable. (Objects that -inherit from pb.Referenceable -but not from pb.Root can be + pb.Referenceable. (Objects that +inherit from pb.Referenceable +but not from pb.Root can be remotely called, but only - pb.Root-ish objects can be given -to the PBServerFactory.)

      + pb.Root-ish objects can be given +to the PBServerFactory.)

      Complete Example

      -

      Here is an example client and server which uses pb.Referenceable as a root object and as the +

      Here is an example client and server which uses pb.Referenceable as a root object and as the result of a remotely exposed method. In each context, methods can be invoked -on the exposed Referenceable +on the exposed Referenceable instance. In this example, the initial root object has a method that returns a reference to the second object.

      @@ -300,11 +300,11 @@ main()
      Source listing - listings/pb/pb1client.py
      -

      pb.PBClientFactory.getRootObject will +

      pb.PBClientFactory.getRootObject will handle all the details of waiting for the creation of a connection. -It returns a Deferred, which will have its +It returns a Deferred, which will have its callback called when the reactor connects to the remote server and - pb.PBClientFactory gets the + pb.PBClientFactory gets the root, and have its errback called when the object-connection fails for any reason, whether it was host lookup failure, connection refusal, or some server-side error. @@ -312,24 +312,24 @@

      The root object has a method called remote_getTwo, which returns the Two() instance. On the client end, the callback gets -a RemoteReference to that +a RemoteReference to that instance. The client can then invoke two's .remote_three() method.

      -

      RemoteReference +

      RemoteReference objects have one method which is their purpose for being: callRemote. This method allows you to call a -remote method on the object being referred to by the Reference. RemoteReference.callRemote, like pb.PBClientFactory.getRootObject, returns -a Deferred. -When a response to the method-call being sent arrives, the Deferred's callback or errback +remote method on the object being referred to by the Reference. RemoteReference.callRemote, like pb.PBClientFactory.getRootObject, returns +a Deferred. +When a response to the method-call being sent arrives, the Deferred's callback or errback will be made, depending on whether an error occurred in processing the method call.

      You can use this technique to provide access to arbitrary sets of objects. Just remember that any object that might get passed over the wire must -inherit from Referenceable +inherit from Referenceable (or one of the other flavors). If you try to pass a non-Referenceable object (say, by returning one from a remote_* method), you'll get an - InsecureJelly + InsecureJelly exception2.

      @@ -613,16 +613,16 @@ sort. The Twisted Way is the same.

      The only special thing you do is to define your Exception -subclass by deriving it from pb.Error. When any remotely-invokable method +subclass by deriving it from pb.Error. When any remotely-invokable method (like remote_* or perspective_*) raises a pb.Error-derived exception, a serialized form of that Exception object will be sent back over the wire4. The other side (which did callRemote) will have the errback -callback run with a Failure object that contains a copy of +callback run with a Failure object that contains a copy of the exception object. This Failure object can be queried to retrieve the error message and a stack traceback.

      -

      Failure is a +

      Failure is a special class, defined in twisted/python/failure.py, created to make it easier to handle asynchronous exceptions. Just as exception handlers can be nested, errback functions can be chained. If one errback @@ -790,7 +790,7 @@ traffic), but it will print out an unsightly stack trace on the server's stderr with a message that says Peer Will Receive PB Traceback, just as if the exception had happened outside a remotely-invokable method. (This -message will go the current log target, if log.startLogging was used to redirect it). The +message will go the current log target, if log.startLogging was used to redirect it). The client will get the same Failure object in either case, but subclassing your exception from pb.Error is the way to tell Twisted that you expect this sort of exception, and that it is ok to just @@ -799,7 +799,7 @@ instead of broken() to see the change in the server's behavior.

      -

      If you don't add an errback function to the Deferred, then a remote +

      If you don't add an errback function to the Deferred, then a remote exception will still send a Failure object back over, but it will get lodged in the Deferred with nowhere to go. When that Deferred finally goes out of scope, the side that did @@ -808,9 +808,9 @@ that point (after all, the callRemote that triggered the problem is long gone), but it will emit a traceback. So be a good programmer and always add errback handlers, even if they are just -calls to log.err.

      +calls to log.err.

      -

      Try/Except blocks and Failure.trap

      +

      Try/Except blocks and Failure.trap

      To implement the equivalent of the Python try/except blocks (which can trap particular kinds of exceptions and pass others up to @@ -1063,7 +1063,7 @@

      In this example, callTwo tries to send an instance of a locally-defined class through callRemote. The default security -model implemented by jelly +model implemented by jelly on the remote end will not allow unknown classes to be unserialized (i.e. taken off the wire as a stream of bytes and turned back into an object: a living, breathing instance of some class): one reason is that it does not @@ -1071,7 +1071,7 @@ corresponds to the remote object5.

      The receiving end of the connection gets to decide what to accept and what -to reject. It indicates its disapproval by raising a jelly.InsecureJelly exception. Because it occurs +to reject. It indicates its disapproval by raising a jelly.InsecureJelly exception. Because it occurs at the remote end, the exception is returned to the caller asynchronously, so an errback handler for the associated Deferred is run. That errback receives a Failure which wraps the @@ -1086,7 +1086,7 @@ trap, and it will return the matching member. In this case, the kinds of exceptions we are checking for (MyException and MyOtherException) may be raised by the remote end: they inherit -from pb.Error.

      +from pb.Error.

      The handler can return None to terminate processing of the errback chain (to be precise, it switches to the callback that follows the @@ -1099,19 +1099,19 @@ importance in an asynchronous environment is that an exception that falls off the end of the Deferred will not be signalled until that Deferred goes out of scope, and at that point may only cause a -log message (which could even be thrown away if log.startLogging is not used to point it at +log message (which could even be thrown away if log.startLogging is not used to point it at stdout or a log file). In contrast, a synchronous exception that is not handled by any other except: block will very visibly terminate the program immediately with a noisy stack trace.

      callFour shows another kind of exception that can occur -while using callRemote: pb.DeadReferenceError. This one occurs when the +while using callRemote: pb.DeadReferenceError. This one occurs when the remote end has disconnected or crashed, leaving the local side with a stale reference. This kind of exception happens to be reported right away (XXX: is this guaranteed? probably not), so must be caught in a traditional synchronous try: except pb.DeadReferenceError block.

      -

      Yet another kind that can occur is a pb.PBConnectionLost exception. This occurs +

      Yet another kind that can occur is a pb.PBConnectionLost exception. This occurs (asynchronously) if the connection was lost while you were waiting for a callRemote call to complete. When the line goes dead, all pending requests are terminated with this exception. Note that you have no @@ -1142,15 +1142,15 @@ or even more powerful classes that you have available in your server program). Allowing a remote entity to create arbitrary classes in your namespace is nearly equivalent to allowing them to run arbitrary code.

      -

      The InsecureJelly +

      The InsecureJelly exception arises because the class being sent over the wire has not been -registered with the serialization layer (known as jelly). The easiest way to make it possible to -copy entire class instances over the wire is to have them inherit from pb.Copyable, and then to use +registered with the serialization layer (known as jelly). The easiest way to make it possible to +copy entire class instances over the wire is to have them inherit from pb.Copyable, and then to use setUnjellyableForClass(remoteClass, localClass) on the receiving side. See Passing Complex Types for an example.

      Index

      - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/plugin.html twisted-12.1.0/doc/howto/plugin.html --- twisted-11.1.0/doc/howto/plugin.html 2011-11-17 10:51:08.000000000 +0000 +++ twisted-12.1.0/doc/howto/plugin.html 2012-06-04 08:46:18.000000000 +0000 @@ -16,7 +16,7 @@ extensibility is achieved through the definition of one or more APIs and a mechanism for collecting code plugins which implement this API to provide some additional functionality. - At the base of this system is the twisted.plugin module.

      + At the base of this system is the twisted.plugin module.

      Making an application extensible using the plugin system has several strong advantages over other techniques:

      @@ -35,7 +35,7 @@

      Writing Extensible Programs

      -

      Taking advantage of twisted.plugin is +

      Taking advantage of twisted.plugin is a two step process:

        @@ -57,7 +57,7 @@
      1. - At one or more places in your program, invoke twisted.plugin.getPlugins and iterate over its + At one or more places in your program, invoke twisted.plugin.getPlugins and iterate over its result.
      @@ -193,7 +193,7 @@

      steelPlate and brassPlate now provide both - IPlugin and IMaterial. + IPlugin and IMaterial. All that remains is to make this module available at an appropriate location. For this, there are two options. The first of these is primarily useful during development: if a directory which @@ -215,7 +215,7 @@

      Alternate Plugin Packages

      -

      getPlugins takes one +

      getPlugins takes one additional argument not mentioned above. If passed in, the 2nd argument should be a module or package to be used instead of twisted.plugins as the plugin meta-package. If you @@ -289,6 +289,6 @@

      Index

      - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/process.html twisted-12.1.0/doc/howto/process.html --- twisted-11.1.0/doc/howto/process.html 2011-11-17 10:51:09.000000000 +0000 +++ twisted-12.1.0/doc/howto/process.html 2012-06-04 08:46:18.000000000 +0000 @@ -16,9 +16,9 @@ connects to local processes with much the same API. The API is described in more detail in the documentation of:

      @@ -53,7 +53,7 @@

      Index

      - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/quotes.html twisted-12.1.0/doc/howto/quotes.html --- twisted-11.1.0/doc/howto/quotes.html 2011-11-17 10:51:07.000000000 +0000 +++ twisted-12.1.0/doc/howto/quotes.html 2012-06-04 08:46:20.000000000 +0000 @@ -209,6 +209,6 @@

      Index

      - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/rdbms.html twisted-12.1.0/doc/howto/rdbms.html --- twisted-11.1.0/doc/howto/rdbms.html 2011-11-17 10:51:09.000000000 +0000 +++ twisted-12.1.0/doc/howto/rdbms.html 2012-06-04 08:46:19.000000000 +0000 @@ -14,7 +14,7 @@

      Twisted is an asynchronous networking framework, but most database API implementations unfortunately have blocking - interfaces -- for this reason, twisted.enterprise.adbapi was created. It is + interfaces -- for this reason, twisted.enterprise.adbapi was created. It is a non-blocking interface to the standardized DB-API 2.0 API, which allows you to access a number of different RDBMSes.

      @@ -59,11 +59,11 @@

      Those delays are unacceptable when using an asynchronous framework such as Twisted. For this reason, twisted provides - twisted.enterprise.adbapi, an + twisted.enterprise.adbapi, an asynchronous wrapper for any DB-API 2.0-compliant module.

      -

      enterprise.adbapi will do +

      enterprise.adbapi will do blocking database operations in separate threads, which trigger callbacks in the originating thread when they complete. In the @@ -73,9 +73,9 @@

      How do I use adbapi?

      Rather than creating a database connection directly, use the - adbapi.ConnectionPool + adbapi.ConnectionPool class to manage - a connections for you. This allows enterprise.adbapi to use multiple + a connections for you. This allows enterprise.adbapi to use multiple connections, one per thread. This is easy:

      1 2 @@ -89,10 +89,10 @@

      @@ -123,13 +123,13 @@

      This is straightforward, except perhaps for the return value - of getAge. It returns a twisted.internet.defer.Deferred, which allows + of getAge. It returns a twisted.internet.defer.Deferred, which allows arbitrary callbacks to be called upon completion (or upon failure). More documentation on Deferred is available here.

      In addition to runQuery, there is also runOperation, and runInteraction that gets called with a callable (e.g. a function). - The function will be called in the thread with a twisted.enterprise.adbapi.Transaction, + The function will be called in the thread with a twisted.enterprise.adbapi.Transaction, which basically mimics a DB-API cursor. In all cases a database transaction will be commited after your database usage is finished, unless an exception is raised in which case it will be rolled back.

      @@ -223,6 +223,6 @@

      Index

      - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/reactor-basics.html twisted-12.1.0/doc/howto/reactor-basics.html --- twisted-11.1.0/doc/howto/reactor-basics.html 2011-11-17 10:51:10.000000000 +0000 +++ twisted-12.1.0/doc/howto/reactor-basics.html 2012-06-04 08:46:21.000000000 +0000 @@ -48,7 +48,7 @@

      - Twisted applications can use the interfaces in twisted.application.service to configure and run the + Twisted applications can use the interfaces in twisted.application.service to configure and run the application instead of using boilerplate reactor code. See Using Application for an introduction to Application. @@ -56,7 +56,7 @@

      Using the reactor object

      -

      You can get to the reactor object using the following code:

      +

      You can get to the reactor object using the following code:

      1

      from twisted.internet import reactor @@ -67,26 +67,27 @@ the interfaces may not be implemented:

      Index

      - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/row.html twisted-12.1.0/doc/howto/row.html --- twisted-11.1.0/doc/howto/row.html 2011-11-17 10:51:08.000000000 +0000 +++ twisted-12.1.0/doc/howto/row.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,280 +0,0 @@ - - -Twisted Documentation: Twisted Enterprise Row Objects - - - - -

      Twisted Enterprise Row Objects

      - -
      - -
      Note: -

      -Due to lack of maintenance, twisted.enterprise.row -and twisted.enterprise.reflector have been deprecated since -Twisted 8.0. -

      - -

      -This documentation is maintained only for users with an existing -codebase. -

      -
      - - - - -

      The twisted.enterprise.row module is a method of -interfacing simple python objects with rows in relational database -tables. It has two components: the RowObject class which -developers sub-class for each relational table that their code -interacts with, and the Reflector which is responsible -for updates, inserts, queries and deletes against the database.

      - -

      The row module is intended for applications such as on-line -games, and websites that require a back-end database interface. -It is not a full functioned object-relational mapper for python -- it deals best with simple data types structured in ways that -can be easily represented in a relational database. It is well -suited to building a python interface to an existing relational -database, and slightly less suited to added database persistance -to an existing python application.

      - -
      Note: -If row does not fit your model, you will be best off using -the low-level database API directly, -or writing your own object/relational layer on top of it. -
      - -

      Class Definitions

      - -

      To interface to relational database tables, the developer must -create a class derived from the twisted.enterprise.row.RowObject -class for each table. These derived classes must define a number -of class attributes which contains information about the database -table that class corresponds to. The required class attributes -are:

      - -
        -
      • rowColumns - list of the column names and types in the table with - the correct case
      • -
      • rowKeyColumns - list of key columns in form: [(columnName, - typeName)]
      • -
      • rowTableName - the name of the database table
      • -
      - -

      There are also two optional class attributes that can be specified:

      - -
        -
      • rowForeignKeys - list of foreign keys to other database tables - in the form: [(tableName, [(childColumnName, childColumnType), ...], - [(parentColumnName, parentColumnType), ...], containerMethodName, autoLoad]
      • -
      • rowFactoryMethod - a method that creates instances of this - class
      • -
      - -

      For example:

      - -

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

      class RoomRow(row.RowObject): - rowColumns = [("roomId", "int"), - ("town_id", "int"), - ("name", "varchar"), - ("owner", "varchar"), - ("posx", "int"), - ("posy", "int"), - ("width", "int"), - ("height", "int")] - rowKeyColumns = [("roomId", "int4")] - rowTableName = "testrooms" - rowFactoryMethod = [testRoomFactory] -
      - -

      The items in the rowColumns list will become data members of -classes of this type when they are created by the Reflector.

      - -

      Initialization

      - -

      The initialization phase builds the SQL for the database interactions. -It uses the system catalogs of the database to do this, but requires -some basic information to get started. The class attributes of -the classes derived from RowClass are used for this. Those classes -are passed to a Reflector when it is created.

      - -

      There are currently two available reflectors in Twisted Enterprise, -the SQL Reflector for relational databases which uses the python DB -API, and the XML Reflector which uses a file system containing XML -files. The XML reflector is currently extremely slow.

      - -

      An example class list for the RoomRow class we specified above using the SQLReflector:

      - -

      1 -2 -3 -4 -

      from twisted.enterprise.sqlreflector import SQLReflector - -dbpool = adbapi.ConnectionPool("pyPgSQL.PgSQL") -reflector = SQLReflector( dbpool, [RoomRow] ) -
      - -

      Creating Row Objects

      - -

      There are two methods of creating RowObjects - loading from -the database, and creating a new instance ready to be inserted.

      - -

      To load rows from the database and create RowObject instances -for each of the rows, use the loadObjectsFrom method of the Reflector. -This takes a tableName, an optional user data parameter, -and an optional where clause. The where clause may -be omitted which will retrieve all the rows from the table. For -example:

      - -

      1 -2 -3 -4 -5 -6 -7 -

      def gotRooms(rooms): - for room in rooms: - print "Got room:", room.id - -d = reflector.loadObjectsFrom("testrooms", - whereClause=[("id", reflector.EQUAL, 5)]) -d.addCallback(gotRooms) -
      - -

      For more advanced RowObject construction, loadObjectsFrom may -use a factoryMethod that was specified as a class attribute for -the RowClass derived class. This method will be called for each -of the rows with the class object, the userData parameter, and -a dictionary of data from the database keyed by column name. This -factory method should return a fully populated RowObject instance -and may be used to do pre-processing, lookups, and data transformations -before exposing the data to user code. An example factory method:

      - -

      1 -2 -3 -4 -

      def testRoomFactory(roomClass, userData, kw): - newRoom = roomClass(userData) - newRoom.__dict__.update(kw) - return newRoom -
      - -

      The last method of creating a row object is for new instances -that do not already exist in the database table. In this case, -create a new instance and assign its primary key attributes and -all of its member data attributes, then pass it to the insertRow -method of the Reflector. For example:

      - -

      1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -

      newRoom = RoomRow() - newRoom.assignKeyAttr("roomI", 11) - newRoom.town_id = 20 - newRoom.name = 'newRoom1' - newRoom.owner = 'fred' - newRoom.posx = 100 - newRoom.posy = 100 - newRoom.width = 15 - newRoom.height = 20 - reflector.insertRow(newRoom).addCallback(onInsert) -
      - -

      This will insert a new row into the database table for this -new RowObject instance. Note that the assignKeyAttr -method must be used to set primary key attributes - regular attribute -assignment of a primary key attribute of a rowObject will raise -an exception. This prevents the database identity of RowObject -from being changed by mistake.

      - - -

      Relationships Between Tables

      - -

      Specifying a foreign key for a RowClass creates a relationship -between database tables. When loadObjectsFrom is called for a table, it will -automatically load all the children rows for the rows from the specified -table. The child rows will be put into a list member variable of the -rowObject instance with the name childRows or if a containerMethod is specified for the foreign key relationship, -that method will be called on the parent row object for each row that is -being added to it as a child.

      - -

      The autoLoad member of the foreign key definition is a flag -that specifies whether child rows should be auto-loaded for that -relationship when a parent row is loaded.

      - -

      Duplicate Row Objects

      - -

      If a reflector tries to load an instance of a rowObject that -is already loaded, it will return a reference to the existing -rowObject rather than creating a new instance. The reflector maintains -a cache of weak references to all loaded row objects by their -unique keys for this purpose.

      - -

      Updating Row Objects

      - -

      RowObjects have a dirty member attribute that is -set to 1 when any of the member attributes of the instance that -map to database columns are changed. This dirty flag can be used -to tell when RowObjects need to be updated back to the database. -In addition, the setDirty method can be overridden -to provide more complex automated handling such as dirty lists -(be sure to call the base class setDirty though!).

      - -

      When it is determined that a RowObject instance is dirty and -need to have its state updated into the database, pass that object -to the updateRow method of the Reflector. For example:

      - -

      1 -

      reflector.updateRow(room).addCallback(onUpdated) -
      - -

      For more complex behavior, the reflector can generate the SQL -for the update but not perform the update. This can be useful -for batching up multiple updates into single requests. For example:

      - -

      1 -

      updateSQL = reflector.updateRowSQL(room) -
      - -

      Deleting Row Objects

      - -

      To delete a row from a database pass the RowObject instance -for that row to the Reflector deleteRow method. -Deleting the python Rowobject instance does not automatically -delete the row from the database. For example:

      - -

      1 -

      reflector.deleteRow(room) -
      - -
      - -

      Index

      - Version: 11.1.0 - - \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/sendmsg.html twisted-12.1.0/doc/howto/sendmsg.html --- twisted-11.1.0/doc/howto/sendmsg.html 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/doc/howto/sendmsg.html 2012-06-04 08:46:18.000000000 +0000 @@ -0,0 +1,221 @@ + + +Twisted Documentation: Extremely Low-Level Socket Operations + + + + +

      Extremely Low-Level Socket Operations

      + +
      + + +

      Introduction

      + +

      + Beyond supporting streams of data (SOCK_STREAM) or datagrams (SOCK_DGRAM), + POSIX sockets have additional features not accessible via send(2) and + recv(2). These features include things like scatter/gather I/O, + duplicating file descriptors into other processes, and accessing + out-of-band data. +

      + +

      + Twisted includes a wrapper around the two C APIs which make these things + possible, + sendmsg + and + recvmsg. + This document covers their usage. It is intended for Twisted maintainers. + Application developers looking for this functionality should look for the + high-level APIs Twisted provides on top of these wrappers. +

      + +

      sendmsg

      + +

      + sendmsg(2) exposes nearly all sender-side functionality of a + socket. For a SOCK_STREAM socket, it can send bytes that become part of + the stream of data being carried over the connection. For a SOCK_DGRAM + socket, it can send bytes that become datagrams sent from the socket. It + can send data from multiple memory locations (gather I/O). Over AF_UNIX + sockets, it can copy file descriptors into whichever process is receiving + on the other side. The wrapper included in Twisted, + send1msg, exposes + many (but not all) of these features. This document covers the usage of + the features it does expose. The alternate spelling for the wrapper is + used to indicate the primary limitation, which is it that the interface + supports sending only one iovec at a time. +

      + +

      recvmsg

      + +

      + Likewise, recvmsg(2) exposes nearly all the receiver-side + functionality of a socket. It can receive stream data over from a + SOCK_STREAM socket or datagrams from a SOCK_DGRAM socket. It can receive + that data into multiple memory locations (scatter I/O), and it can receive + those copied file descriptors. The wrapper included in + Twisted, recv1msg, + exposes many (but not all) of these features. This document covers the + usage of the features it does expose. The alternate spelling for the + wrapper is used to indicate the primary limitation, which is that the + interface supports receiving only one iovec at a time. +

      + +

      Sending And Receiving Regular Data

      + +

      + sendmsg can be used in a way which makes it equivalent to using the send + call. The first argument to sendmsg is (in this case and all others) a + file descriptor over which to send the data. The second argument is a + string giving the data to send. +

      + +

      + On the other end, recvmsg can be used to replace a recv call. The first + argument to recvmsg is (again, in all cases) a file descriptor over which + to receive the data. The second argument is an integer giving the maximum + number of data to receive. +

      + +
      + +

      Copying File Descriptors

      + +

      + Used with an AF_UNIX socket, sendmsg send a copy of a file descriptor into + whatever process is receiving on the other end of the socket. This is + done using the ancillary data argument. Ancillary data consists of a list + of three-tuples. A three-tuple constructed with SOL_SOCKET, SCM_RIGHTS, + and a platform-endian packed file descriptor number will copy that file + descriptor. +

      + +

      + File descriptors copied this way must be received using a recvmsg call. + No special arguments are required to receive these descriptors. They will + appear, encoded as a native-order string, in the ancillary data list + returned by recvmsg. +

      + +
      + +
      + +

      Index

      + Version: 12.1.0 + + \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/servers.html twisted-12.1.0/doc/howto/servers.html --- twisted-11.1.0/doc/howto/servers.html 2011-11-17 10:51:08.000000000 +0000 +++ twisted-12.1.0/doc/howto/servers.html 2012-06-04 08:46:18.000000000 +0000 @@ -17,7 +17,7 @@ code can be reused for SSL and Unix socket servers). There is a separate document covering UDP.

      -

      Your protocol handling class will usually subclass twisted.internet.protocol.Protocol. Most +

      Your protocol handling class will usually subclass 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 is instantiated per-connection, on demand, and will go @@ -27,7 +27,7 @@

      The persistent configuration is kept in a Factory class, which usually inherits - from twisted.internet.protocol.Factory. The buildProtocol + from twisted.internet.protocol.Factory. The buildProtocol method of the Factory is used to create a Protocol for each new connection.

      @@ -37,7 +37,7 @@ fact does not know anything about the network. See the endpoints documentation for more information, - or twisted.internet.interfaces.IReactorTCP.listenTCP, + or twisted.internet.interfaces.IReactorTCP.listenTCP, and the other IReactor*.listen* APIs for the lower level APIs that endpoints are based on.

      @@ -516,7 +516,7 @@
      Source listing - listings/servers/chat.py

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

      @@ -543,6 +543,6 @@

      Index

      - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/ssl.html twisted-12.1.0/doc/howto/ssl.html --- twisted-11.1.0/doc/howto/ssl.html 2011-11-17 10:51:08.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: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/tap.html twisted-12.1.0/doc/howto/tap.html --- twisted-11.1.0/doc/howto/tap.html 2011-11-17 10:51:08.000000000 +0000 +++ twisted-12.1.0/doc/howto/tap.html 2012-06-04 08:46:20.000000000 +0000 @@ -21,7 +21,7 @@

      There are a few prerequisites to understanding this document:

      • A basic understanding of the Twisted Plugin System (i.e., - the twisted.plugin module) is + the twisted.plugin module) is necessary, however, step-by-step instructions will be given. Reading The Twisted Plugin System is recommended, in particular the Extending an @@ -81,15 +81,15 @@

        In this file, define an object which provides the interfaces - twisted.plugin.IPlugin - and twisted.application.service.IServiceMaker. + twisted.plugin.IPlugin + and twisted.application.service.IServiceMaker.

        The tapname attribute of your IServiceMaker provider will be used as the subcommand name in a command like twistd [subcommand] [args...], and the options attribute (which should be -a usage.Options +a usage.Options subclass) will be used to parse the given args.

        1 @@ -181,7 +181,7 @@ If you are building a twistd plugin and you want to support a wide variety of authentication patterns, Twisted provides an easy-to-use mixin for your Options subclass: - strcred.AuthOptionMixin. + strcred.AuthOptionMixin. The following code is an example of using this mixin:

        @@ -296,7 +296,7 @@

        - For a full list of cred plugins supported, see twisted.plugins, or use the command-line help: + For a full list of cred plugins supported, see twisted.plugins, or use the command-line help:

        @@ -318,6 +318,6 @@
         
         
             

        Index

        - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/telnet.html twisted-12.1.0/doc/howto/telnet.html --- twisted-11.1.0/doc/howto/telnet.html 2011-11-17 10:51:10.000000000 +0000 +++ twisted-12.1.0/doc/howto/telnet.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,92 +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 the following command at your shell prompt:

          - -
          -$ twistd telnet -p 4040 -u admin -w admin
          -
          - -

          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 run:

          - -
          -$ 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: 11.1.0 - - \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/testing.html twisted-12.1.0/doc/howto/testing.html --- twisted-11.1.0/doc/howto/testing.html 2011-11-17 10:51:07.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 @@ -73,7 +73,7 @@ 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 + 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 @@ -86,21 +86,21 @@ 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, @@ -130,7 +130,7 @@ 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.flushWarnings +

          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 @@ -162,6 +162,6 @@

          Index

          - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/threading.html twisted-12.1.0/doc/howto/threading.html --- twisted-11.1.0/doc/howto/threading.html 2011-11-17 10:51:08.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: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/time.html twisted-12.1.0/doc/howto/time.html --- twisted-11.1.0/doc/howto/time.html 2011-11-17 10:51:07.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: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/trial.html twisted-12.1.0/doc/howto/trial.html --- twisted-11.1.0/doc/howto/trial.html 2011-11-17 10:51:07.000000000 +0000 +++ twisted-12.1.0/doc/howto/trial.html 2012-06-04 08:46:19.000000000 +0000 @@ -6,7 +6,7 @@

          Test-driven development with Twisted

          - +
          @@ -22,8 +22,8 @@ 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 +the unittest -- +Unit testing framework chapter of the Python Library Reference. There is also a ton of information available online and in books.

          @@ -652,7 +652,7 @@ try: return map(int, args) except ValueError: - raise TypeError("Coudln't coerce arguments to integers: %s" % args) + raise TypeError("Couldn't coerce arguments to integers: %s" % args) def add(self, a, b): a, b = self._make_ints(a, b) @@ -685,7 +685,7 @@

          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 + 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, @@ -786,11 +786,9 @@ 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 -StringTransport class (note that test packages are generally not part of -Twisted's public API; proto_helpers is an exception). This 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.

          @@ -916,7 +914,7 @@ main()
          -

          As mentioned, this server creates a protocol that inherits from basic.LineReceiver, and then a +

          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.

          @@ -1120,11 +1118,11 @@
          -

          More good pratices

          +

          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.

          +

          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...). @@ -2039,6 +2037,6 @@

          Index

          - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/tutorial/backends.html twisted-12.1.0/doc/howto/tutorial/backends.html --- twisted-11.1.0/doc/howto/tutorial/backends.html 2011-11-17 10:51:11.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/backends.html 2012-06-04 08:46:22.000000000 +0000 @@ -1343,6 +1343,6 @@

          Index

          - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/tutorial/client.html twisted-12.1.0/doc/howto/tutorial/client.html --- twisted-11.1.0/doc/howto/tutorial/client.html 2011-11-17 10:51:11.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: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/tutorial/components.html twisted-12.1.0/doc/howto/tutorial/components.html --- twisted-11.1.0/doc/howto/tutorial/components.html 2011-11-17 10:51:10.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/components.html 2012-06-04 08:46:21.000000000 +0000 @@ -1127,6 +1127,6 @@

          Index

          - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/tutorial/configuration.html twisted-12.1.0/doc/howto/tutorial/configuration.html --- twisted-11.1.0/doc/howto/tutorial/configuration.html 2011-11-17 10:51:10.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/configuration.html 2012-06-04 08:46:21.000000000 +0000 @@ -823,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.

          @@ -865,6 +865,6 @@

          Index

          - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/tutorial/factory.html twisted-12.1.0/doc/howto/tutorial/factory.html --- twisted-11.1.0/doc/howto/tutorial/factory.html 2011-11-17 10:51:10.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/factory.html 2012-06-04 08:46:21.000000000 +0000 @@ -708,6 +708,6 @@

          Index

          - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/tutorial/index.html twisted-12.1.0/doc/howto/tutorial/index.html --- twisted-11.1.0/doc/howto/tutorial/index.html 2011-11-17 10:51:11.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: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/tutorial/intro.html twisted-12.1.0/doc/howto/tutorial/intro.html --- twisted-11.1.0/doc/howto/tutorial/intro.html 2011-11-17 10:51:11.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: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/tutorial/library.html twisted-12.1.0/doc/howto/tutorial/library.html --- twisted-11.1.0/doc/howto/tutorial/library.html 2011-11-17 10:51:11.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: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/tutorial/pb.html twisted-12.1.0/doc/howto/tutorial/pb.html --- twisted-11.1.0/doc/howto/tutorial/pb.html 2011-11-17 10:51:10.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/pb.html 2012-06-04 08:46:22.000000000 +0000 @@ -723,6 +723,6 @@

          Index

          - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/tutorial/protocol.html twisted-12.1.0/doc/howto/tutorial/protocol.html --- twisted-11.1.0/doc/howto/tutorial/protocol.html 2011-11-17 10:51:10.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

          @@ -453,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 @@ -1116,6 +1116,6 @@

          Index

          - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/tutorial/style.html twisted-12.1.0/doc/howto/tutorial/style.html --- twisted-11.1.0/doc/howto/tutorial/style.html 2011-11-17 10:51:10.000000000 +0000 +++ twisted-12.1.0/doc/howto/tutorial/style.html 2012-06-04 08:46:22.000000000 +0000 @@ -328,6 +328,6 @@

          Index

          - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/tutorial/web.html twisted-12.1.0/doc/howto/tutorial/web.html --- twisted-11.1.0/doc/howto/tutorial/web.html 2011-11-17 10:51:10.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 @@ -605,6 +605,6 @@

          Index

          - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/udp.html twisted-12.1.0/doc/howto/udp.html --- twisted-11.1.0/doc/howto/udp.html 2011-11-17 10:51:09.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

          @@ -166,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 @@ -195,43 +199,51 @@ 22 23 24 +25 +26 +27 +28

          from twisted.internet.protocol import DatagramProtocol from twisted.internet import reactor -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 @@ -246,42 +258,47 @@ 10 11 12 +13 +14 +15 +16 +17 +18 +19

          from twisted.internet.protocol import DatagramProtocol from twisted.internet import reactor -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 -port = reactor.listenUDP(0, MulticastClientUDP()) -port.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: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/upgrading.html twisted-12.1.0/doc/howto/upgrading.html --- twisted-11.1.0/doc/howto/upgrading.html 2011-11-17 10:51:09.000000000 +0000 +++ twisted-12.1.0/doc/howto/upgrading.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,330 +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 accommodate 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 compatibility, 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 compatibility 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 service.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: 11.1.0 - - \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/vision.html twisted-12.1.0/doc/howto/vision.html --- twisted-11.1.0/doc/howto/vision.html 2011-11-17 10:51:09.000000000 +0000 +++ twisted-12.1.0/doc/howto/vision.html 2012-06-04 08:46:21.000000000 +0000 @@ -38,6 +38,6 @@

          Index

          - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/howto/website-template.tpl twisted-12.1.0/doc/howto/website-template.tpl --- twisted-11.1.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/qJazRnmRZ1/twisted-11.1.0/doc/img/twisted-overview.dia and /tmp/NW8iPqmSSh/twisted-12.1.0/doc/img/twisted-overview.dia differ Binary files /tmp/qJazRnmRZ1/twisted-11.1.0/doc/img/twisted-overview.png and /tmp/NW8iPqmSSh/twisted-12.1.0/doc/img/twisted-overview.png differ diff -Nru twisted-11.1.0/doc/index.html twisted-12.1.0/doc/index.html --- twisted-11.1.0/doc/index.html 2011-11-17 10:51:07.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: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/man/manhole-man.html twisted-12.1.0/doc/man/manhole-man.html --- twisted-11.1.0/doc/man/manhole-man.html 2011-11-17 10:51:11.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: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/man/pyhtmlizer-man.html twisted-12.1.0/doc/man/pyhtmlizer-man.html --- twisted-11.1.0/doc/man/pyhtmlizer-man.html 2011-11-17 10:51:11.000000000 +0000 +++ twisted-12.1.0/doc/man/pyhtmlizer-man.html 2012-06-04 08:46:17.000000000 +0000 @@ -46,6 +46,6 @@

            Index

            - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/man/tap2deb-man.html twisted-12.1.0/doc/man/tap2deb-man.html --- twisted-11.1.0/doc/man/tap2deb-man.html 2011-11-17 10:51:11.000000000 +0000 +++ twisted-12.1.0/doc/man/tap2deb-man.html 2012-06-04 08:46:17.000000000 +0000 @@ -96,6 +96,6 @@

            Index

            - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/man/tap2rpm-man.html twisted-12.1.0/doc/man/tap2rpm-man.html --- twisted-11.1.0/doc/man/tap2rpm-man.html 2011-11-17 10:51:11.000000000 +0000 +++ twisted-12.1.0/doc/man/tap2rpm-man.html 2012-06-04 08:46:17.000000000 +0000 @@ -95,6 +95,6 @@

            Index

            - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/man/tapconvert.1 twisted-12.1.0/doc/man/tapconvert.1 --- twisted-11.1.0/doc/man/tapconvert.1 2008-10-28 20:12:14.000000000 +0000 +++ twisted-12.1.0/doc/man/tapconvert.1 2012-02-19 20:39:01.000000000 +0000 @@ -34,7 +34,7 @@ .SH "REPORTING BUGS" To report a bug, visit \fIhttp://twistedmatrix.com/bugs/\fR .SH COPYRIGHT -Copyright \(co 2000-2008 Twisted Matrix Laboratories. +Copyright \(co 2000-2012 Twisted Matrix Laboratories. .br This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff -Nru twisted-11.1.0/doc/man/tapconvert-man.html twisted-12.1.0/doc/man/tapconvert-man.html --- twisted-11.1.0/doc/man/tapconvert-man.html 2011-11-17 10:51:11.000000000 +0000 +++ twisted-12.1.0/doc/man/tapconvert-man.html 2012-06-04 08:46:17.000000000 +0000 @@ -69,7 +69,7 @@

            COPYRIGHT

            -

            Copyright © 2000-2008 Twisted Matrix Laboratories. +

            Copyright © 2000-2012 Twisted Matrix Laboratories. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

            @@ -77,6 +77,6 @@

            Index

            - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/man/trial-man.html twisted-12.1.0/doc/man/trial-man.html --- twisted-11.1.0/doc/man/trial-man.html 2011-11-17 10:51:11.000000000 +0000 +++ twisted-12.1.0/doc/man/trial-man.html 2012-06-04 08:46:17.000000000 +0000 @@ -270,6 +270,6 @@

            Index

            - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/man/twistd-man.html twisted-12.1.0/doc/man/twistd-man.html --- twisted-11.1.0/doc/man/twistd-man.html 2011-11-17 10:51:11.000000000 +0000 +++ twisted-12.1.0/doc/man/twistd-man.html 2012-06-04 08:46:17.000000000 +0000 @@ -182,6 +182,6 @@

            Index

            - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/specifications/banana.html twisted-12.1.0/doc/specifications/banana.html --- twisted-11.1.0/doc/specifications/banana.html 2011-11-17 10:51:11.000000000 +0000 +++ twisted-12.1.0/doc/specifications/banana.html 2012-06-04 08:46:18.000000000 +0000 @@ -194,6 +194,6 @@

            Index

            - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/specifications/index.html twisted-12.1.0/doc/specifications/index.html --- twisted-11.1.0/doc/specifications/index.html 2011-11-17 10:51:11.000000000 +0000 +++ twisted-12.1.0/doc/specifications/index.html 2012-06-04 08:46:18.000000000 +0000 @@ -16,6 +16,6 @@

            Index

            - Version: 11.1.0 + Version: 12.1.0 \ No newline at end of file diff -Nru twisted-11.1.0/doc/upgrades/2.0/components.html twisted-12.1.0/doc/upgrades/2.0/components.html --- twisted-11.1.0/doc/upgrades/2.0/components.html 2011-11-17 10:51:11.000000000 +0000 +++ twisted-12.1.0/doc/upgrades/2.0/components.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,115 +0,0 @@ - - -Twisted Documentation: The Twisted Zope Interfaces FAQ - - - - -

            The Twisted Zope Interfaces FAQ

            - -
            - - - -

            Twisted components system in 2.0

            - -

            Twisted code's own use of the twisted.python.components package has been updated to use Zope Interfaces in -the 2.0 release.

            - -

            New code developed starting with the 2.0 release of Twisted Core should use Zope -Interfaces directly rather than using the twisted.python.components -package.

            - -

            FAQ

            - -

            Why did Twisted switch to Zope Interfaces?

            - -

            -The twisted.python.components package is a large amount of on-going -maintenance. Using the Zope Interface package also provides a greater level of -compatibility between Twisted interfaces and Zope interfaces. -

            - -

            Why did Twisted switch to Zope Interfaces rather than PyProtocols?

            - -

            -The Zope Interface package was chosen over PyProtocols because of its greater -conceptual similarity to twisted.python.components. -

            - -

            Will this affect my deployment?

            - -

            -No. Releases of Twisted Core will include Zope Interfaces. -

            - -

            How can I update my own code?

            - -

            -Classes written using twisted.python.components declare which interfaces they -implement in this style: -

            - - -class C: - __implements__ = IFoo, - - -

            -This should be changed to: -

            - - -class C: - zope.interface.implements(IFoo) - - -

            - -What about third party classes dependant on the old style of implements -declarations? - -

            - -

            -Use backwardsCompatImplements to fix this. -

            - - -twisted.python.components.backwardsCompatImplements(C) - - -

            What about using third party classes?

            - -

            -If you are using third party libraries that only declare __implements__, these -objects should be made compatible with fixClassImplements:

            - - -# import o where o is some third party library -from thirdparty.lib import o - -twisted.python.components.fixClassImplements(o.__class__) - - -

            -This will make sure that __implements__ declarations get converted to the new -style of implements declarations. -

            - -

            Acknowledgements

            - -

            This document is the work of Jason A. Mobarak, with contributions from Mary -Gardiner.

            - -
            - -

            Index

            - Version: 11.1.0 - - \ No newline at end of file diff -Nru twisted-11.1.0/doc/upgrades/2.0/index.html twisted-12.1.0/doc/upgrades/2.0/index.html --- twisted-11.1.0/doc/upgrades/2.0/index.html 2011-11-17 10:51:11.000000000 +0000 +++ twisted-12.1.0/doc/upgrades/2.0/index.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ - - -Twisted Documentation: Upgrading to Twisted 2.0 - - - - -

            Upgrading to Twisted 2.0

            -
              -
              - - - -
              - -

              Index

              - Version: 11.1.0 - - \ No newline at end of file diff -Nru twisted-11.1.0/doc/upgrades/2.0/split.html twisted-12.1.0/doc/upgrades/2.0/split.html --- twisted-11.1.0/doc/upgrades/2.0/split.html 2011-11-17 10:51:11.000000000 +0000 +++ twisted-12.1.0/doc/upgrades/2.0/split.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,163 +0,0 @@ - - -Twisted Documentation: The Twisted Split FAQ - - - - -

              The Twisted Split FAQ

              - -
              - - - -

              What is the Twisted Split?

              - -

              -Twisted is very large. At last -count, it has around 80 thousand lines of code (yes, that is very -large for a Python project, maybe not so for a C++ project. ;). We broke it -into several smaller packages with the 2.0 release. -

              - -

              Why was Twisted being split?

              - -

              -The biggest reason was to make our release process more -agile. A regression in twisted.names, for example, could hold up the release -of the entire thing, when really it should only be holding up the release of -twisted.names. -

              - -

              -The other big reason is visibility. Twisted has a ton of -functionality, but many people miss out on it because they don't know -where it is hidden inside Twisted. The Twisted split gave every -sub-project its own web site and thus more visibility. -

              - -

              But I liked the monolithic packages. Can I still get them?

              - -

              -Yes. Tarball and Windows releases for Twisted and all of its -sub-projects will still be maintained. We encourage maintainers of -packages for OSes with automatic packaging systems to break up the -packages as well, so, for example, Debian will have -python2.3-twisted-core, python2.3-twisted-conch, -python2.3-twisted-names, and so on. -

              - -

              Where can I find information about the individual projects?

              - -

              -A list of Twisted -projects is available on the website. The list includes maintainer -information and links to project-specific pages with more detailed -information. -

              - -

              What are the new packages?

              - -

              -

                - -
              • Twisted - Core - This contains twisted.application, twisted.cred, - twisted.enterprise, twisted.internet, twisted.manhole, - twisted.persisted, twisted.protocols[1], twisted.python, twisted.spread, - twisted.trial
              • - -
              • Twisted - Conch - This contains twisted.conch.
              • - -
              • Twisted - Lore - This contains twisted.lore
              • - -
              • Twisted - Mail - This contains twisted.mail; NOTE the mail protocols - that were in twisted.protocols.(imap4,pop3,smtp) were moved to - twisted.mail.
              • - -
              • Twisted - Names - This contains twisted.names; NOTE - twisted.protocols.dns was moved to twisted.names.dns.
              • - -
              • Twisted - News - This contains twisted.news; NOTE - twisted.protocols.nntp was moved to twisted.news.nntp
              • - -
              • Twisted - Pair - This contains twisted.pair; NOTE ethernet, ip, raw, - and rawudp protocol support was moved from twisted.protocols to - twisted.pair. (deprecated)
              • - -
              • Twisted - Runner - This contains twisted.runner.
              • - -
              • Twisted - Web - This contains twisted.web; NOTE that - twisted.protocols.http was moved to twisted.web.http.
              • - -
              • Twisted - Words - This contains twisted.words; NOTE that twisted.im was - moved to twisted.words.im, twisted.xish was moved to - twisted.words.xish, AND the chat protocols (irc, msn, jabber, toc, - oscar) were moved to twisted.words.protocols.
              • -
              -

              - -

              [1]: twisted.protocols is very stripped -down now; it only includes the protocols that didn't belong anywhere -else. It still contains the simple protocols, the helper utilities, -and, ahem, FTP.

              - - -

              Will I have to rewrite my code? What API changes are there?

              - -

              -No existing code should break, however, many modules were -moved. Backwards compatibility support does exist in older versions of -Twisted, but was removed in Twisted 9.0.

              - -

              What about my deployments? What will I have to do to have the new packages?

              - -

              -It depends on your OS and how you installed Twisted originally. If -you're using Debian, we are planning on breaking up the Debian -packages to e.g. python2.3-twisted-core, python2.3-twisted-web, and so -on. If you're using Windows, or generally install Twisted from the -tarball or from an SVN checkout, monolithic options will still be -available. -

              - -

              -If you try to run code that imports a sub-package when that -sub-package is not available on the system, an ImportError will be -raised directing the user to the web site for that particular -sub-project. -

              - -

              Why are all the packages still named twisted.subproject?

              - -

              -This is controversial. While this does mean that there is a -mashed-together namespace under twisted., it's also the -simplest thing to do, and means less breakage for user-code, so we did that. -

              - -

              What does this mean for existing Twisted developers?

              - -

              -Not much. The repository is rearranged a bit; protocols have been -moved to their relevant packages and documentation is now stored in -doc/subproject/ instead of everything at the top-level of -doc/. Everything is still in the same repository and everyone still -has the same access levels they used to. -

              - -
              - -

              Index

              - Version: 11.1.0 - - \ No newline at end of file diff -Nru twisted-11.1.0/doc/upgrades/index.html twisted-12.1.0/doc/upgrades/index.html --- twisted-11.1.0/doc/upgrades/index.html 2011-11-17 10:51:11.000000000 +0000 +++ twisted-12.1.0/doc/upgrades/index.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ - - -Twisted Documentation: Upgrading - - - - -

              Upgrading

              - - - -

              Index

              - Version: 11.1.0 - - \ No newline at end of file diff -Nru twisted-11.1.0/LICENSE twisted-12.1.0/LICENSE --- twisted-11.1.0/LICENSE 2011-05-05 02:48:02.000000000 +0000 +++ twisted-12.1.0/LICENSE 2012-02-11 13:47:35.000000000 +0000 @@ -1,4 +1,4 @@ -Copyright (c) 2001-2011 +Copyright (c) 2001-2012 Allen Short Andy Gayton Andrew Bennetts diff -Nru twisted-11.1.0/NEWS twisted-12.1.0/NEWS --- twisted-11.1.0/NEWS 2011-11-15 21:39:09.000000000 +0000 +++ twisted-12.1.0/NEWS 2012-06-04 08:41:07.000000000 +0000 @@ -1,6 +1,173 @@ Ticket numbers in this file can be looked up by visiting http://twistedmatrix.com/trac/ticket/ +Twisted Core 12.1.0 (2012-06-02) +================================ + +Features +-------- + - The kqueue reactor has been revived. (#1918) + - twisted.python.filepath now provides IFilePath, an interface for + file path objects. (#2176) + - New gtk3 and gobject-introspection reactors have been added. + (#4558) + - gtk and glib reactors now run I/O and scheduled events with lower + priority, to ensure the UI stays responsive. (#5067) + - IReactorTCP.connectTCP() can now accept IPv6 address literals + (although not hostnames) in order to support connecting to IPv6 + hosts. (#5085) + - twisted.internet.interfaces.IReactorSocket, a new interface, is now + supported by some reactors to listen on sockets set up by external + software (eg systemd or launchd). (#5248) + - twisted.internet.endpoints.clientFromString now also supports + strings in the form of tcp:example.com:80 and ssl:example.com:4321 + (#5358) + - twisted.python.constants.Flags now provides a way to define + collections of flags for bitvector-type uses. (#5384) + - The epoll(7)-based reactor is now the default reactor on Linux. + (#5478) + - twisted.python.runtime.platform.isLinux can be used to check if + Twisted is running on Linux. (#5491) + - twisted.internet.endpoints.serverFromString now recognizes a + "systemd" endpoint type, for listening on a server port inherited + from systemd. (#5575) + - Connections created using twisted.internet.interfaces.IReactorUNIX + now support sending and receiving file descriptors between + different processes. (#5615) + - twisted.internet.endpoints.clientFromString now supports UNIX + client endpoint strings with the path argument specified like + "unix:/foo/bar" in addition to the old style, "unix:path=/foo/bar". + (#5640) + - twisted.protocols.amp.Descriptor is a new AMP argument type which + supports passing file descriptors as AMP command arguments over + UNIX connections. (#5650) + +Bugfixes +-------- + - twisted.internet.abstract.FileDescriptor implements + twisted.internet.interfaces.IPushProducer instead of + twisted.internet.interfaces.IProducer. + twisted.internet.iocpreactor.abstract.FileHandle implements + twisted.internet.interfaces.IPushProducer instead of + twisted.internet.interfaces.IProducer. (#4386) + - The epoll reactor now supports reading/writing to regular files on + stdin/stdout. (#4429) + - Calling .cancel() on any Twisted-provided client endpoint + (TCP4ClientEndpoint, UNIXClientEndpoint, SSL4ClientEndpoint) now + works as documented, rather than logging an AlreadyCalledError. + (#4710) + - A leak of OVERLAPPED structures in some IOCP error cases has been + fixed. (#5372) + - twisted.internet._pollingfile._PollableWritePipe now checks for + outgoing unicode data in write() and writeSequence() instead of + checkWork(). (#5412) + +Improved Documentation +---------------------- + - "Working from Twisted's Subversion repository" links to UQDS and + Combinator are now updated. (#5545) + - Added tkinterdemo.py, an example of Tkinter integration. (#5631) + +Deprecations and Removals +------------------------- + - The 'unsigned' flag to twisted.scripts.tap2rpm.MyOptions is now + deprecated. (#4086) + - Removed the unreachable _fileUrandom method from + twisted.python.randbytes.RandomFactory. (#4530) + - twisted.persisted.journal is removed, deprecated since Twisted + 11.0. (#4805) + - Support for pyOpenSSL 0.9 and older is now deprecated. pyOpenSSL + 0.10 or newer will soon be required in order to use Twisted's SSL + features. (#4974) + - backwardsCompatImplements and fixClassImplements are removed from + twisted.python.components, deprecated in 2006. (#5034) + - twisted.python.reflect.macro was removed, deprecated since Twisted + 8.2. (#5035) + - twisted.python.text.docstringLStrip, deprecated since Twisted + 10.2.0, has been removed (#5036) + - Removed the deprecated dispatch and dispatchWithCallback methods + from twisted.python.threadpool.ThreadPool (deprecated since 8.0) + (#5037) + - twisted.scripts.tapconvert is now deprecated. (#5038) + - twisted.python.reflect's Settable, AccessorType, PropertyAccessor, + Accessor, OriginalAccessor and Summer are now deprecated. (#5451) + - twisted.python.threadpool.ThreadSafeList (deprecated in 10.1) is + removed. (#5473) + - twisted.application.app.initialLog, deprecated since Twisted 8.2.0, + has been removed. (#5480) + - twisted.spread.refpath was deleted, deprecated since Twisted 9.0. + (#5482) + - twisted.python.otp, deprecated since 9.0, is removed. (#5493) + - Removed `dsu`, `moduleMovedForSplit`, and `dict` from + twisted.python.util (deprecated since 10.2) (#5516) + +Other +----- + - #2723, #3114, #3398, #4388, #4489, #5055, #5116, #5242, #5380, + #5392, #5447, #5457, #5484, #5489, #5492, #5494, #5512, #5523, + #5558, #5572, #5583, #5593, #5620, #5621, #5623, #5625, #5637, + #5652, #5653, #5656, #5657, #5660, #5673 + + +Twisted Core 12.0.0 (2012-02-10) +================================ + +Features +-------- + - The interface argument to IReactorTCP.listenTCP may now be an IPv6 + address literal, allowing the creation of IPv6 TCP servers. (#5084) + - twisted.python.constants.Names now provides a way to define + collections of named constants, similar to the "enum type" feature + of C or Java. (#5382) + - twisted.python.constants.Values now provides a way to define + collections of named constants with arbitrary values. (#5383) + +Bugfixes +-------- + - Fixed an obscure case where connectionLost wasn't called on the + protocol when using half-close. (#3037) + - UDP ports handle socket errors better on Windows. (#3396) + - When idle, the gtk2 and glib2 reactors no longer wake up 10 times a + second. (#4376) + - Prevent a rare situation involving TLS transports, where a producer + may be erroneously left unpaused. (#5347) + - twisted.internet.iocpreactor.iocpsupport now has fewer 64-bit + compile warnings. (#5373) + - The GTK2 reactor is now more responsive on Windows. (#5396) + - TLS transports now correctly handle producer registration after the + connection has been lost. (#5439) + - twisted.protocols.htb.Bucket now empties properly with a non-zero + drip rate. (#5448) + - IReactorSSL and ITCPTransport.startTLS now synchronously propagate + errors from the getContext method of context factories, instead of + being capturing them and logging them as unhandled. (#5449) + +Improved Documentation +---------------------- + - The multicast documentation has been expanded. (#4262) + - twisted.internet.defer.Deferred now documents more return values. + (#5399) + - Show a better starting page at + http://twistedmatrix.com/documents/current (#5429) + +Deprecations and Removals +------------------------- + - Remove the deprecated module twisted.enterprise.reflector. (#4108) + - Removed the deprecated module twisted.enterprise.row. (#4109) + - Remove the deprecated module twisted.enterprise.sqlreflector. + (#4110) + - Removed the deprecated module twisted.enterprise.util, as well as + twisted.enterprise.adbapi.safe. (#4111) + - Python 2.4 is no longer supported on any platform. (#5060) + - Removed printTraceback and noOperation from twisted.spread.pb, + deprecated since Twisted 8.2. (#5370) + +Other +----- + - #1712, #2725, #5284, #5325, #5331, #5362, #5364, #5371, #5407, + #5427, #5430, #5431, #5440, #5441 + + Twisted Core 11.1.0 (2011-11-15) ================================ diff -Nru twisted-11.1.0/README twisted-12.1.0/README --- twisted-11.1.0/README 2011-11-15 16:39:18.000000000 +0000 +++ twisted-12.1.0/README 2012-06-02 07:04:01.000000000 +0000 @@ -1,4 +1,4 @@ -Twisted Core 11.1.0 +Twisted Core 12.1.0 =================== Twisted Core makes up the core parts of Twisted, including: diff -Nru twisted-11.1.0/setup.py twisted-12.1.0/setup.py --- twisted-11.1.0/setup.py 2011-09-26 16:28:23.000000000 +0000 +++ twisted-12.1.0/setup.py 2012-04-14 10:02:04.000000000 +0000 @@ -9,8 +9,8 @@ import os import sys -if sys.version_info < (2,3): - print >>sys.stderr, "You must use at least Python 2.3 for Twisted" +if sys.version_info < (2, 5): + print >>sys.stderr, "You must use at least Python 2.5 for Twisted" sys.exit(3) if os.path.exists('twisted'): @@ -28,7 +28,8 @@ Extension("twisted.python._epoll", ["twisted/python/_epoll.c"], - condition=lambda builder: _isCPython and _hasEpoll(builder)), + condition=lambda builder: (_isCPython and _hasEpoll(builder) and + sys.version_info[:2] < (2, 6))), Extension("twisted.internet.iocpreactor.iocpsupport", ["twisted/internet/iocpreactor/iocpsupport/iocpsupport.c", @@ -38,6 +39,9 @@ Extension("twisted.python._initgroups", ["twisted/python/_initgroups.c"]), + Extension("twisted.python.sendmsg", + sources=["twisted/python/sendmsg.c"], + condition=lambda _: sys.platform != "win32"), Extension("twisted.internet._sigchld", ["twisted/internet/_sigchld.c"], condition=lambda _: sys.platform != "win32"), diff -Nru twisted-11.1.0/twisted/application/app.py twisted-12.1.0/twisted/application/app.py --- twisted-11.1.0/twisted/application/app.py 2011-10-18 10:31:11.000000000 +0000 +++ twisted-12.1.0/twisted/application/app.py 2012-03-12 07:01:11.000000000 +0000 @@ -653,12 +653,6 @@ -def initialLog(): - AppLogger({})._initialLog() -initialLog = deprecated(Version("Twisted", 8, 2, 0))(initialLog) - - - def convertStyle(filein, typein, passphrase, fileout, typeout, encrypt): application = service.loadApplication(filein, typein, passphrase) sob.IPersistable(application).setStyle(typeout) diff -Nru twisted-11.1.0/twisted/application/strports.py twisted-12.1.0/twisted/application/strports.py --- twisted-11.1.0/twisted/application/strports.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/application/strports.py 2012-04-07 15:52:13.000000000 +0000 @@ -51,8 +51,8 @@ @type default: C{str} or C{None} - @param default: Do not use this parameter. It is deprecated since Twisted - 10.2.0. + @param default: Do not use this parameter. It has been deprecated since + Twisted 10.2.0. @rtype: C{twisted.application.service.IService} diff -Nru twisted-11.1.0/twisted/copyright.py twisted-12.1.0/twisted/copyright.py --- twisted-11.1.0/twisted/copyright.py 2011-04-03 18:50:17.000000000 +0000 +++ twisted-12.1.0/twisted/copyright.py 2012-02-11 13:47:35.000000000 +0000 @@ -10,7 +10,7 @@ longversion = str(longversion) copyright="""\ -Copyright (c) 2001-2011 Twisted Matrix Laboratories. +Copyright (c) 2001-2012 Twisted Matrix Laboratories. See LICENSE for details.""" disclaimer=''' diff -Nru twisted-11.1.0/twisted/enterprise/adbapi.py twisted-12.1.0/twisted/enterprise/adbapi.py --- twisted-11.1.0/twisted/enterprise/adbapi.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/enterprise/adbapi.py 2012-01-06 13:16:05.000000000 +0000 @@ -480,28 +480,4 @@ self.__init__(self.dbapiName, *self.connargs, **self.connkw) - -# Common deprecation decorator used for all deprecations. -_unreleasedVersion = Version("Twisted", 8, 0, 0) -_unreleasedDeprecation = deprecated(_unreleasedVersion) - - - -def _safe(text): - """ - Something really stupid that replaces quotes with escaped quotes. - """ - return text.replace("'", "''").replace("\\", "\\\\") - - - -def safe(text): - """ - Make a string safe to include in an SQL statement. - """ - return _safe(text) - -safe = _unreleasedDeprecation(safe) - - -__all__ = ['Transaction', 'ConnectionPool', 'safe'] +__all__ = ['Transaction', 'ConnectionPool'] diff -Nru twisted-11.1.0/twisted/enterprise/__init__.py twisted-12.1.0/twisted/enterprise/__init__.py --- twisted-11.1.0/twisted/enterprise/__init__.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/enterprise/__init__.py 2012-01-06 13:16:05.000000000 +0000 @@ -6,4 +6,4 @@ Twisted Enterprise: database support for Twisted services. """ -__all__ = ['adbapi', 'reflector', 'row', 'sqlreflector', 'util'] +__all__ = ['adbapi'] diff -Nru twisted-11.1.0/twisted/enterprise/reflector.py twisted-12.1.0/twisted/enterprise/reflector.py --- twisted-11.1.0/twisted/enterprise/reflector.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/enterprise/reflector.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,167 +0,0 @@ -# -*- test-case-name: twisted.test.test_reflector -*- -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - - -import weakref, warnings - -from twisted.enterprise.util import DBError - -class Reflector: - """ - DEPRECATED. - - Base class for enterprise reflectors. This implements row caching. - """ - populated = 0 - - def __init__(self, rowClasses): - """ - Initialize me against a database. - - @param rowClasses: a list of row class objects that describe the - database schema. - """ - warnings.warn("twisted.enterprise.reflector is deprecated since " - "Twisted 8.0", category=DeprecationWarning, stacklevel=2) - # does not hold references to cached rows. - self.rowCache = weakref.WeakValueDictionary() - self.rowClasses = rowClasses - self.schema = {} - self._populate() - - def __getstate__(self): - d = self.__dict__.copy() - del d['rowCache'] - return d - - def __setstate__(self, state): - self.__dict__ = state - self.rowCache = weakref.WeakValueDictionary() - self._populate() - - def _populate(self): - """Implement me to populate schema information for the reflector. - """ - raise DBError("not implemented") - - def populateSchemaFor(self, tableInfo): - """This is called once for each registered rowClass to add it - and its foreign key relationships for that rowClass to the - schema.""" - - self.schema[ tableInfo.rowTableName ] = tableInfo - - # add the foreign key to the foreign table. - for foreignTableName, childColumns, parentColumns, containerMethod, autoLoad in tableInfo.rowForeignKeys: - self.schema[foreignTableName].addForeignKey(childColumns, - parentColumns, tableInfo.rowClass, - containerMethod, autoLoad) - - def getTableInfo(self, rowObject): - """Get a TableInfo record about a particular instance. - - This record contains various information about the instance's - class as registered with this reflector. - - @param rowObject: a L{RowObject} instance of a class previously - registered with me. - @raises twisted.enterprise.row.DBError: raised if this class was not - previously registered. - """ - try: - return self.schema[rowObject.rowTableName] - except KeyError: - raise DBError("class %s was not registered with %s" % ( - rowObject.__class__, self)) - - def buildWhereClause(self, relationship, row): - """util method used by reflectors. builds a where clause to link a row to another table. - """ - whereClause = [] - for i in range(0,len(relationship.childColumns)): - value = getattr(row, relationship.parentColumns[i][0]) - whereClause.append( [relationship.childColumns[i][0], EQUAL, value] ) - return whereClause - - def addToParent(self, parentRow, rows, tableName): - """util method used by reflectors. adds these rows to the parent row object. - If a rowClass does not have a containerMethod, then a list attribute "childRows" - will be used. - """ - parentInfo = self.getTableInfo(parentRow) - relationship = parentInfo.getRelationshipFor(tableName) - if not relationship: - raise DBError("no relationship from %s to %s" % ( parentRow.rowTableName, tableName) ) - - if not relationship.containerMethod: - if hasattr(parentRow, "childRows"): - for row in rows: - if row not in parentRow.childRows: - parentRow.childRows.append(row) - else: - parentRow.childRows = rows - return - - if not hasattr(parentRow, relationship.containerMethod): - raise DBError("parent row (%s) doesnt have container method <%s>!" % (parentRow, relationship.containerMethod)) - - meth = getattr(parentRow, relationship.containerMethod) - for row in rows: - meth(row) - - ####### Row Cache ######## - - def addToCache(self, rowObject): - """NOTE: Should this be recursive?! requires better container knowledge...""" - self.rowCache[ rowObject.getKeyTuple() ] = rowObject - - def findInCache(self, rowClass, kw): - keys = [] - keys.append(rowClass.rowTableName) - for keyName, keyType in rowClass.rowKeyColumns: - keys.append( kw[keyName] ) - keyTuple = tuple(keys) - return self.rowCache.get(keyTuple) - - def removeFromCache(self, rowObject): - """NOTE: should this be recursive!??""" - key = rowObject.getKeyTuple() - if self.rowCache.has_key(key): - del self.rowCache[key] - - ####### Row Operations ######## - - def loadObjectsFrom(self, tableName, parent=None, data=None, - whereClause=[], loadChildren=1): - """Implement me to load objects from the database. - - @param whereClause: a list of tuples of (columnName, conditional, value) - so it can be parsed by all types of reflectors. eg.:: - whereClause = [("name", EQUALS, "fred"), ("age", GREATERTHAN, 18)] - """ - raise DBError("not implemented") - - def updateRow(self, rowObject): - """update this rowObject to the database. - """ - raise DBError("not implemented") - - def insertRow(self, rowObject): - """insert a new row for this object instance. - """ - raise DBError("not implemented") - - def deleteRow(self, rowObject): - """delete the row for this object from the database. - """ - raise DBError("not implemented") - -# conditionals -EQUAL = 0 -LESSTHAN = 1 -GREATERTHAN = 2 -LIKE = 3 - - -__all__ = ['Reflector', 'EQUAL', 'LESSTHAN', 'GREATERTHAN', 'LIKE'] diff -Nru twisted-11.1.0/twisted/enterprise/row.py twisted-12.1.0/twisted/enterprise/row.py --- twisted-11.1.0/twisted/enterprise/row.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/enterprise/row.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,127 +0,0 @@ -# -*- test-case-name: twisted.test.test_reflector -*- -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - - -""" -DEPRECATED. - -A (R)elational (O)bject (W)rapper. - -This is an extremely thin wrapper. - -Maintainer: Dave Peticolas -""" - -import warnings - -from twisted.enterprise.util import DBError, NOQUOTE, getKeyColumn, dbTypeMap - - -class RowObject: - """ - I represent a row in a table in a relational database. - - My class is "populated" by a Reflector object. After I am - populated, instances of me are able to interact with a particular - database table. - - You should use a class derived from this class for each database - table. - - reflector.loadObjectsFrom() is used to create sets of - instance of objects of this class from database tables. - - Once created, the "key column" attributes cannot be changed. - - - Class Attributes that users must supply:: - - rowKeyColumns # list of key columns in form: [(columnName, typeName)] - rowTableName # name of database table - rowColumns # list of the columns in the table with the correct - # case.this will be used to create member variables. - rowFactoryMethod # method to create an instance of this class. - # HACK: must be in a list!!! [factoryMethod] (optional) - rowForeignKeys # keys to other tables (optional) - """ - - populated = 0 # set on the class when the class is "populated" with SQL - dirty = 0 # set on an instance when the instance is out-of-sync with the database - - def __init__(self): - """ - DEPRECATED. - """ - warnings.warn("twisted.enterprise.row is deprecated since Twisted 8.0", - category=DeprecationWarning, stacklevel=2) - - def assignKeyAttr(self, attrName, value): - """Assign to a key attribute. - - This cannot be done through normal means to protect changing - keys of db objects. - """ - found = 0 - for keyColumn, type in self.rowKeyColumns: - if keyColumn == attrName: - found = 1 - if not found: - raise DBError("%s is not a key columns." % attrName) - self.__dict__[attrName] = value - - def findAttribute(self, attrName): - """Find an attribute by caseless name. - """ - for attr, type in self.rowColumns: - if attr.lower() == attrName.lower(): - return getattr(self, attr) - raise DBError("Unable to find attribute %s" % attrName) - - def __setattr__(self, name, value): - """Special setattr to prevent changing of key values. - """ - # build where clause - if getKeyColumn(self.__class__, name): - raise DBError("cannot assign value <%s> to key column attribute <%s> of RowObject class" % (value,name)) - - if name in self.rowColumns: - if value != self.__dict__.get(name,None) and not self.dirty: - self.setDirty(1) - - self.__dict__[name] = value - - def createDefaultAttributes(self): - """Populate instance with default attributes. - - This is used when creating a new instance NOT from the - database. - """ - for attr in self.rowColumns: - if getKeyColumn(self.__class__, attr): - continue - for column, ctype, typeid in self.dbColumns: - if column.lower(column) == attr.lower(): - q = dbTypeMap.get(ctype, None) - if q == NOQUOTE: - setattr(self, attr, 0) - else: - setattr(self, attr, "") - - def setDirty(self, flag): - """Use this to set the 'dirty' flag. - - (note: this avoids infinite recursion in __setattr__, and - prevents the 'dirty' flag ) - """ - self.__dict__["dirty"] = flag - - def getKeyTuple(self): - keys = [] - keys.append(self.rowTableName) - for keyName, keyType in self.rowKeyColumns: - keys.append( getattr(self, keyName) ) - return tuple(keys) - - -__all__ = ['RowObject'] diff -Nru twisted-11.1.0/twisted/enterprise/sqlreflector.py twisted-12.1.0/twisted/enterprise/sqlreflector.py --- twisted-11.1.0/twisted/enterprise/sqlreflector.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/enterprise/sqlreflector.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,327 +0,0 @@ -# -*- test-case-name: twisted.test.test_reflector -*- -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - - -from twisted.enterprise import reflector -from twisted.enterprise.util import DBError, getKeyColumn, quote, safe -from twisted.enterprise.util import _TableInfo -from twisted.enterprise.row import RowObject - -from twisted.python import reflect - -class SQLReflector(reflector.Reflector): - """ - DEPRECATED. - - I reflect on a database and load RowObjects from it. - - In order to do this, I interrogate a relational database to - extract schema information and interface with RowObject class - objects that can interact with specific tables. - """ - populated = 0 - conditionalLabels = { - reflector.EQUAL : "=", - reflector.LESSTHAN : "<", - reflector.GREATERTHAN : ">", - reflector.LIKE : "like" - } - - def __init__(self, dbpool, rowClasses): - """Initialize me against a database. - """ - reflector.Reflector.__init__(self, rowClasses) - self.dbpool = dbpool - - def _populate(self): - self._transPopulateSchema() - - def _transPopulateSchema(self): - """Used to construct the row classes in a single interaction. - """ - for rc in self.rowClasses: - if not issubclass(rc, RowObject): - raise DBError("Stub class (%s) is not derived from RowObject" % reflect.qual(rc.rowClass)) - - self._populateSchemaFor(rc) - self.populated = 1 - - def _populateSchemaFor(self, rc): - """Construct all the SQL templates for database operations on - and populate the class with that info. - """ - attributes = ("rowColumns", "rowKeyColumns", "rowTableName" ) - for att in attributes: - if not hasattr(rc, att): - raise DBError("RowClass %s must have class variable: %s" % (rc, att)) - - tableInfo = _TableInfo(rc) - tableInfo.updateSQL = self.buildUpdateSQL(tableInfo) - tableInfo.insertSQL = self.buildInsertSQL(tableInfo) - tableInfo.deleteSQL = self.buildDeleteSQL(tableInfo) - self.populateSchemaFor(tableInfo) - - def escape_string(self, text): - """Escape a string for use in an SQL statement. The default - implementation escapes ' with '' and \ with \\. Redefine this - function in a subclass if your database server uses different - escaping rules. - """ - return safe(text) - - def quote_value(self, value, type): - """Format a value for use in an SQL statement. - - @param value: a value to format as data in SQL. - @param type: a key in util.dbTypeMap. - """ - return quote(value, type, string_escaper=self.escape_string) - - def loadObjectsFrom(self, tableName, parentRow=None, data=None, - whereClause=None, forceChildren=0): - """Load a set of RowObjects from a database. - - Create a set of python objects of from the contents - of a table populated with appropriate data members. - Example:: - - | class EmployeeRow(row.RowObject): - | pass - | - | def gotEmployees(employees): - | for emp in employees: - | emp.manager = "fred smith" - | manager.updateRow(emp) - | - | reflector.loadObjectsFrom("employee", - | data = userData, - | whereClause = [("manager" , EQUAL, "fred smith")] - | ).addCallback(gotEmployees) - - NOTE: the objects and all children should be loaded in a single transaction. - NOTE: can specify a parentRow _OR_ a whereClause. - - """ - if parentRow and whereClause: - raise DBError("Must specify one of parentRow _OR_ whereClause") - if parentRow: - info = self.getTableInfo(parentRow) - relationship = info.getRelationshipFor(tableName) - whereClause = self.buildWhereClause(relationship, parentRow) - elif whereClause: - pass - else: - whereClause = [] - return self.dbpool.runInteraction(self._rowLoader, tableName, - parentRow, data, whereClause, - forceChildren) - - def _rowLoader(self, transaction, tableName, parentRow, data, - whereClause, forceChildren): - """immediate loading of rowobjects from the table with the whereClause. - """ - tableInfo = self.schema[tableName] - # Build the SQL for the query - sql = "SELECT " - first = 1 - for column, type in tableInfo.rowColumns: - if first: - first = 0 - else: - sql = sql + "," - sql = sql + " %s" % column - sql = sql + " FROM %s " % (tableName) - if whereClause: - sql += " WHERE " - first = 1 - for wItem in whereClause: - if first: - first = 0 - else: - sql += " AND " - (columnName, cond, value) = wItem - t = self.findTypeFor(tableName, columnName) - quotedValue = self.quote_value(value, t) - sql += "%s %s %s" % (columnName, self.conditionalLabels[cond], - quotedValue) - - # execute the query - transaction.execute(sql) - rows = transaction.fetchall() - - # construct the row objects - results = [] - newRows = [] - for args in rows: - kw = {} - for i in range(0,len(args)): - ColumnName = tableInfo.rowColumns[i][0].lower() - for attr, type in tableInfo.rowClass.rowColumns: - if attr.lower() == ColumnName: - kw[attr] = args[i] - break - # find the row in the cache or add it - resultObject = self.findInCache(tableInfo.rowClass, kw) - if not resultObject: - meth = tableInfo.rowFactoryMethod[0] - resultObject = meth(tableInfo.rowClass, data, kw) - self.addToCache(resultObject) - newRows.append(resultObject) - results.append(resultObject) - - # add these rows to the parentRow if required - if parentRow: - self.addToParent(parentRow, newRows, tableName) - - # load children or each of these rows if required - for relationship in tableInfo.relationships: - if not forceChildren and not relationship.autoLoad: - continue - for row in results: - # build where clause - childWhereClause = self.buildWhereClause(relationship, row) - # load the children immediately, but do nothing with them - self._rowLoader(transaction, - relationship.childRowClass.rowTableName, - row, data, childWhereClause, forceChildren) - - return results - - def findTypeFor(self, tableName, columnName): - tableInfo = self.schema[tableName] - columnName = columnName.lower() - for column, type in tableInfo.rowColumns: - if column.lower() == columnName: - return type - - def buildUpdateSQL(self, tableInfo): - """(Internal) Build SQL template to update a RowObject. - - Returns: SQL that is used to contruct a rowObject class. - """ - sql = "UPDATE %s SET" % tableInfo.rowTableName - # build update attributes - first = 1 - for column, type in tableInfo.rowColumns: - if getKeyColumn(tableInfo.rowClass, column): - continue - if not first: - sql = sql + ", " - sql = sql + " %s = %s" % (column, "%s") - first = 0 - - # build where clause - first = 1 - sql = sql + " WHERE " - for keyColumn, type in tableInfo.rowKeyColumns: - if not first: - sql = sql + " AND " - sql = sql + " %s = %s " % (keyColumn, "%s") - first = 0 - return sql - - def buildInsertSQL(self, tableInfo): - """(Internal) Build SQL template to insert a new row. - - Returns: SQL that is used to insert a new row for a rowObject - instance not created from the database. - """ - sql = "INSERT INTO %s (" % tableInfo.rowTableName - # build column list - first = 1 - for column, type in tableInfo.rowColumns: - if not first: - sql = sql + ", " - sql = sql + column - first = 0 - - sql = sql + " ) VALUES (" - - # build values list - first = 1 - for column, type in tableInfo.rowColumns: - if not first: - sql = sql + ", " - sql = sql + "%s" - first = 0 - - sql = sql + ")" - return sql - - def buildDeleteSQL(self, tableInfo): - """Build the SQL template to delete a row from the table. - """ - sql = "DELETE FROM %s " % tableInfo.rowTableName - # build where clause - first = 1 - sql = sql + " WHERE " - for keyColumn, type in tableInfo.rowKeyColumns: - if not first: - sql = sql + " AND " - sql = sql + " %s = %s " % (keyColumn, "%s") - first = 0 - return sql - - def updateRowSQL(self, rowObject): - """Build SQL to update the contents of rowObject. - """ - args = [] - tableInfo = self.schema[rowObject.rowTableName] - # build update attributes - for column, type in tableInfo.rowColumns: - if not getKeyColumn(rowObject.__class__, column): - args.append(self.quote_value(rowObject.findAttribute(column), - type)) - # build where clause - for keyColumn, type in tableInfo.rowKeyColumns: - args.append(self.quote_value(rowObject.findAttribute(keyColumn), - type)) - - return self.getTableInfo(rowObject).updateSQL % tuple(args) - - def updateRow(self, rowObject): - """Update the contents of rowObject to the database. - """ - sql = self.updateRowSQL(rowObject) - rowObject.setDirty(0) - return self.dbpool.runOperation(sql) - - def insertRowSQL(self, rowObject): - """Build SQL to insert the contents of rowObject. - """ - args = [] - tableInfo = self.schema[rowObject.rowTableName] - # build values - for column, type in tableInfo.rowColumns: - args.append(self.quote_value(rowObject.findAttribute(column),type)) - return self.getTableInfo(rowObject).insertSQL % tuple(args) - - def insertRow(self, rowObject): - """Insert a new row for rowObject. - """ - rowObject.setDirty(0) - sql = self.insertRowSQL(rowObject) - return self.dbpool.runOperation(sql) - - def deleteRowSQL(self, rowObject): - """Build SQL to delete rowObject from the database. - """ - args = [] - tableInfo = self.schema[rowObject.rowTableName] - # build where clause - for keyColumn, type in tableInfo.rowKeyColumns: - args.append(self.quote_value(rowObject.findAttribute(keyColumn), - type)) - - return self.getTableInfo(rowObject).deleteSQL % tuple(args) - - def deleteRow(self, rowObject): - """Delete the row for rowObject from the database. - """ - sql = self.deleteRowSQL(rowObject) - self.removeFromCache(rowObject) - return self.dbpool.runOperation(sql) - - -__all__ = ['SQLReflector'] diff -Nru twisted-11.1.0/twisted/enterprise/util.py twisted-12.1.0/twisted/enterprise/util.py --- twisted-11.1.0/twisted/enterprise/util.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/enterprise/util.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,200 +0,0 @@ -# -*- test-case-name: twisted.test.test_enterprise -*- -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - - -import warnings, types - -from twisted.python.versions import Version, getVersionString -from twisted.python.deprecate import deprecated -from twisted.enterprise.adbapi import _safe - -# Common deprecation decorator used for all deprecations. -_deprecatedVersion = Version("Twisted", 8, 0, 0) -_releasedDeprecation = deprecated(_deprecatedVersion) - -warnings.warn( - "twisted.enterprise.util is deprecated since %s." % ( - getVersionString(_deprecatedVersion),), - category=DeprecationWarning) - -NOQUOTE = 1 -USEQUOTE = 2 - -dbTypeMap = { - "bigint": NOQUOTE, - "bool": USEQUOTE, - "boolean": USEQUOTE, - "bytea": USEQUOTE, - "date": USEQUOTE, - "int2": NOQUOTE, - "int4": NOQUOTE, - "int8": NOQUOTE, - "int": NOQUOTE, - "integer": NOQUOTE, - "float4": NOQUOTE, - "float8": NOQUOTE, - "numeric": NOQUOTE, - "real": NOQUOTE, - "smallint": NOQUOTE, - "char": USEQUOTE, - "text": USEQUOTE, - "time": USEQUOTE, - "timestamp": USEQUOTE, - "varchar": USEQUOTE - } - -class DBError(Exception): - pass - - - -### Utility functions - -def getKeyColumn(rowClass, name): - lcname = name.lower() - for keyColumn, type in rowClass.rowKeyColumns: - if lcname == keyColumn.lower(): - return name - return None -getKeyColumn = _releasedDeprecation(getKeyColumn) - - - -def quote(value, typeCode, string_escaper=_safe): - """Add quotes for text types and no quotes for integer types. - NOTE: uses Postgresql type codes. - """ - q = dbTypeMap.get(typeCode, None) - if q is None: - raise DBError("Type %s not known" % typeCode) - if value is None: - return 'null' - if q == NOQUOTE: - return str(value) - elif q == USEQUOTE: - if typeCode.startswith('bool'): - if value: - value = '1' - else: - value = '0' - if typeCode == "bytea": - l = ["'"] - for c in value: - i = ord(c) - if i == 0: - l.append("\\\\000") - elif i == 92: - l.append(c * 4) - elif 32 <= i <= 126: - l.append(c) - else: - l.append("\\%03o" % i) - l.append("'") - return "".join(l) - if not isinstance(value, types.StringType) and \ - not isinstance(value, types.UnicodeType): - value = str(value) - return "'%s'" % string_escaper(value) -quote = _releasedDeprecation(quote) - - -def safe(text): - """ - Make a string safe to include in an SQL statement. - """ - return _safe(text) - -safe = _releasedDeprecation(safe) - - -def makeKW(rowClass, args): - """Utility method to construct a dictionary for the attributes - of an object from set of args. This also fixes the case of column names. - """ - kw = {} - for i in range(0,len(args)): - columnName = rowClass.dbColumns[i][0].lower() - for attr in rowClass.rowColumns: - if attr.lower() == columnName: - kw[attr] = args[i] - break - return kw -makeKW = _releasedDeprecation(makeKW) - - -def defaultFactoryMethod(rowClass, data, kw): - """Used by loadObjects to create rowObject instances. - """ - newObject = rowClass() - newObject.__dict__.update(kw) - return newObject -defaultFactoryMethod = _releasedDeprecation(defaultFactoryMethod) - -### utility classes - -class _TableInfo: - """(internal) - - Info about a table/class and it's relationships. Also serves as a container for - generated SQL. - """ - def __init__(self, rc): - self.rowClass = rc - self.rowTableName = rc.rowTableName - self.rowKeyColumns = rc.rowKeyColumns - self.rowColumns = rc.rowColumns - - if hasattr(rc, "rowForeignKeys"): - self.rowForeignKeys = rc.rowForeignKeys - else: - self.rowForeignKeys = [] - - if hasattr(rc, "rowFactoryMethod"): - if rc.rowFactoryMethod: - self.rowFactoryMethod = rc.rowFactoryMethod - else: - self.rowFactoryMethod = [defaultFactoryMethod] - else: - self.rowFactoryMethod = [defaultFactoryMethod] - - self.updateSQL = None - self.deleteSQL = None - self.insertSQL = None - self.relationships = [] - self.dbColumns = [] - - def addForeignKey(self, childColumns, parentColumns, childRowClass, containerMethod, autoLoad): - """This information is attached to the "parent" table - childColumns - columns of the "child" table - parentColumns - columns of the "parent" table, the one being joined to... the "foreign" table - """ - self.relationships.append( _TableRelationship(childColumns, parentColumns, - childRowClass, containerMethod, autoLoad) ) - - def getRelationshipFor(self, tableName): - for relationship in self.relationships: - if relationship.childRowClass.rowTableName == tableName: - return relationship - return None - -class _TableRelationship: - """(Internal) - - A foreign key relationship between two tables. - """ - def __init__(self, - childColumns, - parentColumns, - childRowClass, - containerMethod, - autoLoad): - self.childColumns = childColumns - self.parentColumns = parentColumns - self.childRowClass = childRowClass - self.containerMethod = containerMethod - self.autoLoad = autoLoad - - -__all__ = ['NOQUOTE', 'USEQUOTE', 'dbTypeMap', 'DBError', 'getKeyColumn', - 'safe', 'quote'] diff -Nru twisted-11.1.0/twisted/__init__.py twisted-12.1.0/twisted/__init__.py --- twisted-11.1.0/twisted/__init__.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/__init__.py 2011-11-20 15:19:42.000000000 +0000 @@ -10,8 +10,8 @@ # Ensure the user is running the version of python we require. import sys -if not hasattr(sys, "version_info") or sys.version_info < (2, 4): - raise RuntimeError("Twisted requires Python 2.4 or later.") +if not hasattr(sys, "version_info") or sys.version_info < (2, 5): + raise RuntimeError("Twisted requires Python 2.5 or later.") del sys # Ensure compat gets imported diff -Nru twisted-11.1.0/twisted/internet/abstract.py twisted-12.1.0/twisted/internet/abstract.py --- twisted-11.1.0/twisted/internet/abstract.py 2011-10-28 15:35:02.000000000 +0000 +++ twisted-12.1.0/twisted/internet/abstract.py 2012-04-26 13:46:20.000000000 +0000 @@ -7,6 +7,8 @@ Support for generic select()able objects. """ +from socket import AF_INET6, inet_pton, error + from zope.interface import implements # Twisted Imports @@ -153,7 +155,7 @@ SEND_LIMIT = 128*1024 - implements(interfaces.IProducer, interfaces.IReadWriteDescriptor, + implements(interfaces.IPushProducer, interfaces.IReadWriteDescriptor, interfaces.IConsumer, interfaces.ITransport, interfaces.IHalfCloseableDescriptor) def __init__(self, reactor=None): @@ -232,7 +234,7 @@ l = self.writeSomeData(self.dataBuffer) # There is no writeSomeData implementation in Twisted which returns - # 0, but the documentation for writeSomeData used to claim negative + # < 0, but the documentation for writeSomeData used to claim negative # integers meant connection lost. Keep supporting this here, # although it may be worth deprecating and removing at some point. if l < 0 or isinstance(l, Exception): @@ -259,9 +261,12 @@ # so. return self._postLoseConnection() elif self._writeDisconnecting: - # I was previously asked to to half-close the connection. - result = self._closeWriteConnection() + # I was previously asked to half-close the connection. We + # set _writeDisconnected before calling handler, in case the + # handler calls loseConnection(), which will want to check for + # this attribute. self._writeDisconnected = True + result = self._closeWriteConnection() return result return result @@ -285,6 +290,34 @@ # override in subclasses self.connectionLost(reason) + + def _isSendBufferFull(self): + """ + Determine whether the user-space send buffer for this transport is full + or not. + + When the buffer contains more than C{self.bufferSize} bytes, it is + considered full. This might be improved by considering the size of the + kernel send buffer and how much of it is free. + + @return: C{True} if it is full, C{False} otherwise. + """ + return len(self.dataBuffer) + self._tempDataLen > self.bufferSize + + + def _maybePauseProducer(self): + """ + Possibly pause a producer, if there is one and the send buffer is full. + """ + # If we are responsible for pausing our producer, + if self.producer is not None and self.streamingProducer: + # and our buffer is full, + if self._isSendBufferFull(): + # pause it. + self.producerPaused = 1 + self.producer.pauseProducing() + + def write(self, data): """Reliably write some data. @@ -300,17 +333,13 @@ if data: self._tempDataBuffer.append(data) self._tempDataLen += len(data) - # If we are responsible for pausing our producer, - if self.producer is not None and self.streamingProducer: - # and our buffer is full, - if len(self.dataBuffer) + self._tempDataLen > self.bufferSize: - # pause it. - self.producerPaused = 1 - self.producer.pauseProducing() + self._maybePauseProducer() self.startWriting() + def writeSequence(self, iovec): - """Reliably write a sequence of data. + """ + Reliably write a sequence of data. Currently, this is a convenience method roughly equivalent to:: @@ -332,15 +361,10 @@ self._tempDataBuffer.extend(iovec) for i in iovec: self._tempDataLen += len(i) - # If we are responsible for pausing our producer, - if self.producer is not None and self.streamingProducer: - # and our buffer is full, - if len(self.dataBuffer) + self._tempDataLen > self.bufferSize: - # pause it. - self.producerPaused = 1 - self.producer.pauseProducing() + self._maybePauseProducer() self.startWriting() + def loseConnection(self, _connDone=failure.Failure(main.CONNECTION_DONE)): """Close the connection at the next available opportunity. @@ -465,4 +489,29 @@ return False -__all__ = ["FileDescriptor"] +def isIPv6Address(addr): + """ + Determine whether the given string represents an IPv6 address. + + @param addr: A string which may or may not be the hex + representation of an IPv6 address. + @type addr: C{str} + + @return: C{True} if C{addr} represents an IPv6 address, C{False} + otherwise. + @rtype: C{bool} + """ + if '%' in addr: + addr = addr.split('%', 1)[0] + if not addr: + return False + try: + # This might be a native implementation or the one from + # twisted.python.compat. + inet_pton(AF_INET6, addr) + except (ValueError, error): + return False + return True + + +__all__ = ["FileDescriptor", "isIPAddress", "isIPv6Address"] diff -Nru twisted-11.1.0/twisted/internet/address.py twisted-12.1.0/twisted/internet/address.py --- twisted-11.1.0/twisted/internet/address.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/internet/address.py 2012-04-24 21:19:37.000000000 +0000 @@ -13,31 +13,36 @@ from twisted.python import util -class IPv4Address(object, util.FancyEqMixin): +class _IPAddress(object, util.FancyEqMixin): """ - Object representing an IPv4 socket endpoint. + An L{_IPAddress} represents the address of an IP socket endpoint, providing + common behavior for IPv4 and IPv6. @ivar type: A string describing the type of transport, either 'TCP' or 'UDP'. - @ivar host: A string containing the dotted-quad IP address. + + @ivar host: A string containing the presentation format of the IP address; + for example, "127.0.0.1" or "::1". + @type host: C{str} + @ivar port: An integer representing the port number. + @type port: C{int} """ implements(IAddress) compareAttributes = ('type', 'host', 'port') - def __init__(self, type, host, port, _bwHack = None): + def __init__(self, type, host, port): assert type in ('TCP', 'UDP') self.type = type self.host = host self.port = port - if _bwHack is not None: - warnings.warn("twisted.internet.address.IPv4Address._bwHack is deprecated since Twisted 11.0", - DeprecationWarning, stacklevel=2) + def __repr__(self): - return 'IPv4Address(%s, %r, %d)' % (self.type, self.host, self.port) + return '%s(%s, %r, %d)' % ( + self.__class__.__name__, self.type, self.host, self.port) def __hash__(self): @@ -45,6 +50,35 @@ +class IPv4Address(_IPAddress): + """ + An L{IPv4Address} represents the address of an IPv4 socket endpoint. + + @ivar host: A string containing a dotted-quad IPv4 address; for example, + "127.0.0.1". + @type host: C{str} + """ + + def __init__(self, type, host, port, _bwHack=None): + _IPAddress.__init__(self, type, host, port) + if _bwHack is not None: + warnings.warn("twisted.internet.address.IPv4Address._bwHack " + "is deprecated since Twisted 11.0", + DeprecationWarning, stacklevel=2) + + + +class IPv6Address(_IPAddress): + """ + An L{IPv6Address} represents the address of an IPv6 socket endpoint. + + @ivar host: A string containing a colon-separated, hexadecimal formatted + IPv6 address; for example, "::1". + @type host: C{str} + """ + + + class UNIXAddress(object, util.FancyEqMixin): """ Object representing a UNIX socket endpoint. @@ -67,11 +101,11 @@ if getattr(os.path, 'samefile', None) is not None: def __eq__(self, other): """ - overriding L{util.FancyEqMixin} to ensure the os level samefile check - is done if the name attributes do not match. + overriding L{util.FancyEqMixin} to ensure the os level samefile + check is done if the name attributes do not match. """ res = super(UNIXAddress, self).__eq__(other) - if res == False: + if not res and self.name and other.name: try: return os.path.samefile(self.name, other.name) except OSError: @@ -84,6 +118,8 @@ def __hash__(self): + if self.name is None: + return hash((self.__class__, None)) try: s1 = os.stat(self.name) return hash((s1.st_ino, s1.st_dev)) diff -Nru twisted-11.1.0/twisted/internet/default.py twisted-12.1.0/twisted/internet/default.py --- twisted-11.1.0/twisted/internet/default.py 2011-05-05 02:48:02.000000000 +0000 +++ twisted-12.1.0/twisted/internet/default.py 2012-05-08 00:03:40.000000000 +0000 @@ -24,8 +24,7 @@ @return: A zero-argument callable which will install the selected reactor. """ - # Linux: Once is fixed - # epoll should be the default. + # Linux: epoll(7) is the fault, since it scales well. # # OS X: poll(2) is not exposed by Python because it doesn't # support all file descriptors (in particular, lack of PTY support @@ -34,15 +33,22 @@ # ), and also has same # restriction as poll(2) as far PTY support goes. # - # Windows: IOCP should eventually be default, but still has a few - # remaining bugs, - # e.g. . + # Windows: IOCP should eventually be default, but still has some serious + # bugs, e.g. . # - # We therefore choose poll(2) on non-OS X POSIX platforms, and - # select(2) everywhere else. - if platform.getType() == 'posix' and not platform.isMacOSX(): - from twisted.internet.pollreactor import install - else: + # We therefore choose epoll(7) on Linux, poll(2) on other non-OS X POSIX + # platforms, and select(2) everywhere else. + try: + if platform.isLinux(): + try: + from twisted.internet.epollreactor import install + except ImportError: + from twisted.internet.pollreactor import install + elif platform.getType() == 'posix' and not platform.isMacOSX(): + from twisted.internet.pollreactor import install + else: + from twisted.internet.selectreactor import install + except ImportError: from twisted.internet.selectreactor import install return install diff -Nru twisted-11.1.0/twisted/internet/defer.py twisted-12.1.0/twisted/internet/defer.py --- twisted-11.1.0/twisted/internet/defer.py 2011-10-04 19:09:00.000000000 +0000 +++ twisted-12.1.0/twisted/internet/defer.py 2011-12-04 00:55:24.000000000 +0000 @@ -276,6 +276,9 @@ Add a pair of callbacks (success and error) to this L{Deferred}. These will be executed when the 'master' callback is run. + + @return: C{self}. + @rtype: a L{Deferred} """ assert callable(callback) assert errback == None or callable(errback) @@ -341,6 +344,9 @@ being returned from a callback, it is possible to cause the call stack size limit to be exceeded by chaining many L{Deferred}s together with C{chainDeferred}. + + @return: C{self}. + @rtype: a L{Deferred} """ d._chainedTo = self return self.addCallbacks(d.callback, d.errback) diff -Nru twisted-11.1.0/twisted/internet/endpoints.py twisted-12.1.0/twisted/internet/endpoints.py --- twisted-11.1.0/twisted/internet/endpoints.py 2011-10-11 11:43:33.000000000 +0000 +++ twisted-12.1.0/twisted/internet/endpoints.py 2012-04-26 13:46:20.000000000 +0000 @@ -11,22 +11,25 @@ @since: 10.1 """ +import os, socket + from zope.interface import implements, directlyProvides import warnings -from twisted.internet import interfaces, defer, error +from twisted.internet import interfaces, defer, error, fdesc from twisted.internet.protocol import ClientFactory, Protocol -from twisted.plugin import getPlugins +from twisted.plugin import IPlugin, getPlugins from twisted.internet.interfaces import IStreamServerEndpointStringParser from twisted.internet.interfaces import IStreamClientEndpointStringParser from twisted.python.filepath import FilePath - +from twisted.python.systemd import ListenFDs __all__ = ["clientFromString", "serverFromString", "TCP4ServerEndpoint", "TCP4ClientEndpoint", "UNIXServerEndpoint", "UNIXClientEndpoint", - "SSL4ServerEndpoint", "SSL4ClientEndpoint"] + "SSL4ServerEndpoint", "SSL4ClientEndpoint", + "AdoptedStreamServerEndpoint"] class _WrappingProtocol(Protocol): @@ -52,9 +55,10 @@ self._connectedDeferred = connectedDeferred self._wrappedProtocol = wrappedProtocol - if interfaces.IHalfCloseableProtocol.providedBy( - self._wrappedProtocol): - directlyProvides(self, interfaces.IHalfCloseableProtocol) + for iface in [interfaces.IHalfCloseableProtocol, + interfaces.IFileDescriptorReceiver]: + if iface.providedBy(self._wrappedProtocol): + directlyProvides(self, iface) def logPrefix(self): @@ -82,6 +86,13 @@ return self._wrappedProtocol.dataReceived(data) + def fileDescriptorReceived(self, descriptor): + """ + Proxy C{fileDescriptorReceived} calls to our C{self._wrappedProtocol} + """ + return self._wrappedProtocol.fileDescriptorReceived(descriptor) + + def connectionLost(self, reason): """ Proxy C{connectionLost} calls to our C{self._wrappedProtocol} @@ -110,25 +121,58 @@ """ Wrap a factory in order to wrap the protocols it builds. - @ivar _wrappedFactory: A provider of I{IProtocolFactory} whose - buildProtocol method will be called and whose resulting protocol - will be wrapped. + @ivar _wrappedFactory: A provider of I{IProtocolFactory} whose buildProtocol + method will be called and whose resulting protocol will be wrapped. @ivar _onConnection: An L{Deferred} that fires when the protocol is connected + + @ivar _connector: A L{connector } + that is managing the current or previous connection attempt. """ protocol = _WrappingProtocol - def __init__(self, wrappedFactory, canceller): + def __init__(self, wrappedFactory): """ @param wrappedFactory: A provider of I{IProtocolFactory} whose buildProtocol method will be called and whose resulting protocol will be wrapped. - @param canceller: An object that will be called to cancel the - L{self._onConnection} L{Deferred} """ self._wrappedFactory = wrappedFactory - self._onConnection = defer.Deferred(canceller=canceller) + self._onConnection = defer.Deferred(canceller=self._canceller) + + + def startedConnecting(self, connector): + """ + A connection attempt was started. Remember the connector which started + said attempt, for use later. + """ + self._connector = connector + + + def _canceller(self, deferred): + """ + The outgoing connection attempt was cancelled. Fail that L{Deferred} + with a L{error.ConnectingCancelledError}. + + @param deferred: The L{Deferred } that was cancelled; + should be the same as C{self._onConnection}. + @type deferred: L{Deferred } + + @note: This relies on startedConnecting having been called, so it may + seem as though there's a race condition where C{_connector} may not + have been set. However, using public APIs, this condition is + impossible to catch, because a connection API + (C{connectTCP}/C{SSL}/C{UNIX}) is always invoked before a + L{_WrappingFactory}'s L{Deferred } is returned to + C{connect()}'s caller. + + @return: C{None} + """ + deferred.errback( + error.ConnectingCancelledError( + self._connector.getDestination())) + self._connector.stopConnecting() def doStart(self): @@ -165,7 +209,8 @@ Errback the C{self._onConnection} L{Deferred} when the client connection fails. """ - self._onConnection.errback(reason) + if not self._onConnection.called: + self._onConnection.errback(reason) @@ -255,14 +300,9 @@ """ Implement L{IStreamClientEndpoint.connect} to connect via TCP. """ - def _canceller(deferred): - connector.stopConnecting() - deferred.errback( - error.ConnectingCancelledError(connector.getDestination())) - try: - wf = _WrappingFactory(protocolFactory, _canceller) - connector = self._reactor.connectTCP( + wf = _WrappingFactory(protocolFactory) + self._reactor.connectTCP( self._host, self._port, wf, timeout=self._timeout, bindAddress=self._bindAddress) return wf._onConnection @@ -379,14 +419,9 @@ Implement L{IStreamClientEndpoint.connect} to connect with SSL over TCP. """ - def _canceller(deferred): - connector.stopConnecting() - deferred.errback( - error.ConnectingCancelledError(connector.getDestination())) - try: - wf = _WrappingFactory(protocolFactory, _canceller) - connector = self._reactor.connectSSL( + wf = _WrappingFactory(protocolFactory) + self._reactor.connectSSL( self._host, self._port, wf, self._sslContextFactory, timeout=self._timeout, bindAddress=self._bindAddress) return wf._onConnection @@ -480,14 +515,9 @@ Implement L{IStreamClientEndpoint.connect} to connect via a UNIX Socket """ - def _canceller(deferred): - connector.stopConnecting() - deferred.errback( - error.ConnectingCancelledError(connector.getDestination())) - try: - wf = _WrappingFactory(protocolFactory, _canceller) - connector = self._reactor.connectUNIX( + wf = _WrappingFactory(protocolFactory) + self._reactor.connectUNIX( self._path, wf, timeout=self._timeout, checkPID=self._checkPID) @@ -497,6 +527,53 @@ +class AdoptedStreamServerEndpoint(object): + """ + An endpoint for listening on a file descriptor initialized outside of + Twisted. + + @ivar _used: A C{bool} indicating whether this endpoint has been used to + listen with a factory yet. C{True} if so. + """ + _close = os.close + _setNonBlocking = staticmethod(fdesc.setNonBlocking) + + def __init__(self, reactor, fileno, addressFamily): + """ + @param reactor: An L{IReactorSocket} provider. + + @param fileno: An integer file descriptor corresponding to a listening + I{SOCK_STREAM} socket. + + @param addressFamily: The address family of the socket given by + C{fileno}. + """ + self.reactor = reactor + self.fileno = fileno + self.addressFamily = addressFamily + self._used = False + + + def listen(self, factory): + """ + Implement L{IStreamServerEndpoint.listen} to start listening on, and + then close, C{self._fileno}. + """ + if self._used: + return defer.fail(error.AlreadyListened()) + self._used = True + + try: + self._setNonBlocking(self.fileno) + port = self.reactor.adoptStreamPort( + self.fileno, self.addressFamily, factory) + self._close(self.fileno) + except: + return defer.fail() + return defer.succeed(port) + + + def _parseTCP(factory, port, interface="", backlog=50): """ Internal parser function for L{_parseServer} to convert the string @@ -601,9 +678,62 @@ return ((int(port), factory, cf), {'interface': interface, 'backlog': int(backlog)}) + +class _SystemdParser(object): + """ + Stream server endpoint string parser for the I{systemd} endpoint type. + + @ivar prefix: See L{IStreamClientEndpointStringParser.prefix}. + + @ivar _sddaemon: A L{ListenFDs} instance used to translate an index into an + actual file descriptor. + """ + implements(IPlugin, IStreamServerEndpointStringParser) + + _sddaemon = ListenFDs.fromEnvironment() + + prefix = "systemd" + + def _parseServer(self, reactor, domain, index): + """ + Internal parser function for L{_parseServer} to convert the string + arguments for a systemd server endpoint into structured arguments for + L{AdoptedStreamServerEndpoint}. + + @param reactor: An L{IReactorSocket} provider. + + @param domain: The domain (or address family) of the socket inherited + from systemd. This is a string like C{"INET"} or C{"UNIX"}, ie the + name of an address family from the L{socket} module, without the + C{"AF_"} prefix. + @type domain: C{str} + + @param index: An offset into the list of file descriptors inherited from + systemd. + @type index: C{str} + + @return: A two-tuple of parsed positional arguments and parsed keyword + arguments (a tuple and a dictionary). These can be used to + construct a L{AdoptedStreamServerEndpoint}. + """ + index = int(index) + fileno = self._sddaemon.inheritedDescriptors()[index] + addressFamily = getattr(socket, 'AF_' + domain) + return AdoptedStreamServerEndpoint(reactor, fileno, addressFamily) + + + def parseStreamServer(self, reactor, *args, **kwargs): + # Delegate to another function with a sane signature. This function has + # an insane signature to trick zope.interface into believing the + # interface is correctly implemented. + return self._parseServer(reactor, *args, **kwargs) + + + _serverParsers = {"tcp": _parseTCP, "unix": _parseUNIX, - "ssl": _parseSSL} + "ssl": _parseSSL, + } _OP, _STRING = range(2) @@ -728,7 +858,7 @@ parser = _serverParsers.get(endpointType) if parser is None: for plugin in getPlugins(IStreamServerEndpointStringParser): - if plugin.prefix == endpointType: + if plugin.prefix == endpointType: return (plugin, args[1:], kw) raise ValueError("Unknown endpoint type: '%s'" % (endpointType,)) return (endpointType.upper(),) + parser(factory, *args[1:], **kw) @@ -849,16 +979,32 @@ -def _parseClientTCP(**kwargs): +def _parseClientTCP(*args, **kwargs): """ Perform any argument value coercion necessary for TCP client parameters. + Valid positional arguments to this function are host and port. + Valid keyword arguments to this function are all L{IReactorTCP.connectTCP} arguments. @return: The coerced values as a C{dict}. """ - kwargs['port'] = int(kwargs['port']) + + if len(args) == 2: + kwargs['port'] = int(args[1]) + kwargs['host'] = args[0] + elif len(args) == 1: + if 'host' in kwargs: + kwargs['port'] = int(args[0]) + else: + kwargs['host'] = args[0] + + try: + kwargs['port'] = int(kwargs['port']) + except KeyError: + pass + try: kwargs['timeout'] = int(kwargs['timeout']) except KeyError: @@ -898,7 +1044,7 @@ -def _parseClientSSL(**kwargs): +def _parseClientSSL(*args, **kwargs): """ Perform any argument value coercion necessary for SSL client parameters. @@ -907,7 +1053,9 @@ of the certificate file) C{privateKey} (the path name of the private key associated with the certificate) are accepted and used to construct a context factory. - + + Valid positional arguments to this function are host and port. + @param caCertsDir: The one parameter which is not part of L{IReactorSSL.connectSSL}'s signature, this is a path name used to construct a list of certificate authority certificates. The directory @@ -919,7 +1067,7 @@ @return: The coerced values as a C{dict}. """ from twisted.internet import ssl - kwargs = _parseClientTCP(**kwargs) + kwargs = _parseClientTCP(*args, **kwargs) certKey = kwargs.pop('certKey', None) privateKey = kwargs.pop('privateKey', None) caCertsDir = kwargs.pop('caCertsDir', None) @@ -950,16 +1098,21 @@ -def _parseClientUNIX(**kwargs): +def _parseClientUNIX(*args, **kwargs): """ Perform any argument value coercion necessary for UNIX client parameters. Valid keyword arguments to this function are all L{IReactorUNIX.connectUNIX} - arguments except for C{checkPID}. Instead, C{lockfile} is accepted and has - the same meaning. + keyword arguments except for C{checkPID}. Instead, C{lockfile} is accepted + and has the same meaning. Also C{path} is used instead of C{address}. + + Valid positional arguments to this function are C{path}. @return: The coerced values as a C{dict}. """ + if len(args) == 1: + kwargs['path'] = args[0] + try: kwargs['checkPID'] = bool(int(kwargs.pop('lockfile'))) except KeyError: @@ -983,19 +1136,27 @@ Construct a client endpoint from a description string. Client description strings are much like server description strings, - although they take all of their arguments as keywords, since even the - simplest client endpoint (plain TCP) requires at least 2 arguments (host - and port) to construct. + although they take all of their arguments as keywords, aside from host and + port. You can create a TCP client endpoint with the 'host' and 'port' arguments, like so:: clientFromString(reactor, "tcp:host=www.example.com:port=80") + or, without specifying host and port keywords:: + + clientFromString(reactor, "tcp:www.example.com:80") + + Or you can specify only one or the other, as in the following 2 examples:: + + clientFromString(reactor, "tcp:host=www.example.com:80") + clientFromString(reactor, "tcp:www.example.com:port=80") + or an SSL client endpoint with those arguments, plus the arguments used by the server SSL, for a client certificate:: - clientFromString(reactor, "ssl:host=web.example.com:port=443:" + clientFromString(reactor, "ssl:web.example.com:443:" "privateKey=foo.pem:certKey=foo.pem") to specify your certificate trust roots, you can identify a directory with @@ -1003,6 +1164,17 @@ clientFromString(reactor, "ssl:host=web.example.com:port=443:" "caCertsDir=/etc/ssl/certs") + + You can create a UNIX client endpoint with the 'path' argument and optional + 'lockfile' and 'timeout' arguments:: + + clientFromString(reactor, "unix:path=/var/foo/bar:lockfile=1:timeout=9") + + or, with the path as a positional argument with or without optional + arguments as in the following 2 examples:: + + clientFromString(reactor, "unix:/var/foo/bar") + clientFromString(reactor, "unix:/var/foo/bar:lockfile=1:timeout=9") This function is also extensible; new endpoint types may be registered as L{IStreamClientEndpointStringParser} plugins. See that interface for more diff -Nru twisted-11.1.0/twisted/internet/epollreactor.py twisted-12.1.0/twisted/internet/epollreactor.py --- twisted-11.1.0/twisted/internet/epollreactor.py 2011-04-16 20:39:52.000000000 +0000 +++ twisted-12.1.0/twisted/internet/epollreactor.py 2012-05-04 18:49:18.000000000 +0000 @@ -17,53 +17,204 @@ from twisted.internet.interfaces import IReactorFDSet -from twisted.python import log, _epoll +from twisted.python import log from twisted.internet import posixbase +try: + # In Python 2.6+, select.epoll provides epoll functionality. Try to import + # it, and fall back to Twisted's own epoll wrapper if it isn't available + # for any reason. + from select import epoll +except ImportError: + from twisted.python import _epoll +else: + del epoll + import select as _epoll + + + +class _ContinuousPolling(posixbase._PollLikeMixin, + posixbase._DisconnectSelectableMixin): + """ + Schedule reads and writes based on the passage of time, rather than + notification. + + This is useful for supporting polling filesystem files, which C{epoll(7)} + does not support. + + The implementation uses L{posixbase._PollLikeMixin}, which is a bit hacky, + but re-implementing and testing the relevant code yet again is + unappealing. + + @ivar _reactor: The L{EPollReactor} that is using this instance. + + @ivar _loop: A C{LoopingCall} that drives the polling, or C{None}. + + @ivar _readers: A C{set} of C{FileDescriptor} objects that should be read + from. + + @ivar _writers: A C{set} of C{FileDescriptor} objects that should be + written to. + """ + implements(IReactorFDSet) + + # Attributes for _PollLikeMixin + _POLL_DISCONNECTED = 1 + _POLL_IN = 2 + _POLL_OUT = 4 + + + def __init__(self, reactor): + self._reactor = reactor + self._loop = None + self._readers = set() + self._writers = set() + self.isReading = self._readers.__contains__ + self.isWriting = self._writers.__contains__ + + + def _checkLoop(self): + """ + Start or stop a C{LoopingCall} based on whether there are readers and + writers. + """ + if self._readers or self._writers: + if self._loop is None: + from twisted.internet.task import LoopingCall, _EPSILON + self._loop = LoopingCall(self.iterate) + self._loop.clock = self._reactor + # LoopingCall seems unhappy with timeout of 0, so use very + # small number: + self._loop.start(_EPSILON, now=False) + elif self._loop: + self._loop.stop() + self._loop = None + + + def iterate(self): + """ + Call C{doRead} and C{doWrite} on all readers and writers respectively. + """ + for reader in list(self._readers): + self._doReadOrWrite(reader, reader, self._POLL_IN) + for reader in list(self._writers): + self._doReadOrWrite(reader, reader, self._POLL_OUT) + + + def addReader(self, reader): + """ + Add a C{FileDescriptor} for notification of data available to read. + """ + self._readers.add(reader) + self._checkLoop() + + + def addWriter(self, writer): + """ + Add a C{FileDescriptor} for notification of data available to write. + """ + self._writers.add(writer) + self._checkLoop() + + + def removeReader(self, reader): + """ + Remove a C{FileDescriptor} from notification of data available to read. + """ + try: + self._readers.remove(reader) + except KeyError: + return + self._checkLoop() + + + def removeWriter(self, writer): + """ + Remove a C{FileDescriptor} from notification of data available to write. + """ + try: + self._writers.remove(writer) + except KeyError: + return + self._checkLoop() + + + def removeAll(self): + """ + Remove all readers and writers. + """ + result = list(self._readers | self._writers) + # Don't reset to new value, since self.isWriting and .isReading refer + # to the existing instance: + self._readers.clear() + self._writers.clear() + return result + + + def getReaders(self): + """ + Return a list of the readers. + """ + return list(self._readers) + + + def getWriters(self): + """ + Return a list of the writers. + """ + return list(self._writers) + + class EPollReactor(posixbase.PosixReactorBase, posixbase._PollLikeMixin): """ - A reactor that uses epoll(4). + A reactor that uses epoll(7). - @ivar _poller: A L{poll} which will be used to check for I/O + @ivar _poller: A C{epoll} which will be used to check for I/O readiness. @ivar _selectables: A dictionary mapping integer file descriptors to - instances of L{FileDescriptor} which have been registered with the - reactor. All L{FileDescriptors} which are currently receiving read or + instances of C{FileDescriptor} which have been registered with the + reactor. All C{FileDescriptors} which are currently receiving read or write readiness notifications will be present as values in this dictionary. @ivar _reads: A dictionary mapping integer file descriptors to arbitrary values (this is essentially a set). Keys in this dictionary will be registered with C{_poller} for read readiness notifications which will - be dispatched to the corresponding L{FileDescriptor} instances in + be dispatched to the corresponding C{FileDescriptor} instances in C{_selectables}. @ivar _writes: A dictionary mapping integer file descriptors to arbitrary values (this is essentially a set). Keys in this dictionary will be registered with C{_poller} for write readiness notifications which will - be dispatched to the corresponding L{FileDescriptor} instances in + be dispatched to the corresponding C{FileDescriptor} instances in C{_selectables}. + + @ivar _continuousPolling: A L{_ContinuousPolling} instance, used to handle + file descriptors (e.g. filesytem files) that are not supported by + C{epoll(7)}. """ implements(IReactorFDSet) # Attributes for _PollLikeMixin - _POLL_DISCONNECTED = (_epoll.HUP | _epoll.ERR) - _POLL_IN = _epoll.IN - _POLL_OUT = _epoll.OUT + _POLL_DISCONNECTED = (_epoll.EPOLLHUP | _epoll.EPOLLERR) + _POLL_IN = _epoll.EPOLLIN + _POLL_OUT = _epoll.EPOLLOUT def __init__(self): """ Initialize epoll object, file descriptor tracking dictionaries, and the base class. """ - # Create the poller we're going to use. The 1024 here is just a hint - # to the kernel, it is not a hard maximum. + # Create the poller we're going to use. The 1024 here is just a hint to + # the kernel, it is not a hard maximum. After Linux 2.6.8, the size + # argument is completely ignored. self._poller = _epoll.epoll(1024) self._reads = {} self._writes = {} self._selectables = {} + self._continuousPolling = _ContinuousPolling(self) posixbase.PosixReactorBase.__init__(self) @@ -76,17 +227,17 @@ """ fd = xer.fileno() if fd not in primary: - cmd = _epoll.CTL_ADD flags = event - if fd in other: - flags |= antievent - cmd = _epoll.CTL_MOD # epoll_ctl can raise all kinds of IOErrors, and every one # indicates a bug either in the reactor or application-code. # Let them all through so someone sees a traceback and fixes # something. We'll do the same thing for every other call to # this method in this file. - self._poller._control(cmd, fd, flags) + if fd in other: + flags |= antievent + self._poller.modify(fd, flags) + else: + self._poller.register(fd, flags) # Update our own tracking state *only* after the epoll call has # succeeded. Otherwise we may get out of sync. @@ -98,14 +249,34 @@ """ Add a FileDescriptor for notification of data available to read. """ - self._add(reader, self._reads, self._writes, self._selectables, _epoll.IN, _epoll.OUT) + try: + self._add(reader, self._reads, self._writes, self._selectables, + _epoll.EPOLLIN, _epoll.EPOLLOUT) + except IOError, e: + if e.errno == errno.EPERM: + # epoll(7) doesn't support certain file descriptors, + # e.g. filesystem files, so for those we just poll + # continuously: + self._continuousPolling.addReader(reader) + else: + raise def addWriter(self, writer): """ Add a FileDescriptor for notification of data available to write. """ - self._add(writer, self._writes, self._reads, self._selectables, _epoll.OUT, _epoll.IN) + try: + self._add(writer, self._writes, self._reads, self._selectables, + _epoll.EPOLLOUT, _epoll.EPOLLIN) + except IOError, e: + if e.errno == errno.EPERM: + # epoll(7) doesn't support certain file descriptors, + # e.g. filesystem files, so for those we just poll + # continuously: + self._continuousPolling.addWriter(writer) + else: + raise def _remove(self, xer, primary, other, selectables, event, antievent): @@ -123,46 +294,57 @@ else: return if fd in primary: - cmd = _epoll.CTL_DEL - flags = event if fd in other: flags = antievent - cmd = _epoll.CTL_MOD + # See comment above modify call in _add. + self._poller.modify(fd, flags) else: del selectables[fd] + # See comment above _control call in _add. + self._poller.unregister(fd) del primary[fd] - # See comment above _control call in _add. - self._poller._control(cmd, fd, flags) def removeReader(self, reader): """ Remove a Selectable for notification of data available to read. """ - self._remove(reader, self._reads, self._writes, self._selectables, _epoll.IN, _epoll.OUT) + if self._continuousPolling.isReading(reader): + self._continuousPolling.removeReader(reader) + return + self._remove(reader, self._reads, self._writes, self._selectables, + _epoll.EPOLLIN, _epoll.EPOLLOUT) def removeWriter(self, writer): """ Remove a Selectable for notification of data available to write. """ - self._remove(writer, self._writes, self._reads, self._selectables, _epoll.OUT, _epoll.IN) + if self._continuousPolling.isWriting(writer): + self._continuousPolling.removeWriter(writer) + return + self._remove(writer, self._writes, self._reads, self._selectables, + _epoll.EPOLLOUT, _epoll.EPOLLIN) + def removeAll(self): """ Remove all selectables, and return a list of them. """ - return self._removeAll( - [self._selectables[fd] for fd in self._reads], - [self._selectables[fd] for fd in self._writes]) + return (self._removeAll( + [self._selectables[fd] for fd in self._reads], + [self._selectables[fd] for fd in self._writes]) + + self._continuousPolling.removeAll()) def getReaders(self): - return [self._selectables[fd] for fd in self._reads] + return ([self._selectables[fd] for fd in self._reads] + + self._continuousPolling.getReaders()) def getWriters(self): - return [self._selectables[fd] for fd in self._writes] + return ([self._selectables[fd] for fd in self._writes] + + self._continuousPolling.getWriters()) def doPoll(self, timeout): @@ -170,15 +352,14 @@ Poll the poller for new events. """ if timeout is None: - timeout = 1 - timeout = int(timeout * 1000) # convert seconds to milliseconds + timeout = -1 # Wait indefinitely. try: # Limit the number of events to the number of io objects we're # currently tracking (because that's maybe a good heuristic) and # the amount of time we block to the value specified by our # caller. - l = self._poller.wait(len(self._selectables), timeout) + l = self._poller.poll(timeout, len(self._selectables)) except IOError, err: if err.errno == errno.EINTR: return diff -Nru twisted-11.1.0/twisted/internet/error.py twisted-12.1.0/twisted/internet/error.py --- twisted-11.1.0/twisted/internet/error.py 2011-10-31 22:29:28.000000000 +0000 +++ twisted-12.1.0/twisted/internet/error.py 2012-04-26 13:46:20.000000000 +0000 @@ -243,6 +243,19 @@ +class FileDescriptorOverrun(ConnectionLost): + """ + A mis-use of L{IUNIXTransport.sendFileDescriptor} caused the connection to + be closed. + + Each file descriptor sent using C{sendFileDescriptor} must be associated + with at least one byte sent using L{ITransport.write}. If at any point + fewer bytes have been written than file descriptors have been sent, the + connection is closed with this exception. + """ + + + class ConnectionFdescWentAway(ConnectionLost): """Uh""" #TODO @@ -397,6 +410,28 @@ +class UnsupportedAddressFamily(Exception): + """ + An attempt was made to use a socket with an address family (eg I{AF_INET}, + I{AF_INET6}, etc) which is not supported by the reactor. + """ + + + +class UnsupportedSocketType(Exception): + """ + An attempt was made to use a socket of a type (eg I{SOCK_STREAM}, + I{SOCK_DGRAM}, etc) which is not supported by the reactor. + """ + + +class AlreadyListened(Exception): + """ + An attempt was made to listen on a file descriptor which can only be + listened on once. + """ + + __all__ = [ 'BindError', 'CannotListenError', 'MulticastJoinError', 'MessageLengthError', 'DNSLookupError', 'ConnectInProgressError', @@ -409,4 +444,5 @@ 'AlreadyCancelled', 'PotentialZombieWarning', 'ProcessDone', 'ProcessTerminated', 'ProcessExitedAlready', 'NotConnectingError', 'NotListeningError', 'ReactorNotRunning', 'ReactorAlreadyRunning', - 'ReactorAlreadyInstalledError', 'ConnectingCancelledError'] + 'ReactorAlreadyInstalledError', 'ConnectingCancelledError', + 'UnsupportedAddressFamily', 'UnsupportedSocketType'] diff -Nru twisted-11.1.0/twisted/internet/gireactor.py twisted-12.1.0/twisted/internet/gireactor.py --- twisted-11.1.0/twisted/internet/gireactor.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/internet/gireactor.py 2012-05-12 22:44:21.000000000 +0000 @@ -0,0 +1,139 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +This module provides support for Twisted to interact with the glib +mainloop via GObject Introspection. + +In order to use this support, simply do the following:: + + from twisted.internet import gireactor + gireactor.install() + +If you wish to use a GApplication, register it with the reactor:: + + from twisted.internet import reactor + reactor.registerGApplication(app) + +Then use twisted.internet APIs as usual. +""" + +import sys +from twisted.internet.error import ReactorAlreadyRunning +from twisted.internet import _glibbase +from twisted.python import runtime + +# We can't immediately prevent imports, because that confuses some buggy code +# in gi: +_glibbase.ensureNotImported( + ['gobject' 'glib', 'gio', 'gtk'], + "Introspected and static glib/gtk bindings must not be mixed; can't " + "import gireactor since pygtk2 module is already imported.") + +from gi.repository import GLib +GLib.threads_init() + +_glibbase.ensureNotImported([], "", + preventImports=['gobject' 'glib', 'gio', 'gtk']) + + + +class GIReactor(_glibbase.GlibReactorBase): + """ + GObject-introspection event loop reactor. + + @ivar _gapplication: A C{Gio.Application} instance that was registered + with C{registerGApplication}. + """ + _POLL_DISCONNECTED = (GLib.IOCondition.HUP | GLib.IOCondition.ERR | + GLib.IOCondition.NVAL) + _POLL_IN = GLib.IOCondition.IN + _POLL_OUT = GLib.IOCondition.OUT + + # glib's iochannel sources won't tell us about any events that we haven't + # asked for, even if those events aren't sensible inputs to the poll() + # call. + INFLAGS = _POLL_IN | _POLL_DISCONNECTED + OUTFLAGS = _POLL_OUT | _POLL_DISCONNECTED + + # By default no Application is registered: + _gapplication = None + + + def __init__(self, useGtk=False): + _gtk = None + if useGtk is True: + from gi.repository import Gtk as _gtk + + _glibbase.GlibReactorBase.__init__(self, GLib, _gtk, useGtk=useGtk) + + + def registerGApplication(self, app): + """ + Register a C{Gio.Application} or C{Gtk.Application}, whose main loop + will be used instead of the default one. + + We will C{hold} the application so it doesn't exit on its own. In + versions of C{python-gi} 3.2 and later, we exit the event loop using + the C{app.quit} method which overrides any holds. Older versions are + not supported. + """ + if self._gapplication is not None: + raise RuntimeError( + "Can't register more than one application instance.") + if self._started: + raise ReactorAlreadyRunning( + "Can't register application after reactor was started.") + if not hasattr(app, "quit"): + raise RuntimeError("Application registration is not supported in" + " versions of PyGObject prior to 3.2.") + self._gapplication = app + def run(): + app.hold() + app.run(None) + self._run = run + + self._crash = app.quit + + + +class PortableGIReactor(_glibbase.PortableGlibReactorBase): + """ + Portable GObject Introspection event loop reactor. + """ + def __init__(self, useGtk=False): + _gtk = None + if useGtk is True: + from gi.repository import Gtk as _gtk + + _glibbase.PortableGlibReactorBase.__init__(self, GLib, _gtk, + useGtk=useGtk) + + + def registerGApplication(self, app): + """ + Register a C{Gio.Application} or C{Gtk.Application}, whose main loop + will be used instead of the default one. + """ + raise NotImplementedError("GApplication is not currently supported on Windows.") + + + +def install(useGtk=False): + """ + Configure the twisted mainloop to be run inside the glib mainloop. + + @param useGtk: should GTK+ rather than glib event loop be + used (this will be slightly slower but does support GUI). + """ + if runtime.platform.getType() == 'posix': + reactor = GIReactor(useGtk=useGtk) + else: + reactor = PortableGIReactor(useGtk=useGtk) + + from twisted.internet.main import installReactor + installReactor(reactor) + return reactor + + +__all__ = ['install'] diff -Nru twisted-11.1.0/twisted/internet/glib2reactor.py twisted-12.1.0/twisted/internet/glib2reactor.py --- twisted-11.1.0/twisted/internet/glib2reactor.py 2008-07-29 20:13:54.000000000 +0000 +++ twisted-12.1.0/twisted/internet/glib2reactor.py 2012-01-25 03:20:58.000000000 +0000 @@ -1,3 +1,5 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. """ This module provides support for Twisted to interact with the glib mainloop. @@ -7,23 +9,16 @@ In order to use this support, simply do the following:: - | from twisted.internet import glib2reactor - | glib2reactor.install() + from twisted.internet import glib2reactor + glib2reactor.install() Then use twisted.internet APIs as usual. The other methods here are not intended to be called directly. - -When installing the reactor, you can choose whether to use the glib -event loop or the GTK+ event loop which is based on it but adds GUI -integration. - -Maintainer: Itamar Shtull-Trauring """ from twisted.internet import gtk2reactor - class Glib2Reactor(gtk2reactor.Gtk2Reactor): """ The reactor using the glib mainloop. @@ -44,6 +39,6 @@ reactor = Glib2Reactor() from twisted.internet.main import installReactor installReactor(reactor) - -__all__ = ['install'] + +__all__ = ['install'] diff -Nru twisted-11.1.0/twisted/internet/_glibbase.py twisted-12.1.0/twisted/internet/_glibbase.py --- twisted-11.1.0/twisted/internet/_glibbase.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/internet/_glibbase.py 2012-05-12 13:55:41.000000000 +0000 @@ -0,0 +1,387 @@ +# -*- test-case-name: twisted.internet.test -*- +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +This module provides base support for Twisted to interact with the glib/gtk +mainloops. + +The classes in this module should not be used directly, but rather you should +import gireactor or gtk3reactor for GObject Introspection based applications, +or glib2reactor or gtk2reactor for applications using legacy static bindings. +""" + +import sys + +from twisted.internet import base, posixbase, selectreactor +from twisted.internet.interfaces import IReactorFDSet +from twisted.python import log +from twisted.python.compat import set +from zope.interface import implements + + +def ensureNotImported(moduleNames, errorMessage, preventImports=[]): + """ + Check whether the given modules were imported, and if requested, ensure + they will not be importable in the future. + + @param moduleNames: A list of module names we make sure aren't imported. + @type moduleNames: C{list} of C{str} + + @param preventImports: A list of module name whose future imports should + be prevented. + @type preventImports: C{list} of C{str} + + @param errorMessage: Message to use when raising an C{ImportError}. + @type errorMessage: C{str} + + @raises: C{ImportError} with given error message if a given module name + has already been imported. + """ + for name in moduleNames: + if sys.modules.get(name) is not None: + raise ImportError(errorMessage) + + # Disable module imports to avoid potential problems. + for name in preventImports: + sys.modules[name] = None + + + +class GlibWaker(posixbase._UnixWaker): + """ + Run scheduled events after waking up. + """ + + def doRead(self): + posixbase._UnixWaker.doRead(self) + self.reactor._simulate() + + + +class GlibReactorBase(posixbase.PosixReactorBase, posixbase._PollLikeMixin): + """ + Base class for GObject event loop reactors. + + Notification for I/O events (reads and writes on file descriptors) is done + by the the gobject-based event loop. File descriptors are registered with + gobject with the appropriate flags for read/write/disconnect notification. + + Time-based events, the results of C{callLater} and C{callFromThread}, are + handled differently. Rather than registering each event with gobject, a + single gobject timeout is registered for the earliest scheduled event, the + output of C{reactor.timeout()}. For example, if there are timeouts in 1, 2 + and 3.4 seconds, a single timeout is registered for 1 second in the + future. When this timeout is hit, C{_simulate} is called, which calls the + appropriate Twisted-level handlers, and a new timeout is added to gobject + by the C{_reschedule} method. + + To handle C{callFromThread} events, we use a custom waker that calls + C{_simulate} whenever it wakes up. + + @ivar _sources: A dictionary mapping L{FileDescriptor} instances to + GSource handles. + + @ivar _reads: A set of L{FileDescriptor} instances currently monitored for + reading. + + @ivar _writes: A set of L{FileDescriptor} instances currently monitored for + writing. + + @ivar _simtag: A GSource handle for the next L{simulate} call. + """ + implements(IReactorFDSet) + + # Install a waker that knows it needs to call C{_simulate} in order to run + # callbacks queued from a thread: + _wakerFactory = GlibWaker + + def __init__(self, glib_module, gtk_module, useGtk=False): + self._simtag = None + self._reads = set() + self._writes = set() + self._sources = {} + self._glib = glib_module + self._gtk = gtk_module + posixbase.PosixReactorBase.__init__(self) + + self._source_remove = self._glib.source_remove + self._timeout_add = self._glib.timeout_add + + def _mainquit(): + if self._gtk.main_level(): + self._gtk.main_quit() + + if useGtk: + self._pending = self._gtk.events_pending + self._iteration = self._gtk.main_iteration_do + self._crash = _mainquit + self._run = self._gtk.main + else: + self.context = self._glib.main_context_default() + self._pending = self.context.pending + self._iteration = self.context.iteration + self.loop = self._glib.MainLoop() + self._crash = lambda: self._glib.idle_add(self.loop.quit) + self._run = self.loop.run + + + def _handleSignals(self): + # First, install SIGINT and friends: + base._SignalReactorMixin._handleSignals(self) + # Next, since certain versions of gtk will clobber our signal handler, + # set all signal handlers again after the event loop has started to + # ensure they're *really* set. We don't call this twice so we don't + # leak file descriptors created in the SIGCHLD initialization: + self.callLater(0, posixbase.PosixReactorBase._handleSignals, self) + + + # The input_add function in pygtk1 checks for objects with a + # 'fileno' method and, if present, uses the result of that method + # as the input source. The pygtk2 input_add does not do this. The + # function below replicates the pygtk1 functionality. + + # In addition, pygtk maps gtk.input_add to _gobject.io_add_watch, and + # g_io_add_watch() takes different condition bitfields than + # gtk_input_add(). We use g_io_add_watch() here in case pygtk fixes this + # bug. + def input_add(self, source, condition, callback): + if hasattr(source, 'fileno'): + # handle python objects + def wrapper(ignored, condition): + return callback(source, condition) + fileno = source.fileno() + else: + fileno = source + wrapper = callback + return self._glib.io_add_watch( + fileno, condition, wrapper, + priority=self._glib.PRIORITY_DEFAULT_IDLE) + + + def _ioEventCallback(self, source, condition): + """ + Called by event loop when an I/O event occurs. + """ + log.callWithLogger( + source, self._doReadOrWrite, source, source, condition) + return True # True = don't auto-remove the source + + + def _add(self, source, primary, other, primaryFlag, otherFlag): + """ + Add the given L{FileDescriptor} for monitoring either for reading or + writing. If the file is already monitored for the other operation, we + delete the previous registration and re-register it for both reading + and writing. + """ + if source in primary: + return + flags = primaryFlag + if source in other: + self._source_remove(self._sources[source]) + flags |= otherFlag + self._sources[source] = self.input_add( + source, flags, self._ioEventCallback) + primary.add(source) + + + def addReader(self, reader): + """ + Add a L{FileDescriptor} for monitoring of data available to read. + """ + self._add(reader, self._reads, self._writes, + self.INFLAGS, self.OUTFLAGS) + + + def addWriter(self, writer): + """ + Add a L{FileDescriptor} for monitoring ability to write data. + """ + self._add(writer, self._writes, self._reads, + self.OUTFLAGS, self.INFLAGS) + + + def getReaders(self): + """ + Retrieve the list of current L{FileDescriptor} monitored for reading. + """ + return list(self._reads) + + + def getWriters(self): + """ + Retrieve the list of current L{FileDescriptor} monitored for writing. + """ + return list(self._writes) + + + def removeAll(self): + """ + Remove monitoring for all registered L{FileDescriptor}s. + """ + return self._removeAll(self._reads, self._writes) + + + def _remove(self, source, primary, other, flags): + """ + Remove monitoring the given L{FileDescriptor} for either reading or + writing. If it's still monitored for the other operation, we + re-register the L{FileDescriptor} for only that operation. + """ + if source not in primary: + return + self._source_remove(self._sources[source]) + primary.remove(source) + if source in other: + self._sources[source] = self.input_add( + source, flags, self._ioEventCallback) + else: + self._sources.pop(source) + + + def removeReader(self, reader): + """ + Stop monitoring the given L{FileDescriptor} for reading. + """ + self._remove(reader, self._reads, self._writes, self.OUTFLAGS) + + + def removeWriter(self, writer): + """ + Stop monitoring the given L{FileDescriptor} for writing. + """ + self._remove(writer, self._writes, self._reads, self.INFLAGS) + + + def iterate(self, delay=0): + """ + One iteration of the event loop, for trial's use. + + This is not used for actual reactor runs. + """ + self.runUntilCurrent() + while self._pending(): + self._iteration(0) + + + def crash(self): + """ + Crash the reactor. + """ + posixbase.PosixReactorBase.crash(self) + self._crash() + + + def stop(self): + """ + Stop the reactor. + """ + posixbase.PosixReactorBase.stop(self) + # The base implementation only sets a flag, to ensure shutting down is + # not reentrant. Unfortunately, this flag is not meaningful to the + # gobject event loop. We therefore call wakeUp() to ensure the event + # loop will call back into Twisted once this iteration is done. This + # will result in self.runUntilCurrent() being called, where the stop + # flag will trigger the actual shutdown process, eventually calling + # crash() which will do the actual gobject event loop shutdown. + self.wakeUp() + + + def run(self, installSignalHandlers=True): + """ + Run the reactor. + """ + self.callWhenRunning(self._reschedule) + self.startRunning(installSignalHandlers=installSignalHandlers) + if self._started: + self._run() + + + def callLater(self, *args, **kwargs): + """ + Schedule a C{DelayedCall}. + """ + result = posixbase.PosixReactorBase.callLater(self, *args, **kwargs) + # Make sure we'll get woken up at correct time to handle this new + # scheduled call: + self._reschedule() + return result + + + def _reschedule(self): + """ + Schedule a glib timeout for C{_simulate}. + """ + if self._simtag is not None: + self._source_remove(self._simtag) + self._simtag = None + timeout = self.timeout() + if timeout is not None: + self._simtag = self._timeout_add( + int(timeout * 1000), self._simulate, + priority=self._glib.PRIORITY_DEFAULT_IDLE) + + + def _simulate(self): + """ + Run timers, and then reschedule glib timeout for next scheduled event. + """ + self.runUntilCurrent() + self._reschedule() + + + +class PortableGlibReactorBase(selectreactor.SelectReactor): + """ + Base class for GObject event loop reactors that works on Windows. + + Sockets aren't supported by GObject's input_add on Win32. + """ + def __init__(self, glib_module, gtk_module, useGtk=False): + self._simtag = None + self._glib = glib_module + self._gtk = gtk_module + selectreactor.SelectReactor.__init__(self) + + self._source_remove = self._glib.source_remove + self._timeout_add = self._glib.timeout_add + + def _mainquit(): + if self._gtk.main_level(): + self._gtk.main_quit() + + if useGtk: + self._crash = _mainquit + self._run = self._gtk.main + else: + self.loop = self._glib.MainLoop() + self._crash = lambda: self._glib.idle_add(self.loop.quit) + self._run = self.loop.run + + + def crash(self): + selectreactor.SelectReactor.crash(self) + self._crash() + + + def run(self, installSignalHandlers=True): + self.startRunning(installSignalHandlers=installSignalHandlers) + self._timeout_add(0, self.simulate) + if self._started: + self._run() + + + def simulate(self): + """ + Run simulation loops and reschedule callbacks. + """ + if self._simtag is not None: + self._source_remove(self._simtag) + self.iterate() + timeout = min(self.timeout(), 0.01) + if timeout is None: + timeout = 0.01 + self._simtag = self._timeout_add( + int(timeout * 1000), self.simulate, + priority=self._glib.PRIORITY_DEFAULT_IDLE) diff -Nru twisted-11.1.0/twisted/internet/gtk2reactor.py twisted-12.1.0/twisted/internet/gtk2reactor.py --- twisted-11.1.0/twisted/internet/gtk2reactor.py 2011-04-16 20:39:52.000000000 +0000 +++ twisted-12.1.0/twisted/internet/gtk2reactor.py 2012-03-13 14:46:45.000000000 +0000 @@ -9,21 +9,25 @@ In order to use this support, simply do the following:: - | from twisted.internet import gtk2reactor - | gtk2reactor.install() + from twisted.internet import gtk2reactor + gtk2reactor.install() Then use twisted.internet APIs as usual. The other methods here are not intended to be called directly. - -When installing the reactor, you can choose whether to use the glib -event loop or the GTK+ event loop which is based on it but adds GUI -integration. """ # System Imports -import sys, signal +import sys + +# Twisted Imports +from twisted.internet import _glibbase +from twisted.python import runtime -from zope.interface import implements +_glibbase.ensureNotImported( + ["gi"], + "Introspected and static glib/gtk bindings must not be mixed; can't " + "import gtk2reactor since gi module is already imported.", + preventImports=["gi"]) try: if not hasattr(sys, 'frozen'): @@ -32,6 +36,7 @@ pygtk.require('2.0') except (ImportError, AttributeError): pass # maybe we're using pygtk before this hack existed. + import gobject if hasattr(gobject, "threads_init"): # recent versions of python-gtk expose this. python-gtk=2.4.1 @@ -39,310 +44,44 @@ # glib-2.2.3) does not. gobject.threads_init() -# Twisted Imports -from twisted.python import log, runtime -from twisted.python.compat import set -from twisted.internet.interfaces import IReactorFDSet -from twisted.internet import base, posixbase, selectreactor - -POLL_DISCONNECTED = gobject.IO_HUP | gobject.IO_ERR | gobject.IO_NVAL - -# glib's iochannel sources won't tell us about any events that we haven't -# asked for, even if those events aren't sensible inputs to the poll() -# call. -INFLAGS = gobject.IO_IN | POLL_DISCONNECTED -OUTFLAGS = gobject.IO_OUT | POLL_DISCONNECTED - - - -def _our_mainquit(): - # XXX: gtk.main_quit() (which is used for crash()) raises an exception if - # gtk.main_level() == 0; however, all the tests freeze if we use this - # function to stop the reactor. what gives? (I believe this may have been - # a stupid mistake where I forgot to import gtk here... I will remove this - # comment if the tests pass) - import gtk - if gtk.main_level(): - gtk.main_quit() - - - -class _Gtk2SignalMixin(object): - if runtime.platformType == 'posix': - def _handleSignals(self): - # Let the base class do its thing, but pygtk is probably - # going to stomp on us so go beyond that and set up some - # signal handling which pygtk won't mess with. This would - # be better done by letting this reactor select a - # different implementation of installHandler for - # _SIGCHLDWaker to use. Then, at least, we could fall - # back to our extension module. See #4286. - from twisted.internet.process import reapAllProcesses as _reapAllProcesses - base._SignalReactorMixin._handleSignals(self) - signal.signal(signal.SIGCHLD, lambda *a: self.callFromThread(_reapAllProcesses)) - if getattr(signal, "siginterrupt", None) is not None: - signal.siginterrupt(signal.SIGCHLD, False) - # Like the base, reap processes now in case a process - # exited before the handlers above were installed. - _reapAllProcesses() - -class Gtk2Reactor(_Gtk2SignalMixin, posixbase.PosixReactorBase, posixbase._PollLikeMixin): +class Gtk2Reactor(_glibbase.GlibReactorBase): """ - GTK+-2 event loop reactor. - - @ivar _sources: A dictionary mapping L{FileDescriptor} instances to gtk - watch handles. - - @ivar _reads: A set of L{FileDescriptor} instances currently monitored for - reading. - - @ivar _writes: A set of L{FileDescriptor} instances currently monitored for - writing. - - @ivar _simtag: A gtk timeout handle for the next L{simulate} call. + PyGTK+ 2 event loop reactor. """ - implements(IReactorFDSet) - - _POLL_DISCONNECTED = POLL_DISCONNECTED + _POLL_DISCONNECTED = gobject.IO_HUP | gobject.IO_ERR | gobject.IO_NVAL _POLL_IN = gobject.IO_IN _POLL_OUT = gobject.IO_OUT + # glib's iochannel sources won't tell us about any events that we haven't + # asked for, even if those events aren't sensible inputs to the poll() + # call. + INFLAGS = _POLL_IN | _POLL_DISCONNECTED + OUTFLAGS = _POLL_OUT | _POLL_DISCONNECTED + def __init__(self, useGtk=True): - self._simtag = None - self._reads = set() - self._writes = set() - self._sources = {} - posixbase.PosixReactorBase.__init__(self) - # pre 2.3.91 the glib iteration and mainloop functions didn't release - # global interpreter lock, thus breaking thread and signal support. - if getattr(gobject, "pygtk_version", ()) >= (2, 3, 91) and not useGtk: - self.context = gobject.main_context_default() - self.__pending = self.context.pending - self.__iteration = self.context.iteration - self.loop = gobject.MainLoop() - self.__crash = self.loop.quit - self.__run = self.loop.run - else: - import gtk - self.__pending = gtk.events_pending - self.__iteration = gtk.main_iteration - self.__crash = _our_mainquit - self.__run = gtk.main - - - # The input_add function in pygtk1 checks for objects with a - # 'fileno' method and, if present, uses the result of that method - # as the input source. The pygtk2 input_add does not do this. The - # function below replicates the pygtk1 functionality. - - # In addition, pygtk maps gtk.input_add to _gobject.io_add_watch, and - # g_io_add_watch() takes different condition bitfields than - # gtk_input_add(). We use g_io_add_watch() here in case pygtk fixes this - # bug. - def input_add(self, source, condition, callback): - if hasattr(source, 'fileno'): - # handle python objects - def wrapper(source, condition, real_s=source, real_cb=callback): - return real_cb(real_s, condition) - return gobject.io_add_watch(source.fileno(), condition, wrapper) - else: - return gobject.io_add_watch(source, condition, callback) - - - def _add(self, source, primary, other, primaryFlag, otherFlag): - """ - Add the given L{FileDescriptor} for monitoring either for reading or - writing. If the file is already monitored for the other operation, we - delete the previous registration and re-register it for both reading - and writing. - """ - if source in primary: - return - flags = primaryFlag - if source in other: - gobject.source_remove(self._sources[source]) - flags |= otherFlag - self._sources[source] = self.input_add(source, flags, self.callback) - primary.add(source) - - - def addReader(self, reader): - """ - Add a L{FileDescriptor} for monitoring of data available to read. - """ - self._add(reader, self._reads, self._writes, INFLAGS, OUTFLAGS) - - - def addWriter(self, writer): - """ - Add a L{FileDescriptor} for monitoring ability to write data. - """ - self._add(writer, self._writes, self._reads, OUTFLAGS, INFLAGS) - - - def getReaders(self): - """ - Retrieve the list of current L{FileDescriptor} monitored for reading. - """ - return list(self._reads) - - - def getWriters(self): - """ - Retrieve the list of current L{FileDescriptor} monitored for writing. - """ - return list(self._writes) - - - def removeAll(self): - """ - Remove monitoring for all registered L{FileDescriptor}s. - """ - return self._removeAll(self._reads, self._writes) - - - def _remove(self, source, primary, other, flags): - """ - Remove monitoring the given L{FileDescriptor} for either reading or - writing. If it's still monitored for the other operation, we - re-register the L{FileDescriptor} for only that operation. - """ - if source not in primary: - return - gobject.source_remove(self._sources[source]) - primary.remove(source) - if source in other: - self._sources[source] = self.input_add( - source, flags, self.callback) - else: - self._sources.pop(source) - - - def removeReader(self, reader): - """ - Stop monitoring the given L{FileDescriptor} for reading. - """ - self._remove(reader, self._reads, self._writes, OUTFLAGS) - - - def removeWriter(self, writer): - """ - Stop monitoring the given L{FileDescriptor} for writing. - """ - self._remove(writer, self._writes, self._reads, INFLAGS) - - - doIterationTimer = None - - def doIterationTimeout(self, *args): - self.doIterationTimer = None - return 0 # auto-remove - - - def doIteration(self, delay): - # flush some pending events, return if there was something to do - # don't use the usual "while self.context.pending(): self.context.iteration()" - # idiom because lots of IO (in particular test_tcp's - # ProperlyCloseFilesTestCase) can keep us from ever exiting. - log.msg(channel='system', event='iteration', reactor=self) - if self.__pending(): - self.__iteration(0) - return - # nothing to do, must delay - if delay == 0: - return # shouldn't delay, so just return - self.doIterationTimer = gobject.timeout_add(int(delay * 1000), - self.doIterationTimeout) - # This will either wake up from IO or from a timeout. - self.__iteration(1) # block - # note: with the .simulate timer below, delays > 0.1 will always be - # woken up by the .simulate timer - if self.doIterationTimer: - # if woken by IO, need to cancel the timer - gobject.source_remove(self.doIterationTimer) - self.doIterationTimer = None - - - def crash(self): - posixbase.PosixReactorBase.crash(self) - self.__crash() - - - def run(self, installSignalHandlers=1): - self.startRunning(installSignalHandlers=installSignalHandlers) - gobject.timeout_add(0, self.simulate) - if self._started: - self.__run() - - - def callback(self, source, condition): - log.callWithLogger( - source, self._doReadOrWrite, source, source, condition) - self.simulate() # fire Twisted timers - return 1 # 1=don't auto-remove the source - - - def simulate(self): - """ - Run simulation loops and reschedule callbacks. - """ - if self._simtag is not None: - gobject.source_remove(self._simtag) - self.runUntilCurrent() - timeout = min(self.timeout(), 0.1) - if timeout is None: - timeout = 0.1 - # grumble - self._simtag = gobject.timeout_add(int(timeout * 1010), self.simulate) + _gtk = None + if useGtk is True: + import gtk as _gtk + _glibbase.GlibReactorBase.__init__(self, gobject, _gtk, useGtk=useGtk) -class PortableGtkReactor(_Gtk2SignalMixin, selectreactor.SelectReactor): + +class PortableGtkReactor(_glibbase.PortableGlibReactorBase): """ Reactor that works on Windows. Sockets aren't supported by GTK+'s input_add on Win32. """ - _simtag = None - - def crash(self): - selectreactor.SelectReactor.crash(self) - import gtk - # mainquit is deprecated in newer versions - if gtk.main_level(): - if hasattr(gtk, 'main_quit'): - gtk.main_quit() - else: - gtk.mainquit() - - - def run(self, installSignalHandlers=1): - import gtk - self.startRunning(installSignalHandlers=installSignalHandlers) - gobject.timeout_add(0, self.simulate) - # mainloop is deprecated in newer versions - if self._started: - if hasattr(gtk, 'main'): - gtk.main() - else: - gtk.mainloop() - - - def simulate(self): - """ - Run simulation loops and reschedule callbacks. - """ - if self._simtag is not None: - gobject.source_remove(self._simtag) - self.iterate() - timeout = min(self.timeout(), 0.1) - if timeout is None: - timeout = 0.1 - # grumble - self._simtag = gobject.timeout_add(int(timeout * 1010), self.simulate) + def __init__(self, useGtk=True): + _gtk = None + if useGtk is True: + import gtk as _gtk + _glibbase.PortableGlibReactorBase.__init__(self, gobject, _gtk, + useGtk=useGtk) def install(useGtk=True): @@ -358,7 +97,6 @@ return reactor - def portableInstall(useGtk=True): """ Configure the twisted mainloop to be run inside the gtk mainloop. @@ -369,10 +107,8 @@ return reactor - if runtime.platform.getType() != 'posix': install = portableInstall - __all__ = ['install'] diff -Nru twisted-11.1.0/twisted/internet/gtk3reactor.py twisted-12.1.0/twisted/internet/gtk3reactor.py --- twisted-11.1.0/twisted/internet/gtk3reactor.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/internet/gtk3reactor.py 2012-05-12 22:44:21.000000000 +0000 @@ -0,0 +1,65 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +This module provides support for Twisted to interact with the gtk3 mainloop +via Gobject introspection. This is like gi, but slightly slower and requires a +working $DISPLAY. + +In order to use this support, simply do the following:: + + from twisted.internet import gtk3reactor + gtk3reactor.install() + +If you wish to use a GApplication, register it with the reactor:: + + from twisted.internet import reactor + reactor.registerGApplication(app) + +Then use twisted.internet APIs as usual. +""" + +from twisted.internet import gireactor +from twisted.python import runtime + + +class Gtk3Reactor(gireactor.GIReactor): + """ + A reactor using the gtk3+ event loop. + """ + + def __init__(self): + """ + Override init to set the C{useGtk} flag. + """ + gireactor.GIReactor.__init__(self, useGtk=True) + + + +class PortableGtk3Reactor(gireactor.PortableGIReactor): + """ + Portable GTK+ 3.x reactor. + """ + def __init__(self): + """ + Override init to set the C{useGtk} flag. + """ + gireactor.PortableGIReactor.__init__(self, useGtk=True) + + + +def install(): + """ + Configure the Twisted mainloop to be run inside the gtk3+ mainloop. + """ + if runtime.platform.getType() == 'posix': + reactor = Gtk3Reactor() + else: + reactor = PortableGtk3Reactor() + + from twisted.internet.main import installReactor + installReactor(reactor) + return reactor + + +__all__ = ['install'] diff -Nru twisted-11.1.0/twisted/internet/interfaces.py twisted-12.1.0/twisted/internet/interfaces.py --- twisted-11.1.0/twisted/internet/interfaces.py 2011-10-15 21:21:45.000000000 +0000 +++ twisted-12.1.0/twisted/internet/interfaces.py 2012-04-26 13:46:20.000000000 +0000 @@ -250,7 +250,9 @@ @param backlog: size of the listen queue - @param interface: the hostname to bind to, defaults to '' (all) + @param interface: The local IPv4 or IPv6 address to which to bind; + defaults to '', ie all IPv4 addresses. To bind to all IPv4 and IPv6 + addresses, you must call this method twice. @return: an object that provides L{IListeningPort}. @@ -492,6 +494,73 @@ +class IReactorSocket(Interface): + """ + Methods which allow a reactor to use externally created sockets. + + For example, to use C{adoptStreamPort} to implement behavior equivalent + to that of L{IReactorTCP.listenTCP}, you might write code like this:: + + from socket import SOMAXCONN, AF_INET, SOCK_STREAM, socket + portSocket = socket(AF_INET, SOCK_STREAM) + # Set FD_CLOEXEC on port, left as an exercise. Then make it into a + # non-blocking listening port: + portSocket.setblocking(False) + portSocket.bind(('192.168.1.2', 12345)) + portSocket.listen(SOMAXCONN) + + # Now have the reactor use it as a TCP port + port = reactor.adoptStreamPort( + portSocket.fileno(), AF_INET, YourFactory()) + + # portSocket itself is no longer necessary, and needs to be cleaned + # up by us. + portSocket.close() + + # Whenever the server is no longer needed, stop it as usual. + stoppedDeferred = port.stopListening() + + Another potential use is to inherit a listening descriptor from a parent + process (for example, systemd or launchd), or to receive one over a UNIX + domain socket. + + Some plans for extending this interface exist. See: + + - U{http://twistedmatrix.com/trac/ticket/5570}: established connections + - U{http://twistedmatrix.com/trac/ticket/5573}: AF_UNIX ports + - U{http://twistedmatrix.com/trac/ticket/5574}: SOCK_DGRAM sockets + """ + + def adoptStreamPort(fileDescriptor, addressFamily, factory): + """ + Add an existing listening I{SOCK_STREAM} socket to the reactor to + monitor for new connections to accept and handle. + @param fileDescriptor: A file descriptor associated with a socket which + is already bound to an address and marked as listening. The socket + must be set non-blocking. Any additional flags (for example, + close-on-exec) must also be set by application code. Application + code is responsible for closing the file descriptor, which may be + done as soon as C{adoptStreamPort} returns. + @type fileDescriptor: C{int} + + @param addressFamily: The address family (or I{domain}) of the socket. + For example, L{socket.AF_INET6}. + + @param factory: A L{ServerFactory} instance to use to create new + protocols to handle connections accepted via this socket. + + @return: An object providing L{IListeningPort}. + + @raise UnsupportedAddressFamily: If the given address family is not + supported by this reactor, or not supported with the given socket + type. + + @raise UnsupportedSocketType: If the given socket type is not supported + by this reactor, or not supported with the given socket type. + """ + + + class IReactorProcess(Interface): def spawnProcess(processProtocol, executable, args=(), env={}, path=None, @@ -870,6 +939,37 @@ """ +class IReactorDaemonize(Interface): + """ + A reactor which provides hooks that need to be called before and after + daemonization. + + Notes: + - This interface SHOULD NOT be called by applications. + - This interface should only be implemented by reactors as a workaround + (in particular, it's implemented currently only by kqueue()). + For details please see the comments on ticket #1918. + """ + + def beforeDaemonize(): + """ + Hook to be called immediately before daemonization. No reactor methods + may be called until L{afterDaemonize} is called. + + @return: C{None}. + """ + + + def afterDaemonize(): + """ + Hook to be called immediately after daemonization. This may only be + called after L{beforeDaemonize} had been called previously. + + @return: C{None}. + """ + + + class IReactorFDSet(Interface): """ Implement me to be able to use L{IFileDescriptor} type resources. @@ -1189,7 +1289,7 @@ class IPushProducer(IProducer): """ A push producer, also known as a streaming producer is expected to - produce (write to this consumer) data on a continous basis, unless + produce (write to this consumer) data on a continuous basis, unless it has been paused. A paused push producer will resume producing after its resumeProducing() method is called. For a push producer which is not pauseable, these functions may be noops. @@ -1355,7 +1455,7 @@ Notification of the read connection being closed. This indicates peer did half-close of write side. It is now - the responsiblity of the this protocol to call + the responsibility of the this protocol to call loseConnection(). In addition, the protocol MUST make sure a reference to it still exists (i.e. by doing a callLater with one of its methods, etc.) as the reactor will only have a @@ -1374,6 +1474,26 @@ """ + +class IFileDescriptorReceiver(Interface): + """ + Protocols may implement L{IFileDescriptorReceiver} to receive file + descriptors sent to them. This is useful in conjunction with + L{IUNIXTransport}, which allows file descriptors to be sent between + processes on a single host. + """ + def fileDescriptorReceived(descriptor): + """ + Called when a file descriptor is received over the connection. + + @param descriptor: The descriptor which was received. + @type descriptor: C{int} + + @return: C{None} + """ + + + class IProtocolFactory(Interface): """ Interface for protocol factories. @@ -1523,15 +1643,43 @@ def getHost(): """ - Returns L{IPv4Address}. + Returns L{IPv4Address} or L{IPv6Address}. """ def getPeer(): """ - Returns L{IPv4Address}. + Returns L{IPv4Address} or L{IPv6Address}. + """ + + + +class IUNIXTransport(ITransport): + """ + Transport for stream-oriented unix domain connections. + """ + def sendFileDescriptor(descriptor): + """ + Send a duplicate of this (file, socket, pipe, etc) descriptor to the + other end of this connection. + + The send is non-blocking and will be queued if it cannot be performed + immediately. The send will be processed in order with respect to other + C{sendFileDescriptor} calls on this transport, but not necessarily with + respect to C{write} calls on this transport. The send can only be + processed if there are also bytes in the normal connection-oriented send + buffer (ie, you must call C{write} at least as many times as you call + C{sendFileDescriptor}). + + @param descriptor: An C{int} giving a valid file descriptor in this + process. Note that a I{file descriptor} may actually refer to a + socket, a pipe, or anything else POSIX tries to treat in the same + way as a file. + + @return: C{None} """ + class ITLSTransport(ITCPTransport): """ A TCP transport that supports switching to TLS midstream. @@ -1899,4 +2047,3 @@ @return: a client endpoint @rtype: L{IStreamClientEndpoint} """ - diff -Nru twisted-11.1.0/twisted/internet/iocpreactor/abstract.py twisted-12.1.0/twisted/internet/iocpreactor/abstract.py --- twisted-11.1.0/twisted/internet/iocpreactor/abstract.py 2011-10-28 15:35:02.000000000 +0000 +++ twisted-12.1.0/twisted/internet/iocpreactor/abstract.py 2012-03-15 20:18:28.000000000 +0000 @@ -22,7 +22,7 @@ """ File handle that can read and write asynchronously """ - implements(interfaces.IProducer, interfaces.IConsumer, + implements(interfaces.IPushProducer, interfaces.IConsumer, interfaces.ITransport, interfaces.IHalfCloseableDescriptor) # read stuff maxReadBuffers = 16 @@ -227,8 +227,8 @@ self.connectionLost(failure.Failure(main.CONNECTION_DONE)) elif self._writeDisconnecting: # I was previously asked to to half-close the connection. - self._closeWriteConnection() self._writeDisconnected = True + self._closeWriteConnection() return False else: return True diff -Nru twisted-11.1.0/twisted/internet/iocpreactor/iocpsupport/acceptex.pxi twisted-12.1.0/twisted/internet/iocpreactor/iocpsupport/acceptex.pxi --- twisted-11.1.0/twisted/internet/iocpreactor/iocpsupport/acceptex.pxi 2011-03-17 03:34:22.000000000 +0000 +++ twisted-12.1.0/twisted/internet/iocpreactor/iocpsupport/acceptex.pxi 2012-03-12 23:15:18.000000000 +0000 @@ -7,7 +7,8 @@ CAUTION: unlike system AcceptEx(), this function returns 0 on success """ cdef unsigned long bytes - cdef int size, rc + cdef int rc + cdef Py_ssize_t size cdef void *mem_buffer cdef myOVERLAPPED *ov @@ -17,11 +18,13 @@ if obj is not None: ov.obj = obj - rc = lpAcceptEx(listening, accepting, mem_buffer, 0, size / 2, size / 2, + rc = lpAcceptEx(listening, accepting, mem_buffer, 0, + size / 2, size / 2, &bytes, ov) if not rc: rc = WSAGetLastError() if rc != ERROR_IO_PENDING: + PyMem_Free(ov) return rc # operation is in progress @@ -30,12 +33,14 @@ def get_accept_addrs(long s, object buff): cdef WSAPROTOCOL_INFO wsa_pi - cdef int size, locallen, remotelen + cdef int locallen, remotelen + cdef Py_ssize_t size cdef void *mem_buffer cdef sockaddr *localaddr, *remoteaddr PyObject_AsReadBuffer(buff, &mem_buffer, &size) - lpGetAcceptExSockaddrs(mem_buffer, 0, size / 2, size / 2, &localaddr, &locallen, &remoteaddr, &remotelen) + lpGetAcceptExSockaddrs(mem_buffer, 0, size / 2, size / 2, + &localaddr, &locallen, &remoteaddr, &remotelen) return remoteaddr.sa_family, _makesockaddr(localaddr, locallen), _makesockaddr(remoteaddr, remotelen) diff -Nru twisted-11.1.0/twisted/internet/iocpreactor/iocpsupport/connectex.pxi twisted-12.1.0/twisted/internet/iocpreactor/iocpsupport/connectex.pxi --- twisted-11.1.0/twisted/internet/iocpreactor/iocpsupport/connectex.pxi 2011-03-17 03:34:22.000000000 +0000 +++ twisted-12.1.0/twisted/internet/iocpreactor/iocpsupport/connectex.pxi 2012-03-27 12:27:04.000000000 +0000 @@ -8,14 +8,23 @@ """ cdef int family, rc cdef myOVERLAPPED *ov - cdef sockaddr name + cdef sockaddr_in ipv4_name + cdef sockaddr_in6 ipv6_name + cdef sockaddr *name + cdef int namelen if not have_connectex: raise ValueError, 'ConnectEx is not available on this system' family = getAddrFamily(s) if family == AF_INET: - fillinetaddr(&name, addr) + name = &ipv4_name + namelen = sizeof(ipv4_name) + fillinetaddr(&ipv4_name, addr) + elif family == AF_INET6: + name = &ipv6_name + namelen = sizeof(ipv6_name) + fillinet6addr(&ipv6_name, addr) else: raise ValueError, 'unsupported address family' name.sa_family = family @@ -24,11 +33,12 @@ if obj is not None: ov.obj = obj - rc = lpConnectEx(s, &name, sizeof(name), NULL, 0, NULL, ov) + rc = lpConnectEx(s, name, namelen, NULL, 0, NULL, ov) if not rc: rc = WSAGetLastError() if rc != ERROR_IO_PENDING: + PyMem_Free(ov) return rc # operation is in progress diff -Nru twisted-11.1.0/twisted/internet/iocpreactor/iocpsupport/iocpsupport.c twisted-12.1.0/twisted/internet/iocpreactor/iocpsupport/iocpsupport.c --- twisted-11.1.0/twisted/internet/iocpreactor/iocpsupport/iocpsupport.c 2011-06-03 22:55:35.000000000 +0000 +++ twisted-12.1.0/twisted/internet/iocpreactor/iocpsupport/iocpsupport.c 2012-03-27 12:27:04.000000000 +0000 @@ -1,4 +1,4 @@ -/* Generated by Cython 0.14.1 on Sat May 14 18:30:23 2011 */ +/* Generated by Cython 0.15.1 on Tue Mar 27 07:16:06 2012 */ #define PY_SSIZE_T_CLEAN #include "Python.h" @@ -46,7 +46,7 @@ #define PY_SSIZE_T_MIN INT_MIN #define PY_FORMAT_SIZE_T "" #define PyInt_FromSsize_t(z) PyInt_FromLong(z) - #define PyInt_AsSsize_t(o) PyInt_AsLong(o) + #define PyInt_AsSsize_t(o) __Pyx_PyInt_AsInt(o) #define PyNumber_Index(o) PyNumber_Int(o) #define PyIndex_Check(o) PyNumber_Check(o) #define PyErr_WarnEx(category, message, stacklevel) PyErr_Warn(category, message) @@ -159,6 +159,15 @@ #define PyBoolObject PyLongObject #endif +#if PY_VERSION_HEX < 0x03020000 + typedef long Py_hash_t; + #define __Pyx_PyInt_FromHash_t PyInt_FromLong + #define __Pyx_PyInt_AsHash_t PyInt_AsLong +#else + #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t + #define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t +#endif + #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) @@ -209,16 +218,19 @@ #define __Pyx_DOCSTR(n) (n) #endif -#ifdef __cplusplus -#define __PYX_EXTERN_C extern "C" -#else -#define __PYX_EXTERN_C extern +#ifndef __PYX_EXTERN_C + #ifdef __cplusplus + #define __PYX_EXTERN_C extern "C" + #else + #define __PYX_EXTERN_C extern + #endif #endif #if defined(WIN32) || defined(MS_WINDOWS) #define _USE_MATH_DEFINES #endif #include +#define __PYX_HAVE__iocpsupport #define __PYX_HAVE_API__iocpsupport #include "io.h" #include "errno.h" @@ -228,6 +240,9 @@ #include "python.h" #include "string.h" #include "winsock_pointers.h" +#ifdef _OPENMP +#include +#endif /* _OPENMP */ #ifdef PYREX_WITHOUT_ASSERTIONS #define CYTHON_WITHOUT_ASSERTIONS @@ -270,6 +285,7 @@ #define __Pyx_PyBytes_FromUString(s) PyBytes_FromString((char*)s) #define __Pyx_PyBytes_AsUString(s) ((unsigned char*) PyBytes_AsString(s)) +#define __Pyx_Owned_Py_None(b) (Py_INCREF(Py_None), Py_None) #define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False)) static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x); @@ -282,17 +298,17 @@ #ifdef __GNUC__ -/* Test for GCC > 2.95 */ -#if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)) -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) -#else /* __GNUC__ > 2 ... */ -#define likely(x) (x) -#define unlikely(x) (x) -#endif /* __GNUC__ > 2 ... */ + /* Test for GCC > 2.95 */ + #if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)) + #define likely(x) __builtin_expect(!!(x), 1) + #define unlikely(x) __builtin_expect(!!(x), 0) + #else /* __GNUC__ > 2 ... */ + #define likely(x) (x) + #define unlikely(x) (x) + #endif /* __GNUC__ > 2 ... */ #else /* __GNUC__ */ -#define likely(x) (x) -#define unlikely(x) (x) + #define likely(x) (x) + #define unlikely(x) (x) #endif /* __GNUC__ */ static PyObject *__pyx_m; @@ -313,46 +329,80 @@ "wsasend.pxi", }; -typedef int __pyx_t_11iocpsupport_size_t; - -typedef unsigned long __pyx_t_11iocpsupport_HANDLE; - -typedef unsigned long __pyx_t_11iocpsupport_SOCKET; - +/* "iocpsupport.pyx":6 + * + * # HANDLE and SOCKET are pointer-sized (they are 64 bit wide in 64-bit builds) + * ctypedef size_t HANDLE # <<<<<<<<<<<<<< + * ctypedef size_t SOCKET + * ctypedef unsigned long DWORD + */ +typedef size_t __pyx_t_11iocpsupport_HANDLE; + +/* "iocpsupport.pyx":7 + * # HANDLE and SOCKET are pointer-sized (they are 64 bit wide in 64-bit builds) + * ctypedef size_t HANDLE + * ctypedef size_t SOCKET # <<<<<<<<<<<<<< + * ctypedef unsigned long DWORD + * # it's really a pointer, but we use it as an integer + */ +typedef size_t __pyx_t_11iocpsupport_SOCKET; + +/* "iocpsupport.pyx":8 + * ctypedef size_t HANDLE + * ctypedef size_t SOCKET + * ctypedef unsigned long DWORD # <<<<<<<<<<<<<< + * # it's really a pointer, but we use it as an integer + * ctypedef size_t ULONG_PTR + */ typedef unsigned long __pyx_t_11iocpsupport_DWORD; -typedef unsigned long __pyx_t_11iocpsupport_ULONG_PTR; +/* "iocpsupport.pyx":10 + * ctypedef unsigned long DWORD + * # it's really a pointer, but we use it as an integer + * ctypedef size_t ULONG_PTR # <<<<<<<<<<<<<< + * ctypedef int BOOL + * + */ +typedef size_t __pyx_t_11iocpsupport_ULONG_PTR; +/* "iocpsupport.pyx":11 + * # it's really a pointer, but we use it as an integer + * ctypedef size_t ULONG_PTR + * ctypedef int BOOL # <<<<<<<<<<<<<< + * + * cdef extern from 'io.h': + */ typedef int __pyx_t_11iocpsupport_BOOL; -/* Type declarations */ +/*--- Type declarations ---*/ +struct __pyx_obj_11iocpsupport_CompletionPort; +struct __pyx_t_11iocpsupport_myOVERLAPPED; -/* "iocpsupport.pyx":114 +/* "iocpsupport.pyx":124 * # BOOL (*lpTransmitFile)(SOCKET s, HANDLE hFile, DWORD size, DWORD buffer_size, OVERLAPPED *ov, TRANSMIT_FILE_BUFFERS *buff, DWORD flags) * * cdef struct myOVERLAPPED: # <<<<<<<<<<<<<< * OVERLAPPED ov * PyObject *obj */ - struct __pyx_t_11iocpsupport_myOVERLAPPED { OVERLAPPED ov; struct PyObject *obj; }; -/* "iocpsupport.pyx":138 +/* "iocpsupport.pyx":148 * setattr(self, k, v) * * cdef class CompletionPort: # <<<<<<<<<<<<<< * cdef HANDLE port * def __init__(self): */ - struct __pyx_obj_11iocpsupport_CompletionPort { PyObject_HEAD __pyx_t_11iocpsupport_HANDLE port; }; + #ifndef CYTHON_REFNANNY #define CYTHON_REFNANNY 0 #endif @@ -367,44 +417,38 @@ void (*FinishContext)(void**); } __Pyx_RefNannyAPIStruct; static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; - static __Pyx_RefNannyAPIStruct * __Pyx_RefNannyImportAPI(const char *modname) { - PyObject *m = NULL, *p = NULL; - void *r = NULL; - m = PyImport_ImportModule((char *)modname); - if (!m) goto end; - p = PyObject_GetAttrString(m, (char *)"RefNannyAPI"); - if (!p) goto end; - r = PyLong_AsVoidPtr(p); - end: - Py_XDECREF(p); - Py_XDECREF(m); - return (__Pyx_RefNannyAPIStruct *)r; - } - #define __Pyx_RefNannySetupContext(name) void *__pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) + static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); /*proto*/ + #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; + #define __Pyx_RefNannySetupContext(name) __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) #define __Pyx_RefNannyFinishContext() __Pyx_RefNanny->FinishContext(&__pyx_refnanny) - #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r);} } while(0) + #define __Pyx_XINCREF(r) do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0) + #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0) + #define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0) + #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0) #else + #define __Pyx_RefNannyDeclarations #define __Pyx_RefNannySetupContext(name) #define __Pyx_RefNannyFinishContext() #define __Pyx_INCREF(r) Py_INCREF(r) #define __Pyx_DECREF(r) Py_DECREF(r) #define __Pyx_GOTREF(r) #define __Pyx_GIVEREF(r) + #define __Pyx_XINCREF(r) Py_XINCREF(r) #define __Pyx_XDECREF(r) Py_XDECREF(r) + #define __Pyx_XGOTREF(r) + #define __Pyx_XGIVEREF(r) #endif /* CYTHON_REFNANNY */ -#define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);} } while(0) -#define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r);} } while(0) static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/ static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/ static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/ -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/ +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); /*proto*/ static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/ @@ -418,8 +462,7 @@ static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected); -static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/ -static int __Pyx_EndUnpack(PyObject *, Py_ssize_t expected); /*proto*/ +static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected); /*proto*/ static CYTHON_INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict, const char* function_name, int kw_allowed); /*proto*/ @@ -498,8 +541,6 @@ return r; } -static CYTHON_INLINE long __Pyx_div_long(long, long); /* proto */ - static PyObject *__Pyx_FindPy2Metaclass(PyObject *bases); /*proto*/ static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, @@ -519,7 +560,19 @@ static int __pyx_binding_PyCFunctionType_init(void); /* proto */ -static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/ +static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level); /*proto*/ + +#include + +static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals); /*proto*/ + +static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals); /*proto*/ + +#if PY_MAJOR_VERSION >= 3 +#define __Pyx_PyString_Equals __Pyx_PyUnicode_Equals +#else +#define __Pyx_PyString_Equals __Pyx_PyBytes_Equals +#endif static CYTHON_INLINE unsigned char __Pyx_PyInt_AsUnsignedChar(PyObject *); @@ -553,98 +606,99 @@ static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject *); -static void __Pyx_AddTraceback(const char *funcname); /*proto*/ +static int __Pyx_check_binary_version(void); + +static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno, + int __pyx_lineno, const char *__pyx_filename); /*proto*/ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/ -/* Module declarations from iocpsupport */ +/* Module declarations from 'iocpsupport' */ static PyTypeObject *__pyx_ptype_11iocpsupport_CompletionPort = 0; static struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_f_11iocpsupport_makeOV(void); /*proto*/ static void __pyx_f_11iocpsupport_raise_error(int, PyObject *); /*proto*/ -static PyObject *__pyx_f_11iocpsupport__makesockaddr(struct sockaddr *, int); /*proto*/ +static PyObject *__pyx_f_11iocpsupport__makesockaddr(struct sockaddr *, Py_ssize_t); /*proto*/ static PyObject *__pyx_f_11iocpsupport_fillinetaddr(struct sockaddr_in *, PyObject *); /*proto*/ +static PyObject *__pyx_f_11iocpsupport_fillinet6addr(struct sockaddr_in6 *, PyObject *); /*proto*/ static int __pyx_f_11iocpsupport_getAddrFamily(__pyx_t_11iocpsupport_SOCKET); /*proto*/ #define __Pyx_MODULE_NAME "iocpsupport" -static int __pyx_module_is_main_iocpsupport = 0; +int __pyx_module_is_main_iocpsupport = 0; -/* Implementation of iocpsupport */ +/* Implementation of 'iocpsupport' */ static PyObject *__pyx_builtin_ValueError; static PyObject *__pyx_builtin_MemoryError; -static PyObject *__pyx_builtin_WindowsError; +static PyObject *__pyx_builtin_RuntimeError; static char __pyx_k_1[] = "CreateIoCompletionPort"; static char __pyx_k_2[] = "PostQueuedCompletionStatus"; static char __pyx_k_3[] = ":"; static char __pyx_k_5[] = "["; static char __pyx_k_6[] = "]"; static char __pyx_k_7[] = "invalid IP address"; -static char __pyx_k_8[] = "ConnectEx is not available on this system"; -static char __pyx_k_9[] = "unsupported address family"; -static char __pyx_k_10[] = "second argument needs to be a list"; -static char __pyx_k_11[] = "length of address length buffer needs to be sizeof(int)"; -static char __pyx_k_12[] = "Failed to initialize Winsock function vectors"; +static char __pyx_k_8[] = "%"; +static char __pyx_k_10[] = "invalid IPv6 address %r"; +static char __pyx_k_11[] = "undefined error occurred during address parsing"; +static char __pyx_k_12[] = "ConnectEx is not available on this system"; +static char __pyx_k_13[] = "unsupported address family"; +static char __pyx_k_14[] = "second argument needs to be a list"; +static char __pyx_k_15[] = "length of address length buffer needs to be sizeof(int)"; +static char __pyx_k_16[] = "Failed to initialize Winsock function vectors"; static char __pyx_k__s[] = "s"; -static char __pyx_k__buf[] = "buf"; static char __pyx_k__key[] = "key"; -static char __pyx_k__len[] = "len"; static char __pyx_k__obj[] = "obj"; static char __pyx_k__addr[] = "addr"; static char __pyx_k__buff[] = "buff"; -static char __pyx_k__port[] = "port"; static char __pyx_k__recv[] = "recv"; static char __pyx_k__self[] = "self"; static char __pyx_k__send[] = "send"; static char __pyx_k__Event[] = "Event"; static char __pyx_k__bytes[] = "bytes"; static char __pyx_k__flags[] = "flags"; -static char __pyx_k__items[] = "items"; static char __pyx_k__owner[] = "owner"; +static char __pyx_k__split[] = "split"; static char __pyx_k__accept[] = "accept"; static char __pyx_k__handle[] = "handle"; static char __pyx_k__rsplit[] = "rsplit"; -static char __pyx_k__s_addr[] = "s_addr"; static char __pyx_k__socket[] = "socket"; static char __pyx_k__connect[] = "connect"; -static char __pyx_k__sa_data[] = "sa_data"; static char __pyx_k____init__[] = "__init__"; static char __pyx_k____main__[] = "__main__"; static char __pyx_k____test__[] = "__test__"; static char __pyx_k__bufflist[] = "bufflist"; static char __pyx_k__callback[] = "callback"; static char __pyx_k__recvfrom[] = "recvfrom"; -static char __pyx_k__sin_addr[] = "sin_addr"; -static char __pyx_k__sin_port[] = "sin_port"; static char __pyx_k__accepting[] = "accepting"; static char __pyx_k__addr_buff[] = "addr_buff"; static char __pyx_k__listening[] = "listening"; -static char __pyx_k__sa_family[] = "sa_family"; -static char __pyx_k__sin6_port[] = "sin6_port"; static char __pyx_k__ValueError[] = "ValueError"; static char __pyx_k__getsockopt[] = "getsockopt"; static char __pyx_k__maxAddrLen[] = "maxAddrLen"; static char __pyx_k__MemoryError[] = "MemoryError"; static char __pyx_k__iocpsupport[] = "iocpsupport"; +static char __pyx_k__RuntimeError[] = "RuntimeError"; static char __pyx_k__WindowsError[] = "WindowsError"; -static char __pyx_k__iMaxSockAddr[] = "iMaxSockAddr"; static char __pyx_k__makesockaddr[] = "makesockaddr"; static char __pyx_k__addr_len_buff[] = "addr_len_buff"; static char __pyx_k__have_connectex[] = "have_connectex"; -static char __pyx_k__iAddressFamily[] = "iAddressFamily"; static char __pyx_k__get_accept_addrs[] = "get_accept_addrs"; static char __pyx_k__AllocateReadBuffer[] = "AllocateReadBuffer"; static char __pyx_k__WSAAddressToString[] = "WSAAddressToString"; static PyObject *__pyx_n_s_1; +static PyObject *__pyx_kp_s_10; static PyObject *__pyx_kp_s_11; static PyObject *__pyx_kp_s_12; +static PyObject *__pyx_kp_s_13; +static PyObject *__pyx_kp_s_15; +static PyObject *__pyx_kp_s_16; static PyObject *__pyx_n_s_2; static PyObject *__pyx_kp_s_3; static PyObject *__pyx_kp_s_5; static PyObject *__pyx_kp_s_6; static PyObject *__pyx_kp_s_7; static PyObject *__pyx_kp_s_8; -static PyObject *__pyx_kp_s_9; static PyObject *__pyx_n_s__AllocateReadBuffer; static PyObject *__pyx_n_s__Event; static PyObject *__pyx_n_s__MemoryError; +static PyObject *__pyx_n_s__RuntimeError; static PyObject *__pyx_n_s__ValueError; static PyObject *__pyx_n_s__WSAAddressToString; static PyObject *__pyx_n_s__WindowsError; @@ -656,7 +710,6 @@ static PyObject *__pyx_n_s__addr; static PyObject *__pyx_n_s__addr_buff; static PyObject *__pyx_n_s__addr_len_buff; -static PyObject *__pyx_n_s__buf; static PyObject *__pyx_n_s__buff; static PyObject *__pyx_n_s__bufflist; static PyObject *__pyx_n_s__bytes; @@ -667,36 +720,27 @@ static PyObject *__pyx_n_s__getsockopt; static PyObject *__pyx_n_s__handle; static PyObject *__pyx_n_s__have_connectex; -static PyObject *__pyx_n_s__iAddressFamily; -static PyObject *__pyx_n_s__iMaxSockAddr; static PyObject *__pyx_n_s__iocpsupport; -static PyObject *__pyx_n_s__items; static PyObject *__pyx_n_s__key; -static PyObject *__pyx_n_s__len; static PyObject *__pyx_n_s__listening; static PyObject *__pyx_n_s__makesockaddr; static PyObject *__pyx_n_s__maxAddrLen; static PyObject *__pyx_n_s__obj; static PyObject *__pyx_n_s__owner; -static PyObject *__pyx_n_s__port; static PyObject *__pyx_n_s__recv; static PyObject *__pyx_n_s__recvfrom; static PyObject *__pyx_n_s__rsplit; static PyObject *__pyx_n_s__s; -static PyObject *__pyx_n_s__s_addr; -static PyObject *__pyx_n_s__sa_data; -static PyObject *__pyx_n_s__sa_family; static PyObject *__pyx_n_s__self; static PyObject *__pyx_n_s__send; -static PyObject *__pyx_n_s__sin6_port; -static PyObject *__pyx_n_s__sin_addr; -static PyObject *__pyx_n_s__sin_port; static PyObject *__pyx_n_s__socket; +static PyObject *__pyx_n_s__split; static PyObject *__pyx_int_0; static PyObject *__pyx_int_1; static PyObject *__pyx_k_tuple_4; +static PyObject *__pyx_k_tuple_9; -/* "iocpsupport.pyx":118 +/* "iocpsupport.pyx":128 * PyObject *obj * * cdef myOVERLAPPED *makeOV() except NULL: # <<<<<<<<<<<<<< @@ -704,24 +748,28 @@ * res = PyMem_Malloc(sizeof(myOVERLAPPED)) */ -static struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_f_11iocpsupport_makeOV(void) { +static struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_f_11iocpsupport_makeOV(void) { struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_v_res; struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_r; + __Pyx_RefNannyDeclarations void *__pyx_t_1; int __pyx_t_2; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; __Pyx_RefNannySetupContext("makeOV"); - /* "iocpsupport.pyx":120 + /* "iocpsupport.pyx":130 * cdef myOVERLAPPED *makeOV() except NULL: * cdef myOVERLAPPED *res * res = PyMem_Malloc(sizeof(myOVERLAPPED)) # <<<<<<<<<<<<<< * if not res: * raise MemoryError */ - __pyx_t_1 = PyMem_Malloc((sizeof(struct __pyx_t_11iocpsupport_myOVERLAPPED))); if (unlikely(__pyx_t_1 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyMem_Malloc((sizeof(struct __pyx_t_11iocpsupport_myOVERLAPPED))); if (unlikely(__pyx_t_1 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __pyx_v_res = ((struct __pyx_t_11iocpsupport_myOVERLAPPED *)__pyx_t_1); - /* "iocpsupport.pyx":121 + /* "iocpsupport.pyx":131 * cdef myOVERLAPPED *res * res = PyMem_Malloc(sizeof(myOVERLAPPED)) * if not res: # <<<<<<<<<<<<<< @@ -731,19 +779,19 @@ __pyx_t_2 = (!(__pyx_v_res != 0)); if (__pyx_t_2) { - /* "iocpsupport.pyx":122 + /* "iocpsupport.pyx":132 * res = PyMem_Malloc(sizeof(myOVERLAPPED)) * if not res: * raise MemoryError # <<<<<<<<<<<<<< * memset(res, 0, sizeof(myOVERLAPPED)) * return res */ - PyErr_NoMemory(); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + PyErr_NoMemory(); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;} goto __pyx_L3; } __pyx_L3:; - /* "iocpsupport.pyx":123 + /* "iocpsupport.pyx":133 * if not res: * raise MemoryError * memset(res, 0, sizeof(myOVERLAPPED)) # <<<<<<<<<<<<<< @@ -752,7 +800,7 @@ */ memset(__pyx_v_res, 0, (sizeof(struct __pyx_t_11iocpsupport_myOVERLAPPED))); - /* "iocpsupport.pyx":124 + /* "iocpsupport.pyx":134 * raise MemoryError * memset(res, 0, sizeof(myOVERLAPPED)) * return res # <<<<<<<<<<<<<< @@ -765,14 +813,14 @@ __pyx_r = 0; goto __pyx_L0; __pyx_L1_error:; - __Pyx_AddTraceback("iocpsupport.makeOV"); + __Pyx_AddTraceback("iocpsupport.makeOV", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } -/* "iocpsupport.pyx":126 +/* "iocpsupport.pyx":136 * return res * * cdef void raise_error(int err, object message) except *: # <<<<<<<<<<<<<< @@ -780,13 +828,18 @@ * err = GetLastError() */ -static void __pyx_f_11iocpsupport_raise_error(int __pyx_v_err, PyObject *__pyx_v_message) { +static void __pyx_f_11iocpsupport_raise_error(int __pyx_v_err, PyObject *__pyx_v_message) { + __Pyx_RefNannyDeclarations int __pyx_t_1; PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; __Pyx_RefNannySetupContext("raise_error"); - /* "iocpsupport.pyx":127 + /* "iocpsupport.pyx":137 * * cdef void raise_error(int err, object message) except *: * if not err: # <<<<<<<<<<<<<< @@ -796,7 +849,7 @@ __pyx_t_1 = (!__pyx_v_err); if (__pyx_t_1) { - /* "iocpsupport.pyx":128 + /* "iocpsupport.pyx":138 * cdef void raise_error(int err, object message) except *: * if not err: * err = GetLastError() # <<<<<<<<<<<<<< @@ -808,40 +861,44 @@ } __pyx_L3:; - /* "iocpsupport.pyx":129 + /* "iocpsupport.pyx":139 * if not err: * err = GetLastError() * raise WindowsError(message, err) # <<<<<<<<<<<<<< * * class Event: */ - __pyx_t_2 = PyInt_FromLong(__pyx_v_err); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = __Pyx_GetName(__pyx_b, __pyx_n_s__WindowsError); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 139; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_3)); + __pyx_t_3 = PyInt_FromLong(__pyx_v_err); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 139; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 139; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_4)); __Pyx_INCREF(__pyx_v_message); - PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_message); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_message); __Pyx_GIVEREF(__pyx_v_message); - PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_2); - __Pyx_GIVEREF(__pyx_t_2); - __pyx_t_2 = 0; - __pyx_t_2 = PyObject_Call(__pyx_builtin_WindowsError, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0; - __Pyx_Raise(__pyx_t_2, 0, 0); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + __pyx_t_3 = 0; + __pyx_t_3 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 139; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0; + __Pyx_Raise(__pyx_t_3, 0, 0, 0); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 139; __pyx_clineno = __LINE__; goto __pyx_L1_error;} goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_2); __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("iocpsupport.raise_error"); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_AddTraceback("iocpsupport.raise_error", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_L0:; __Pyx_RefNannyFinishContext(); } -/* "iocpsupport.pyx":132 +/* "iocpsupport.pyx":142 * * class Event: * def __init__(self, callback, owner, **kw): # <<<<<<<<<<<<<< @@ -856,189 +913,218 @@ PyObject *__pyx_v_callback = 0; PyObject *__pyx_v_owner = 0; PyObject *__pyx_v_kw = 0; - PyObject *__pyx_v_k; - PyObject *__pyx_v_v; + PyObject *__pyx_v_k = NULL; + PyObject *__pyx_v_v = NULL; PyObject *__pyx_r = NULL; - Py_ssize_t __pyx_t_1; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - PyObject *__pyx_t_4 = NULL; + Py_ssize_t __pyx_t_3; + PyObject *(*__pyx_t_4)(PyObject *); PyObject *__pyx_t_5 = NULL; PyObject *__pyx_t_6 = NULL; - int __pyx_t_7; + PyObject *__pyx_t_7 = NULL; + PyObject *(*__pyx_t_8)(PyObject *); + int __pyx_t_9; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__self,&__pyx_n_s__callback,&__pyx_n_s__owner,0}; __Pyx_RefNannySetupContext("__init__"); __pyx_self = __pyx_self; __pyx_v_kw = PyDict_New(); if (unlikely(!__pyx_v_kw)) return NULL; __Pyx_GOTREF(__pyx_v_kw); - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + { PyObject* values[3] = {0,0,0}; - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 0: - values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__self); - if (likely(values[0])) kw_args--; - else goto __pyx_L5_argtuple_error; - case 1: - values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__callback); - if (likely(values[1])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("__init__", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; } - case 2: - values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__owner); - if (likely(values[2])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("__init__", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + kw_args = PyDict_Size(__pyx_kwds); + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__self); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__callback); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__init__", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 2: + values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__owner); + if (likely(values[2])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__init__", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, __pyx_v_kw, values, PyTuple_GET_SIZE(__pyx_args), "__init__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, __pyx_v_kw, values, PyTuple_GET_SIZE(__pyx_args), "__init__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); } __pyx_v_self = values[0]; __pyx_v_callback = values[1]; __pyx_v_owner = values[2]; - } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { - goto __pyx_L5_argtuple_error; - } else { - __pyx_v_self = PyTuple_GET_ITEM(__pyx_args, 0); - __pyx_v_callback = PyTuple_GET_ITEM(__pyx_args, 1); - __pyx_v_owner = PyTuple_GET_ITEM(__pyx_args, 2); } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("__init__", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __Pyx_RaiseArgtupleInvalid("__init__", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __pyx_L3_error:; - __Pyx_DECREF(__pyx_v_kw); - __Pyx_AddTraceback("iocpsupport.Event.__init__"); + __Pyx_DECREF(__pyx_v_kw); __pyx_v_kw = 0; + __Pyx_AddTraceback("iocpsupport.Event.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; - __pyx_v_k = Py_None; __Pyx_INCREF(Py_None); - __pyx_v_v = Py_None; __Pyx_INCREF(Py_None); - /* "iocpsupport.pyx":133 + /* "iocpsupport.pyx":143 * class Event: * def __init__(self, callback, owner, **kw): * self.callback = callback # <<<<<<<<<<<<<< * self.owner = owner * for k, v in kw.items(): */ - if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__callback, __pyx_v_callback) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 133; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__callback, __pyx_v_callback) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 143; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - /* "iocpsupport.pyx":134 + /* "iocpsupport.pyx":144 * def __init__(self, callback, owner, **kw): * self.callback = callback * self.owner = owner # <<<<<<<<<<<<<< * for k, v in kw.items(): * setattr(self, k, v) */ - if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__owner, __pyx_v_owner) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_v_self, __pyx_n_s__owner, __pyx_v_owner) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - /* "iocpsupport.pyx":135 + /* "iocpsupport.pyx":145 * self.callback = callback * self.owner = owner * for k, v in kw.items(): # <<<<<<<<<<<<<< * setattr(self, k, v) * */ - if (unlikely(__pyx_v_kw == Py_None)) { - PyErr_SetString(PyExc_AttributeError, "'NoneType' object has no attribute 'items'"); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (unlikely(((PyObject *)__pyx_v_kw) == Py_None)) { + PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", "items"); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;} } - __pyx_t_2 = PyDict_Items(__pyx_v_kw); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - if (PyList_CheckExact(__pyx_t_2) || PyTuple_CheckExact(__pyx_t_2)) { - __pyx_t_1 = 0; __pyx_t_3 = __pyx_t_2; __Pyx_INCREF(__pyx_t_3); + __pyx_t_1 = PyDict_Items(__pyx_v_kw); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (PyList_CheckExact(__pyx_t_1) || PyTuple_CheckExact(__pyx_t_1)) { + __pyx_t_2 = __pyx_t_1; __Pyx_INCREF(__pyx_t_2); __pyx_t_3 = 0; + __pyx_t_4 = NULL; } else { - __pyx_t_1 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); + __pyx_t_3 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = Py_TYPE(__pyx_t_2)->tp_iternext; } - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; for (;;) { - if (likely(PyList_CheckExact(__pyx_t_3))) { - if (__pyx_t_1 >= PyList_GET_SIZE(__pyx_t_3)) break; - __pyx_t_2 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_1); __Pyx_INCREF(__pyx_t_2); __pyx_t_1++; - } else if (likely(PyTuple_CheckExact(__pyx_t_3))) { - if (__pyx_t_1 >= PyTuple_GET_SIZE(__pyx_t_3)) break; - __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_1); __Pyx_INCREF(__pyx_t_2); __pyx_t_1++; + if (PyList_CheckExact(__pyx_t_2)) { + if (__pyx_t_3 >= PyList_GET_SIZE(__pyx_t_2)) break; + __pyx_t_1 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_1); __pyx_t_3++; + } else if (PyTuple_CheckExact(__pyx_t_2)) { + if (__pyx_t_3 >= PyTuple_GET_SIZE(__pyx_t_2)) break; + __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_1); __pyx_t_3++; } else { - __pyx_t_2 = PyIter_Next(__pyx_t_3); - if (!__pyx_t_2) { - if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = __pyx_t_4(__pyx_t_2); + if (unlikely(!__pyx_t_1)) { + if (PyErr_Occurred()) { + if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear(); + else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } break; } - __Pyx_GOTREF(__pyx_t_2); + __Pyx_GOTREF(__pyx_t_1); } - if (PyTuple_CheckExact(__pyx_t_2) && likely(PyTuple_GET_SIZE(__pyx_t_2) == 2)) { - PyObject* tuple = __pyx_t_2; - __pyx_t_4 = PyTuple_GET_ITEM(tuple, 0); __Pyx_INCREF(__pyx_t_4); - __pyx_t_5 = PyTuple_GET_ITEM(tuple, 1); __Pyx_INCREF(__pyx_t_5); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_DECREF(__pyx_v_k); - __pyx_v_k = __pyx_t_4; - __pyx_t_4 = 0; - __Pyx_DECREF(__pyx_v_v); - __pyx_v_v = __pyx_t_5; - __pyx_t_5 = 0; + if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) { + PyObject* sequence = __pyx_t_1; + if (likely(PyTuple_CheckExact(sequence))) { + if (unlikely(PyTuple_GET_SIZE(sequence) != 2)) { + if (PyTuple_GET_SIZE(sequence) > 2) __Pyx_RaiseTooManyValuesError(2); + else __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(sequence)); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_5 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_6 = PyTuple_GET_ITEM(sequence, 1); + } else { + if (unlikely(PyList_GET_SIZE(sequence) != 2)) { + if (PyList_GET_SIZE(sequence) > 2) __Pyx_RaiseTooManyValuesError(2); + else __Pyx_RaiseNeedMoreValuesError(PyList_GET_SIZE(sequence)); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_5 = PyList_GET_ITEM(sequence, 0); + __pyx_t_6 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; } else { - __pyx_t_6 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_6); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_4 = __Pyx_UnpackItem(__pyx_t_6, 0); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_5 = __Pyx_UnpackItem(__pyx_t_6, 1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + Py_ssize_t index = -1; + __pyx_t_7 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_8 = Py_TYPE(__pyx_t_7)->tp_iternext; + index = 0; __pyx_t_5 = __pyx_t_8(__pyx_t_7); if (unlikely(!__pyx_t_5)) goto __pyx_L8_unpacking_failed; __Pyx_GOTREF(__pyx_t_5); - if (__Pyx_EndUnpack(__pyx_t_6, 2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - __Pyx_DECREF(__pyx_v_k); - __pyx_v_k = __pyx_t_4; - __pyx_t_4 = 0; - __Pyx_DECREF(__pyx_v_v); - __pyx_v_v = __pyx_t_5; - __pyx_t_5 = 0; - } + index = 1; __pyx_t_6 = __pyx_t_8(__pyx_t_7); if (unlikely(!__pyx_t_6)) goto __pyx_L8_unpacking_failed; + __Pyx_GOTREF(__pyx_t_6); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_8(__pyx_t_7), 2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + goto __pyx_L9_unpacking_done; + __pyx_L8_unpacking_failed:; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_StopIteration)) PyErr_Clear(); + if (!PyErr_Occurred()) __Pyx_RaiseNeedMoreValuesError(index); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_L9_unpacking_done:; + } + __Pyx_XDECREF(__pyx_v_k); + __pyx_v_k = __pyx_t_5; + __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_v_v); + __pyx_v_v = __pyx_t_6; + __pyx_t_6 = 0; - /* "iocpsupport.pyx":136 + /* "iocpsupport.pyx":146 * self.owner = owner * for k, v in kw.items(): * setattr(self, k, v) # <<<<<<<<<<<<<< * * cdef class CompletionPort: */ - __pyx_t_2 = __pyx_v_self; - __Pyx_INCREF(__pyx_t_2); - __pyx_t_7 = PyObject_SetAttr(__pyx_t_2, __pyx_v_k, __pyx_v_v); if (unlikely(__pyx_t_7 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 136; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_9 = PyObject_SetAttr(__pyx_v_self, __pyx_v_k, __pyx_v_v); if (unlikely(__pyx_t_9 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 146; __pyx_clineno = __LINE__; goto __pyx_L1_error;} } - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __pyx_r = Py_None; __Pyx_INCREF(Py_None); goto __pyx_L0; __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_4); __Pyx_XDECREF(__pyx_t_5); __Pyx_XDECREF(__pyx_t_6); - __Pyx_AddTraceback("iocpsupport.Event.__init__"); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_AddTraceback("iocpsupport.Event.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; - __Pyx_DECREF(__pyx_v_kw); - __Pyx_DECREF(__pyx_v_k); - __Pyx_DECREF(__pyx_v_v); + __Pyx_XDECREF(__pyx_v_kw); + __Pyx_XDECREF(__pyx_v_k); + __Pyx_XDECREF(__pyx_v_v); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } -/* "iocpsupport.pyx":140 +/* "iocpsupport.pyx":150 * cdef class CompletionPort: * cdef HANDLE port * def __init__(self): # <<<<<<<<<<<<<< @@ -1050,15 +1136,18 @@ static int __pyx_pf_11iocpsupport_14CompletionPort___init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { __pyx_t_11iocpsupport_HANDLE __pyx_v_res; int __pyx_r; + __Pyx_RefNannyDeclarations int __pyx_t_1; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; __Pyx_RefNannySetupContext("__init__"); if (unlikely(PyTuple_GET_SIZE(__pyx_args) > 0)) { __Pyx_RaiseArgtupleInvalid("__init__", 1, 0, 0, PyTuple_GET_SIZE(__pyx_args)); return -1;} if (unlikely(__pyx_kwds) && unlikely(PyDict_Size(__pyx_kwds) > 0) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "__init__", 0))) return -1; - /* "iocpsupport.pyx":142 + /* "iocpsupport.pyx":152 * def __init__(self): * cdef HANDLE res * res = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0) # <<<<<<<<<<<<<< @@ -1067,7 +1156,7 @@ */ __pyx_v_res = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0); - /* "iocpsupport.pyx":143 + /* "iocpsupport.pyx":153 * cdef HANDLE res * res = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0) * if not res: # <<<<<<<<<<<<<< @@ -1077,110 +1166,114 @@ __pyx_t_1 = (!__pyx_v_res); if (__pyx_t_1) { - /* "iocpsupport.pyx":144 + /* "iocpsupport.pyx":154 * res = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0) * if not res: * raise_error(0, 'CreateIoCompletionPort') # <<<<<<<<<<<<<< * self.port = res * */ - __pyx_t_2 = 0; - __pyx_t_3 = ((PyObject *)__pyx_n_s_1); - __Pyx_INCREF(__pyx_t_3); - __pyx_f_11iocpsupport_raise_error(__pyx_t_2, __pyx_t_3); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_2 = ((PyObject *)__pyx_n_s_1); + __Pyx_INCREF(__pyx_t_2); + __pyx_f_11iocpsupport_raise_error(0, __pyx_t_2); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 154; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; goto __pyx_L5; } __pyx_L5:; - /* "iocpsupport.pyx":145 + /* "iocpsupport.pyx":155 * if not res: * raise_error(0, 'CreateIoCompletionPort') * self.port = res # <<<<<<<<<<<<<< * - * def addHandle(self, long handle, long key=0): + * def addHandle(self, HANDLE handle, size_t key=0): */ ((struct __pyx_obj_11iocpsupport_CompletionPort *)__pyx_v_self)->port = __pyx_v_res; __pyx_r = 0; goto __pyx_L0; __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("iocpsupport.CompletionPort.__init__"); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("iocpsupport.CompletionPort.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = -1; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } -/* "iocpsupport.pyx":147 +/* "iocpsupport.pyx":157 * self.port = res * - * def addHandle(self, long handle, long key=0): # <<<<<<<<<<<<<< + * def addHandle(self, HANDLE handle, size_t key=0): # <<<<<<<<<<<<<< * cdef HANDLE res * res = CreateIoCompletionPort(handle, self.port, key, 0) */ static PyObject *__pyx_pf_11iocpsupport_14CompletionPort_1addHandle(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ static PyObject *__pyx_pf_11iocpsupport_14CompletionPort_1addHandle(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - long __pyx_v_handle; - long __pyx_v_key; + __pyx_t_11iocpsupport_HANDLE __pyx_v_handle; + size_t __pyx_v_key; __pyx_t_11iocpsupport_HANDLE __pyx_v_res; PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations int __pyx_t_1; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__handle,&__pyx_n_s__key,0}; __Pyx_RefNannySetupContext("addHandle"); - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + { PyObject* values[2] = {0,0}; - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 0: - values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__handle); - if (likely(values[0])) kw_args--; - else goto __pyx_L5_argtuple_error; - case 1: - if (kw_args > 0) { - PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__key); - if (value) { values[1] = value; kw_args--; } + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__handle); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + if (kw_args > 0) { + PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__key); + if (value) { values[1] = value; kw_args--; } + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "addHandle") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } else { + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + break; + default: goto __pyx_L5_argtuple_error; } } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "addHandle") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - } - __pyx_v_handle = __Pyx_PyInt_AsLong(values[0]); if (unlikely((__pyx_v_handle == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_v_handle = __Pyx_PyInt_AsSize_t(values[0]); if (unlikely((__pyx_v_handle == (size_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L3_error;} if (values[1]) { - __pyx_v_key = __Pyx_PyInt_AsLong(values[1]); if (unlikely((__pyx_v_key == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_v_key = __Pyx_PyInt_AsSize_t(values[1]); if (unlikely((__pyx_v_key == (size_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L3_error;} } else { - __pyx_v_key = ((long)0); - } - } else { - __pyx_v_key = ((long)0); - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 2: __pyx_v_key = __Pyx_PyInt_AsLong(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_key == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - case 1: __pyx_v_handle = __Pyx_PyInt_AsLong(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_handle == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - break; - default: goto __pyx_L5_argtuple_error; + __pyx_v_key = ((size_t)0); } } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("addHandle", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __Pyx_RaiseArgtupleInvalid("addHandle", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __pyx_L3_error:; - __Pyx_AddTraceback("iocpsupport.CompletionPort.addHandle"); + __Pyx_AddTraceback("iocpsupport.CompletionPort.addHandle", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; - /* "iocpsupport.pyx":149 - * def addHandle(self, long handle, long key=0): + /* "iocpsupport.pyx":159 + * def addHandle(self, HANDLE handle, size_t key=0): * cdef HANDLE res * res = CreateIoCompletionPort(handle, self.port, key, 0) # <<<<<<<<<<<<<< * if not res: @@ -1188,7 +1281,7 @@ */ __pyx_v_res = CreateIoCompletionPort(__pyx_v_handle, ((struct __pyx_obj_11iocpsupport_CompletionPort *)__pyx_v_self)->port, __pyx_v_key, 0); - /* "iocpsupport.pyx":150 + /* "iocpsupport.pyx":160 * cdef HANDLE res * res = CreateIoCompletionPort(handle, self.port, key, 0) * if not res: # <<<<<<<<<<<<<< @@ -1198,18 +1291,17 @@ __pyx_t_1 = (!__pyx_v_res); if (__pyx_t_1) { - /* "iocpsupport.pyx":151 + /* "iocpsupport.pyx":161 * res = CreateIoCompletionPort(handle, self.port, key, 0) * if not res: * raise_error(0, 'CreateIoCompletionPort') # <<<<<<<<<<<<<< * * def getEvent(self, long timeout): */ - __pyx_t_2 = 0; - __pyx_t_3 = ((PyObject *)__pyx_n_s_1); - __Pyx_INCREF(__pyx_t_3); - __pyx_f_11iocpsupport_raise_error(__pyx_t_2, __pyx_t_3); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_2 = ((PyObject *)__pyx_n_s_1); + __Pyx_INCREF(__pyx_t_2); + __pyx_f_11iocpsupport_raise_error(0, __pyx_t_2); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 161; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; goto __pyx_L6; } __pyx_L6:; @@ -1217,8 +1309,8 @@ __pyx_r = Py_None; __Pyx_INCREF(Py_None); goto __pyx_L0; __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("iocpsupport.CompletionPort.addHandle"); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("iocpsupport.CompletionPort.addHandle", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); @@ -1226,12 +1318,12 @@ return __pyx_r; } -/* "iocpsupport.pyx":153 +/* "iocpsupport.pyx":163 * raise_error(0, 'CreateIoCompletionPort') * * def getEvent(self, long timeout): # <<<<<<<<<<<<<< * cdef PyThreadState *_save - * cdef unsigned long bytes, key, rc + * cdef unsigned long bytes, rc */ static PyObject *__pyx_pf_11iocpsupport_14CompletionPort_2getEvent(PyObject *__pyx_v_self, PyObject *__pyx_arg_timeout); /*proto*/ @@ -1239,29 +1331,32 @@ long __pyx_v_timeout; struct PyThreadState *__pyx_v__save; unsigned long __pyx_v_bytes; - unsigned long __pyx_v_key; unsigned long __pyx_v_rc; + size_t __pyx_v_key; struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_v_ov; - PyObject *__pyx_v_obj; + PyObject *__pyx_v_obj = NULL; PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations int __pyx_t_1; PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; PyObject *__pyx_t_4 = NULL; PyObject *__pyx_t_5 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; __Pyx_RefNannySetupContext("getEvent"); assert(__pyx_arg_timeout); { - __pyx_v_timeout = __Pyx_PyInt_AsLong(__pyx_arg_timeout); if (unlikely((__pyx_v_timeout == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_v_timeout = __Pyx_PyInt_AsLong(__pyx_arg_timeout); if (unlikely((__pyx_v_timeout == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 163; __pyx_clineno = __LINE__; goto __pyx_L3_error;} } goto __pyx_L4_argument_unpacking_done; __pyx_L3_error:; - __Pyx_AddTraceback("iocpsupport.CompletionPort.getEvent"); + __Pyx_AddTraceback("iocpsupport.CompletionPort.getEvent", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; - __pyx_v_obj = Py_None; __Pyx_INCREF(Py_None); - /* "iocpsupport.pyx":158 + /* "iocpsupport.pyx":169 * cdef myOVERLAPPED *ov * * _save = PyEval_SaveThread() # <<<<<<<<<<<<<< @@ -1270,7 +1365,7 @@ */ __pyx_v__save = PyEval_SaveThread(); - /* "iocpsupport.pyx":159 + /* "iocpsupport.pyx":170 * * _save = PyEval_SaveThread() * rc = GetQueuedCompletionStatus(self.port, &bytes, &key, &ov, timeout) # <<<<<<<<<<<<<< @@ -1279,7 +1374,7 @@ */ __pyx_v_rc = GetQueuedCompletionStatus(((struct __pyx_obj_11iocpsupport_CompletionPort *)__pyx_v_self)->port, (&__pyx_v_bytes), (&__pyx_v_key), ((OVERLAPPED **)(&__pyx_v_ov)), __pyx_v_timeout); - /* "iocpsupport.pyx":160 + /* "iocpsupport.pyx":171 * _save = PyEval_SaveThread() * rc = GetQueuedCompletionStatus(self.port, &bytes, &key, &ov, timeout) * PyEval_RestoreThread(_save) # <<<<<<<<<<<<<< @@ -1288,7 +1383,7 @@ */ PyEval_RestoreThread(__pyx_v__save); - /* "iocpsupport.pyx":162 + /* "iocpsupport.pyx":173 * PyEval_RestoreThread(_save) * * if not rc: # <<<<<<<<<<<<<< @@ -1298,7 +1393,7 @@ __pyx_t_1 = (!__pyx_v_rc); if (__pyx_t_1) { - /* "iocpsupport.pyx":163 + /* "iocpsupport.pyx":174 * * if not rc: * rc = GetLastError() # <<<<<<<<<<<<<< @@ -1310,7 +1405,7 @@ } /*else*/ { - /* "iocpsupport.pyx":165 + /* "iocpsupport.pyx":176 * rc = GetLastError() * else: * rc = 0 # <<<<<<<<<<<<<< @@ -1321,7 +1416,7 @@ } __pyx_L5:; - /* "iocpsupport.pyx":167 + /* "iocpsupport.pyx":178 * rc = 0 * * obj = None # <<<<<<<<<<<<<< @@ -1329,10 +1424,9 @@ * if ov.obj: */ __Pyx_INCREF(Py_None); - __Pyx_DECREF(__pyx_v_obj); __pyx_v_obj = Py_None; - /* "iocpsupport.pyx":168 + /* "iocpsupport.pyx":179 * * obj = None * if ov: # <<<<<<<<<<<<<< @@ -1342,7 +1436,7 @@ __pyx_t_1 = (__pyx_v_ov != 0); if (__pyx_t_1) { - /* "iocpsupport.pyx":169 + /* "iocpsupport.pyx":180 * obj = None * if ov: * if ov.obj: # <<<<<<<<<<<<<< @@ -1352,7 +1446,7 @@ __pyx_t_1 = (__pyx_v_ov->obj != 0); if (__pyx_t_1) { - /* "iocpsupport.pyx":170 + /* "iocpsupport.pyx":181 * if ov: * if ov.obj: * obj = ov.obj # <<<<<<<<<<<<<< @@ -1363,7 +1457,7 @@ __Pyx_DECREF(__pyx_v_obj); __pyx_v_obj = ((PyObject *)__pyx_v_ov->obj); - /* "iocpsupport.pyx":171 + /* "iocpsupport.pyx":182 * if ov.obj: * obj = ov.obj * Py_DECREF(obj) # we are stealing a reference here # <<<<<<<<<<<<<< @@ -1375,7 +1469,7 @@ } __pyx_L7:; - /* "iocpsupport.pyx":172 + /* "iocpsupport.pyx":183 * obj = ov.obj * Py_DECREF(obj) # we are stealing a reference here * PyMem_Free(ov) # <<<<<<<<<<<<<< @@ -1387,21 +1481,21 @@ } __pyx_L6:; - /* "iocpsupport.pyx":174 + /* "iocpsupport.pyx":185 * PyMem_Free(ov) * * return (rc, bytes, key, obj) # <<<<<<<<<<<<<< * - * def postEvent(self, unsigned long bytes, unsigned long key, obj): + * def postEvent(self, unsigned long bytes, size_t key, obj): */ __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = PyLong_FromUnsignedLong(__pyx_v_rc); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = PyLong_FromUnsignedLong(__pyx_v_rc); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 185; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyLong_FromUnsignedLong(__pyx_v_bytes); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = PyLong_FromUnsignedLong(__pyx_v_bytes); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 185; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_3); - __pyx_t_4 = PyLong_FromUnsignedLong(__pyx_v_key); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = __Pyx_PyInt_FromSize_t(__pyx_v_key); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 185; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_4); - __pyx_t_5 = PyTuple_New(4); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_5 = PyTuple_New(4); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 185; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(((PyObject *)__pyx_t_5)); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_2); __Pyx_GIVEREF(__pyx_t_2); @@ -1426,19 +1520,19 @@ __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_4); __Pyx_XDECREF(__pyx_t_5); - __Pyx_AddTraceback("iocpsupport.CompletionPort.getEvent"); + __Pyx_AddTraceback("iocpsupport.CompletionPort.getEvent", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; - __Pyx_DECREF(__pyx_v_obj); + __Pyx_XDECREF(__pyx_v_obj); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } -/* "iocpsupport.pyx":176 +/* "iocpsupport.pyx":187 * return (rc, bytes, key, obj) * - * def postEvent(self, unsigned long bytes, unsigned long key, obj): # <<<<<<<<<<<<<< + * def postEvent(self, unsigned long bytes, size_t key, obj): # <<<<<<<<<<<<<< * cdef myOVERLAPPED *ov * cdef unsigned long rc */ @@ -1446,68 +1540,74 @@ static PyObject *__pyx_pf_11iocpsupport_14CompletionPort_3postEvent(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ static PyObject *__pyx_pf_11iocpsupport_14CompletionPort_3postEvent(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { unsigned long __pyx_v_bytes; - unsigned long __pyx_v_key; + size_t __pyx_v_key; PyObject *__pyx_v_obj = 0; struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_v_ov; unsigned long __pyx_v_rc; PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations int __pyx_t_1; struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_t_2; PyObject *__pyx_t_3 = NULL; - int __pyx_t_4; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__bytes,&__pyx_n_s__key,&__pyx_n_s__obj,0}; __Pyx_RefNannySetupContext("postEvent"); - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + { PyObject* values[3] = {0,0,0}; - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 0: - values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__bytes); - if (likely(values[0])) kw_args--; - else goto __pyx_L5_argtuple_error; - case 1: - values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__key); - if (likely(values[1])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("postEvent", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 176; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; } - case 2: - values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__obj); - if (likely(values[2])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("postEvent", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 176; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + kw_args = PyDict_Size(__pyx_kwds); + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__bytes); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__key); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("postEvent", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 187; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 2: + values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__obj); + if (likely(values[2])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("postEvent", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 187; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "postEvent") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 187; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "postEvent") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 176; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - } - __pyx_v_bytes = __Pyx_PyInt_AsUnsignedLong(values[0]); if (unlikely((__pyx_v_bytes == (unsigned long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 176; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __pyx_v_key = __Pyx_PyInt_AsUnsignedLong(values[1]); if (unlikely((__pyx_v_key == (unsigned long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 176; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_v_bytes = __Pyx_PyInt_AsUnsignedLong(values[0]); if (unlikely((__pyx_v_bytes == (unsigned long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 187; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_v_key = __Pyx_PyInt_AsSize_t(values[1]); if (unlikely((__pyx_v_key == (size_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 187; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __pyx_v_obj = values[2]; - } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { - goto __pyx_L5_argtuple_error; - } else { - __pyx_v_bytes = __Pyx_PyInt_AsUnsignedLong(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_bytes == (unsigned long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 176; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __pyx_v_key = __Pyx_PyInt_AsUnsignedLong(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_key == (unsigned long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 176; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __pyx_v_obj = PyTuple_GET_ITEM(__pyx_args, 2); } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("postEvent", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 176; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __Pyx_RaiseArgtupleInvalid("postEvent", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 187; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __pyx_L3_error:; - __Pyx_AddTraceback("iocpsupport.CompletionPort.postEvent"); + __Pyx_AddTraceback("iocpsupport.CompletionPort.postEvent", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; - /* "iocpsupport.pyx":180 + /* "iocpsupport.pyx":191 * cdef unsigned long rc * * if obj is not None: # <<<<<<<<<<<<<< @@ -1517,29 +1617,26 @@ __pyx_t_1 = (__pyx_v_obj != Py_None); if (__pyx_t_1) { - /* "iocpsupport.pyx":181 + /* "iocpsupport.pyx":192 * * if obj is not None: * ov = makeOV() # <<<<<<<<<<<<<< * Py_INCREF(obj) # give ov its own reference to obj * ov.obj = obj */ - __pyx_t_2 = __pyx_f_11iocpsupport_makeOV(); if (unlikely(__pyx_t_2 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 181; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = __pyx_f_11iocpsupport_makeOV(); if (unlikely(__pyx_t_2 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 192; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __pyx_v_ov = __pyx_t_2; - /* "iocpsupport.pyx":182 + /* "iocpsupport.pyx":193 * if obj is not None: * ov = makeOV() * Py_INCREF(obj) # give ov its own reference to obj # <<<<<<<<<<<<<< * ov.obj = obj * else: */ - __pyx_t_3 = __pyx_v_obj; - __Pyx_INCREF(__pyx_t_3); - Py_INCREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + Py_INCREF(__pyx_v_obj); - /* "iocpsupport.pyx":183 + /* "iocpsupport.pyx":194 * ov = makeOV() * Py_INCREF(obj) # give ov its own reference to obj * ov.obj = obj # <<<<<<<<<<<<<< @@ -1551,7 +1648,7 @@ } /*else*/ { - /* "iocpsupport.pyx":185 + /* "iocpsupport.pyx":196 * ov.obj = obj * else: * ov = NULL # <<<<<<<<<<<<<< @@ -1562,36 +1659,66 @@ } __pyx_L6:; - /* "iocpsupport.pyx":187 + /* "iocpsupport.pyx":198 * ov = NULL * * rc = PostQueuedCompletionStatus(self.port, bytes, key, ov) # <<<<<<<<<<<<<< * if not rc: - * raise_error(0, 'PostQueuedCompletionStatus') + * if ov: */ __pyx_v_rc = PostQueuedCompletionStatus(((struct __pyx_obj_11iocpsupport_CompletionPort *)__pyx_v_self)->port, __pyx_v_bytes, __pyx_v_key, ((OVERLAPPED *)__pyx_v_ov)); - /* "iocpsupport.pyx":188 + /* "iocpsupport.pyx":199 * * rc = PostQueuedCompletionStatus(self.port, bytes, key, ov) * if not rc: # <<<<<<<<<<<<<< - * raise_error(0, 'PostQueuedCompletionStatus') - * + * if ov: + * Py_DECREF(obj) */ __pyx_t_1 = (!__pyx_v_rc); if (__pyx_t_1) { - /* "iocpsupport.pyx":189 + /* "iocpsupport.pyx":200 * rc = PostQueuedCompletionStatus(self.port, bytes, key, ov) * if not rc: + * if ov: # <<<<<<<<<<<<<< + * Py_DECREF(obj) + * PyMem_Free(ov) + */ + __pyx_t_1 = (__pyx_v_ov != 0); + if (__pyx_t_1) { + + /* "iocpsupport.pyx":201 + * if not rc: + * if ov: + * Py_DECREF(obj) # <<<<<<<<<<<<<< + * PyMem_Free(ov) + * raise_error(0, 'PostQueuedCompletionStatus') + */ + Py_DECREF(__pyx_v_obj); + + /* "iocpsupport.pyx":202 + * if ov: + * Py_DECREF(obj) + * PyMem_Free(ov) # <<<<<<<<<<<<<< + * raise_error(0, 'PostQueuedCompletionStatus') + * + */ + PyMem_Free(__pyx_v_ov); + goto __pyx_L8; + } + __pyx_L8:; + + /* "iocpsupport.pyx":203 + * Py_DECREF(obj) + * PyMem_Free(ov) * raise_error(0, 'PostQueuedCompletionStatus') # <<<<<<<<<<<<<< * * def __del__(self): */ - __pyx_t_4 = 0; __pyx_t_3 = ((PyObject *)__pyx_n_s_2); __Pyx_INCREF(__pyx_t_3); - __pyx_f_11iocpsupport_raise_error(__pyx_t_4, __pyx_t_3); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_f_11iocpsupport_raise_error(0, __pyx_t_3); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; goto __pyx_L7; } @@ -1601,7 +1728,7 @@ goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("iocpsupport.CompletionPort.postEvent"); + __Pyx_AddTraceback("iocpsupport.CompletionPort.postEvent", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); @@ -1609,7 +1736,7 @@ return __pyx_r; } -/* "iocpsupport.pyx":191 +/* "iocpsupport.pyx":205 * raise_error(0, 'PostQueuedCompletionStatus') * * def __del__(self): # <<<<<<<<<<<<<< @@ -1620,9 +1747,10 @@ static PyObject *__pyx_pf_11iocpsupport_14CompletionPort_4__del__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ static PyObject *__pyx_pf_11iocpsupport_14CompletionPort_4__del__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__del__"); - /* "iocpsupport.pyx":192 + /* "iocpsupport.pyx":206 * * def __del__(self): * CloseHandle(self.port) # <<<<<<<<<<<<<< @@ -1637,56 +1765,57 @@ return __pyx_r; } -/* "iocpsupport.pyx":194 +/* "iocpsupport.pyx":208 * CloseHandle(self.port) * * def makesockaddr(object buff): # <<<<<<<<<<<<<< * cdef void *mem_buffer - * cdef int size + * cdef Py_ssize_t size */ static PyObject *__pyx_pf_11iocpsupport_makesockaddr(PyObject *__pyx_self, PyObject *__pyx_v_buff); /*proto*/ static PyMethodDef __pyx_mdef_11iocpsupport_makesockaddr = {__Pyx_NAMESTR("makesockaddr"), (PyCFunction)__pyx_pf_11iocpsupport_makesockaddr, METH_O, __Pyx_DOCSTR(0)}; static PyObject *__pyx_pf_11iocpsupport_makesockaddr(PyObject *__pyx_self, PyObject *__pyx_v_buff) { void *__pyx_v_mem_buffer; - int __pyx_v_size; + Py_ssize_t __pyx_v_size; PyObject *__pyx_r = NULL; - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; __Pyx_RefNannySetupContext("makesockaddr"); __pyx_self = __pyx_self; - /* "iocpsupport.pyx":198 - * cdef int size + /* "iocpsupport.pyx":212 + * cdef Py_ssize_t size * * PyObject_AsReadBuffer(buff, &mem_buffer, &size) # <<<<<<<<<<<<<< * # XXX: this should really return the address family as well * return _makesockaddr(mem_buffer, size) */ - __pyx_t_1 = __pyx_v_buff; - __Pyx_INCREF(__pyx_t_1); - __pyx_t_2 = PyObject_AsReadBuffer(__pyx_t_1, (&__pyx_v_mem_buffer), (&__pyx_v_size)); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 198; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyObject_AsReadBuffer(__pyx_v_buff, (&__pyx_v_mem_buffer), (&__pyx_v_size)); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - /* "iocpsupport.pyx":200 + /* "iocpsupport.pyx":214 * PyObject_AsReadBuffer(buff, &mem_buffer, &size) * # XXX: this should really return the address family as well * return _makesockaddr(mem_buffer, size) # <<<<<<<<<<<<<< * - * cdef object _makesockaddr(sockaddr *addr, int len): + * cdef object _makesockaddr(sockaddr *addr, Py_ssize_t len): */ __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = __pyx_f_11iocpsupport__makesockaddr(((struct sockaddr *)__pyx_v_mem_buffer), __pyx_v_size); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; + __pyx_t_2 = __pyx_f_11iocpsupport__makesockaddr(((struct sockaddr *)__pyx_v_mem_buffer), __pyx_v_size); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; goto __pyx_L0; __pyx_r = Py_None; __Pyx_INCREF(Py_None); goto __pyx_L0; __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("iocpsupport.makesockaddr"); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("iocpsupport.makesockaddr", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); @@ -1694,36 +1823,38 @@ return __pyx_r; } -/* "iocpsupport.pyx":202 +/* "iocpsupport.pyx":216 * return _makesockaddr(mem_buffer, size) * - * cdef object _makesockaddr(sockaddr *addr, int len): # <<<<<<<<<<<<<< + * cdef object _makesockaddr(sockaddr *addr, Py_ssize_t len): # <<<<<<<<<<<<<< * cdef sockaddr_in *sin * cdef sockaddr_in6 *sin6 */ -static PyObject *__pyx_f_11iocpsupport__makesockaddr(struct sockaddr *__pyx_v_addr, int __pyx_v_len) { +static PyObject *__pyx_f_11iocpsupport__makesockaddr(struct sockaddr *__pyx_v_addr, Py_ssize_t __pyx_v_len) { struct sockaddr_in *__pyx_v_sin; struct sockaddr_in6 *__pyx_v_sin6; char __pyx_v_buff[256]; int __pyx_v_rc; __pyx_t_11iocpsupport_DWORD __pyx_v_buff_size; - PyObject *__pyx_v_host; + PyObject *__pyx_v_host = NULL; unsigned short __pyx_v_sa_port; - PyObject *__pyx_v_port; + PyObject *__pyx_v_port = NULL; PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations int __pyx_t_1; PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; PyObject *__pyx_t_4 = NULL; - int __pyx_t_5; - unsigned short __pyx_t_6; - PyObject *__pyx_t_7 = NULL; + unsigned short __pyx_t_5; + PyObject *__pyx_t_6 = NULL; + PyObject *(*__pyx_t_7)(PyObject *); + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; __Pyx_RefNannySetupContext("_makesockaddr"); - __pyx_v_host = Py_None; __Pyx_INCREF(Py_None); - __pyx_v_port = Py_None; __Pyx_INCREF(Py_None); - /* "iocpsupport.pyx":207 + /* "iocpsupport.pyx":221 * cdef char buff[256] * cdef int rc * cdef DWORD buff_size = sizeof(buff) # <<<<<<<<<<<<<< @@ -1732,7 +1863,7 @@ */ __pyx_v_buff_size = (sizeof(__pyx_v_buff)); - /* "iocpsupport.pyx":208 + /* "iocpsupport.pyx":222 * cdef int rc * cdef DWORD buff_size = sizeof(buff) * if not len: # <<<<<<<<<<<<<< @@ -1742,7 +1873,7 @@ __pyx_t_1 = (!__pyx_v_len); if (__pyx_t_1) { - /* "iocpsupport.pyx":209 + /* "iocpsupport.pyx":223 * cdef DWORD buff_size = sizeof(buff) * if not len: * return None # <<<<<<<<<<<<<< @@ -1757,7 +1888,7 @@ } __pyx_L3:; - /* "iocpsupport.pyx":213 + /* "iocpsupport.pyx":227 * sin = addr * return PyString_FromString(inet_ntoa(sin.sin_addr)), ntohs(sin.sin_port) * elif addr.sa_family == AF_INET6: # <<<<<<<<<<<<<< @@ -1766,7 +1897,7 @@ */ switch (__pyx_v_addr->sa_family) { - /* "iocpsupport.pyx":210 + /* "iocpsupport.pyx":224 * if not len: * return None * if addr.sa_family == AF_INET: # <<<<<<<<<<<<<< @@ -1775,7 +1906,7 @@ */ case AF_INET: - /* "iocpsupport.pyx":211 + /* "iocpsupport.pyx":225 * return None * if addr.sa_family == AF_INET: * sin = addr # <<<<<<<<<<<<<< @@ -1784,7 +1915,7 @@ */ __pyx_v_sin = ((struct sockaddr_in *)__pyx_v_addr); - /* "iocpsupport.pyx":212 + /* "iocpsupport.pyx":226 * if addr.sa_family == AF_INET: * sin = addr * return PyString_FromString(inet_ntoa(sin.sin_addr)), ntohs(sin.sin_port) # <<<<<<<<<<<<<< @@ -1792,11 +1923,11 @@ * sin6 = addr */ __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = PyString_FromString(inet_ntoa(__pyx_v_sin->sin_addr)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = PyString_FromString(inet_ntoa(__pyx_v_sin->sin_addr)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 226; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyInt_FromLong(ntohs(__pyx_v_sin->sin_port)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = PyInt_FromLong(ntohs(__pyx_v_sin->sin_port)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 226; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_3); - __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 226; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(((PyObject *)__pyx_t_4)); PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2); __Pyx_GIVEREF(__pyx_t_2); @@ -1809,7 +1940,7 @@ goto __pyx_L0; break; - /* "iocpsupport.pyx":213 + /* "iocpsupport.pyx":227 * sin = addr * return PyString_FromString(inet_ntoa(sin.sin_addr)), ntohs(sin.sin_port) * elif addr.sa_family == AF_INET6: # <<<<<<<<<<<<<< @@ -1818,7 +1949,7 @@ */ case AF_INET6: - /* "iocpsupport.pyx":214 + /* "iocpsupport.pyx":228 * return PyString_FromString(inet_ntoa(sin.sin_addr)), ntohs(sin.sin_port) * elif addr.sa_family == AF_INET6: * sin6 = addr # <<<<<<<<<<<<<< @@ -1827,7 +1958,7 @@ */ __pyx_v_sin6 = ((struct sockaddr_in6 *)__pyx_v_addr); - /* "iocpsupport.pyx":215 + /* "iocpsupport.pyx":229 * elif addr.sa_family == AF_INET6: * sin6 = addr * rc = WSAAddressToStringA(addr, sizeof(sockaddr_in6), NULL, buff, &buff_size) # <<<<<<<<<<<<<< @@ -1836,7 +1967,7 @@ */ __pyx_v_rc = WSAAddressToStringA(__pyx_v_addr, (sizeof(struct sockaddr_in6)), NULL, __pyx_v_buff, (&__pyx_v_buff_size)); - /* "iocpsupport.pyx":216 + /* "iocpsupport.pyx":230 * sin6 = addr * rc = WSAAddressToStringA(addr, sizeof(sockaddr_in6), NULL, buff, &buff_size) * if rc == SOCKET_ERROR: # <<<<<<<<<<<<<< @@ -1846,98 +1977,115 @@ __pyx_t_1 = (__pyx_v_rc == SOCKET_ERROR); if (__pyx_t_1) { - /* "iocpsupport.pyx":217 + /* "iocpsupport.pyx":231 * rc = WSAAddressToStringA(addr, sizeof(sockaddr_in6), NULL, buff, &buff_size) * if rc == SOCKET_ERROR: * raise_error(0, 'WSAAddressToString') # <<<<<<<<<<<<<< * host, sa_port = PyString_FromString(buff), ntohs(sin6.sin6_port) * host, port = host.rsplit(':', 1) */ - __pyx_t_5 = 0; __pyx_t_4 = ((PyObject *)__pyx_n_s__WSAAddressToString); __Pyx_INCREF(__pyx_t_4); - __pyx_f_11iocpsupport_raise_error(__pyx_t_5, __pyx_t_4); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 217; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_f_11iocpsupport_raise_error(0, __pyx_t_4); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 231; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; goto __pyx_L4; } __pyx_L4:; - /* "iocpsupport.pyx":218 + /* "iocpsupport.pyx":232 * if rc == SOCKET_ERROR: * raise_error(0, 'WSAAddressToString') * host, sa_port = PyString_FromString(buff), ntohs(sin6.sin6_port) # <<<<<<<<<<<<<< * host, port = host.rsplit(':', 1) * port = int(port) */ - __pyx_t_4 = PyString_FromString(__pyx_v_buff); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 218; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = PyString_FromString(__pyx_v_buff); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 232; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_4); - __pyx_t_6 = ntohs(__pyx_v_sin6->sin6_port); - __Pyx_DECREF(__pyx_v_host); + __pyx_t_5 = ntohs(__pyx_v_sin6->sin6_port); __pyx_v_host = __pyx_t_4; __pyx_t_4 = 0; - __pyx_v_sa_port = __pyx_t_6; + __pyx_v_sa_port = __pyx_t_5; - /* "iocpsupport.pyx":219 + /* "iocpsupport.pyx":233 * raise_error(0, 'WSAAddressToString') * host, sa_port = PyString_FromString(buff), ntohs(sin6.sin6_port) * host, port = host.rsplit(':', 1) # <<<<<<<<<<<<<< * port = int(port) * assert host[0] == '[' */ - __pyx_t_4 = PyObject_GetAttr(__pyx_v_host, __pyx_n_s__rsplit); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 219; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = PyObject_GetAttr(__pyx_v_host, __pyx_n_s__rsplit); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_4); - __pyx_t_3 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 219; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - if (PyTuple_CheckExact(__pyx_t_3) && likely(PyTuple_GET_SIZE(__pyx_t_3) == 2)) { - PyObject* tuple = __pyx_t_3; - __pyx_t_4 = PyTuple_GET_ITEM(tuple, 0); __Pyx_INCREF(__pyx_t_4); - __pyx_t_2 = PyTuple_GET_ITEM(tuple, 1); __Pyx_INCREF(__pyx_t_2); + if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) { + PyObject* sequence = __pyx_t_3; + if (likely(PyTuple_CheckExact(sequence))) { + if (unlikely(PyTuple_GET_SIZE(sequence) != 2)) { + if (PyTuple_GET_SIZE(sequence) > 2) __Pyx_RaiseTooManyValuesError(2); + else __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(sequence)); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_2 = PyTuple_GET_ITEM(sequence, 1); + } else { + if (unlikely(PyList_GET_SIZE(sequence) != 2)) { + if (PyList_GET_SIZE(sequence) > 2) __Pyx_RaiseTooManyValuesError(2); + else __Pyx_RaiseNeedMoreValuesError(PyList_GET_SIZE(sequence)); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_4 = PyList_GET_ITEM(sequence, 0); + __pyx_t_2 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __Pyx_DECREF(__pyx_v_host); - __pyx_v_host = __pyx_t_4; - __pyx_t_4 = 0; - __Pyx_DECREF(__pyx_v_port); - __pyx_v_port = __pyx_t_2; - __pyx_t_2 = 0; } else { - __pyx_t_7 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 219; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_7); + Py_ssize_t index = -1; + __pyx_t_6 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_6); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_4 = __Pyx_UnpackItem(__pyx_t_7, 0); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 219; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_7 = Py_TYPE(__pyx_t_6)->tp_iternext; + index = 0; __pyx_t_4 = __pyx_t_7(__pyx_t_6); if (unlikely(!__pyx_t_4)) goto __pyx_L5_unpacking_failed; __Pyx_GOTREF(__pyx_t_4); - __pyx_t_2 = __Pyx_UnpackItem(__pyx_t_7, 1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 219; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + index = 1; __pyx_t_2 = __pyx_t_7(__pyx_t_6); if (unlikely(!__pyx_t_2)) goto __pyx_L5_unpacking_failed; __Pyx_GOTREF(__pyx_t_2); - if (__Pyx_EndUnpack(__pyx_t_7, 2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 219; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - __Pyx_DECREF(__pyx_v_host); - __pyx_v_host = __pyx_t_4; - __pyx_t_4 = 0; - __Pyx_DECREF(__pyx_v_port); - __pyx_v_port = __pyx_t_2; - __pyx_t_2 = 0; + if (__Pyx_IternextUnpackEndCheck(__pyx_t_7(__pyx_t_6), 2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + goto __pyx_L6_unpacking_done; + __pyx_L5_unpacking_failed:; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_StopIteration)) PyErr_Clear(); + if (!PyErr_Occurred()) __Pyx_RaiseNeedMoreValuesError(index); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_L6_unpacking_done:; } + __Pyx_DECREF(__pyx_v_host); + __pyx_v_host = __pyx_t_4; + __pyx_t_4 = 0; + __pyx_v_port = __pyx_t_2; + __pyx_t_2 = 0; - /* "iocpsupport.pyx":220 + /* "iocpsupport.pyx":234 * host, sa_port = PyString_FromString(buff), ntohs(sin6.sin6_port) * host, port = host.rsplit(':', 1) * port = int(port) # <<<<<<<<<<<<<< * assert host[0] == '[' * assert host[-1] == ']' */ - __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(((PyObject *)__pyx_t_3)); __Pyx_INCREF(__pyx_v_port); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_port); __Pyx_GIVEREF(__pyx_v_port); - __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)(&PyInt_Type))), ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)(&PyInt_Type))), ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0; __Pyx_DECREF(__pyx_v_port); __pyx_v_port = __pyx_t_2; __pyx_t_2 = 0; - /* "iocpsupport.pyx":221 + /* "iocpsupport.pyx":235 * host, port = host.rsplit(':', 1) * port = int(port) * assert host[0] == '[' # <<<<<<<<<<<<<< @@ -1945,20 +2093,17 @@ * assert port == sa_port */ #ifndef CYTHON_WITHOUT_ASSERTIONS - __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_host, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 221; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_host, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyObject_RichCompare(__pyx_t_2, ((PyObject *)__pyx_kp_s_5), Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 221; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = __Pyx_PyString_Equals(__pyx_t_2, ((PyObject *)__pyx_kp_s_5), Py_EQ); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 221; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (unlikely(!__pyx_t_1)) { PyErr_SetNone(PyExc_AssertionError); - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 221; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L1_error;} } #endif - /* "iocpsupport.pyx":222 + /* "iocpsupport.pyx":236 * port = int(port) * assert host[0] == '[' * assert host[-1] == ']' # <<<<<<<<<<<<<< @@ -1966,20 +2111,17 @@ * return host[1:-1], port */ #ifndef CYTHON_WITHOUT_ASSERTIONS - __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_host, -1, sizeof(long), PyInt_FromLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 222; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_2 = PyObject_RichCompare(__pyx_t_3, ((PyObject *)__pyx_kp_s_6), Py_EQ); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 222; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_host, -1, sizeof(long), PyInt_FromLong); if (!__pyx_t_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 236; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 222; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = __Pyx_PyString_Equals(__pyx_t_2, ((PyObject *)__pyx_kp_s_6), Py_EQ); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 236; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; if (unlikely(!__pyx_t_1)) { PyErr_SetNone(PyExc_AssertionError); - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 222; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 236; __pyx_clineno = __LINE__; goto __pyx_L1_error;} } #endif - /* "iocpsupport.pyx":223 + /* "iocpsupport.pyx":237 * assert host[0] == '[' * assert host[-1] == ']' * assert port == sa_port # <<<<<<<<<<<<<< @@ -1987,20 +2129,20 @@ * else: */ #ifndef CYTHON_WITHOUT_ASSERTIONS - __pyx_t_2 = PyInt_FromLong(__pyx_v_sa_port); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 223; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = PyInt_FromLong(__pyx_v_sa_port); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 237; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyObject_RichCompare(__pyx_v_port, __pyx_t_2, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 223; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = PyObject_RichCompare(__pyx_v_port, __pyx_t_2, Py_EQ); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 237; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 223; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 237; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (unlikely(!__pyx_t_1)) { PyErr_SetNone(PyExc_AssertionError); - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 223; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 237; __pyx_clineno = __LINE__; goto __pyx_L1_error;} } #endif - /* "iocpsupport.pyx":224 + /* "iocpsupport.pyx":238 * assert host[-1] == ']' * assert port == sa_port * return host[1:-1], port # <<<<<<<<<<<<<< @@ -2008,9 +2150,9 @@ * return PyString_FromStringAndSize(addr.sa_data, sizeof(addr.sa_data)) */ __Pyx_XDECREF(__pyx_r); - __pyx_t_3 = __Pyx_PySequence_GetSlice(__pyx_v_host, 1, -1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 224; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = __Pyx_PySequence_GetSlice(__pyx_v_host, 1, -1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 238; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_3); - __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 224; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 238; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(((PyObject *)__pyx_t_2)); PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_3); __Pyx_GIVEREF(__pyx_t_3); @@ -2024,15 +2166,15 @@ break; default: - /* "iocpsupport.pyx":226 + /* "iocpsupport.pyx":240 * return host[1:-1], port * else: * return PyString_FromStringAndSize(addr.sa_data, sizeof(addr.sa_data)) # <<<<<<<<<<<<<< * - * cdef object fillinetaddr(sockaddr_in *dest, object addr): + * */ __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = PyString_FromStringAndSize(__pyx_v_addr->sa_data, (sizeof(__pyx_v_addr->sa_data))); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 226; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = PyString_FromStringAndSize(__pyx_v_addr->sa_data, (sizeof(__pyx_v_addr->sa_data))); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 240; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_2); __pyx_r = __pyx_t_2; __pyx_t_2 = 0; @@ -2046,85 +2188,108 @@ __Pyx_XDECREF(__pyx_t_2); __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_7); - __Pyx_AddTraceback("iocpsupport._makesockaddr"); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("iocpsupport._makesockaddr", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; - __Pyx_DECREF(__pyx_v_host); - __Pyx_DECREF(__pyx_v_port); + __Pyx_XDECREF(__pyx_v_host); + __Pyx_XDECREF(__pyx_v_port); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } -/* "iocpsupport.pyx":228 - * return PyString_FromStringAndSize(addr.sa_data, sizeof(addr.sa_data)) +/* "iocpsupport.pyx":243 + * * * cdef object fillinetaddr(sockaddr_in *dest, object addr): # <<<<<<<<<<<<<< * cdef unsigned short port * cdef unsigned long res */ -static PyObject *__pyx_f_11iocpsupport_fillinetaddr(struct sockaddr_in *__pyx_v_dest, PyObject *__pyx_v_addr) { +static PyObject *__pyx_f_11iocpsupport_fillinetaddr(struct sockaddr_in *__pyx_v_dest, PyObject *__pyx_v_addr) { unsigned short __pyx_v_port; unsigned long __pyx_v_res; char *__pyx_v_hoststr; - PyObject *__pyx_v_host; + PyObject *__pyx_v_host = NULL; PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; - unsigned short __pyx_t_3; - PyObject *__pyx_t_4 = NULL; - char *__pyx_t_5; - int __pyx_t_6; + PyObject *__pyx_t_3 = NULL; + PyObject *(*__pyx_t_4)(PyObject *); + unsigned short __pyx_t_5; + char *__pyx_t_6; + int __pyx_t_7; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; __Pyx_RefNannySetupContext("fillinetaddr"); - __pyx_v_host = Py_None; __Pyx_INCREF(Py_None); - /* "iocpsupport.pyx":232 + /* "iocpsupport.pyx":247 * cdef unsigned long res * cdef char *hoststr * host, port = addr # <<<<<<<<<<<<<< * * hoststr = PyString_AsString(host) */ - if (PyTuple_CheckExact(__pyx_v_addr) && likely(PyTuple_GET_SIZE(__pyx_v_addr) == 2)) { - PyObject* tuple = __pyx_v_addr; - __pyx_t_1 = PyTuple_GET_ITEM(tuple, 0); __Pyx_INCREF(__pyx_t_1); - __pyx_t_2 = PyTuple_GET_ITEM(tuple, 1); __Pyx_INCREF(__pyx_t_2); - __pyx_t_3 = __Pyx_PyInt_AsUnsignedShort(__pyx_t_2); if (unlikely((__pyx_t_3 == (unsigned short)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 232; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_DECREF(__pyx_v_host); - __pyx_v_host = __pyx_t_1; - __pyx_t_1 = 0; - __pyx_v_port = __pyx_t_3; + if ((likely(PyTuple_CheckExact(__pyx_v_addr))) || (PyList_CheckExact(__pyx_v_addr))) { + PyObject* sequence = __pyx_v_addr; + if (likely(PyTuple_CheckExact(sequence))) { + if (unlikely(PyTuple_GET_SIZE(sequence) != 2)) { + if (PyTuple_GET_SIZE(sequence) > 2) __Pyx_RaiseTooManyValuesError(2); + else __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(sequence)); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 247; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_2 = PyTuple_GET_ITEM(sequence, 1); + } else { + if (unlikely(PyList_GET_SIZE(sequence) != 2)) { + if (PyList_GET_SIZE(sequence) > 2) __Pyx_RaiseTooManyValuesError(2); + else __Pyx_RaiseNeedMoreValuesError(PyList_GET_SIZE(sequence)); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 247; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_1 = PyList_GET_ITEM(sequence, 0); + __pyx_t_2 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_2); } else { - __pyx_t_4 = PyObject_GetIter(__pyx_v_addr); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 232; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_1 = __Pyx_UnpackItem(__pyx_t_4, 0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 232; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + Py_ssize_t index = -1; + __pyx_t_3 = PyObject_GetIter(__pyx_v_addr); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 247; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = Py_TYPE(__pyx_t_3)->tp_iternext; + index = 0; __pyx_t_1 = __pyx_t_4(__pyx_t_3); if (unlikely(!__pyx_t_1)) goto __pyx_L3_unpacking_failed; __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_UnpackItem(__pyx_t_4, 1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 232; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + index = 1; __pyx_t_2 = __pyx_t_4(__pyx_t_3); if (unlikely(!__pyx_t_2)) goto __pyx_L3_unpacking_failed; __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = __Pyx_PyInt_AsUnsignedShort(__pyx_t_2); if (unlikely((__pyx_t_3 == (unsigned short)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 232; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - if (__Pyx_EndUnpack(__pyx_t_4, 2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 232; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_DECREF(__pyx_v_host); - __pyx_v_host = __pyx_t_1; - __pyx_t_1 = 0; - __pyx_v_port = __pyx_t_3; + if (__Pyx_IternextUnpackEndCheck(__pyx_t_4(__pyx_t_3), 2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 247; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + goto __pyx_L4_unpacking_done; + __pyx_L3_unpacking_failed:; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_StopIteration)) PyErr_Clear(); + if (!PyErr_Occurred()) __Pyx_RaiseNeedMoreValuesError(index); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 247; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_L4_unpacking_done:; } + __pyx_t_5 = __Pyx_PyInt_AsUnsignedShort(__pyx_t_2); if (unlikely((__pyx_t_5 == (unsigned short)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 247; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_v_host = __pyx_t_1; + __pyx_t_1 = 0; + __pyx_v_port = __pyx_t_5; - /* "iocpsupport.pyx":234 + /* "iocpsupport.pyx":249 * host, port = addr * * hoststr = PyString_AsString(host) # <<<<<<<<<<<<<< * res = inet_addr(hoststr) * if res == INADDR_ANY: */ - __pyx_t_5 = PyString_AsString(__pyx_v_host); if (unlikely(__pyx_t_5 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_v_hoststr = __pyx_t_5; + __pyx_t_6 = PyString_AsString(__pyx_v_host); if (unlikely(__pyx_t_6 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 249; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_v_hoststr = __pyx_t_6; - /* "iocpsupport.pyx":235 + /* "iocpsupport.pyx":250 * * hoststr = PyString_AsString(host) * res = inet_addr(hoststr) # <<<<<<<<<<<<<< @@ -2133,30 +2298,30 @@ */ __pyx_v_res = inet_addr(__pyx_v_hoststr); - /* "iocpsupport.pyx":236 + /* "iocpsupport.pyx":251 * hoststr = PyString_AsString(host) * res = inet_addr(hoststr) * if res == INADDR_ANY: # <<<<<<<<<<<<<< * raise ValueError, 'invalid IP address' * dest.sin_addr.s_addr = res */ - __pyx_t_6 = (__pyx_v_res == INADDR_ANY); - if (__pyx_t_6) { + __pyx_t_7 = (__pyx_v_res == INADDR_ANY); + if (__pyx_t_7) { - /* "iocpsupport.pyx":237 + /* "iocpsupport.pyx":252 * res = inet_addr(hoststr) * if res == INADDR_ANY: * raise ValueError, 'invalid IP address' # <<<<<<<<<<<<<< * dest.sin_addr.s_addr = res * */ - __Pyx_Raise(__pyx_builtin_ValueError, ((PyObject *)__pyx_kp_s_7), 0); - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 237; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - goto __pyx_L3; + __Pyx_Raise(__pyx_builtin_ValueError, ((PyObject *)__pyx_kp_s_7), 0, 0); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 252; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L5; } - __pyx_L3:; + __pyx_L5:; - /* "iocpsupport.pyx":238 + /* "iocpsupport.pyx":253 * if res == INADDR_ANY: * raise ValueError, 'invalid IP address' * dest.sin_addr.s_addr = res # <<<<<<<<<<<<<< @@ -2165,12 +2330,12 @@ */ __pyx_v_dest->sin_addr.s_addr = __pyx_v_res; - /* "iocpsupport.pyx":240 + /* "iocpsupport.pyx":255 * dest.sin_addr.s_addr = res * * dest.sin_port = htons(port) # <<<<<<<<<<<<<< * - * def AllocateReadBuffer(int size): + * */ __pyx_v_dest->sin_port = htons(__pyx_v_port); @@ -2179,18 +2344,268 @@ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_AddTraceback("iocpsupport.fillinetaddr"); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_AddTraceback("iocpsupport.fillinetaddr", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; + __Pyx_XDECREF(__pyx_v_host); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "iocpsupport.pyx":258 + * + * + * cdef object fillinet6addr(sockaddr_in6 *dest, object addr): # <<<<<<<<<<<<<< + * cdef unsigned short port + * cdef unsigned long res + */ + +static PyObject *__pyx_f_11iocpsupport_fillinet6addr(struct sockaddr_in6 *__pyx_v_dest, PyObject *__pyx_v_addr) { + unsigned short __pyx_v_port; + char *__pyx_v_hoststr; + int __pyx_v_addrlen; + PyObject *__pyx_v_host = NULL; + PyObject *__pyx_v_flow = NULL; + PyObject *__pyx_v_scope = NULL; + int __pyx_v_parseresult; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *(*__pyx_t_6)(PyObject *); + unsigned short __pyx_t_7; + char *__pyx_t_8; + int __pyx_t_9; + unsigned long __pyx_t_10; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("fillinet6addr"); + + /* "iocpsupport.pyx":262 + * cdef unsigned long res + * cdef char *hoststr + * cdef int addrlen = sizeof(sockaddr_in6) # <<<<<<<<<<<<<< + * host, port, flow, scope = addr + * host = host.split("%")[0] # remove scope ID, if any + */ + __pyx_v_addrlen = (sizeof(struct sockaddr_in6)); + + /* "iocpsupport.pyx":263 + * cdef char *hoststr + * cdef int addrlen = sizeof(sockaddr_in6) + * host, port, flow, scope = addr # <<<<<<<<<<<<<< + * host = host.split("%")[0] # remove scope ID, if any + * + */ + if ((likely(PyTuple_CheckExact(__pyx_v_addr))) || (PyList_CheckExact(__pyx_v_addr))) { + PyObject* sequence = __pyx_v_addr; + if (likely(PyTuple_CheckExact(sequence))) { + if (unlikely(PyTuple_GET_SIZE(sequence) != 4)) { + if (PyTuple_GET_SIZE(sequence) > 4) __Pyx_RaiseTooManyValuesError(4); + else __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(sequence)); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 263; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_2 = PyTuple_GET_ITEM(sequence, 1); + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 2); + __pyx_t_4 = PyTuple_GET_ITEM(sequence, 3); + } else { + if (unlikely(PyList_GET_SIZE(sequence) != 4)) { + if (PyList_GET_SIZE(sequence) > 4) __Pyx_RaiseTooManyValuesError(4); + else __Pyx_RaiseNeedMoreValuesError(PyList_GET_SIZE(sequence)); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 263; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + } + __pyx_t_1 = PyList_GET_ITEM(sequence, 0); + __pyx_t_2 = PyList_GET_ITEM(sequence, 1); + __pyx_t_3 = PyList_GET_ITEM(sequence, 2); + __pyx_t_4 = PyList_GET_ITEM(sequence, 3); + } + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_2); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_4); + } else { + Py_ssize_t index = -1; + __pyx_t_5 = PyObject_GetIter(__pyx_v_addr); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 263; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = Py_TYPE(__pyx_t_5)->tp_iternext; + index = 0; __pyx_t_1 = __pyx_t_6(__pyx_t_5); if (unlikely(!__pyx_t_1)) goto __pyx_L3_unpacking_failed; + __Pyx_GOTREF(__pyx_t_1); + index = 1; __pyx_t_2 = __pyx_t_6(__pyx_t_5); if (unlikely(!__pyx_t_2)) goto __pyx_L3_unpacking_failed; + __Pyx_GOTREF(__pyx_t_2); + index = 2; __pyx_t_3 = __pyx_t_6(__pyx_t_5); if (unlikely(!__pyx_t_3)) goto __pyx_L3_unpacking_failed; + __Pyx_GOTREF(__pyx_t_3); + index = 3; __pyx_t_4 = __pyx_t_6(__pyx_t_5); if (unlikely(!__pyx_t_4)) goto __pyx_L3_unpacking_failed; + __Pyx_GOTREF(__pyx_t_4); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_6(__pyx_t_5), 4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 263; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + goto __pyx_L4_unpacking_done; + __pyx_L3_unpacking_failed:; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_StopIteration)) PyErr_Clear(); + if (!PyErr_Occurred()) __Pyx_RaiseNeedMoreValuesError(index); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 263; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_L4_unpacking_done:; + } + __pyx_t_7 = __Pyx_PyInt_AsUnsignedShort(__pyx_t_2); if (unlikely((__pyx_t_7 == (unsigned short)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 263; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_v_host = __pyx_t_1; + __pyx_t_1 = 0; + __pyx_v_port = __pyx_t_7; + __pyx_v_flow = __pyx_t_3; + __pyx_t_3 = 0; + __pyx_v_scope = __pyx_t_4; + __pyx_t_4 = 0; + + /* "iocpsupport.pyx":264 + * cdef int addrlen = sizeof(sockaddr_in6) + * host, port, flow, scope = addr + * host = host.split("%")[0] # remove scope ID, if any # <<<<<<<<<<<<<< + * + * hoststr = PyString_AsString(host) + */ + __pyx_t_4 = PyObject_GetAttr(__pyx_v_host, __pyx_n_s__split); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_9), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = __Pyx_GetItemInt(__pyx_t_3, 0, sizeof(long), PyInt_FromLong); if (!__pyx_t_4) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __Pyx_DECREF(__pyx_v_host); + __pyx_v_host = __pyx_t_4; + __pyx_t_4 = 0; + + /* "iocpsupport.pyx":266 + * host = host.split("%")[0] # remove scope ID, if any + * + * hoststr = PyString_AsString(host) # <<<<<<<<<<<<<< + * cdef int parseresult = WSAStringToAddressA(hoststr, AF_INET6, NULL, + * dest, &addrlen) + */ + __pyx_t_8 = PyString_AsString(__pyx_v_host); if (unlikely(__pyx_t_8 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 266; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_v_hoststr = __pyx_t_8; + + /* "iocpsupport.pyx":268 + * hoststr = PyString_AsString(host) + * cdef int parseresult = WSAStringToAddressA(hoststr, AF_INET6, NULL, + * dest, &addrlen) # <<<<<<<<<<<<<< + * if parseresult == SOCKET_ERROR: + * raise ValueError, 'invalid IPv6 address %r' % (host,) + */ + __pyx_v_parseresult = WSAStringToAddressA(__pyx_v_hoststr, AF_INET6, NULL, ((struct sockaddr *)__pyx_v_dest), (&__pyx_v_addrlen)); + + /* "iocpsupport.pyx":269 + * cdef int parseresult = WSAStringToAddressA(hoststr, AF_INET6, NULL, + * dest, &addrlen) + * if parseresult == SOCKET_ERROR: # <<<<<<<<<<<<<< + * raise ValueError, 'invalid IPv6 address %r' % (host,) + * if parseresult != 0: + */ + __pyx_t_9 = (__pyx_v_parseresult == SOCKET_ERROR); + if (__pyx_t_9) { + + /* "iocpsupport.pyx":270 + * dest, &addrlen) + * if parseresult == SOCKET_ERROR: + * raise ValueError, 'invalid IPv6 address %r' % (host,) # <<<<<<<<<<<<<< + * if parseresult != 0: + * raise RuntimeError, 'undefined error occurred during address parsing' + */ + __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 270; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_4)); + __Pyx_INCREF(__pyx_v_host); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_host); + __Pyx_GIVEREF(__pyx_v_host); + __pyx_t_3 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_10), ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 270; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_3)); + __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0; + __Pyx_Raise(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_3), 0, 0); + __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 270; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L5; + } + __pyx_L5:; + + /* "iocpsupport.pyx":271 + * if parseresult == SOCKET_ERROR: + * raise ValueError, 'invalid IPv6 address %r' % (host,) + * if parseresult != 0: # <<<<<<<<<<<<<< + * raise RuntimeError, 'undefined error occurred during address parsing' + * # sin6_host field was handled by WSAStringToAddress + */ + __pyx_t_9 = (__pyx_v_parseresult != 0); + if (__pyx_t_9) { + + /* "iocpsupport.pyx":272 + * raise ValueError, 'invalid IPv6 address %r' % (host,) + * if parseresult != 0: + * raise RuntimeError, 'undefined error occurred during address parsing' # <<<<<<<<<<<<<< + * # sin6_host field was handled by WSAStringToAddress + * dest.sin6_port = htons(port) + */ + __Pyx_Raise(__pyx_builtin_RuntimeError, ((PyObject *)__pyx_kp_s_11), 0, 0); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L6; + } + __pyx_L6:; + + /* "iocpsupport.pyx":274 + * raise RuntimeError, 'undefined error occurred during address parsing' + * # sin6_host field was handled by WSAStringToAddress + * dest.sin6_port = htons(port) # <<<<<<<<<<<<<< + * dest.sin6_flowinfo = flow + * dest.sin6_scope_id = scope + */ + __pyx_v_dest->sin6_port = htons(__pyx_v_port); + + /* "iocpsupport.pyx":275 + * # sin6_host field was handled by WSAStringToAddress + * dest.sin6_port = htons(port) + * dest.sin6_flowinfo = flow # <<<<<<<<<<<<<< + * dest.sin6_scope_id = scope + * + */ + __pyx_t_10 = __Pyx_PyInt_AsUnsignedLong(__pyx_v_flow); if (unlikely((__pyx_t_10 == (unsigned long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_v_dest->sin6_flowinfo = __pyx_t_10; + + /* "iocpsupport.pyx":276 + * dest.sin6_port = htons(port) + * dest.sin6_flowinfo = flow + * dest.sin6_scope_id = scope # <<<<<<<<<<<<<< + * + * + */ + __pyx_t_10 = __Pyx_PyInt_AsUnsignedLong(__pyx_v_scope); if (unlikely((__pyx_t_10 == (unsigned long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_v_dest->sin6_scope_id = __pyx_t_10; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("iocpsupport.fillinet6addr", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_host); + __Pyx_XDECREF(__pyx_v_flow); + __Pyx_XDECREF(__pyx_v_scope); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } -/* "iocpsupport.pyx":242 - * dest.sin_port = htons(port) +/* "iocpsupport.pyx":279 + * * * def AllocateReadBuffer(int size): # <<<<<<<<<<<<<< * return PyBuffer_New(size) @@ -2202,20 +2617,24 @@ static PyObject *__pyx_pf_11iocpsupport_1AllocateReadBuffer(PyObject *__pyx_self, PyObject *__pyx_arg_size) { int __pyx_v_size; PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; __Pyx_RefNannySetupContext("AllocateReadBuffer"); __pyx_self = __pyx_self; assert(__pyx_arg_size); { - __pyx_v_size = __Pyx_PyInt_AsInt(__pyx_arg_size); if (unlikely((__pyx_v_size == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 242; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_v_size = __Pyx_PyInt_AsInt(__pyx_arg_size); if (unlikely((__pyx_v_size == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L3_error;} } goto __pyx_L4_argument_unpacking_done; __pyx_L3_error:; - __Pyx_AddTraceback("iocpsupport.AllocateReadBuffer"); + __Pyx_AddTraceback("iocpsupport.AllocateReadBuffer", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; - /* "iocpsupport.pyx":243 + /* "iocpsupport.pyx":280 * * def AllocateReadBuffer(int size): * return PyBuffer_New(size) # <<<<<<<<<<<<<< @@ -2223,7 +2642,7 @@ * def maxAddrLen(long s): */ __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PyBuffer_New(__pyx_v_size); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 243; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyBuffer_New(__pyx_v_size); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 280; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; @@ -2233,7 +2652,7 @@ goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("iocpsupport.AllocateReadBuffer"); + __Pyx_AddTraceback("iocpsupport.AllocateReadBuffer", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); @@ -2241,7 +2660,7 @@ return __pyx_r; } -/* "iocpsupport.pyx":245 +/* "iocpsupport.pyx":282 * return PyBuffer_New(size) * * def maxAddrLen(long s): # <<<<<<<<<<<<<< @@ -2257,22 +2676,25 @@ int __pyx_v_size; int __pyx_v_rc; PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations int __pyx_t_1; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; __Pyx_RefNannySetupContext("maxAddrLen"); __pyx_self = __pyx_self; assert(__pyx_arg_s); { - __pyx_v_s = __Pyx_PyInt_AsLong(__pyx_arg_s); if (unlikely((__pyx_v_s == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_v_s = __Pyx_PyInt_AsLong(__pyx_arg_s); if (unlikely((__pyx_v_s == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 282; __pyx_clineno = __LINE__; goto __pyx_L3_error;} } goto __pyx_L4_argument_unpacking_done; __pyx_L3_error:; - __Pyx_AddTraceback("iocpsupport.maxAddrLen"); + __Pyx_AddTraceback("iocpsupport.maxAddrLen", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; - /* "iocpsupport.pyx":249 + /* "iocpsupport.pyx":286 * cdef int size, rc * * size = sizeof(wsa_pi) # <<<<<<<<<<<<<< @@ -2281,7 +2703,7 @@ */ __pyx_v_size = (sizeof(__pyx_v_wsa_pi)); - /* "iocpsupport.pyx":250 + /* "iocpsupport.pyx":287 * * size = sizeof(wsa_pi) * rc = getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFO, &wsa_pi, &size) # <<<<<<<<<<<<<< @@ -2290,7 +2712,7 @@ */ __pyx_v_rc = getsockopt(__pyx_v_s, SOL_SOCKET, SO_PROTOCOL_INFO, ((char *)(&__pyx_v_wsa_pi)), (&__pyx_v_size)); - /* "iocpsupport.pyx":251 + /* "iocpsupport.pyx":288 * size = sizeof(wsa_pi) * rc = getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFO, &wsa_pi, &size) * if rc == SOCKET_ERROR: # <<<<<<<<<<<<<< @@ -2300,23 +2722,22 @@ __pyx_t_1 = (__pyx_v_rc == SOCKET_ERROR); if (__pyx_t_1) { - /* "iocpsupport.pyx":252 + /* "iocpsupport.pyx":289 * rc = getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFO, &wsa_pi, &size) * if rc == SOCKET_ERROR: * raise_error(WSAGetLastError(), 'getsockopt') # <<<<<<<<<<<<<< * return wsa_pi.iMaxSockAddr * */ - __pyx_t_2 = WSAGetLastError(); - __pyx_t_3 = ((PyObject *)__pyx_n_s__getsockopt); - __Pyx_INCREF(__pyx_t_3); - __pyx_f_11iocpsupport_raise_error(__pyx_t_2, __pyx_t_3); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 252; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_2 = ((PyObject *)__pyx_n_s__getsockopt); + __Pyx_INCREF(__pyx_t_2); + __pyx_f_11iocpsupport_raise_error(WSAGetLastError(), __pyx_t_2); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 289; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; goto __pyx_L5; } __pyx_L5:; - /* "iocpsupport.pyx":253 + /* "iocpsupport.pyx":290 * if rc == SOCKET_ERROR: * raise_error(WSAGetLastError(), 'getsockopt') * return wsa_pi.iMaxSockAddr # <<<<<<<<<<<<<< @@ -2324,17 +2745,17 @@ * cdef int getAddrFamily(SOCKET s) except *: */ __Pyx_XDECREF(__pyx_r); - __pyx_t_3 = PyInt_FromLong(__pyx_v_wsa_pi.iMaxSockAddr); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __pyx_r = __pyx_t_3; - __pyx_t_3 = 0; + __pyx_t_2 = PyInt_FromLong(__pyx_v_wsa_pi.iMaxSockAddr); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 290; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; goto __pyx_L0; __pyx_r = Py_None; __Pyx_INCREF(Py_None); goto __pyx_L0; __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("iocpsupport.maxAddrLen"); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("iocpsupport.maxAddrLen", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); @@ -2342,7 +2763,7 @@ return __pyx_r; } -/* "iocpsupport.pyx":255 +/* "iocpsupport.pyx":292 * return wsa_pi.iMaxSockAddr * * cdef int getAddrFamily(SOCKET s) except *: # <<<<<<<<<<<<<< @@ -2350,17 +2771,20 @@ * cdef int size, rc */ -static int __pyx_f_11iocpsupport_getAddrFamily(__pyx_t_11iocpsupport_SOCKET __pyx_v_s) { +static int __pyx_f_11iocpsupport_getAddrFamily(__pyx_t_11iocpsupport_SOCKET __pyx_v_s) { WSAPROTOCOL_INFO __pyx_v_wsa_pi; int __pyx_v_size; int __pyx_v_rc; int __pyx_r; + __Pyx_RefNannyDeclarations int __pyx_t_1; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; __Pyx_RefNannySetupContext("getAddrFamily"); - /* "iocpsupport.pyx":259 + /* "iocpsupport.pyx":296 * cdef int size, rc * * size = sizeof(wsa_pi) # <<<<<<<<<<<<<< @@ -2369,7 +2793,7 @@ */ __pyx_v_size = (sizeof(__pyx_v_wsa_pi)); - /* "iocpsupport.pyx":260 + /* "iocpsupport.pyx":297 * * size = sizeof(wsa_pi) * rc = getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFO, &wsa_pi, &size) # <<<<<<<<<<<<<< @@ -2378,7 +2802,7 @@ */ __pyx_v_rc = getsockopt(__pyx_v_s, SOL_SOCKET, SO_PROTOCOL_INFO, ((char *)(&__pyx_v_wsa_pi)), (&__pyx_v_size)); - /* "iocpsupport.pyx":261 + /* "iocpsupport.pyx":298 * size = sizeof(wsa_pi) * rc = getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFO, &wsa_pi, &size) * if rc == SOCKET_ERROR: # <<<<<<<<<<<<<< @@ -2388,23 +2812,22 @@ __pyx_t_1 = (__pyx_v_rc == SOCKET_ERROR); if (__pyx_t_1) { - /* "iocpsupport.pyx":262 + /* "iocpsupport.pyx":299 * rc = getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFO, &wsa_pi, &size) * if rc == SOCKET_ERROR: * raise_error(WSAGetLastError(), 'getsockopt') # <<<<<<<<<<<<<< * return wsa_pi.iAddressFamily * */ - __pyx_t_2 = WSAGetLastError(); - __pyx_t_3 = ((PyObject *)__pyx_n_s__getsockopt); - __Pyx_INCREF(__pyx_t_3); - __pyx_f_11iocpsupport_raise_error(__pyx_t_2, __pyx_t_3); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 262; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_2 = ((PyObject *)__pyx_n_s__getsockopt); + __Pyx_INCREF(__pyx_t_2); + __pyx_f_11iocpsupport_raise_error(WSAGetLastError(), __pyx_t_2); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 299; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; goto __pyx_L3; } __pyx_L3:; - /* "iocpsupport.pyx":263 + /* "iocpsupport.pyx":300 * if rc == SOCKET_ERROR: * raise_error(WSAGetLastError(), 'getsockopt') * return wsa_pi.iAddressFamily # <<<<<<<<<<<<<< @@ -2417,15 +2840,15 @@ __pyx_r = 0; goto __pyx_L0; __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("iocpsupport.getAddrFamily"); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("iocpsupport.getAddrFamily", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } -/* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":5 +/* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":5 * * * def accept(long listening, long accepting, object buff, object obj): # <<<<<<<<<<<<<< @@ -2442,171 +2865,184 @@ PyObject *__pyx_v_buff = 0; PyObject *__pyx_v_obj = 0; unsigned long __pyx_v_bytes; - int __pyx_v_size; int __pyx_v_rc; + Py_ssize_t __pyx_v_size; void *__pyx_v_mem_buffer; struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_v_ov; PyObject *__pyx_r = NULL; - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_t_3; - int __pyx_t_4; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__listening,&__pyx_n_s__accepting,&__pyx_n_s__buff,&__pyx_n_s__obj,0}; __Pyx_RefNannySetupContext("accept"); __pyx_self = __pyx_self; - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + { PyObject* values[4] = {0,0,0,0}; - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); - case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 0: - values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__listening); - if (likely(values[0])) kw_args--; - else goto __pyx_L5_argtuple_error; - case 1: - values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__accepting); - if (likely(values[1])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("accept", 1, 4, 4, 1); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; } - case 2: - values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__buff); - if (likely(values[2])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("accept", 1, 4, 4, 2); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + kw_args = PyDict_Size(__pyx_kwds); + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__listening); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__accepting); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("accept", 1, 4, 4, 1); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 2: + values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__buff); + if (likely(values[2])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("accept", 1, 4, 4, 2); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 3: + values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__obj); + if (likely(values[3])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("accept", 1, 4, 4, 3); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } } - case 3: - values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__obj); - if (likely(values[3])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("accept", 1, 4, 4, 3); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "accept") < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "accept") < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } else if (PyTuple_GET_SIZE(__pyx_args) != 4) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + values[3] = PyTuple_GET_ITEM(__pyx_args, 3); } __pyx_v_listening = __Pyx_PyInt_AsLong(values[0]); if (unlikely((__pyx_v_listening == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __pyx_v_accepting = __Pyx_PyInt_AsLong(values[1]); if (unlikely((__pyx_v_accepting == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __pyx_v_buff = values[2]; __pyx_v_obj = values[3]; - } else if (PyTuple_GET_SIZE(__pyx_args) != 4) { - goto __pyx_L5_argtuple_error; - } else { - __pyx_v_listening = __Pyx_PyInt_AsLong(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_listening == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __pyx_v_accepting = __Pyx_PyInt_AsLong(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_accepting == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __pyx_v_buff = PyTuple_GET_ITEM(__pyx_args, 2); - __pyx_v_obj = PyTuple_GET_ITEM(__pyx_args, 3); } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; __Pyx_RaiseArgtupleInvalid("accept", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __pyx_L3_error:; - __Pyx_AddTraceback("iocpsupport.accept"); + __Pyx_AddTraceback("iocpsupport.accept", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":14 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":15 * cdef myOVERLAPPED *ov * * PyObject_AsWriteBuffer(buff, &mem_buffer, &size) # <<<<<<<<<<<<<< * * ov = makeOV() */ - __pyx_t_1 = __pyx_v_buff; - __Pyx_INCREF(__pyx_t_1); - __pyx_t_2 = PyObject_AsWriteBuffer(__pyx_t_1, (&__pyx_v_mem_buffer), (&__pyx_v_size)); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyObject_AsWriteBuffer(__pyx_v_buff, (&__pyx_v_mem_buffer), (&__pyx_v_size)); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":16 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":17 * PyObject_AsWriteBuffer(buff, &mem_buffer, &size) * * ov = makeOV() # <<<<<<<<<<<<<< * if obj is not None: * ov.obj = obj */ - __pyx_t_3 = __pyx_f_11iocpsupport_makeOV(); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_v_ov = __pyx_t_3; + __pyx_t_2 = __pyx_f_11iocpsupport_makeOV(); if (unlikely(__pyx_t_2 == NULL)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_v_ov = __pyx_t_2; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":17 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":18 * * ov = makeOV() * if obj is not None: # <<<<<<<<<<<<<< * ov.obj = obj * */ - __pyx_t_4 = (__pyx_v_obj != Py_None); - if (__pyx_t_4) { + __pyx_t_3 = (__pyx_v_obj != Py_None); + if (__pyx_t_3) { - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":18 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":19 * ov = makeOV() * if obj is not None: * ov.obj = obj # <<<<<<<<<<<<<< * - * rc = lpAcceptEx(listening, accepting, mem_buffer, 0, size / 2, size / 2, + * rc = lpAcceptEx(listening, accepting, mem_buffer, 0, */ __pyx_v_ov->obj = ((struct PyObject *)__pyx_v_obj); goto __pyx_L6; } __pyx_L6:; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":21 - * - * rc = lpAcceptEx(listening, accepting, mem_buffer, 0, size / 2, size / 2, + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":23 + * rc = lpAcceptEx(listening, accepting, mem_buffer, 0, + * size / 2, size / 2, * &bytes, ov) # <<<<<<<<<<<<<< * if not rc: * rc = WSAGetLastError() */ - __pyx_v_rc = lpAcceptEx(__pyx_v_listening, __pyx_v_accepting, __pyx_v_mem_buffer, 0, __Pyx_div_long(__pyx_v_size, 2), __Pyx_div_long(__pyx_v_size, 2), (&__pyx_v_bytes), ((OVERLAPPED *)__pyx_v_ov)); + __pyx_v_rc = lpAcceptEx(__pyx_v_listening, __pyx_v_accepting, __pyx_v_mem_buffer, 0, (((__pyx_t_11iocpsupport_DWORD)__pyx_v_size) / 2), (((__pyx_t_11iocpsupport_DWORD)__pyx_v_size) / 2), (&__pyx_v_bytes), ((OVERLAPPED *)__pyx_v_ov)); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":22 - * rc = lpAcceptEx(listening, accepting, mem_buffer, 0, size / 2, size / 2, + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":24 + * size / 2, size / 2, * &bytes, ov) * if not rc: # <<<<<<<<<<<<<< * rc = WSAGetLastError() * if rc != ERROR_IO_PENDING: */ - __pyx_t_4 = (!__pyx_v_rc); - if (__pyx_t_4) { + __pyx_t_3 = (!__pyx_v_rc); + if (__pyx_t_3) { - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":23 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":25 * &bytes, ov) * if not rc: * rc = WSAGetLastError() # <<<<<<<<<<<<<< * if rc != ERROR_IO_PENDING: - * return rc + * PyMem_Free(ov) */ __pyx_v_rc = WSAGetLastError(); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":24 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":26 * if not rc: * rc = WSAGetLastError() * if rc != ERROR_IO_PENDING: # <<<<<<<<<<<<<< + * PyMem_Free(ov) * return rc - * */ - __pyx_t_4 = (__pyx_v_rc != ERROR_IO_PENDING); - if (__pyx_t_4) { + __pyx_t_3 = (__pyx_v_rc != ERROR_IO_PENDING); + if (__pyx_t_3) { - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":25 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":27 * rc = WSAGetLastError() * if rc != ERROR_IO_PENDING: + * PyMem_Free(ov) # <<<<<<<<<<<<<< + * return rc + * + */ + PyMem_Free(__pyx_v_ov); + + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":28 + * if rc != ERROR_IO_PENDING: + * PyMem_Free(ov) * return rc # <<<<<<<<<<<<<< * * # operation is in progress */ __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PyInt_FromLong(__pyx_v_rc); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; + __pyx_t_4 = PyInt_FromLong(__pyx_v_rc); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; goto __pyx_L0; goto __pyx_L8; } @@ -2615,19 +3051,16 @@ } __pyx_L7:; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":28 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":31 * * # operation is in progress * Py_XINCREF(obj) # <<<<<<<<<<<<<< * return 0 * */ - __pyx_t_1 = __pyx_v_obj; - __Pyx_INCREF(__pyx_t_1); - Py_XINCREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + Py_XINCREF(__pyx_v_obj); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":29 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":32 * # operation is in progress * Py_XINCREF(obj) * return 0 # <<<<<<<<<<<<<< @@ -2642,8 +3075,8 @@ __pyx_r = Py_None; __Pyx_INCREF(Py_None); goto __pyx_L0; __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("iocpsupport.accept"); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_AddTraceback("iocpsupport.accept", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); @@ -2651,12 +3084,12 @@ return __pyx_r; } -/* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":31 +/* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":34 * return 0 * * def get_accept_addrs(long s, object buff): # <<<<<<<<<<<<<< * cdef WSAPROTOCOL_INFO wsa_pi - * cdef int size, locallen, remotelen + * cdef int locallen, remotelen */ static PyObject *__pyx_pf_11iocpsupport_4get_accept_addrs(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ @@ -2664,105 +3097,109 @@ static PyObject *__pyx_pf_11iocpsupport_4get_accept_addrs(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { long __pyx_v_s; PyObject *__pyx_v_buff = 0; - int __pyx_v_size; int __pyx_v_locallen; int __pyx_v_remotelen; + Py_ssize_t __pyx_v_size; void *__pyx_v_mem_buffer; struct sockaddr *__pyx_v_localaddr; struct sockaddr *__pyx_v_remoteaddr; PyObject *__pyx_r = NULL; - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; PyObject *__pyx_t_4 = NULL; PyObject *__pyx_t_5 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__s,&__pyx_n_s__buff,0}; __Pyx_RefNannySetupContext("get_accept_addrs"); __pyx_self = __pyx_self; - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + { PyObject* values[2] = {0,0}; - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 0: - values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__s); - if (likely(values[0])) kw_args--; - else goto __pyx_L5_argtuple_error; - case 1: - values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__buff); - if (likely(values[1])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("get_accept_addrs", 1, 2, 2, 1); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; } + kw_args = PyDict_Size(__pyx_kwds); + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__s); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__buff); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("get_accept_addrs", 1, 2, 2, 1); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "get_accept_addrs") < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "get_accept_addrs") < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - } - __pyx_v_s = __Pyx_PyInt_AsLong(values[0]); if (unlikely((__pyx_v_s == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_v_s = __Pyx_PyInt_AsLong(values[0]); if (unlikely((__pyx_v_s == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __pyx_v_buff = values[1]; - } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { - goto __pyx_L5_argtuple_error; - } else { - __pyx_v_s = __Pyx_PyInt_AsLong(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_s == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __pyx_v_buff = PyTuple_GET_ITEM(__pyx_args, 1); } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("get_accept_addrs", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __Pyx_RaiseArgtupleInvalid("get_accept_addrs", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __pyx_L3_error:; - __Pyx_AddTraceback("iocpsupport.get_accept_addrs"); + __Pyx_AddTraceback("iocpsupport.get_accept_addrs", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":37 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":41 * cdef sockaddr *localaddr, *remoteaddr * * PyObject_AsReadBuffer(buff, &mem_buffer, &size) # <<<<<<<<<<<<<< * - * lpGetAcceptExSockaddrs(mem_buffer, 0, size / 2, size / 2, &localaddr, &locallen, &remoteaddr, &remotelen) + * lpGetAcceptExSockaddrs(mem_buffer, 0, size / 2, size / 2, */ - __pyx_t_1 = __pyx_v_buff; - __Pyx_INCREF(__pyx_t_1); - __pyx_t_2 = PyObject_AsReadBuffer(__pyx_t_1, (&__pyx_v_mem_buffer), (&__pyx_v_size)); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 37; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyObject_AsReadBuffer(__pyx_v_buff, (&__pyx_v_mem_buffer), (&__pyx_v_size)); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":39 - * PyObject_AsReadBuffer(buff, &mem_buffer, &size) + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":44 * - * lpGetAcceptExSockaddrs(mem_buffer, 0, size / 2, size / 2, &localaddr, &locallen, &remoteaddr, &remotelen) # <<<<<<<<<<<<<< + * lpGetAcceptExSockaddrs(mem_buffer, 0, size / 2, size / 2, + * &localaddr, &locallen, &remoteaddr, &remotelen) # <<<<<<<<<<<<<< * return remoteaddr.sa_family, _makesockaddr(localaddr, locallen), _makesockaddr(remoteaddr, remotelen) * */ - lpGetAcceptExSockaddrs(__pyx_v_mem_buffer, 0, __Pyx_div_long(__pyx_v_size, 2), __Pyx_div_long(__pyx_v_size, 2), (&__pyx_v_localaddr), (&__pyx_v_locallen), (&__pyx_v_remoteaddr), (&__pyx_v_remotelen)); + lpGetAcceptExSockaddrs(__pyx_v_mem_buffer, 0, (((__pyx_t_11iocpsupport_DWORD)__pyx_v_size) / 2), (((__pyx_t_11iocpsupport_DWORD)__pyx_v_size) / 2), (&__pyx_v_localaddr), (&__pyx_v_locallen), (&__pyx_v_remoteaddr), (&__pyx_v_remotelen)); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":40 - * - * lpGetAcceptExSockaddrs(mem_buffer, 0, size / 2, size / 2, &localaddr, &locallen, &remoteaddr, &remotelen) + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":45 + * lpGetAcceptExSockaddrs(mem_buffer, 0, size / 2, size / 2, + * &localaddr, &locallen, &remoteaddr, &remotelen) * return remoteaddr.sa_family, _makesockaddr(localaddr, locallen), _makesockaddr(remoteaddr, remotelen) # <<<<<<<<<<<<<< * */ __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PyInt_FromLong(__pyx_v_remoteaddr->sa_family); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_3 = __pyx_f_11iocpsupport__makesockaddr(__pyx_v_localaddr, __pyx_v_locallen); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = PyInt_FromLong(__pyx_v_remoteaddr->sa_family); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 45; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = __pyx_f_11iocpsupport__makesockaddr(__pyx_v_localaddr, __pyx_v_locallen); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 45; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_3); - __pyx_t_4 = __pyx_f_11iocpsupport__makesockaddr(__pyx_v_remoteaddr, __pyx_v_remotelen); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = __pyx_f_11iocpsupport__makesockaddr(__pyx_v_remoteaddr, __pyx_v_remotelen); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 45; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_4); - __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 45; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(((PyObject *)__pyx_t_5)); - PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_3); __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_5, 2, __pyx_t_4); __Pyx_GIVEREF(__pyx_t_4); - __pyx_t_1 = 0; + __pyx_t_2 = 0; __pyx_t_3 = 0; __pyx_t_4 = 0; __pyx_r = ((PyObject *)__pyx_t_5); @@ -2772,11 +3209,11 @@ __pyx_r = Py_None; __Pyx_INCREF(Py_None); goto __pyx_L0; __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_4); __Pyx_XDECREF(__pyx_t_5); - __Pyx_AddTraceback("iocpsupport.get_accept_addrs"); + __Pyx_AddTraceback("iocpsupport.get_accept_addrs", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); @@ -2784,7 +3221,7 @@ return __pyx_r; } -/* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":5 +/* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":5 * * * def connect(long s, object addr, object obj): # <<<<<<<<<<<<<< @@ -2802,165 +3239,233 @@ int __pyx_v_family; int __pyx_v_rc; struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_v_ov; - struct sockaddr __pyx_v_name; + struct sockaddr_in __pyx_v_ipv4_name; + struct sockaddr_in6 __pyx_v_ipv6_name; + struct sockaddr *__pyx_v_name; + int __pyx_v_namelen; PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; int __pyx_t_2; int __pyx_t_3; int __pyx_t_4; - struct sockaddr_in *__pyx_t_5; - PyObject *__pyx_t_6 = NULL; - struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_t_7; + struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_t_5; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__s,&__pyx_n_s__addr,&__pyx_n_s__obj,0}; __Pyx_RefNannySetupContext("connect"); __pyx_self = __pyx_self; - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + { PyObject* values[3] = {0,0,0}; - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 0: - values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__s); - if (likely(values[0])) kw_args--; - else goto __pyx_L5_argtuple_error; - case 1: - values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__addr); - if (likely(values[1])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("connect", 1, 3, 3, 1); {__pyx_filename = __pyx_f[2]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; } - case 2: - values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__obj); - if (likely(values[2])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("connect", 1, 3, 3, 2); {__pyx_filename = __pyx_f[2]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + kw_args = PyDict_Size(__pyx_kwds); + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__s); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__addr); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("connect", 1, 3, 3, 1); {__pyx_filename = __pyx_f[2]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 2: + values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__obj); + if (likely(values[2])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("connect", 1, 3, 3, 2); {__pyx_filename = __pyx_f[2]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "connect") < 0)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "connect") < 0)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); } __pyx_v_s = __Pyx_PyInt_AsLong(values[0]); if (unlikely((__pyx_v_s == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __pyx_v_addr = values[1]; __pyx_v_obj = values[2]; - } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { - goto __pyx_L5_argtuple_error; - } else { - __pyx_v_s = __Pyx_PyInt_AsLong(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_s == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __pyx_v_addr = PyTuple_GET_ITEM(__pyx_args, 1); - __pyx_v_obj = PyTuple_GET_ITEM(__pyx_args, 2); } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; __Pyx_RaiseArgtupleInvalid("connect", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[2]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __pyx_L3_error:; - __Pyx_AddTraceback("iocpsupport.connect"); + __Pyx_AddTraceback("iocpsupport.connect", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":13 - * cdef sockaddr name + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":16 + * cdef int namelen * * if not have_connectex: # <<<<<<<<<<<<<< * raise ValueError, 'ConnectEx is not available on this system' * */ - __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__have_connectex); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__have_connectex); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_3 = (!__pyx_t_2); if (__pyx_t_3) { - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":14 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":17 * * if not have_connectex: * raise ValueError, 'ConnectEx is not available on this system' # <<<<<<<<<<<<<< * * family = getAddrFamily(s) */ - __Pyx_Raise(__pyx_builtin_ValueError, ((PyObject *)__pyx_kp_s_8), 0); - {__pyx_filename = __pyx_f[2]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_Raise(__pyx_builtin_ValueError, ((PyObject *)__pyx_kp_s_12), 0, 0); + {__pyx_filename = __pyx_f[2]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;} goto __pyx_L6; } __pyx_L6:; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":16 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":19 * raise ValueError, 'ConnectEx is not available on this system' * * family = getAddrFamily(s) # <<<<<<<<<<<<<< * if family == AF_INET: - * fillinetaddr(&name, addr) + * name = &ipv4_name */ - __pyx_t_4 = __pyx_f_11iocpsupport_getAddrFamily(__pyx_v_s); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = __pyx_f_11iocpsupport_getAddrFamily(__pyx_v_s); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __pyx_v_family = __pyx_t_4; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":17 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":24 + * namelen = sizeof(ipv4_name) + * fillinetaddr(&ipv4_name, addr) + * elif family == AF_INET6: # <<<<<<<<<<<<<< + * name = &ipv6_name + * namelen = sizeof(ipv6_name) + */ + switch (__pyx_v_family) { + + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":20 * * family = getAddrFamily(s) * if family == AF_INET: # <<<<<<<<<<<<<< - * fillinetaddr(&name, addr) - * else: + * name = &ipv4_name + * namelen = sizeof(ipv4_name) */ - __pyx_t_3 = (__pyx_v_family == AF_INET); - if (__pyx_t_3) { + case AF_INET: - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":18 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":21 * family = getAddrFamily(s) * if family == AF_INET: - * fillinetaddr(&name, addr) # <<<<<<<<<<<<<< + * name = &ipv4_name # <<<<<<<<<<<<<< + * namelen = sizeof(ipv4_name) + * fillinetaddr(&ipv4_name, addr) + */ + __pyx_v_name = ((struct sockaddr *)(&__pyx_v_ipv4_name)); + + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":22 + * if family == AF_INET: + * name = &ipv4_name + * namelen = sizeof(ipv4_name) # <<<<<<<<<<<<<< + * fillinetaddr(&ipv4_name, addr) + * elif family == AF_INET6: + */ + __pyx_v_namelen = (sizeof(__pyx_v_ipv4_name)); + + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":23 + * name = &ipv4_name + * namelen = sizeof(ipv4_name) + * fillinetaddr(&ipv4_name, addr) # <<<<<<<<<<<<<< + * elif family == AF_INET6: + * name = &ipv6_name + */ + __pyx_t_1 = __pyx_f_11iocpsupport_fillinetaddr((&__pyx_v_ipv4_name), __pyx_v_addr); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + break; + + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":24 + * namelen = sizeof(ipv4_name) + * fillinetaddr(&ipv4_name, addr) + * elif family == AF_INET6: # <<<<<<<<<<<<<< + * name = &ipv6_name + * namelen = sizeof(ipv6_name) + */ + case AF_INET6: + + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":25 + * fillinetaddr(&ipv4_name, addr) + * elif family == AF_INET6: + * name = &ipv6_name # <<<<<<<<<<<<<< + * namelen = sizeof(ipv6_name) + * fillinet6addr(&ipv6_name, addr) + */ + __pyx_v_name = ((struct sockaddr *)(&__pyx_v_ipv6_name)); + + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":26 + * elif family == AF_INET6: + * name = &ipv6_name + * namelen = sizeof(ipv6_name) # <<<<<<<<<<<<<< + * fillinet6addr(&ipv6_name, addr) + * else: + */ + __pyx_v_namelen = (sizeof(__pyx_v_ipv6_name)); + + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":27 + * name = &ipv6_name + * namelen = sizeof(ipv6_name) + * fillinet6addr(&ipv6_name, addr) # <<<<<<<<<<<<<< * else: * raise ValueError, 'unsupported address family' */ - __pyx_t_5 = ((struct sockaddr_in *)(&__pyx_v_name)); - __pyx_t_1 = __pyx_v_addr; - __Pyx_INCREF(__pyx_t_1); - __pyx_t_6 = __pyx_f_11iocpsupport_fillinetaddr(__pyx_t_5, __pyx_t_1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_6); + __pyx_t_1 = __pyx_f_11iocpsupport_fillinet6addr((&__pyx_v_ipv6_name), __pyx_v_addr); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - goto __pyx_L7; - } - /*else*/ { + break; + default: - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":20 - * fillinetaddr(&name, addr) + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":29 + * fillinet6addr(&ipv6_name, addr) * else: * raise ValueError, 'unsupported address family' # <<<<<<<<<<<<<< * name.sa_family = family * */ - __Pyx_Raise(__pyx_builtin_ValueError, ((PyObject *)__pyx_kp_s_9), 0); - {__pyx_filename = __pyx_f[2]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_Raise(__pyx_builtin_ValueError, ((PyObject *)__pyx_kp_s_13), 0, 0); + {__pyx_filename = __pyx_f[2]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + break; } - __pyx_L7:; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":21 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":30 * else: * raise ValueError, 'unsupported address family' * name.sa_family = family # <<<<<<<<<<<<<< * * ov = makeOV() */ - __pyx_v_name.sa_family = __pyx_v_family; + __pyx_v_name->sa_family = __pyx_v_family; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":23 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":32 * name.sa_family = family * * ov = makeOV() # <<<<<<<<<<<<<< * if obj is not None: * ov.obj = obj */ - __pyx_t_7 = __pyx_f_11iocpsupport_makeOV(); if (unlikely(__pyx_t_7 == NULL)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_v_ov = __pyx_t_7; + __pyx_t_5 = __pyx_f_11iocpsupport_makeOV(); if (unlikely(__pyx_t_5 == NULL)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_v_ov = __pyx_t_5; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":24 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":33 * * ov = makeOV() * if obj is not None: # <<<<<<<<<<<<<< @@ -2970,29 +3475,29 @@ __pyx_t_3 = (__pyx_v_obj != Py_None); if (__pyx_t_3) { - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":25 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":34 * ov = makeOV() * if obj is not None: * ov.obj = obj # <<<<<<<<<<<<<< * - * rc = lpConnectEx(s, &name, sizeof(name), NULL, 0, NULL, ov) + * rc = lpConnectEx(s, name, namelen, NULL, 0, NULL, ov) */ __pyx_v_ov->obj = ((struct PyObject *)__pyx_v_obj); - goto __pyx_L8; + goto __pyx_L7; } - __pyx_L8:; + __pyx_L7:; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":27 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":36 * ov.obj = obj * - * rc = lpConnectEx(s, &name, sizeof(name), NULL, 0, NULL, ov) # <<<<<<<<<<<<<< + * rc = lpConnectEx(s, name, namelen, NULL, 0, NULL, ov) # <<<<<<<<<<<<<< * * if not rc: */ - __pyx_v_rc = lpConnectEx(__pyx_v_s, (&__pyx_v_name), (sizeof(__pyx_v_name)), NULL, 0, NULL, ((OVERLAPPED *)__pyx_v_ov)); + __pyx_v_rc = lpConnectEx(__pyx_v_s, __pyx_v_name, __pyx_v_namelen, NULL, 0, NULL, ((OVERLAPPED *)__pyx_v_ov)); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":29 - * rc = lpConnectEx(s, &name, sizeof(name), NULL, 0, NULL, ov) + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":38 + * rc = lpConnectEx(s, name, namelen, NULL, 0, NULL, ov) * * if not rc: # <<<<<<<<<<<<<< * rc = WSAGetLastError() @@ -3001,58 +3506,64 @@ __pyx_t_3 = (!__pyx_v_rc); if (__pyx_t_3) { - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":30 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":39 * * if not rc: * rc = WSAGetLastError() # <<<<<<<<<<<<<< * if rc != ERROR_IO_PENDING: - * return rc + * PyMem_Free(ov) */ __pyx_v_rc = WSAGetLastError(); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":31 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":40 * if not rc: * rc = WSAGetLastError() * if rc != ERROR_IO_PENDING: # <<<<<<<<<<<<<< + * PyMem_Free(ov) * return rc - * */ __pyx_t_3 = (__pyx_v_rc != ERROR_IO_PENDING); if (__pyx_t_3) { - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":32 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":41 * rc = WSAGetLastError() * if rc != ERROR_IO_PENDING: + * PyMem_Free(ov) # <<<<<<<<<<<<<< + * return rc + * + */ + PyMem_Free(__pyx_v_ov); + + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":42 + * if rc != ERROR_IO_PENDING: + * PyMem_Free(ov) * return rc # <<<<<<<<<<<<<< * * # operation is in progress */ __Pyx_XDECREF(__pyx_r); - __pyx_t_6 = PyInt_FromLong(__pyx_v_rc); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_6); - __pyx_r = __pyx_t_6; - __pyx_t_6 = 0; + __pyx_t_1 = PyInt_FromLong(__pyx_v_rc); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 42; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; goto __pyx_L0; - goto __pyx_L10; + goto __pyx_L9; } - __pyx_L10:; - goto __pyx_L9; + __pyx_L9:; + goto __pyx_L8; } - __pyx_L9:; + __pyx_L8:; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":35 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":45 * * # operation is in progress * Py_XINCREF(obj) # <<<<<<<<<<<<<< * return 0 * */ - __pyx_t_6 = __pyx_v_obj; - __Pyx_INCREF(__pyx_t_6); - Py_XINCREF(__pyx_t_6); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + Py_XINCREF(__pyx_v_obj); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":36 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":46 * # operation is in progress * Py_XINCREF(obj) * return 0 # <<<<<<<<<<<<<< @@ -3067,8 +3578,7 @@ goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_6); - __Pyx_AddTraceback("iocpsupport.connect"); + __Pyx_AddTraceback("iocpsupport.connect", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); @@ -3076,11 +3586,11 @@ return __pyx_r; } -/* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":5 +/* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":5 * * * def recv(long s, object bufflist, object obj, unsigned long flags = 0): # <<<<<<<<<<<<<< - * cdef int rc, buffcount, i, res + * cdef int rc, res * cdef myOVERLAPPED *ov */ @@ -3092,60 +3602,77 @@ PyObject *__pyx_v_obj = 0; unsigned long __pyx_v_flags; int __pyx_v_rc; - int __pyx_v_buffcount; - int __pyx_v_i; struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_v_ov; WSABUF *__pyx_v_ws_buf; unsigned long __pyx_v_bytes; struct PyObject **__pyx_v_buffers; + Py_ssize_t __pyx_v_i; + Py_ssize_t __pyx_v_size; + Py_ssize_t __pyx_v_buffcount; PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - void *__pyx_t_3; + void *__pyx_t_2; + Py_ssize_t __pyx_t_3; int __pyx_t_4; - int __pyx_t_5; - struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_t_6; - int __pyx_t_7; + struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_t_5; + int __pyx_t_6; + PyObject *__pyx_t_7 = NULL; PyObject *__pyx_t_8 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__s,&__pyx_n_s__bufflist,&__pyx_n_s__obj,&__pyx_n_s__flags,0}; __Pyx_RefNannySetupContext("recv"); __pyx_self = __pyx_self; - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + { PyObject* values[4] = {0,0,0,0}; - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); - case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 0: - values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__s); - if (likely(values[0])) kw_args--; - else goto __pyx_L5_argtuple_error; - case 1: - values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__bufflist); - if (likely(values[1])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("recv", 0, 3, 4, 1); {__pyx_filename = __pyx_f[3]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; } - case 2: - values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__obj); - if (likely(values[2])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("recv", 0, 3, 4, 2); {__pyx_filename = __pyx_f[3]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + kw_args = PyDict_Size(__pyx_kwds); + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__s); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__bufflist); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("recv", 0, 3, 4, 1); {__pyx_filename = __pyx_f[3]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 2: + values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__obj); + if (likely(values[2])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("recv", 0, 3, 4, 2); {__pyx_filename = __pyx_f[3]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 3: + if (kw_args > 0) { + PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__flags); + if (value) { values[3] = value; kw_args--; } + } } - case 3: - if (kw_args > 0) { - PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__flags); - if (value) { values[3] = value; kw_args--; } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "recv") < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } else { + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + break; + default: goto __pyx_L5_argtuple_error; } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "recv") < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} } __pyx_v_s = __Pyx_PyInt_AsLong(values[0]); if (unlikely((__pyx_v_s == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __pyx_v_bufflist = values[1]; @@ -3155,201 +3682,198 @@ } else { __pyx_v_flags = ((unsigned long)0); } - } else { - __pyx_v_flags = ((unsigned long)0); - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 4: - __pyx_v_flags = __Pyx_PyInt_AsUnsignedLong(PyTuple_GET_ITEM(__pyx_args, 3)); if (unlikely((__pyx_v_flags == (unsigned long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - case 3: - __pyx_v_obj = PyTuple_GET_ITEM(__pyx_args, 2); - __pyx_v_bufflist = PyTuple_GET_ITEM(__pyx_args, 1); - __pyx_v_s = __Pyx_PyInt_AsLong(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_s == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - break; - default: goto __pyx_L5_argtuple_error; - } } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; __Pyx_RaiseArgtupleInvalid("recv", 0, 3, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[3]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __pyx_L3_error:; - __Pyx_AddTraceback("iocpsupport.recv"); + __Pyx_AddTraceback("iocpsupport.recv", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; __Pyx_INCREF(__pyx_v_bufflist); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":12 - * cdef PyObject **buffers + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":13 + * cdef Py_ssize_t i, size, buffcount * * bufflist = PySequence_Fast(bufflist, 'second argument needs to be a list') # <<<<<<<<<<<<<< * buffcount = PySequence_Fast_GET_SIZE(bufflist) * buffers = PySequence_Fast_ITEMS(bufflist) */ - __pyx_t_1 = __pyx_v_bufflist; - __Pyx_INCREF(__pyx_t_1); - __pyx_t_2 = PySequence_Fast(__pyx_t_1, __pyx_k_10); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PySequence_Fast(__pyx_v_bufflist, __pyx_k_14); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_v_bufflist); - __pyx_v_bufflist = __pyx_t_2; - __pyx_t_2 = 0; + __pyx_v_bufflist = __pyx_t_1; + __pyx_t_1 = 0; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":13 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":14 * * bufflist = PySequence_Fast(bufflist, 'second argument needs to be a list') * buffcount = PySequence_Fast_GET_SIZE(bufflist) # <<<<<<<<<<<<<< * buffers = PySequence_Fast_ITEMS(bufflist) * */ - __pyx_t_2 = __pyx_v_bufflist; - __Pyx_INCREF(__pyx_t_2); - __pyx_v_buffcount = PySequence_Fast_GET_SIZE(__pyx_t_2); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_v_buffcount = PySequence_Fast_GET_SIZE(__pyx_v_bufflist); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":14 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":15 * bufflist = PySequence_Fast(bufflist, 'second argument needs to be a list') * buffcount = PySequence_Fast_GET_SIZE(bufflist) * buffers = PySequence_Fast_ITEMS(bufflist) # <<<<<<<<<<<<<< * * ws_buf = PyMem_Malloc(buffcount*sizeof(WSABUF)) */ - __pyx_t_2 = __pyx_v_bufflist; - __Pyx_INCREF(__pyx_t_2); - __pyx_v_buffers = PySequence_Fast_ITEMS(__pyx_t_2); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_v_buffers = PySequence_Fast_ITEMS(__pyx_v_bufflist); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":16 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":17 * buffers = PySequence_Fast_ITEMS(bufflist) * * ws_buf = PyMem_Malloc(buffcount*sizeof(WSABUF)) # <<<<<<<<<<<<<< * * try: */ - __pyx_t_3 = PyMem_Malloc((__pyx_v_buffcount * (sizeof(WSABUF)))); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_v_ws_buf = ((WSABUF *)__pyx_t_3); + __pyx_t_2 = PyMem_Malloc((__pyx_v_buffcount * (sizeof(WSABUF)))); if (unlikely(__pyx_t_2 == NULL)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_v_ws_buf = ((WSABUF *)__pyx_t_2); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":18 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":19 * ws_buf = PyMem_Malloc(buffcount*sizeof(WSABUF)) * * try: # <<<<<<<<<<<<<< * for i from 0 <= i < buffcount: - * PyObject_AsWriteBuffer(buffers[i], &ws_buf[i].buf, &ws_buf[i].len) + * PyObject_AsWriteBuffer(buffers[i], &ws_buf[i].buf, &size) */ /*try:*/ { - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":19 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":20 * * try: * for i from 0 <= i < buffcount: # <<<<<<<<<<<<<< - * PyObject_AsWriteBuffer(buffers[i], &ws_buf[i].buf, &ws_buf[i].len) - * + * PyObject_AsWriteBuffer(buffers[i], &ws_buf[i].buf, &size) + * ws_buf[i].len = size */ - __pyx_t_4 = __pyx_v_buffcount; - for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_4; __pyx_v_i++) { + __pyx_t_3 = __pyx_v_buffcount; + for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_3; __pyx_v_i++) { - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":20 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":21 * try: * for i from 0 <= i < buffcount: - * PyObject_AsWriteBuffer(buffers[i], &ws_buf[i].buf, &ws_buf[i].len) # <<<<<<<<<<<<<< + * PyObject_AsWriteBuffer(buffers[i], &ws_buf[i].buf, &size) # <<<<<<<<<<<<<< + * ws_buf[i].len = size + * + */ + __pyx_t_1 = ((PyObject *)(__pyx_v_buffers[__pyx_v_i])); + __Pyx_INCREF(__pyx_t_1); + __pyx_t_4 = PyObject_AsWriteBuffer(__pyx_t_1, ((void **)(&(__pyx_v_ws_buf[__pyx_v_i]).buf)), (&__pyx_v_size)); if (unlikely(__pyx_t_4 == -1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L7;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":22 + * for i from 0 <= i < buffcount: + * PyObject_AsWriteBuffer(buffers[i], &ws_buf[i].buf, &size) + * ws_buf[i].len = size # <<<<<<<<<<<<<< * * ov = makeOV() */ - __pyx_t_2 = ((PyObject *)(__pyx_v_buffers[__pyx_v_i])); - __Pyx_INCREF(__pyx_t_2); - __pyx_t_5 = PyObject_AsWriteBuffer(__pyx_t_2, ((void **)(&(__pyx_v_ws_buf[__pyx_v_i]).buf)), ((int *)(&(__pyx_v_ws_buf[__pyx_v_i]).len))); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L7;} - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + (__pyx_v_ws_buf[__pyx_v_i]).len = ((__pyx_t_11iocpsupport_DWORD)__pyx_v_size); } - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":22 - * PyObject_AsWriteBuffer(buffers[i], &ws_buf[i].buf, &ws_buf[i].len) + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":24 + * ws_buf[i].len = size * * ov = makeOV() # <<<<<<<<<<<<<< * if obj is not None: * ov.obj = obj */ - __pyx_t_6 = __pyx_f_11iocpsupport_makeOV(); if (unlikely(__pyx_t_6 == NULL)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L7;} - __pyx_v_ov = __pyx_t_6; + __pyx_t_5 = __pyx_f_11iocpsupport_makeOV(); if (unlikely(__pyx_t_5 == NULL)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 24; __pyx_clineno = __LINE__; goto __pyx_L7;} + __pyx_v_ov = __pyx_t_5; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":23 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":25 * * ov = makeOV() * if obj is not None: # <<<<<<<<<<<<<< * ov.obj = obj * */ - __pyx_t_7 = (__pyx_v_obj != Py_None); - if (__pyx_t_7) { + __pyx_t_6 = (__pyx_v_obj != Py_None); + if (__pyx_t_6) { - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":24 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":26 * ov = makeOV() * if obj is not None: * ov.obj = obj # <<<<<<<<<<<<<< * - * rc = WSARecv(s, ws_buf, buffcount, &bytes, &flags, ov, NULL) + * rc = WSARecv(s, ws_buf, buffcount, &bytes, &flags, ov, NULL) */ __pyx_v_ov->obj = ((struct PyObject *)__pyx_v_obj); goto __pyx_L11; } __pyx_L11:; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":26 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":28 * ov.obj = obj * - * rc = WSARecv(s, ws_buf, buffcount, &bytes, &flags, ov, NULL) # <<<<<<<<<<<<<< + * rc = WSARecv(s, ws_buf, buffcount, &bytes, &flags, ov, NULL) # <<<<<<<<<<<<<< * * if rc == SOCKET_ERROR: */ - __pyx_v_rc = WSARecv(__pyx_v_s, __pyx_v_ws_buf, __pyx_v_buffcount, (&__pyx_v_bytes), (&__pyx_v_flags), ((OVERLAPPED *)__pyx_v_ov), NULL); + __pyx_v_rc = WSARecv(__pyx_v_s, __pyx_v_ws_buf, ((__pyx_t_11iocpsupport_DWORD)__pyx_v_buffcount), (&__pyx_v_bytes), (&__pyx_v_flags), ((OVERLAPPED *)__pyx_v_ov), NULL); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":28 - * rc = WSARecv(s, ws_buf, buffcount, &bytes, &flags, ov, NULL) + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":30 + * rc = WSARecv(s, ws_buf, buffcount, &bytes, &flags, ov, NULL) * * if rc == SOCKET_ERROR: # <<<<<<<<<<<<<< * rc = WSAGetLastError() * if rc != ERROR_IO_PENDING: */ - __pyx_t_7 = (__pyx_v_rc == SOCKET_ERROR); - if (__pyx_t_7) { + __pyx_t_6 = (__pyx_v_rc == SOCKET_ERROR); + if (__pyx_t_6) { - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":29 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":31 * * if rc == SOCKET_ERROR: * rc = WSAGetLastError() # <<<<<<<<<<<<<< * if rc != ERROR_IO_PENDING: - * return rc, 0 + * PyMem_Free(ov) */ __pyx_v_rc = WSAGetLastError(); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":30 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":32 * if rc == SOCKET_ERROR: * rc = WSAGetLastError() * if rc != ERROR_IO_PENDING: # <<<<<<<<<<<<<< + * PyMem_Free(ov) * return rc, 0 - * */ - __pyx_t_7 = (__pyx_v_rc != ERROR_IO_PENDING); - if (__pyx_t_7) { + __pyx_t_6 = (__pyx_v_rc != ERROR_IO_PENDING); + if (__pyx_t_6) { - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":31 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":33 * rc = WSAGetLastError() * if rc != ERROR_IO_PENDING: + * PyMem_Free(ov) # <<<<<<<<<<<<<< + * return rc, 0 + * + */ + PyMem_Free(__pyx_v_ov); + + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":34 + * if rc != ERROR_IO_PENDING: + * PyMem_Free(ov) * return rc, 0 # <<<<<<<<<<<<<< * * Py_XINCREF(obj) */ __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = PyInt_FromLong(__pyx_v_rc); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L7;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L7;} - __Pyx_GOTREF(((PyObject *)__pyx_t_1)); - PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2); - __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_1 = PyInt_FromLong(__pyx_v_rc); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L7;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L7;} + __Pyx_GOTREF(((PyObject *)__pyx_t_7)); + PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); __Pyx_INCREF(__pyx_int_0); - PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_0); + PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_int_0); __Pyx_GIVEREF(__pyx_int_0); - __pyx_t_2 = 0; - __pyx_r = ((PyObject *)__pyx_t_1); __pyx_t_1 = 0; + __pyx_r = ((PyObject *)__pyx_t_7); + __pyx_t_7 = 0; goto __pyx_L6; goto __pyx_L13; } @@ -3358,19 +3882,16 @@ } __pyx_L12:; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":33 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":36 * return rc, 0 * * Py_XINCREF(obj) # <<<<<<<<<<<<<< * return rc, bytes * finally: */ - __pyx_t_1 = __pyx_v_obj; - __Pyx_INCREF(__pyx_t_1); - Py_XINCREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + Py_XINCREF(__pyx_v_obj); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":34 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":37 * * Py_XINCREF(obj) * return rc, bytes # <<<<<<<<<<<<<< @@ -3378,24 +3899,24 @@ * PyMem_Free(ws_buf) */ __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PyInt_FromLong(__pyx_v_rc); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L7;} + __pyx_t_7 = PyInt_FromLong(__pyx_v_rc); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 37; __pyx_clineno = __LINE__; goto __pyx_L7;} + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_bytes); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 37; __pyx_clineno = __LINE__; goto __pyx_L7;} __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = PyLong_FromUnsignedLong(__pyx_v_bytes); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L7;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L7;} + __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 37; __pyx_clineno = __LINE__; goto __pyx_L7;} __Pyx_GOTREF(((PyObject *)__pyx_t_8)); - PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7); + __Pyx_GIVEREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_1); __Pyx_GIVEREF(__pyx_t_1); - PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_2); - __Pyx_GIVEREF(__pyx_t_2); + __pyx_t_7 = 0; __pyx_t_1 = 0; - __pyx_t_2 = 0; __pyx_r = ((PyObject *)__pyx_t_8); __pyx_t_8 = 0; goto __pyx_L6; } - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":36 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":39 * return rc, bytes * finally: * PyMem_Free(ws_buf) # <<<<<<<<<<<<<< @@ -3412,8 +3933,8 @@ __pyx_why = 3; goto __pyx_L8; __pyx_L7: { __pyx_why = 4; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; __Pyx_ErrFetch(&__pyx_exc_type, &__pyx_exc_value, &__pyx_exc_tb); __pyx_exc_lineno = __pyx_lineno; @@ -3438,18 +3959,18 @@ goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_7); __Pyx_XDECREF(__pyx_t_8); - __Pyx_AddTraceback("iocpsupport.recv"); + __Pyx_AddTraceback("iocpsupport.recv", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; - __Pyx_DECREF(__pyx_v_bufflist); + __Pyx_XDECREF(__pyx_v_bufflist); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } -/* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":38 +/* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":41 * PyMem_Free(ws_buf) * * def recvfrom(long s, object buff, object addr_buff, object addr_len_buff, object obj, unsigned long flags = 0): # <<<<<<<<<<<<<< @@ -3474,161 +3995,184 @@ unsigned long __pyx_v_bytes; struct sockaddr *__pyx_v_c_addr_buff; int *__pyx_v_c_addr_len_buff; + Py_ssize_t __pyx_v_size; PyObject *__pyx_r = NULL; - PyObject *__pyx_t_1 = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; int __pyx_t_2; - int __pyx_t_3; - struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_t_4; + struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_t_3; + PyObject *__pyx_t_4 = NULL; PyObject *__pyx_t_5 = NULL; PyObject *__pyx_t_6 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__s,&__pyx_n_s__buff,&__pyx_n_s__addr_buff,&__pyx_n_s__addr_len_buff,&__pyx_n_s__obj,&__pyx_n_s__flags,0}; __Pyx_RefNannySetupContext("recvfrom"); __pyx_self = __pyx_self; - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + { PyObject* values[6] = {0,0,0,0,0,0}; - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5); - case 5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4); - case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); - case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 0: - values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__s); - if (likely(values[0])) kw_args--; - else goto __pyx_L5_argtuple_error; - case 1: - values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__buff); - if (likely(values[1])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("recvfrom", 0, 5, 6, 1); {__pyx_filename = __pyx_f[3]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5); + case 5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4); + case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; } - case 2: - values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__addr_buff); - if (likely(values[2])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("recvfrom", 0, 5, 6, 2); {__pyx_filename = __pyx_f[3]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - } - case 3: - values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__addr_len_buff); - if (likely(values[3])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("recvfrom", 0, 5, 6, 3); {__pyx_filename = __pyx_f[3]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + kw_args = PyDict_Size(__pyx_kwds); + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__s); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__buff); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("recvfrom", 0, 5, 6, 1); {__pyx_filename = __pyx_f[3]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 2: + values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__addr_buff); + if (likely(values[2])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("recvfrom", 0, 5, 6, 2); {__pyx_filename = __pyx_f[3]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 3: + values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__addr_len_buff); + if (likely(values[3])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("recvfrom", 0, 5, 6, 3); {__pyx_filename = __pyx_f[3]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 4: + values[4] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__obj); + if (likely(values[4])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("recvfrom", 0, 5, 6, 4); {__pyx_filename = __pyx_f[3]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 5: + if (kw_args > 0) { + PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__flags); + if (value) { values[5] = value; kw_args--; } + } } - case 4: - values[4] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__obj); - if (likely(values[4])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("recvfrom", 0, 5, 6, 4); {__pyx_filename = __pyx_f[3]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "recvfrom") < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L3_error;} } - case 5: - if (kw_args > 0) { - PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__flags); - if (value) { values[5] = value; kw_args--; } + } else { + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5); + case 5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4); + values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + break; + default: goto __pyx_L5_argtuple_error; } } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "recvfrom") < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - } - __pyx_v_s = __Pyx_PyInt_AsLong(values[0]); if (unlikely((__pyx_v_s == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_v_s = __Pyx_PyInt_AsLong(values[0]); if (unlikely((__pyx_v_s == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __pyx_v_buff = values[1]; __pyx_v_addr_buff = values[2]; __pyx_v_addr_len_buff = values[3]; __pyx_v_obj = values[4]; if (values[5]) { - __pyx_v_flags = __Pyx_PyInt_AsUnsignedLong(values[5]); if (unlikely((__pyx_v_flags == (unsigned long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_v_flags = __Pyx_PyInt_AsUnsignedLong(values[5]); if (unlikely((__pyx_v_flags == (unsigned long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L3_error;} } else { __pyx_v_flags = ((unsigned long)0); } - } else { - __pyx_v_flags = ((unsigned long)0); - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 6: - __pyx_v_flags = __Pyx_PyInt_AsUnsignedLong(PyTuple_GET_ITEM(__pyx_args, 5)); if (unlikely((__pyx_v_flags == (unsigned long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - case 5: - __pyx_v_obj = PyTuple_GET_ITEM(__pyx_args, 4); - __pyx_v_addr_len_buff = PyTuple_GET_ITEM(__pyx_args, 3); - __pyx_v_addr_buff = PyTuple_GET_ITEM(__pyx_args, 2); - __pyx_v_buff = PyTuple_GET_ITEM(__pyx_args, 1); - __pyx_v_s = __Pyx_PyInt_AsLong(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_s == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - break; - default: goto __pyx_L5_argtuple_error; - } } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("recvfrom", 0, 5, 6, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[3]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __Pyx_RaiseArgtupleInvalid("recvfrom", 0, 5, 6, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[3]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __pyx_L3_error:; - __Pyx_AddTraceback("iocpsupport.recvfrom"); + __Pyx_AddTraceback("iocpsupport.recvfrom", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":46 - * cdef int *c_addr_len_buff + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":50 + * cdef Py_ssize_t size * - * PyObject_AsWriteBuffer(buff, &ws_buf.buf, &ws_buf.len) # <<<<<<<<<<<<<< - * PyObject_AsWriteBuffer(addr_buff, &c_addr_buff, &c_addr_buff_len) - * PyObject_AsWriteBuffer(addr_len_buff, &c_addr_len_buff, &c_addr_len_buff_len) - */ - __pyx_t_1 = __pyx_v_buff; - __Pyx_INCREF(__pyx_t_1); - __pyx_t_2 = PyObject_AsWriteBuffer(__pyx_t_1, ((void **)(&__pyx_v_ws_buf.buf)), ((int *)(&__pyx_v_ws_buf.len))); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 46; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + * PyObject_AsWriteBuffer(buff, &ws_buf.buf, &size) # <<<<<<<<<<<<<< + * ws_buf.len = size + * PyObject_AsWriteBuffer(addr_buff, &c_addr_buff, &size) + */ + __pyx_t_1 = PyObject_AsWriteBuffer(__pyx_v_buff, ((void **)(&__pyx_v_ws_buf.buf)), (&__pyx_v_size)); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":47 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":51 * - * PyObject_AsWriteBuffer(buff, &ws_buf.buf, &ws_buf.len) - * PyObject_AsWriteBuffer(addr_buff, &c_addr_buff, &c_addr_buff_len) # <<<<<<<<<<<<<< - * PyObject_AsWriteBuffer(addr_len_buff, &c_addr_len_buff, &c_addr_len_buff_len) + * PyObject_AsWriteBuffer(buff, &ws_buf.buf, &size) + * ws_buf.len = size # <<<<<<<<<<<<<< + * PyObject_AsWriteBuffer(addr_buff, &c_addr_buff, &size) + * c_addr_buff_len = size + */ + __pyx_v_ws_buf.len = ((__pyx_t_11iocpsupport_DWORD)__pyx_v_size); + + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":52 + * PyObject_AsWriteBuffer(buff, &ws_buf.buf, &size) + * ws_buf.len = size + * PyObject_AsWriteBuffer(addr_buff, &c_addr_buff, &size) # <<<<<<<<<<<<<< + * c_addr_buff_len = size + * PyObject_AsWriteBuffer(addr_len_buff, &c_addr_len_buff, &size) + */ + __pyx_t_1 = PyObject_AsWriteBuffer(__pyx_v_addr_buff, ((void **)(&__pyx_v_c_addr_buff)), (&__pyx_v_size)); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":53 + * ws_buf.len = size + * PyObject_AsWriteBuffer(addr_buff, &c_addr_buff, &size) + * c_addr_buff_len = size # <<<<<<<<<<<<<< + * PyObject_AsWriteBuffer(addr_len_buff, &c_addr_len_buff, &size) + * c_addr_len_buff_len = size + */ + __pyx_v_c_addr_buff_len = ((int)__pyx_v_size); + + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":54 + * PyObject_AsWriteBuffer(addr_buff, &c_addr_buff, &size) + * c_addr_buff_len = size + * PyObject_AsWriteBuffer(addr_len_buff, &c_addr_len_buff, &size) # <<<<<<<<<<<<<< + * c_addr_len_buff_len = size * */ - __pyx_t_1 = __pyx_v_addr_buff; - __Pyx_INCREF(__pyx_t_1); - __pyx_t_2 = PyObject_AsWriteBuffer(__pyx_t_1, ((void **)(&__pyx_v_c_addr_buff)), (&__pyx_v_c_addr_buff_len)); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyObject_AsWriteBuffer(__pyx_v_addr_len_buff, ((void **)(&__pyx_v_c_addr_len_buff)), (&__pyx_v_size)); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":48 - * PyObject_AsWriteBuffer(buff, &ws_buf.buf, &ws_buf.len) - * PyObject_AsWriteBuffer(addr_buff, &c_addr_buff, &c_addr_buff_len) - * PyObject_AsWriteBuffer(addr_len_buff, &c_addr_len_buff, &c_addr_len_buff_len) # <<<<<<<<<<<<<< + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":55 + * c_addr_buff_len = size + * PyObject_AsWriteBuffer(addr_len_buff, &c_addr_len_buff, &size) + * c_addr_len_buff_len = size # <<<<<<<<<<<<<< * * if c_addr_len_buff_len != sizeof(int): */ - __pyx_t_1 = __pyx_v_addr_len_buff; - __Pyx_INCREF(__pyx_t_1); - __pyx_t_2 = PyObject_AsWriteBuffer(__pyx_t_1, ((void **)(&__pyx_v_c_addr_len_buff)), (&__pyx_v_c_addr_len_buff_len)); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 48; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_c_addr_len_buff_len = ((int)__pyx_v_size); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":50 - * PyObject_AsWriteBuffer(addr_len_buff, &c_addr_len_buff, &c_addr_len_buff_len) + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":57 + * c_addr_len_buff_len = size * * if c_addr_len_buff_len != sizeof(int): # <<<<<<<<<<<<<< * raise ValueError, 'length of address length buffer needs to be sizeof(int)' * */ - __pyx_t_3 = (__pyx_v_c_addr_len_buff_len != (sizeof(int))); - if (__pyx_t_3) { + __pyx_t_2 = (__pyx_v_c_addr_len_buff_len != (sizeof(int))); + if (__pyx_t_2) { - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":51 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":58 * * if c_addr_len_buff_len != sizeof(int): * raise ValueError, 'length of address length buffer needs to be sizeof(int)' # <<<<<<<<<<<<<< * * c_addr_len_buff[0] = c_addr_buff_len */ - __Pyx_Raise(__pyx_builtin_ValueError, ((PyObject *)__pyx_kp_s_11), 0); - {__pyx_filename = __pyx_f[3]; __pyx_lineno = 51; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_Raise(__pyx_builtin_ValueError, ((PyObject *)__pyx_kp_s_15), 0, 0); + {__pyx_filename = __pyx_f[3]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;} goto __pyx_L6; } __pyx_L6:; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":53 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":60 * raise ValueError, 'length of address length buffer needs to be sizeof(int)' * * c_addr_len_buff[0] = c_addr_buff_len # <<<<<<<<<<<<<< @@ -3637,27 +4181,27 @@ */ (__pyx_v_c_addr_len_buff[0]) = __pyx_v_c_addr_buff_len; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":55 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":62 * c_addr_len_buff[0] = c_addr_buff_len * * ov = makeOV() # <<<<<<<<<<<<<< * if obj is not None: * ov.obj = obj */ - __pyx_t_4 = __pyx_f_11iocpsupport_makeOV(); if (unlikely(__pyx_t_4 == NULL)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_v_ov = __pyx_t_4; + __pyx_t_3 = __pyx_f_11iocpsupport_makeOV(); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_v_ov = __pyx_t_3; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":56 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":63 * * ov = makeOV() * if obj is not None: # <<<<<<<<<<<<<< * ov.obj = obj * */ - __pyx_t_3 = (__pyx_v_obj != Py_None); - if (__pyx_t_3) { + __pyx_t_2 = (__pyx_v_obj != Py_None); + if (__pyx_t_2) { - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":57 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":64 * ov = makeOV() * if obj is not None: * ov.obj = obj # <<<<<<<<<<<<<< @@ -3669,7 +4213,7 @@ } __pyx_L7:; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":59 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":66 * ov.obj = obj * * rc = WSARecvFrom(s, &ws_buf, 1, &bytes, &flags, c_addr_buff, c_addr_len_buff, ov, NULL) # <<<<<<<<<<<<<< @@ -3678,53 +4222,62 @@ */ __pyx_v_rc = WSARecvFrom(__pyx_v_s, (&__pyx_v_ws_buf), 1, (&__pyx_v_bytes), (&__pyx_v_flags), __pyx_v_c_addr_buff, __pyx_v_c_addr_len_buff, ((OVERLAPPED *)__pyx_v_ov), NULL); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":61 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":68 * rc = WSARecvFrom(s, &ws_buf, 1, &bytes, &flags, c_addr_buff, c_addr_len_buff, ov, NULL) * * if rc == SOCKET_ERROR: # <<<<<<<<<<<<<< * rc = WSAGetLastError() * if rc != ERROR_IO_PENDING: */ - __pyx_t_3 = (__pyx_v_rc == SOCKET_ERROR); - if (__pyx_t_3) { + __pyx_t_2 = (__pyx_v_rc == SOCKET_ERROR); + if (__pyx_t_2) { - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":62 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":69 * * if rc == SOCKET_ERROR: * rc = WSAGetLastError() # <<<<<<<<<<<<<< * if rc != ERROR_IO_PENDING: - * return rc, 0 + * PyMem_Free(ov) */ __pyx_v_rc = WSAGetLastError(); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":63 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":70 * if rc == SOCKET_ERROR: * rc = WSAGetLastError() * if rc != ERROR_IO_PENDING: # <<<<<<<<<<<<<< + * PyMem_Free(ov) * return rc, 0 - * */ - __pyx_t_3 = (__pyx_v_rc != ERROR_IO_PENDING); - if (__pyx_t_3) { + __pyx_t_2 = (__pyx_v_rc != ERROR_IO_PENDING); + if (__pyx_t_2) { - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":64 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":71 * rc = WSAGetLastError() * if rc != ERROR_IO_PENDING: + * PyMem_Free(ov) # <<<<<<<<<<<<<< + * return rc, 0 + * + */ + PyMem_Free(__pyx_v_ov); + + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":72 + * if rc != ERROR_IO_PENDING: + * PyMem_Free(ov) * return rc, 0 # <<<<<<<<<<<<<< * * Py_XINCREF(obj) */ __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PyInt_FromLong(__pyx_v_rc); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = PyInt_FromLong(__pyx_v_rc); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 72; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 72; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(((PyObject *)__pyx_t_5)); - PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); __Pyx_INCREF(__pyx_int_0); PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_int_0); __Pyx_GIVEREF(__pyx_int_0); - __pyx_t_1 = 0; + __pyx_t_4 = 0; __pyx_r = ((PyObject *)__pyx_t_5); __pyx_t_5 = 0; goto __pyx_L0; @@ -3735,37 +4288,34 @@ } __pyx_L8:; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":66 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":74 * return rc, 0 * * Py_XINCREF(obj) # <<<<<<<<<<<<<< * return rc, bytes * */ - __pyx_t_5 = __pyx_v_obj; - __Pyx_INCREF(__pyx_t_5); - Py_XINCREF(__pyx_t_5); - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + Py_XINCREF(__pyx_v_obj); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":67 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":75 * * Py_XINCREF(obj) * return rc, bytes # <<<<<<<<<<<<<< * */ __Pyx_XDECREF(__pyx_r); - __pyx_t_5 = PyInt_FromLong(__pyx_v_rc); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_5 = PyInt_FromLong(__pyx_v_rc); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_5); - __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_bytes); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = PyLong_FromUnsignedLong(__pyx_v_bytes); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(((PyObject *)__pyx_t_6)); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_5); __Pyx_GIVEREF(__pyx_t_5); - PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); __pyx_t_5 = 0; - __pyx_t_1 = 0; + __pyx_t_4 = 0; __pyx_r = ((PyObject *)__pyx_t_6); __pyx_t_6 = 0; goto __pyx_L0; @@ -3773,10 +4323,10 @@ __pyx_r = Py_None; __Pyx_INCREF(Py_None); goto __pyx_L0; __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); __Pyx_XDECREF(__pyx_t_5); __Pyx_XDECREF(__pyx_t_6); - __Pyx_AddTraceback("iocpsupport.recvfrom"); + __Pyx_AddTraceback("iocpsupport.recvfrom", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); @@ -3784,7 +4334,7 @@ return __pyx_r; } -/* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":5 +/* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":5 * * * def send(long s, object buff, object obj, unsigned long flags = 0): # <<<<<<<<<<<<<< @@ -3803,52 +4353,69 @@ struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_v_ov; WSABUF __pyx_v_ws_buf; unsigned long __pyx_v_bytes; + Py_ssize_t __pyx_v_size; PyObject *__pyx_r = NULL; - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_t_3; - int __pyx_t_4; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + struct __pyx_t_11iocpsupport_myOVERLAPPED *__pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; PyObject *__pyx_t_5 = NULL; PyObject *__pyx_t_6 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__s,&__pyx_n_s__buff,&__pyx_n_s__obj,&__pyx_n_s__flags,0}; __Pyx_RefNannySetupContext("send"); __pyx_self = __pyx_self; - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + { PyObject* values[4] = {0,0,0,0}; - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); - case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 0: - values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__s); - if (likely(values[0])) kw_args--; - else goto __pyx_L5_argtuple_error; - case 1: - values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__buff); - if (likely(values[1])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("send", 0, 3, 4, 1); {__pyx_filename = __pyx_f[4]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; } - case 2: - values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__obj); - if (likely(values[2])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("send", 0, 3, 4, 2); {__pyx_filename = __pyx_f[4]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + kw_args = PyDict_Size(__pyx_kwds); + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__s); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__buff); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("send", 0, 3, 4, 1); {__pyx_filename = __pyx_f[4]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 2: + values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__obj); + if (likely(values[2])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("send", 0, 3, 4, 2); {__pyx_filename = __pyx_f[4]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 3: + if (kw_args > 0) { + PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__flags); + if (value) { values[3] = value; kw_args--; } + } } - case 3: - if (kw_args > 0) { - PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__flags); - if (value) { values[3] = value; kw_args--; } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "send") < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } else { + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + break; + default: goto __pyx_L5_argtuple_error; } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "send") < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} } __pyx_v_s = __Pyx_PyInt_AsLong(values[0]); if (unlikely((__pyx_v_s == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __pyx_v_buff = values[1]; @@ -3858,61 +4425,55 @@ } else { __pyx_v_flags = ((unsigned long)0); } - } else { - __pyx_v_flags = ((unsigned long)0); - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 4: - __pyx_v_flags = __Pyx_PyInt_AsUnsignedLong(PyTuple_GET_ITEM(__pyx_args, 3)); if (unlikely((__pyx_v_flags == (unsigned long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - case 3: - __pyx_v_obj = PyTuple_GET_ITEM(__pyx_args, 2); - __pyx_v_buff = PyTuple_GET_ITEM(__pyx_args, 1); - __pyx_v_s = __Pyx_PyInt_AsLong(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_s == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - break; - default: goto __pyx_L5_argtuple_error; - } } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; __Pyx_RaiseArgtupleInvalid("send", 0, 3, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[4]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __pyx_L3_error:; - __Pyx_AddTraceback("iocpsupport.send"); + __Pyx_AddTraceback("iocpsupport.send", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":11 - * cdef unsigned long bytes + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":12 + * cdef Py_ssize_t size + * + * PyObject_AsReadBuffer(buff, &ws_buf.buf, &size) # <<<<<<<<<<<<<< + * ws_buf.len = size + * + */ + __pyx_t_1 = PyObject_AsReadBuffer(__pyx_v_buff, ((void **)(&__pyx_v_ws_buf.buf)), (&__pyx_v_size)); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":13 * - * PyObject_AsReadBuffer(buff, &ws_buf.buf, &ws_buf.len) # <<<<<<<<<<<<<< + * PyObject_AsReadBuffer(buff, &ws_buf.buf, &size) + * ws_buf.len = size # <<<<<<<<<<<<<< * * ov = makeOV() */ - __pyx_t_1 = __pyx_v_buff; - __Pyx_INCREF(__pyx_t_1); - __pyx_t_2 = PyObject_AsReadBuffer(__pyx_t_1, ((void **)(&__pyx_v_ws_buf.buf)), ((int *)(&__pyx_v_ws_buf.len))); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_ws_buf.len = ((__pyx_t_11iocpsupport_DWORD)__pyx_v_size); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":13 - * PyObject_AsReadBuffer(buff, &ws_buf.buf, &ws_buf.len) + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":15 + * ws_buf.len = size * * ov = makeOV() # <<<<<<<<<<<<<< * if obj is not None: * ov.obj = obj */ - __pyx_t_3 = __pyx_f_11iocpsupport_makeOV(); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_v_ov = __pyx_t_3; + __pyx_t_2 = __pyx_f_11iocpsupport_makeOV(); if (unlikely(__pyx_t_2 == NULL)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_v_ov = __pyx_t_2; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":14 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":16 * * ov = makeOV() * if obj is not None: # <<<<<<<<<<<<<< * ov.obj = obj * */ - __pyx_t_4 = (__pyx_v_obj != Py_None); - if (__pyx_t_4) { + __pyx_t_3 = (__pyx_v_obj != Py_None); + if (__pyx_t_3) { - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":15 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":17 * ov = makeOV() * if obj is not None: * ov.obj = obj # <<<<<<<<<<<<<< @@ -3924,7 +4485,7 @@ } __pyx_L6:; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":17 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":19 * ov.obj = obj * * rc = WSASend(s, &ws_buf, 1, &bytes, flags, ov, NULL) # <<<<<<<<<<<<<< @@ -3933,54 +4494,63 @@ */ __pyx_v_rc = WSASend(__pyx_v_s, (&__pyx_v_ws_buf), 1, (&__pyx_v_bytes), __pyx_v_flags, ((OVERLAPPED *)__pyx_v_ov), NULL); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":19 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":21 * rc = WSASend(s, &ws_buf, 1, &bytes, flags, ov, NULL) * * if rc == SOCKET_ERROR: # <<<<<<<<<<<<<< * rc = WSAGetLastError() * if rc != ERROR_IO_PENDING: */ - __pyx_t_4 = (__pyx_v_rc == SOCKET_ERROR); - if (__pyx_t_4) { + __pyx_t_3 = (__pyx_v_rc == SOCKET_ERROR); + if (__pyx_t_3) { - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":20 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":22 * * if rc == SOCKET_ERROR: * rc = WSAGetLastError() # <<<<<<<<<<<<<< * if rc != ERROR_IO_PENDING: - * return rc, bytes + * PyMem_Free(ov) */ __pyx_v_rc = WSAGetLastError(); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":21 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":23 * if rc == SOCKET_ERROR: * rc = WSAGetLastError() * if rc != ERROR_IO_PENDING: # <<<<<<<<<<<<<< + * PyMem_Free(ov) * return rc, bytes - * */ - __pyx_t_4 = (__pyx_v_rc != ERROR_IO_PENDING); - if (__pyx_t_4) { + __pyx_t_3 = (__pyx_v_rc != ERROR_IO_PENDING); + if (__pyx_t_3) { - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":22 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":24 * rc = WSAGetLastError() * if rc != ERROR_IO_PENDING: + * PyMem_Free(ov) # <<<<<<<<<<<<<< + * return rc, bytes + * + */ + PyMem_Free(__pyx_v_ov); + + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":25 + * if rc != ERROR_IO_PENDING: + * PyMem_Free(ov) * return rc, bytes # <<<<<<<<<<<<<< * * Py_XINCREF(obj) */ __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PyInt_FromLong(__pyx_v_rc); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_5 = PyLong_FromUnsignedLong(__pyx_v_bytes); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = PyInt_FromLong(__pyx_v_rc); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = PyLong_FromUnsignedLong(__pyx_v_bytes); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_5); - __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(((PyObject *)__pyx_t_6)); - PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_t_5); __Pyx_GIVEREF(__pyx_t_5); - __pyx_t_1 = 0; + __pyx_t_4 = 0; __pyx_t_5 = 0; __pyx_r = ((PyObject *)__pyx_t_6); __pyx_t_6 = 0; @@ -3992,19 +4562,16 @@ } __pyx_L7:; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":24 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":27 * return rc, bytes * * Py_XINCREF(obj) # <<<<<<<<<<<<<< * return rc, bytes * */ - __pyx_t_6 = __pyx_v_obj; - __Pyx_INCREF(__pyx_t_6); - Py_XINCREF(__pyx_t_6); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + Py_XINCREF(__pyx_v_obj); - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":25 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":28 * * Py_XINCREF(obj) * return rc, bytes # <<<<<<<<<<<<<< @@ -4012,29 +4579,29 @@ * */ __Pyx_XDECREF(__pyx_r); - __pyx_t_6 = PyInt_FromLong(__pyx_v_rc); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_6 = PyInt_FromLong(__pyx_v_rc); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_6); - __pyx_t_5 = PyLong_FromUnsignedLong(__pyx_v_bytes); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_5 = PyLong_FromUnsignedLong(__pyx_v_bytes); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_5); - __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_1)); - PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_6); + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_4)); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6); __Pyx_GIVEREF(__pyx_t_6); - PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_5); __Pyx_GIVEREF(__pyx_t_5); __pyx_t_6 = 0; __pyx_t_5 = 0; - __pyx_r = ((PyObject *)__pyx_t_1); - __pyx_t_1 = 0; + __pyx_r = ((PyObject *)__pyx_t_4); + __pyx_t_4 = 0; goto __pyx_L0; __pyx_r = Py_None; __Pyx_INCREF(Py_None); goto __pyx_L0; __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); __Pyx_XDECREF(__pyx_t_5); __Pyx_XDECREF(__pyx_t_6); - __Pyx_AddTraceback("iocpsupport.send"); + __Pyx_AddTraceback("iocpsupport.send", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); @@ -4234,18 +4801,22 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_s_1, __pyx_k_1, sizeof(__pyx_k_1), 0, 0, 1, 1}, + {&__pyx_kp_s_10, __pyx_k_10, sizeof(__pyx_k_10), 0, 0, 1, 0}, {&__pyx_kp_s_11, __pyx_k_11, sizeof(__pyx_k_11), 0, 0, 1, 0}, {&__pyx_kp_s_12, __pyx_k_12, sizeof(__pyx_k_12), 0, 0, 1, 0}, + {&__pyx_kp_s_13, __pyx_k_13, sizeof(__pyx_k_13), 0, 0, 1, 0}, + {&__pyx_kp_s_15, __pyx_k_15, sizeof(__pyx_k_15), 0, 0, 1, 0}, + {&__pyx_kp_s_16, __pyx_k_16, sizeof(__pyx_k_16), 0, 0, 1, 0}, {&__pyx_n_s_2, __pyx_k_2, sizeof(__pyx_k_2), 0, 0, 1, 1}, {&__pyx_kp_s_3, __pyx_k_3, sizeof(__pyx_k_3), 0, 0, 1, 0}, {&__pyx_kp_s_5, __pyx_k_5, sizeof(__pyx_k_5), 0, 0, 1, 0}, {&__pyx_kp_s_6, __pyx_k_6, sizeof(__pyx_k_6), 0, 0, 1, 0}, {&__pyx_kp_s_7, __pyx_k_7, sizeof(__pyx_k_7), 0, 0, 1, 0}, {&__pyx_kp_s_8, __pyx_k_8, sizeof(__pyx_k_8), 0, 0, 1, 0}, - {&__pyx_kp_s_9, __pyx_k_9, sizeof(__pyx_k_9), 0, 0, 1, 0}, {&__pyx_n_s__AllocateReadBuffer, __pyx_k__AllocateReadBuffer, sizeof(__pyx_k__AllocateReadBuffer), 0, 0, 1, 1}, {&__pyx_n_s__Event, __pyx_k__Event, sizeof(__pyx_k__Event), 0, 0, 1, 1}, {&__pyx_n_s__MemoryError, __pyx_k__MemoryError, sizeof(__pyx_k__MemoryError), 0, 0, 1, 1}, + {&__pyx_n_s__RuntimeError, __pyx_k__RuntimeError, sizeof(__pyx_k__RuntimeError), 0, 0, 1, 1}, {&__pyx_n_s__ValueError, __pyx_k__ValueError, sizeof(__pyx_k__ValueError), 0, 0, 1, 1}, {&__pyx_n_s__WSAAddressToString, __pyx_k__WSAAddressToString, sizeof(__pyx_k__WSAAddressToString), 0, 0, 1, 1}, {&__pyx_n_s__WindowsError, __pyx_k__WindowsError, sizeof(__pyx_k__WindowsError), 0, 0, 1, 1}, @@ -4257,7 +4828,6 @@ {&__pyx_n_s__addr, __pyx_k__addr, sizeof(__pyx_k__addr), 0, 0, 1, 1}, {&__pyx_n_s__addr_buff, __pyx_k__addr_buff, sizeof(__pyx_k__addr_buff), 0, 0, 1, 1}, {&__pyx_n_s__addr_len_buff, __pyx_k__addr_len_buff, sizeof(__pyx_k__addr_len_buff), 0, 0, 1, 1}, - {&__pyx_n_s__buf, __pyx_k__buf, sizeof(__pyx_k__buf), 0, 0, 1, 1}, {&__pyx_n_s__buff, __pyx_k__buff, sizeof(__pyx_k__buff), 0, 0, 1, 1}, {&__pyx_n_s__bufflist, __pyx_k__bufflist, sizeof(__pyx_k__bufflist), 0, 0, 1, 1}, {&__pyx_n_s__bytes, __pyx_k__bytes, sizeof(__pyx_k__bytes), 0, 0, 1, 1}, @@ -4268,53 +4838,44 @@ {&__pyx_n_s__getsockopt, __pyx_k__getsockopt, sizeof(__pyx_k__getsockopt), 0, 0, 1, 1}, {&__pyx_n_s__handle, __pyx_k__handle, sizeof(__pyx_k__handle), 0, 0, 1, 1}, {&__pyx_n_s__have_connectex, __pyx_k__have_connectex, sizeof(__pyx_k__have_connectex), 0, 0, 1, 1}, - {&__pyx_n_s__iAddressFamily, __pyx_k__iAddressFamily, sizeof(__pyx_k__iAddressFamily), 0, 0, 1, 1}, - {&__pyx_n_s__iMaxSockAddr, __pyx_k__iMaxSockAddr, sizeof(__pyx_k__iMaxSockAddr), 0, 0, 1, 1}, {&__pyx_n_s__iocpsupport, __pyx_k__iocpsupport, sizeof(__pyx_k__iocpsupport), 0, 0, 1, 1}, - {&__pyx_n_s__items, __pyx_k__items, sizeof(__pyx_k__items), 0, 0, 1, 1}, {&__pyx_n_s__key, __pyx_k__key, sizeof(__pyx_k__key), 0, 0, 1, 1}, - {&__pyx_n_s__len, __pyx_k__len, sizeof(__pyx_k__len), 0, 0, 1, 1}, {&__pyx_n_s__listening, __pyx_k__listening, sizeof(__pyx_k__listening), 0, 0, 1, 1}, {&__pyx_n_s__makesockaddr, __pyx_k__makesockaddr, sizeof(__pyx_k__makesockaddr), 0, 0, 1, 1}, {&__pyx_n_s__maxAddrLen, __pyx_k__maxAddrLen, sizeof(__pyx_k__maxAddrLen), 0, 0, 1, 1}, {&__pyx_n_s__obj, __pyx_k__obj, sizeof(__pyx_k__obj), 0, 0, 1, 1}, {&__pyx_n_s__owner, __pyx_k__owner, sizeof(__pyx_k__owner), 0, 0, 1, 1}, - {&__pyx_n_s__port, __pyx_k__port, sizeof(__pyx_k__port), 0, 0, 1, 1}, {&__pyx_n_s__recv, __pyx_k__recv, sizeof(__pyx_k__recv), 0, 0, 1, 1}, {&__pyx_n_s__recvfrom, __pyx_k__recvfrom, sizeof(__pyx_k__recvfrom), 0, 0, 1, 1}, {&__pyx_n_s__rsplit, __pyx_k__rsplit, sizeof(__pyx_k__rsplit), 0, 0, 1, 1}, {&__pyx_n_s__s, __pyx_k__s, sizeof(__pyx_k__s), 0, 0, 1, 1}, - {&__pyx_n_s__s_addr, __pyx_k__s_addr, sizeof(__pyx_k__s_addr), 0, 0, 1, 1}, - {&__pyx_n_s__sa_data, __pyx_k__sa_data, sizeof(__pyx_k__sa_data), 0, 0, 1, 1}, - {&__pyx_n_s__sa_family, __pyx_k__sa_family, sizeof(__pyx_k__sa_family), 0, 0, 1, 1}, {&__pyx_n_s__self, __pyx_k__self, sizeof(__pyx_k__self), 0, 0, 1, 1}, {&__pyx_n_s__send, __pyx_k__send, sizeof(__pyx_k__send), 0, 0, 1, 1}, - {&__pyx_n_s__sin6_port, __pyx_k__sin6_port, sizeof(__pyx_k__sin6_port), 0, 0, 1, 1}, - {&__pyx_n_s__sin_addr, __pyx_k__sin_addr, sizeof(__pyx_k__sin_addr), 0, 0, 1, 1}, - {&__pyx_n_s__sin_port, __pyx_k__sin_port, sizeof(__pyx_k__sin_port), 0, 0, 1, 1}, {&__pyx_n_s__socket, __pyx_k__socket, sizeof(__pyx_k__socket), 0, 0, 1, 1}, + {&__pyx_n_s__split, __pyx_k__split, sizeof(__pyx_k__split), 0, 0, 1, 1}, {0, 0, 0, 0, 0, 0, 0} }; static int __Pyx_InitCachedBuiltins(void) { - __pyx_builtin_ValueError = __Pyx_GetName(__pyx_b, __pyx_n_s__ValueError); if (!__pyx_builtin_ValueError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 267; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_builtin_MemoryError = __Pyx_GetName(__pyx_b, __pyx_n_s__MemoryError); if (!__pyx_builtin_MemoryError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_builtin_WindowsError = __Pyx_GetName(__pyx_b, __pyx_n_s__WindowsError); if (!__pyx_builtin_WindowsError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_builtin_ValueError = __Pyx_GetName(__pyx_b, __pyx_n_s__ValueError); if (!__pyx_builtin_ValueError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 304; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_builtin_MemoryError = __Pyx_GetName(__pyx_b, __pyx_n_s__MemoryError); if (!__pyx_builtin_MemoryError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_builtin_RuntimeError = __Pyx_GetName(__pyx_b, __pyx_n_s__RuntimeError); if (!__pyx_builtin_RuntimeError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;} return 0; __pyx_L1_error:; return -1; } static int __Pyx_InitCachedConstants(void) { + __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants"); - /* "iocpsupport.pyx":219 + /* "iocpsupport.pyx":233 * raise_error(0, 'WSAAddressToString') * host, sa_port = PyString_FromString(buff), ntohs(sin6.sin6_port) * host, port = host.rsplit(':', 1) # <<<<<<<<<<<<<< * port = int(port) * assert host[0] == '[' */ - __pyx_k_tuple_4 = PyTuple_New(2); if (unlikely(!__pyx_k_tuple_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 219; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_k_tuple_4 = PyTuple_New(2); if (unlikely(!__pyx_k_tuple_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_4)); __Pyx_INCREF(((PyObject *)__pyx_kp_s_3)); PyTuple_SET_ITEM(__pyx_k_tuple_4, 0, ((PyObject *)__pyx_kp_s_3)); @@ -4323,6 +4884,20 @@ PyTuple_SET_ITEM(__pyx_k_tuple_4, 1, __pyx_int_1); __Pyx_GIVEREF(__pyx_int_1); __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_4)); + + /* "iocpsupport.pyx":264 + * cdef int addrlen = sizeof(sockaddr_in6) + * host, port, flow, scope = addr + * host = host.split("%")[0] # remove scope ID, if any # <<<<<<<<<<<<<< + * + * hoststr = PyString_AsString(host) + */ + __pyx_k_tuple_9 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_k_tuple_9)); + __Pyx_INCREF(((PyObject *)__pyx_kp_s_8)); + PyTuple_SET_ITEM(__pyx_k_tuple_9, 0, ((PyObject *)__pyx_kp_s_8)); + __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_8)); + __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_9)); __Pyx_RefNannyFinishContext(); return 0; __pyx_L1_error:; @@ -4350,8 +4925,8 @@ PyObject *__pyx_t_1 = NULL; PyObject *__pyx_t_2 = NULL; int __pyx_t_3; + __Pyx_RefNannyDeclarations #if CYTHON_REFNANNY - void* __pyx_refnanny = NULL; __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); if (!__Pyx_RefNanny) { PyErr_Clear(); @@ -4359,8 +4934,9 @@ if (!__Pyx_RefNanny) Py_FatalError("failed to import 'refnanny' module"); } - __pyx_refnanny = __Pyx_RefNanny->SetupContext("PyMODINIT_FUNC PyInit_iocpsupport(void)", __LINE__, __FILE__); #endif + __Pyx_RefNannySetupContext("PyMODINIT_FUNC PyInit_iocpsupport(void)"); + if ( __Pyx_check_binary_version() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} #ifdef __pyx_binding_PyCFunctionType_USED @@ -4396,99 +4972,101 @@ /*--- Constants init code ---*/ if (unlikely(__Pyx_InitCachedConstants() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} /*--- Global init code ---*/ + /*--- Variable export code ---*/ /*--- Function export code ---*/ /*--- Type init code ---*/ - if (PyType_Ready(&__pyx_type_11iocpsupport_CompletionPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 138; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - if (__Pyx_SetAttrString(__pyx_m, "CompletionPort", (PyObject *)&__pyx_type_11iocpsupport_CompletionPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 138; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyType_Ready(&__pyx_type_11iocpsupport_CompletionPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 148; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_SetAttrString(__pyx_m, "CompletionPort", (PyObject *)&__pyx_type_11iocpsupport_CompletionPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 148; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __pyx_ptype_11iocpsupport_CompletionPort = &__pyx_type_11iocpsupport_CompletionPort; /*--- Type import code ---*/ + /*--- Variable import code ---*/ /*--- Function import code ---*/ /*--- Execution code ---*/ - /* "iocpsupport.pyx":131 + /* "iocpsupport.pyx":141 * raise WindowsError(message, err) * * class Event: # <<<<<<<<<<<<<< * def __init__(self, callback, owner, **kw): * self.callback = callback */ - __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 131; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 141; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(((PyObject *)__pyx_t_1)); - /* "iocpsupport.pyx":132 + /* "iocpsupport.pyx":142 * * class Event: * def __init__(self, callback, owner, **kw): # <<<<<<<<<<<<<< * self.callback = callback * self.owner = owner */ - __pyx_t_2 = __pyx_binding_PyCFunctionType_NewEx(&__pyx_mdef_11iocpsupport_5Event___init__, NULL, __pyx_n_s__iocpsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = __pyx_binding_PyCFunctionType_NewEx(&__pyx_mdef_11iocpsupport_5Event___init__, NULL, __pyx_n_s__iocpsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_2); - if (PyObject_SetItem(__pyx_t_1, __pyx_n_s____init__, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetItem(__pyx_t_1, __pyx_n_s____init__, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - /* "iocpsupport.pyx":131 + /* "iocpsupport.pyx":141 * raise WindowsError(message, err) * * class Event: # <<<<<<<<<<<<<< * def __init__(self, callback, owner, **kw): * self.callback = callback */ - __pyx_t_2 = __Pyx_CreateClass(((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1), __pyx_n_s__Event, __pyx_n_s__iocpsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 131; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = __Pyx_CreateClass(((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1), __pyx_n_s__Event, __pyx_n_s__iocpsupport); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 141; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_2); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__Event, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 131; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__Event, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 141; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0; - /* "iocpsupport.pyx":194 + /* "iocpsupport.pyx":208 * CloseHandle(self.port) * * def makesockaddr(object buff): # <<<<<<<<<<<<<< * cdef void *mem_buffer - * cdef int size + * cdef Py_ssize_t size */ - __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_11iocpsupport_makesockaddr, NULL, __pyx_n_s__iocpsupport); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_11iocpsupport_makesockaddr, NULL, __pyx_n_s__iocpsupport); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 208; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__makesockaddr, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__makesockaddr, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 208; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "iocpsupport.pyx":242 - * dest.sin_port = htons(port) + /* "iocpsupport.pyx":279 + * * * def AllocateReadBuffer(int size): # <<<<<<<<<<<<<< * return PyBuffer_New(size) * */ - __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_11iocpsupport_1AllocateReadBuffer, NULL, __pyx_n_s__iocpsupport); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 242; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_11iocpsupport_1AllocateReadBuffer, NULL, __pyx_n_s__iocpsupport); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__AllocateReadBuffer, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 242; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__AllocateReadBuffer, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "iocpsupport.pyx":245 + /* "iocpsupport.pyx":282 * return PyBuffer_New(size) * * def maxAddrLen(long s): # <<<<<<<<<<<<<< * cdef WSAPROTOCOL_INFO wsa_pi * cdef int size, rc */ - __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_11iocpsupport_2maxAddrLen, NULL, __pyx_n_s__iocpsupport); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_11iocpsupport_2maxAddrLen, NULL, __pyx_n_s__iocpsupport); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 282; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__maxAddrLen, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__maxAddrLen, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 282; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "iocpsupport.pyx":265 + /* "iocpsupport.pyx":302 * return wsa_pi.iAddressFamily * * import socket # for WSAStartup # <<<<<<<<<<<<<< * if not initWinsockPointers(): * raise ValueError, 'Failed to initialize Winsock function vectors' */ - __pyx_t_1 = __Pyx_Import(((PyObject *)__pyx_n_s__socket), 0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 265; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = __Pyx_Import(((PyObject *)__pyx_n_s__socket), 0, -1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 302; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__socket, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 265; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__socket, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 302; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "iocpsupport.pyx":266 + /* "iocpsupport.pyx":303 * * import socket # for WSAStartup * if not initWinsockPointers(): # <<<<<<<<<<<<<< @@ -4498,32 +5076,32 @@ __pyx_t_3 = (!initWinsockPointers()); if (__pyx_t_3) { - /* "iocpsupport.pyx":267 + /* "iocpsupport.pyx":304 * import socket # for WSAStartup * if not initWinsockPointers(): * raise ValueError, 'Failed to initialize Winsock function vectors' # <<<<<<<<<<<<<< * * have_connectex = (lpConnectEx != NULL) */ - __Pyx_Raise(__pyx_builtin_ValueError, ((PyObject *)__pyx_kp_s_12), 0); - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 267; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_Raise(__pyx_builtin_ValueError, ((PyObject *)__pyx_kp_s_16), 0, 0); + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 304; __pyx_clineno = __LINE__; goto __pyx_L1_error;} goto __pyx_L2; } __pyx_L2:; - /* "iocpsupport.pyx":269 + /* "iocpsupport.pyx":306 * raise ValueError, 'Failed to initialize Winsock function vectors' * * have_connectex = (lpConnectEx != NULL) # <<<<<<<<<<<<<< * * include 'acceptex.pxi' */ - __pyx_t_1 = __Pyx_PyBool_FromLong((lpConnectEx != NULL)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 269; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = __Pyx_PyBool_FromLong((lpConnectEx != NULL)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 306; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__have_connectex, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 269; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__have_connectex, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 306; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":5 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":5 * * * def accept(long listening, long accepting, object buff, object obj): # <<<<<<<<<<<<<< @@ -4535,19 +5113,19 @@ if (PyObject_SetAttr(__pyx_m, __pyx_n_s__accept, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":31 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\acceptex.pxi":34 * return 0 * * def get_accept_addrs(long s, object buff): # <<<<<<<<<<<<<< * cdef WSAPROTOCOL_INFO wsa_pi - * cdef int size, locallen, remotelen + * cdef int locallen, remotelen */ - __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_11iocpsupport_4get_accept_addrs, NULL, __pyx_n_s__iocpsupport); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_11iocpsupport_4get_accept_addrs, NULL, __pyx_n_s__iocpsupport); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__get_accept_addrs, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__get_accept_addrs, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":5 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\connectex.pxi":5 * * * def connect(long s, object addr, object obj): # <<<<<<<<<<<<<< @@ -4563,19 +5141,19 @@ if (PyObject_SetAttr(__pyx_m, __pyx_n_s__recv, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":38 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsarecv.pxi":41 * PyMem_Free(ws_buf) * * def recvfrom(long s, object buff, object addr_buff, object addr_len_buff, object obj, unsigned long flags = 0): # <<<<<<<<<<<<<< * cdef int rc, c_addr_buff_len, c_addr_len_buff_len * cdef myOVERLAPPED *ov */ - __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_11iocpsupport_7recvfrom, NULL, __pyx_n_s__iocpsupport); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_11iocpsupport_7recvfrom, NULL, __pyx_n_s__iocpsupport); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__recvfrom, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__recvfrom, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "E:\Twisted.5084\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":5 + /* "C:\t\twisted\twisted\internet\iocpreactor\iocpsupport\wsasend.pxi":5 * * * def send(long s, object buff, object obj, unsigned long flags = 0): # <<<<<<<<<<<<<< @@ -4601,7 +5179,7 @@ __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_2); if (__pyx_m) { - __Pyx_AddTraceback("init iocpsupport"); + __Pyx_AddTraceback("init iocpsupport", __pyx_clineno, __pyx_lineno, __pyx_filename); Py_DECREF(__pyx_m); __pyx_m = 0; } else if (!PyErr_Occurred()) { PyErr_SetString(PyExc_ImportError, "init iocpsupport"); @@ -4617,11 +5195,34 @@ /* Runtime support code */ +#if CYTHON_REFNANNY +static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { + PyObject *m = NULL, *p = NULL; + void *r = NULL; + m = PyImport_ImportModule((char *)modname); + if (!m) goto end; + p = PyObject_GetAttrString(m, (char *)"RefNannyAPI"); + if (!p) goto end; + r = PyLong_AsVoidPtr(p); +end: + Py_XDECREF(p); + Py_XDECREF(m); + return (__Pyx_RefNannyAPIStruct *)r; +} +#endif /* CYTHON_REFNANNY */ + static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) { PyObject *result; result = PyObject_GetAttr(dict, name); - if (!result) - PyErr_SetObject(PyExc_NameError, name); + if (!result) { + if (dict != __pyx_b) { + PyErr_Clear(); + result = PyObject_GetAttr(__pyx_b, name); + } + if (!result) { + PyErr_SetObject(PyExc_NameError, name); + } + } return result; } @@ -4653,7 +5254,8 @@ #if PY_MAJOR_VERSION < 3 -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) { +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { + /* cause is unused */ Py_XINCREF(type); Py_XINCREF(value); Py_XINCREF(tb); @@ -4720,7 +5322,7 @@ #else /* Python 3+ */ -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) { +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { if (tb == Py_None) { tb = 0; } else if (tb && !PyTraceBack_Check(tb)) { @@ -4745,6 +5347,29 @@ goto bad; } + if (cause) { + PyObject *fixed_cause; + if (PyExceptionClass_Check(cause)) { + fixed_cause = PyObject_CallObject(cause, NULL); + if (fixed_cause == NULL) + goto bad; + } + else if (PyExceptionInstance_Check(cause)) { + fixed_cause = cause; + Py_INCREF(fixed_cause); + } + else { + PyErr_SetString(PyExc_TypeError, + "exception causes must derive from " + "BaseException"); + goto bad; + } + if (!value) { + value = PyObject_CallObject(type, NULL); + } + PyException_SetCause(value, fixed_cause); + } + PyErr_SetObject(type, value); if (tb) { @@ -4770,7 +5395,7 @@ Py_ssize_t num_found) { Py_ssize_t num_expected; - const char *number, *more_or_less; + const char *more_or_less; if (num_found < num_min) { num_expected = num_min; @@ -4782,14 +5407,10 @@ if (exact) { more_or_less = "exactly"; } - number = (num_expected == 1) ? "" : "s"; PyErr_Format(PyExc_TypeError, - #if PY_VERSION_HEX < 0x02050000 - "%s() takes %s %d positional argument%s (%d given)", - #else - "%s() takes %s %zd positional argument%s (%zd given)", - #endif - func_name, more_or_less, num_expected, number, num_found); + "%s() takes %s %"PY_FORMAT_SIZE_T"d positional argument%s (%"PY_FORMAT_SIZE_T"d given)", + func_name, more_or_less, num_expected, + (num_expected == 1) ? "" : "s", num_found); } static void __Pyx_RaiseDoubleKeywordsError( @@ -4886,44 +5507,29 @@ static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) { PyErr_Format(PyExc_ValueError, - #if PY_VERSION_HEX < 0x02050000 - "need more than %d value%s to unpack", (int)index, - #else - "need more than %zd value%s to unpack", index, - #endif - (index == 1) ? "" : "s"); + "need more than %"PY_FORMAT_SIZE_T"d value%s to unpack", + index, (index == 1) ? "" : "s"); } static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) { PyErr_Format(PyExc_ValueError, - #if PY_VERSION_HEX < 0x02050000 - "too many values to unpack (expected %d)", (int)expected); - #else - "too many values to unpack (expected %zd)", expected); - #endif + "too many values to unpack (expected %"PY_FORMAT_SIZE_T"d)", expected); } -static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) { - PyObject *item; - if (!(item = PyIter_Next(iter))) { - if (!PyErr_Occurred()) { - __Pyx_RaiseNeedMoreValuesError(index); - } - } - return item; -} - -static int __Pyx_EndUnpack(PyObject *iter, Py_ssize_t expected) { - PyObject *item; - if ((item = PyIter_Next(iter))) { - Py_DECREF(item); +static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected) { + if (unlikely(retval)) { + Py_DECREF(retval); __Pyx_RaiseTooManyValuesError(expected); return -1; + } else if (PyErr_Occurred()) { + if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) { + PyErr_Clear(); + return 0; + } else { + return -1; + } } - else if (!PyErr_Occurred()) - return 0; - else - return -1; + return 0; } static CYTHON_INLINE int __Pyx_CheckKeywordStrings( @@ -4961,20 +5567,13 @@ } -static CYTHON_INLINE long __Pyx_div_long(long a, long b) { - long q = a / b; - long r = a - q*b; - q -= ((r != 0) & ((r ^ b) < 0)); - return q; -} - static PyObject *__Pyx_FindPy2Metaclass(PyObject *bases) { PyObject *metaclass; /* Default metaclass */ #if PY_MAJOR_VERSION < 3 if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0) { PyObject *base = PyTuple_GET_ITEM(bases, 0); - metaclass = PyObject_GetAttrString(base, "__class__"); + metaclass = PyObject_GetAttrString(base, (char *)"__class__"); if (!metaclass) { PyErr_Clear(); metaclass = (PyObject*) Py_TYPE(base); @@ -5016,29 +5615,29 @@ static PyObject *__pyx_binding_PyCFunctionType_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module) { - __pyx_binding_PyCFunctionType_object *op = PyObject_GC_New(__pyx_binding_PyCFunctionType_object, __pyx_binding_PyCFunctionType); + __pyx_binding_PyCFunctionType_object *op = PyObject_GC_New(__pyx_binding_PyCFunctionType_object, __pyx_binding_PyCFunctionType); if (op == NULL) return NULL; - op->func.m_ml = ml; - Py_XINCREF(self); - op->func.m_self = self; - Py_XINCREF(module); - op->func.m_module = module; - PyObject_GC_Track(op); - return (PyObject *)op; + op->func.m_ml = ml; + Py_XINCREF(self); + op->func.m_self = self; + Py_XINCREF(module); + op->func.m_module = module; + PyObject_GC_Track(op); + return (PyObject *)op; } static void __pyx_binding_PyCFunctionType_dealloc(__pyx_binding_PyCFunctionType_object *m) { - PyObject_GC_UnTrack(m); - Py_XDECREF(m->func.m_self); - Py_XDECREF(m->func.m_module); + PyObject_GC_UnTrack(m); + Py_XDECREF(m->func.m_self); + Py_XDECREF(m->func.m_module); PyObject_GC_Del(m); } static PyObject *__pyx_binding_PyCFunctionType_descr_get(PyObject *func, PyObject *obj, PyObject *type) { - if (obj == Py_None) - obj = NULL; - return PyMethod_New(func, obj, type); + if (obj == Py_None) + obj = NULL; + return PyMethod_New(func, obj, type); } static int __pyx_binding_PyCFunctionType_init(void) { @@ -5054,7 +5653,7 @@ } -static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) { +static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level) { PyObject *py_import = 0; PyObject *empty_list = 0; PyObject *module = 0; @@ -5078,8 +5677,23 @@ empty_dict = PyDict_New(); if (!empty_dict) goto bad; + #if PY_VERSION_HEX >= 0x02050000 + { + PyObject *py_level = PyInt_FromLong(level); + if (!py_level) + goto bad; + module = PyObject_CallFunctionObjArgs(py_import, + name, global_dict, empty_dict, list, py_level, NULL); + Py_DECREF(py_level); + } + #else + if (level>0) { + PyErr_SetString(PyExc_RuntimeError, "Relative import is not supported for Python <=2.4."); + goto bad; + } module = PyObject_CallFunctionObjArgs(py_import, name, global_dict, empty_dict, list, NULL); + #endif bad: Py_XDECREF(empty_list); Py_XDECREF(py_import); @@ -5087,6 +5701,68 @@ return module; } +static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals) { + if (s1 == s2) { /* as done by PyObject_RichCompareBool(); also catches the (interned) empty string */ + return (equals == Py_EQ); + } else if (PyBytes_CheckExact(s1) & PyBytes_CheckExact(s2)) { + if (PyBytes_GET_SIZE(s1) != PyBytes_GET_SIZE(s2)) { + return (equals == Py_NE); + } else if (PyBytes_GET_SIZE(s1) == 1) { + if (equals == Py_EQ) + return (PyBytes_AS_STRING(s1)[0] == PyBytes_AS_STRING(s2)[0]); + else + return (PyBytes_AS_STRING(s1)[0] != PyBytes_AS_STRING(s2)[0]); + } else { + int result = memcmp(PyBytes_AS_STRING(s1), PyBytes_AS_STRING(s2), (size_t)PyBytes_GET_SIZE(s1)); + return (equals == Py_EQ) ? (result == 0) : (result != 0); + } + } else if ((s1 == Py_None) & PyBytes_CheckExact(s2)) { + return (equals == Py_NE); + } else if ((s2 == Py_None) & PyBytes_CheckExact(s1)) { + return (equals == Py_NE); + } else { + int result; + PyObject* py_result = PyObject_RichCompare(s1, s2, equals); + if (!py_result) + return -1; + result = __Pyx_PyObject_IsTrue(py_result); + Py_DECREF(py_result); + return result; + } +} + +static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals) { + if (s1 == s2) { /* as done by PyObject_RichCompareBool(); also catches the (interned) empty string */ + return (equals == Py_EQ); + } else if (PyUnicode_CheckExact(s1) & PyUnicode_CheckExact(s2)) { + if (PyUnicode_GET_SIZE(s1) != PyUnicode_GET_SIZE(s2)) { + return (equals == Py_NE); + } else if (PyUnicode_GET_SIZE(s1) == 1) { + if (equals == Py_EQ) + return (PyUnicode_AS_UNICODE(s1)[0] == PyUnicode_AS_UNICODE(s2)[0]); + else + return (PyUnicode_AS_UNICODE(s1)[0] != PyUnicode_AS_UNICODE(s2)[0]); + } else { + int result = PyUnicode_Compare(s1, s2); + if ((result == -1) && unlikely(PyErr_Occurred())) + return -1; + return (equals == Py_EQ) ? (result == 0) : (result != 0); + } + } else if ((s1 == Py_None) & PyUnicode_CheckExact(s2)) { + return (equals == Py_NE); + } else if ((s2 == Py_None) & PyUnicode_CheckExact(s1)) { + return (equals == Py_NE); + } else { + int result; + PyObject* py_result = PyObject_RichCompare(s1, s2, equals); + if (!py_result) + return -1; + result = __Pyx_PyObject_IsTrue(py_result); + Py_DECREF(py_result); + return result; + } +} + static CYTHON_INLINE unsigned char __Pyx_PyInt_AsUnsignedChar(PyObject* x) { const unsigned char neg_one = (unsigned char)-1, const_zero = 0; const int is_unsigned = neg_one > const_zero; @@ -5298,9 +5974,9 @@ "can't convert negative value to unsigned long"); return (unsigned long)-1; } - return PyLong_AsUnsignedLong(x); + return (unsigned long)PyLong_AsUnsignedLong(x); } else { - return PyLong_AsLong(x); + return (unsigned long)PyLong_AsLong(x); } } else { unsigned long val; @@ -5333,9 +6009,9 @@ "can't convert negative value to unsigned PY_LONG_LONG"); return (unsigned PY_LONG_LONG)-1; } - return PyLong_AsUnsignedLongLong(x); + return (unsigned PY_LONG_LONG)PyLong_AsUnsignedLongLong(x); } else { - return PyLong_AsLongLong(x); + return (unsigned PY_LONG_LONG)PyLong_AsLongLong(x); } } else { unsigned PY_LONG_LONG val; @@ -5368,9 +6044,9 @@ "can't convert negative value to long"); return (long)-1; } - return PyLong_AsUnsignedLong(x); + return (long)PyLong_AsUnsignedLong(x); } else { - return PyLong_AsLong(x); + return (long)PyLong_AsLong(x); } } else { long val; @@ -5403,9 +6079,9 @@ "can't convert negative value to PY_LONG_LONG"); return (PY_LONG_LONG)-1; } - return PyLong_AsUnsignedLongLong(x); + return (PY_LONG_LONG)PyLong_AsUnsignedLongLong(x); } else { - return PyLong_AsLongLong(x); + return (PY_LONG_LONG)PyLong_AsLongLong(x); } } else { PY_LONG_LONG val; @@ -5438,9 +6114,9 @@ "can't convert negative value to signed long"); return (signed long)-1; } - return PyLong_AsUnsignedLong(x); + return (signed long)PyLong_AsUnsignedLong(x); } else { - return PyLong_AsLong(x); + return (signed long)PyLong_AsLong(x); } } else { signed long val; @@ -5473,9 +6149,9 @@ "can't convert negative value to signed PY_LONG_LONG"); return (signed PY_LONG_LONG)-1; } - return PyLong_AsUnsignedLongLong(x); + return (signed PY_LONG_LONG)PyLong_AsUnsignedLongLong(x); } else { - return PyLong_AsLongLong(x); + return (signed PY_LONG_LONG)PyLong_AsLongLong(x); } } else { signed PY_LONG_LONG val; @@ -5487,11 +6163,31 @@ } } +static int __Pyx_check_binary_version(void) { + char ctversion[4], rtversion[4]; + PyOS_snprintf(ctversion, 4, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION); + PyOS_snprintf(rtversion, 4, "%s", Py_GetVersion()); + if (ctversion[0] != rtversion[0] || ctversion[2] != rtversion[2]) { + char message[200]; + PyOS_snprintf(message, sizeof(message), + "compiletime version %s of module '%.100s' " + "does not match runtime version %s", + ctversion, __Pyx_MODULE_NAME, rtversion); + #if PY_VERSION_HEX < 0x02050000 + return PyErr_Warn(NULL, message); + #else + return PyErr_WarnEx(NULL, message, 1); + #endif + } + return 0; +} + #include "compile.h" #include "frameobject.h" #include "traceback.h" -static void __Pyx_AddTraceback(const char *funcname) { +static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno, + int __pyx_lineno, const char *__pyx_filename) { PyObject *py_srcfile = 0; PyObject *py_funcname = 0; PyObject *py_globals = 0; diff -Nru twisted-11.1.0/twisted/internet/iocpreactor/iocpsupport/iocpsupport.pyx twisted-12.1.0/twisted/internet/iocpreactor/iocpsupport/iocpsupport.pyx --- twisted-11.1.0/twisted/internet/iocpreactor/iocpsupport/iocpsupport.pyx 2011-06-03 22:55:35.000000000 +0000 +++ twisted-12.1.0/twisted/internet/iocpreactor/iocpsupport/iocpsupport.pyx 2012-03-27 12:27:04.000000000 +0000 @@ -2,11 +2,12 @@ # See LICENSE for details. -ctypedef int size_t -ctypedef unsigned long HANDLE -ctypedef unsigned long SOCKET +# HANDLE and SOCKET are pointer-sized (they are 64 bit wide in 64-bit builds) +ctypedef size_t HANDLE +ctypedef size_t SOCKET ctypedef unsigned long DWORD -ctypedef unsigned long ULONG_PTR +# it's really a pointer, but we use it as an integer +ctypedef size_t ULONG_PTR ctypedef int BOOL cdef extern from 'io.h': @@ -48,29 +49,35 @@ void Py_XINCREF(object o) void Py_DECREF(object o) void Py_XDECREF(object o) - int PyObject_AsWriteBuffer(object obj, void **buffer, int *buffer_len) except -1 - int PyObject_AsReadBuffer(object obj, void **buffer, int *buffer_len) except -1 + int PyObject_AsWriteBuffer(object obj, void **buffer, Py_ssize_t *buffer_len) except -1 + int PyObject_AsReadBuffer(object obj, void **buffer, Py_ssize_t *buffer_len) except -1 object PyString_FromString(char *v) - object PyString_FromStringAndSize(char *v, int len) - object PyBuffer_New(int size) + object PyString_FromStringAndSize(char *v, Py_ssize_t len) + object PyBuffer_New(Py_ssize_t size) char *PyString_AsString(object obj) except NULL object PySequence_Fast(object o, char *m) -# object PySequence_Fast_GET_ITEM(object o, int i) +# object PySequence_Fast_GET_ITEM(object o, Py_ssize_t i) PyObject** PySequence_Fast_ITEMS(object o) - PyObject* PySequence_ITEM( PyObject *o, int i) - int PySequence_Fast_GET_SIZE(object o) + PyObject* PySequence_ITEM(PyObject *o, Py_ssize_t i) + Py_ssize_t PySequence_Fast_GET_SIZE(object o) cdef extern from '': struct sockaddr: - int sa_family + unsigned short int sa_family char sa_data[0] cdef struct in_addr: unsigned long s_addr struct sockaddr_in: int sin_port in_addr sin_addr + cdef struct in6_addr: + char s6_addr[16] struct sockaddr_in6: - int sin6_port + short int sin6_family + unsigned short int sin6_port + unsigned long int sin6_flowinfo + in6_addr sin6_addr + unsigned long int sin6_scope_id int getsockopt(SOCKET s, int level, int optname, char *optval, int *optlen) enum: SOL_SOCKET @@ -100,6 +107,9 @@ WSAPROTOCOL_INFO *lpProtocolInfo, char *lpszAddressString, DWORD *lpdwAddressStringLength) + int WSAStringToAddressA(char *AddressString, int AddressFamily, + WSAPROTOCOL_INFO *lpProtocolInfo, + sockaddr *lpAddress, int *lpAddressLength) cdef extern from 'string.h': void *memset(void *s, int c, size_t n) @@ -144,7 +154,7 @@ raise_error(0, 'CreateIoCompletionPort') self.port = res - def addHandle(self, long handle, long key=0): + def addHandle(self, HANDLE handle, size_t key=0): cdef HANDLE res res = CreateIoCompletionPort(handle, self.port, key, 0) if not res: @@ -152,7 +162,8 @@ def getEvent(self, long timeout): cdef PyThreadState *_save - cdef unsigned long bytes, key, rc + cdef unsigned long bytes, rc + cdef size_t key cdef myOVERLAPPED *ov _save = PyEval_SaveThread() @@ -173,7 +184,7 @@ return (rc, bytes, key, obj) - def postEvent(self, unsigned long bytes, unsigned long key, obj): + def postEvent(self, unsigned long bytes, size_t key, obj): cdef myOVERLAPPED *ov cdef unsigned long rc @@ -186,6 +197,9 @@ rc = PostQueuedCompletionStatus(self.port, bytes, key, ov) if not rc: + if ov: + Py_DECREF(obj) + PyMem_Free(ov) raise_error(0, 'PostQueuedCompletionStatus') def __del__(self): @@ -193,13 +207,13 @@ def makesockaddr(object buff): cdef void *mem_buffer - cdef int size + cdef Py_ssize_t size PyObject_AsReadBuffer(buff, &mem_buffer, &size) # XXX: this should really return the address family as well return _makesockaddr(mem_buffer, size) -cdef object _makesockaddr(sockaddr *addr, int len): +cdef object _makesockaddr(sockaddr *addr, Py_ssize_t len): cdef sockaddr_in *sin cdef sockaddr_in6 *sin6 cdef char buff[256] @@ -225,6 +239,7 @@ else: return PyString_FromStringAndSize(addr.sa_data, sizeof(addr.sa_data)) + cdef object fillinetaddr(sockaddr_in *dest, object addr): cdef unsigned short port cdef unsigned long res @@ -239,6 +254,28 @@ dest.sin_port = htons(port) + +cdef object fillinet6addr(sockaddr_in6 *dest, object addr): + cdef unsigned short port + cdef unsigned long res + cdef char *hoststr + cdef int addrlen = sizeof(sockaddr_in6) + host, port, flow, scope = addr + host = host.split("%")[0] # remove scope ID, if any + + hoststr = PyString_AsString(host) + cdef int parseresult = WSAStringToAddressA(hoststr, AF_INET6, NULL, + dest, &addrlen) + if parseresult == SOCKET_ERROR: + raise ValueError, 'invalid IPv6 address %r' % (host,) + if parseresult != 0: + raise RuntimeError, 'undefined error occurred during address parsing' + # sin6_host field was handled by WSAStringToAddress + dest.sin6_port = htons(port) + dest.sin6_flowinfo = flow + dest.sin6_scope_id = scope + + def AllocateReadBuffer(int size): return PyBuffer_New(size) diff -Nru twisted-11.1.0/twisted/internet/iocpreactor/iocpsupport/wsarecv.pxi twisted-12.1.0/twisted/internet/iocpreactor/iocpsupport/wsarecv.pxi --- twisted-11.1.0/twisted/internet/iocpreactor/iocpsupport/wsarecv.pxi 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/internet/iocpreactor/iocpsupport/wsarecv.pxi 2012-03-12 23:15:18.000000000 +0000 @@ -3,11 +3,12 @@ def recv(long s, object bufflist, object obj, unsigned long flags = 0): - cdef int rc, buffcount, i, res + cdef int rc, res cdef myOVERLAPPED *ov cdef WSABUF *ws_buf cdef unsigned long bytes cdef PyObject **buffers + cdef Py_ssize_t i, size, buffcount bufflist = PySequence_Fast(bufflist, 'second argument needs to be a list') buffcount = PySequence_Fast_GET_SIZE(bufflist) @@ -17,17 +18,19 @@ try: for i from 0 <= i < buffcount: - PyObject_AsWriteBuffer(buffers[i], &ws_buf[i].buf, &ws_buf[i].len) + PyObject_AsWriteBuffer(buffers[i], &ws_buf[i].buf, &size) + ws_buf[i].len = size ov = makeOV() if obj is not None: ov.obj = obj - rc = WSARecv(s, ws_buf, buffcount, &bytes, &flags, ov, NULL) + rc = WSARecv(s, ws_buf, buffcount, &bytes, &flags, ov, NULL) if rc == SOCKET_ERROR: rc = WSAGetLastError() if rc != ERROR_IO_PENDING: + PyMem_Free(ov) return rc, 0 Py_XINCREF(obj) @@ -42,10 +45,14 @@ cdef unsigned long bytes cdef sockaddr *c_addr_buff cdef int *c_addr_len_buff + cdef Py_ssize_t size - PyObject_AsWriteBuffer(buff, &ws_buf.buf, &ws_buf.len) - PyObject_AsWriteBuffer(addr_buff, &c_addr_buff, &c_addr_buff_len) - PyObject_AsWriteBuffer(addr_len_buff, &c_addr_len_buff, &c_addr_len_buff_len) + PyObject_AsWriteBuffer(buff, &ws_buf.buf, &size) + ws_buf.len = size + PyObject_AsWriteBuffer(addr_buff, &c_addr_buff, &size) + c_addr_buff_len = size + PyObject_AsWriteBuffer(addr_len_buff, &c_addr_len_buff, &size) + c_addr_len_buff_len = size if c_addr_len_buff_len != sizeof(int): raise ValueError, 'length of address length buffer needs to be sizeof(int)' @@ -61,6 +68,7 @@ if rc == SOCKET_ERROR: rc = WSAGetLastError() if rc != ERROR_IO_PENDING: + PyMem_Free(ov) return rc, 0 Py_XINCREF(obj) diff -Nru twisted-11.1.0/twisted/internet/iocpreactor/iocpsupport/wsasend.pxi twisted-12.1.0/twisted/internet/iocpreactor/iocpsupport/wsasend.pxi --- twisted-11.1.0/twisted/internet/iocpreactor/iocpsupport/wsasend.pxi 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/internet/iocpreactor/iocpsupport/wsasend.pxi 2012-03-12 23:15:18.000000000 +0000 @@ -7,8 +7,10 @@ cdef myOVERLAPPED *ov cdef WSABUF ws_buf cdef unsigned long bytes + cdef Py_ssize_t size - PyObject_AsReadBuffer(buff, &ws_buf.buf, &ws_buf.len) + PyObject_AsReadBuffer(buff, &ws_buf.buf, &size) + ws_buf.len = size ov = makeOV() if obj is not None: @@ -19,6 +21,7 @@ if rc == SOCKET_ERROR: rc = WSAGetLastError() if rc != ERROR_IO_PENDING: + PyMem_Free(ov) return rc, bytes Py_XINCREF(obj) diff -Nru twisted-11.1.0/twisted/internet/iocpreactor/tcp.py twisted-12.1.0/twisted/internet/iocpreactor/tcp.py --- twisted-11.1.0/twisted/internet/iocpreactor/tcp.py 2011-11-02 00:53:45.000000000 +0000 +++ twisted-12.1.0/twisted/internet/iocpreactor/tcp.py 2012-03-27 12:27:04.000000000 +0000 @@ -10,9 +10,9 @@ from zope.interface import implements, classImplements from twisted.internet import interfaces, error, address, main, defer -from twisted.internet.abstract import _LogOwner, isIPAddress +from twisted.internet.abstract import _LogOwner, isIPAddress, isIPv6Address from twisted.internet.tcp import _SocketCloser, Connector as TCPConnector -from twisted.internet.tcp import _AbortingMixin +from twisted.internet.tcp import _AbortingMixin, _BaseBaseClient, _BaseTCPClient from twisted.python import log, failure, reflect, util from twisted.internet.iocpreactor import iocpsupport as _iocp, abstract @@ -194,11 +194,40 @@ else: abstract.FileHandle.loseConnection(self, reason) + + def registerProducer(self, producer, streaming): + """ + Register a producer. + + If TLS is enabled, the TLS connection handles this. + """ + if self.TLS: + # Registering a producer before we're connected shouldn't be a + # problem. If we end up with a write(), that's already handled in + # the write() code above, and there are no other potential + # side-effects. + self.protocol.registerProducer(producer, streaming) + else: + abstract.FileHandle.registerProducer(self, producer, streaming) + + + def unregisterProducer(self): + """ + Unregister a producer. + + If TLS is enabled, the TLS connection handles this. + """ + if self.TLS: + self.protocol.unregisterProducer() + else: + abstract.FileHandle.unregisterProducer(self) + if _startTLS is not None: classImplements(Connection, interfaces.ITLSTransport) -class Client(Connection): + +class Client(_BaseBaseClient, _BaseTCPClient, Connection): """ @ivar _tlsClientDefault: Always C{True}, indicating that this is a client connection, and by default when TLS is negotiated this class will act as @@ -208,67 +237,43 @@ socketType = socket.SOCK_STREAM _tlsClientDefault = True + _commonConnection = Connection def __init__(self, host, port, bindAddress, connector, reactor): - self.connector = connector - self.addr = (host, port) - self.reactor = reactor # ConnectEx documentation says socket _has_ to be bound if bindAddress is None: bindAddress = ('', 0) - - try: - try: - skt = reactor.createSocket(self.addressFamily, self.socketType) - except socket.error, se: - raise error.ConnectBindError(se[0], se[1]) - else: - try: - skt.bind(bindAddress) - except socket.error, se: - raise error.ConnectBindError(se[0], se[1]) - self.socket = skt - Connection.__init__(self, skt, None, reactor) - reactor.callLater(0, self.resolveAddress) - except error.ConnectBindError, err: - reactor.callLater(0, self.failIfNotConnected, err) - - - def resolveAddress(self): - if isIPAddress(self.addr[0]): - self._setRealAddress(self.addr[0]) - else: - d = self.reactor.resolve(self.addr[0]) - d.addCallbacks(self._setRealAddress, self.failIfNotConnected) + self.reactor = reactor # createInternetSocket needs this + _BaseTCPClient.__init__(self, host, port, bindAddress, connector, + reactor) - def _setRealAddress(self, address): - self.realAddress = (address, self.addr[1]) - self.doConnect() + def createInternetSocket(self): + """ + Create a socket registered with the IOCP reactor. + @see: L{_BaseTCPClient} + """ + return self.reactor.createSocket(self.addressFamily, self.socketType) - def failIfNotConnected(self, err): - if (self.connected or self.disconnected or - not hasattr(self, "connector")): - return - try: - self._closeSocket(True) - except AttributeError: - pass - else: - del self.socket, self.getFileHandle - self.reactor.removeActiveHandle(self) + def _collectSocketDetails(self): + """ + Clean up potentially circular references to the socket and to its + C{getFileHandle} method. - self.connector.connectionFailed(failure.Failure(err)) - del self.connector + @see: L{_BaseBaseClient} + """ + del self.socket, self.getFileHandle - def stopConnecting(self): + def _stopReadingAndWriting(self): """ - Stop attempt to connect. + Remove the active handle from the reactor. + + @see: L{_BaseBaseClient} """ - self.failIfNotConnected(error.UserError()) + self.reactor.removeActiveHandle(self) def cbConnect(self, rc, bytes, evt): @@ -299,39 +304,7 @@ rc = _iocp.connect(self.socket.fileno(), self.realAddress, evt) if rc and rc != ERROR_IO_PENDING: - self.cbConnect(rc, 0, 0, evt) - - - def getHost(self): - """ - Returns an IPv4Address. - - This indicates the address from which I am connecting. - """ - return address.IPv4Address('TCP', *self.socket.getsockname()) - - - def getPeer(self): - """ - Returns an IPv4Address. - - This indicates the address that I am connected to. - """ - return address.IPv4Address('TCP', *self.realAddress) - - - def __repr__(self): - s = ('<%s to %s at %x>' % - (self.__class__, self.addr, util.unsignedID(self))) - return s - - - def connectionLost(self, reason): - if not self.connected: - self.failIfNotConnected(error.ConnectError(string=reason)) - else: - Connection.connectionLost(self, reason) - self.connector.connectionLost(reason) + self.cbConnect(rc, 0, evt) @@ -411,7 +384,7 @@ disconnecting = False addressFamily = socket.AF_INET socketType = socket.SOCK_STREAM - + _addressType = address.IPv4Address sessionno = 0 # Actual port number being listened on, only set to a non-None @@ -430,6 +403,9 @@ self.backlog = backlog self.interface = interface self.reactor = reactor + if isIPv6Address(interface): + self.addressFamily = socket.AF_INET6 + self._addressType = address.IPv6Address def __repr__(self): @@ -447,7 +423,11 @@ skt = self.reactor.createSocket(self.addressFamily, self.socketType) # TODO: resolve self.interface if necessary - skt.bind((self.interface, self.port)) + if self.addressFamily == socket.AF_INET6: + addr = socket.getaddrinfo(self.interface, self.port)[0][4] + else: + addr = (self.interface, self.port) + skt.bind(addr) except socket.error, le: raise error.CannotListenError, (self.interface, self.port, le) @@ -539,7 +519,8 @@ This indicates the server's address. """ - return address.IPv4Address('TCP', *self.socket.getsockname()) + host, port = self.socket.getsockname()[:2] + return self._addressType('TCP', host, port) def cbAccept(self, rc, bytes, evt): @@ -567,15 +548,15 @@ assert family == self.addressFamily protocol = self.factory.buildProtocol( - address._ServerFactoryIPv4Address('TCP', rAddr[0], rAddr[1])) + self._addressType('TCP', rAddr[0], rAddr[1])) if protocol is None: evt.newskt.close() else: s = self.sessionno self.sessionno = s+1 transport = Server(evt.newskt, protocol, - address.IPv4Address('TCP', rAddr[0], rAddr[1]), - address.IPv4Address('TCP', lAddr[0], lAddr[1]), + self._addressType('TCP', rAddr[0], rAddr[1]), + self._addressType('TCP', lAddr[0], lAddr[1]), s, self.reactor) protocol.makeConnection(transport) return True diff -Nru twisted-11.1.0/twisted/internet/kqreactor.py twisted-12.1.0/twisted/internet/kqreactor.py --- twisted-11.1.0/twisted/internet/kqreactor.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/internet/kqreactor.py 2012-01-23 22:55:41.000000000 +0000 @@ -4,68 +4,32 @@ """ A kqueue()/kevent() based implementation of the Twisted main loop. -To install the event loop (and you should do this before any connections, -listeners or connectors are added):: +To use this reactor, start your application specifying the kqueue reactor:: - | from twisted.internet import kqreactor - | kqreactor.install() + twistd --reactor kqueue ... -This reactor only works on FreeBSD and requires PyKQueue 1.3, which is -available at: U{http://people.freebsd.org/~dwhite/PyKQueue/} +To install the event loop from code (and you should do this before any +connections, listeners or connectors are added):: + from twisted.internet import kqreactor + kqreactor.install() +This implementation depends on Python 2.6 or higher which has kqueue support +built in the select module. -You're going to need to patch PyKqueue:: - - ===================================================== - --- PyKQueue-1.3/kqsyscallmodule.c Sun Jan 28 21:59:50 2001 - +++ PyKQueue-1.3/kqsyscallmodule.c.new Tue Jul 30 18:06:08 2002 - @@ -137,7 +137,7 @@ - } - - statichere PyTypeObject KQEvent_Type = { - - PyObject_HEAD_INIT(NULL) - + PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "KQEvent", // tp_name - sizeof(KQEventObject), // tp_basicsize - @@ -291,13 +291,14 @@ - - /* Build timespec for timeout */ - totimespec.tv_sec = timeout / 1000; - - totimespec.tv_nsec = (timeout % 1000) * 100000; - + totimespec.tv_nsec = (timeout % 1000) * 1000000; - - // printf("timespec: sec=%d nsec=%d\\n", totimespec.tv_sec, totimespec.tv_nsec); - - /* Make the call */ - - - + Py_BEGIN_ALLOW_THREADS - gotNumEvents = kevent (self->fd, changelist, haveNumEvents, triggered, wantNumEvents, &totimespec); - + Py_END_ALLOW_THREADS - - /* Don't need the input event list anymore, so get rid of it */ - free (changelist); - @@ -361,7 +362,7 @@ - statichere PyTypeObject KQueue_Type = { - /* The ob_type field must be initialized in the module init function - * to be portable to Windows without using C++. */ - - PyObject_HEAD_INIT(NULL) - + PyObject_HEAD_INIT(&PyType_Type) - 0, /*ob_size*/ - "KQueue", /*tp_name*/ - sizeof(KQueueObject), /*tp_basicsize*/ - +Note, that you should use Python 2.6.5 or higher, since previous implementations +of select.kqueue had U{http://bugs.python.org/issue5910} not yet fixed. """ -import errno, sys +import errno from zope.interface import implements -from kqsyscall import EVFILT_READ, EVFILT_WRITE, EV_DELETE, EV_ADD -from kqsyscall import kqueue, kevent +from select import kqueue, kevent +from select import KQ_FILTER_READ, KQ_FILTER_WRITE +from select import KQ_EV_DELETE, KQ_EV_ADD, KQ_EV_EOF -from twisted.internet.interfaces import IReactorFDSet +from twisted.internet.interfaces import IReactorFDSet, IReactorDaemonize from twisted.python import log, failure from twisted.internet import main, posixbase @@ -73,7 +37,8 @@ class KQueueReactor(posixbase.PosixReactorBase): """ - A reactor that uses kqueue(2)/kevent(2). + A reactor that uses kqueue(2)/kevent(2) and relies on Python 2.6 or higher + which has built in support for kqueue in the select module. @ivar _kq: A L{kqueue} which will be used to check for I/O readiness. @@ -95,12 +60,18 @@ dispatched to the corresponding L{FileDescriptor} instances in C{_selectables}. """ - implements(IReactorFDSet) + implements(IReactorFDSet, IReactorDaemonize) + def __init__(self): """ Initialize kqueue object, file descriptor tracking dictionaries, and the base class. + + See: + - http://docs.python.org/library/select.html + - www.freebsd.org/cgi/man.cgi?query=kqueue + - people.freebsd.org/~jlemon/papers/kqueue.pdf """ self._kq = kqueue() self._reads = {} @@ -109,50 +80,134 @@ posixbase.PosixReactorBase.__init__(self) - def _updateRegistration(self, *args): - self._kq.kevent([kevent(*args)], 0, 0) + def _updateRegistration(self, fd, filter, op): + """ + Private method for changing kqueue registration on a given FD + filtering for events given filter/op. This will never block and + returns nothing. + """ + self._kq.control([kevent(fd, filter, op)], 0, 0) + + + def beforeDaemonize(self): + """ + Implement L{IReactorDaemonize.beforeDaemonize}. + """ + # Twisted-internal method called during daemonization (when application + # is started via twistd). This is called right before the magic double + # forking done for daemonization. We cleanly close the kqueue() and later + # recreate it. This is needed since a) kqueue() are not inherited across + # forks and b) twistd will create the reactor already before daemonization + # (and will also add at least 1 reader to the reactor, an instance of + # twisted.internet.posixbase._UnixWaker). + # + # See: twisted.scripts._twistd_unix.daemonize() + self._kq.close() + self._kq = None + + + def afterDaemonize(self): + """ + Implement L{IReactorDaemonize.afterDaemonize}. + """ + # Twisted-internal method called during daemonization. This is called right + # after daemonization and recreates the kqueue() and any readers/writers + # that were added before. Note that you MUST NOT call any reactor methods + # in between beforeDaemonize() and afterDaemonize()! + self._kq = kqueue() + for fd in self._reads: + self._updateRegistration(fd, KQ_FILTER_READ, KQ_EV_ADD) + for fd in self._writes: + self._updateRegistration(fd, KQ_FILTER_WRITE, KQ_EV_ADD) + def addReader(self, reader): - """Add a FileDescriptor for notification of data available to read. + """ + Implement L{IReactorFDSet.addReader}. """ fd = reader.fileno() if fd not in self._reads: - self._selectables[fd] = reader - self._reads[fd] = 1 - self._updateRegistration(fd, EVFILT_READ, EV_ADD) + try: + self._updateRegistration(fd, KQ_FILTER_READ, KQ_EV_ADD) + except OSError: + pass + finally: + self._selectables[fd] = reader + self._reads[fd] = 1 + def addWriter(self, writer): - """Add a FileDescriptor for notification of data available to write. + """ + Implement L{IReactorFDSet.addWriter}. """ fd = writer.fileno() if fd not in self._writes: - self._selectables[fd] = writer - self._writes[fd] = 1 - self._updateRegistration(fd, EVFILT_WRITE, EV_ADD) + try: + self._updateRegistration(fd, KQ_FILTER_WRITE, KQ_EV_ADD) + except OSError: + pass + finally: + self._selectables[fd] = writer + self._writes[fd] = 1 + def removeReader(self, reader): - """Remove a Selectable for notification of data available to read. """ - fd = reader.fileno() + Implement L{IReactorFDSet.removeReader}. + """ + wasLost = False + try: + fd = reader.fileno() + except: + fd = -1 + if fd == -1: + for fd, fdes in self._selectables.items(): + if reader is fdes: + wasLost = True + break + else: + return if fd in self._reads: del self._reads[fd] if fd not in self._writes: del self._selectables[fd] - self._updateRegistration(fd, EVFILT_READ, EV_DELETE) + if not wasLost: + try: + self._updateRegistration(fd, KQ_FILTER_READ, KQ_EV_DELETE) + except OSError: + pass + def removeWriter(self, writer): - """Remove a Selectable for notification of data available to write. """ - fd = writer.fileno() + Implement L{IReactorFDSet.removeWriter}. + """ + wasLost = False + try: + fd = writer.fileno() + except: + fd = -1 + if fd == -1: + for fd, fdes in self._selectables.items(): + if writer is fdes: + wasLost = True + break + else: + return if fd in self._writes: del self._writes[fd] if fd not in self._reads: del self._selectables[fd] - self._updateRegistration(fd, EVFILT_WRITE, EV_DELETE) + if not wasLost: + try: + self._updateRegistration(fd, KQ_FILTER_WRITE, KQ_EV_DELETE) + except OSError: + pass + def removeAll(self): """ - Remove all selectables, and return a list of them. + Implement L{IReactorFDSet.removeAll}. """ return self._removeAll( [self._selectables[fd] for fd in self._reads], @@ -160,62 +215,91 @@ def getReaders(self): + """ + Implement L{IReactorFDSet.getReaders}. + """ return [self._selectables[fd] for fd in self._reads] def getWriters(self): + """ + Implement L{IReactorFDSet.getWriters}. + """ return [self._selectables[fd] for fd in self._writes] def doKEvent(self, timeout): - """Poll the kqueue for new events.""" + """ + Poll the kqueue for new events. + """ if timeout is None: - timeout = 1000 - else: - timeout = int(timeout * 1000) # convert seconds to milliseconds + timeout = 1 try: - l = self._kq.kevent([], len(self._selectables), timeout) + l = self._kq.control([], len(self._selectables), timeout) except OSError, e: if e[0] == errno.EINTR: return else: raise + _drdw = self._doWriteOrRead for event in l: - why = None - fd, filter = event.ident, event.filter + fd = event.ident try: selectable = self._selectables[fd] except KeyError: # Handles the infrequent case where one selectable's # handler disconnects another. continue - log.callWithLogger(selectable, _drdw, selectable, fd, filter) + else: + log.callWithLogger(selectable, _drdw, selectable, fd, event) - def _doWriteOrRead(self, selectable, fd, filter): - try: - if filter == EVFILT_READ: - why = selectable.doRead() - if filter == EVFILT_WRITE: - why = selectable.doWrite() - if not selectable.fileno() == fd: - why = main.CONNECTION_LOST - except: - why = sys.exc_info()[1] - log.deferr() + + def _doWriteOrRead(self, selectable, fd, event): + """ + Private method called when a FD is ready for reading, writing or was + lost. Do the work and raise errors where necessary. + """ + why = None + inRead = False + (filter, flags, data, fflags) = ( + event.filter, event.flags, event.data, event.fflags) + + if flags & KQ_EV_EOF and data and fflags: + why = main.CONNECTION_LOST + else: + try: + if selectable.fileno() == -1: + inRead = False + why = posixbase._NO_FILEDESC + else: + if filter == KQ_FILTER_READ: + inRead = True + why = selectable.doRead() + if filter == KQ_FILTER_WRITE: + inRead = False + why = selectable.doWrite() + except: + # Any exception from application code gets logged and will + # cause us to disconnect the selectable. + why = failure.Failure() + log.err(why, "An exception was raised from application code" \ + " while processing a reactor selectable") if why: - self.removeReader(selectable) - self.removeWriter(selectable) - selectable.connectionLost(failure.Failure(why)) + self._disconnectSelectable(selectable, why, inRead) doIteration = doKEvent def install(): - k = KQueueReactor() - main.installReactor(k) + """ + Install the kqueue() reactor. + """ + p = KQueueReactor() + from twisted.internet.main import installReactor + installReactor(p) __all__ = ["KQueueReactor", "install"] diff -Nru twisted-11.1.0/twisted/internet/_newtls.py twisted-12.1.0/twisted/internet/_newtls.py --- twisted-11.1.0/twisted/internet/_newtls.py 2011-11-02 12:47:09.000000000 +0000 +++ twisted-12.1.0/twisted/internet/_newtls.py 2011-12-08 19:58:50.000000000 +0000 @@ -71,6 +71,20 @@ return self._base.loseConnection(self._connection, *args, **kwargs) + def registerProducer(self, producer, streaming): + """ + Register a producer with the underlying connection. + """ + return self._base.registerProducer(self._connection, producer, streaming) + + + def unregisterProducer(self): + """ + Unregister a producer with the underlying connection. + """ + return self._base.unregisterProducer(self._connection) + + def startTLS(transport, contextFactory, normal, bypass): """ @@ -114,6 +128,13 @@ else: client = not transport._tlsClientDefault + # If we have a producer, unregister it, and then re-register it below once + # we've switched to TLS mode, so it gets hooked up correctly: + producer, streaming = None, None + if transport.producer is not None: + producer, streaming = transport.producer, transport.streamingProducer + transport.unregisterProducer() + tlsFactory = TLSMemoryBIOFactory(contextFactory, client, None) tlsProtocol = TLSMemoryBIOProtocol(tlsFactory, transport.protocol, False) transport.protocol = tlsProtocol @@ -131,6 +152,10 @@ # Hook it up transport.protocol.makeConnection(_BypassTLS(bypass, transport)) + # Restore producer if necessary: + if producer: + transport.registerProducer(producer, streaming) + class ConnectionMixin(object): @@ -141,28 +166,15 @@ @ivar TLS: A flag indicating whether TLS is currently in use on this transport. This is not a good way for applications to check for TLS, instead use L{ISSLTransport.providedBy}. - - @ivar _tlsWaiting: If TLS has been requested but the write buffer for - non-TLS data still needs to be flushed, this is set to a L{_TLSDelayed} - instance which will buffer data that must only be sent once TLS has been - started. """ implements(ITLSTransport) TLS = False - _tlsWaiting = None def startTLS(self, ctx, normal=True): """ @see: L{ITLSTransport.startTLS} """ - if self.dataBuffer or self._tempDataBuffer: - # pre-TLS bytes are still being written. Starting TLS now - # will do the wrong thing. Instead, mark that we're trying - # to go into the TLS state. - self._tlsWaiting = _TLSDelayed([], ctx, normal) - return False - startTLS(self, ctx, normal, FileDescriptor) @@ -174,8 +186,6 @@ if self.TLS: if self.connected: self.protocol.write(bytes) - elif self._tlsWaiting is not None: - self._tlsWaiting.bufferedData.append(bytes) else: FileDescriptor.write(self, bytes) @@ -189,8 +199,6 @@ if self.TLS: if self.connected: self.protocol.writeSequence(iovec) - elif self._tlsWaiting is not None: - self._tlsWaiting.bufferedData.extend(iovec) else: FileDescriptor.writeSequence(self, iovec) @@ -208,21 +216,32 @@ FileDescriptor.loseConnection(self) - def doWrite(self): + def registerProducer(self, producer, streaming): + """ + Register a producer. + + If TLS is enabled, the TLS connection handles this. + """ + if self.TLS: + # Registering a producer before we're connected shouldn't be a + # problem. If we end up with a write(), that's already handled in + # the write() code above, and there are no other potential + # side-effects. + self.protocol.registerProducer(producer, streaming) + else: + FileDescriptor.registerProducer(self, producer, streaming) + + + def unregisterProducer(self): """ - Write out some data from the send buffer. + Unregister a producer. - If the buffer becomes empty and TLS has been requested but not yet - enabled, enable it. + If TLS is enabled, the TLS connection handles this. """ - result = FileDescriptor.doWrite(self) - if self._tlsWaiting is not None: - if not self.dataBuffer and not self._tempDataBuffer: - waiting = self._tlsWaiting - self._tlsWaiting = None - self.startTLS(waiting.context, waiting.extra) - self.writeSequence(waiting.bufferedData) - return result + if self.TLS: + self.protocol.unregisterProducer() + else: + FileDescriptor.unregisterProducer(self) diff -Nru twisted-11.1.0/twisted/internet/_oldtls.py twisted-12.1.0/twisted/internet/_oldtls.py --- twisted-11.1.0/twisted/internet/_oldtls.py 2011-10-15 21:21:45.000000000 +0000 +++ twisted-12.1.0/twisted/internet/_oldtls.py 2012-05-12 10:07:03.000000000 +0000 @@ -10,13 +10,14 @@ OpenSSL's non-blocking socket-based APIs (which this module probably does about 99% correctly, but see #4455 for an example of a problem with it). -Eventually, use of this module should emit a warning. See #4974 and 5014. +Support for older versions of pyOpenSSL is now deprecated and will be removed +(see #5014). @see: L{twisted.internet._newtls} @since: 11.1 """ -import os +import os, warnings from twisted.python.runtime import platformType if platformType == 'win32': @@ -28,7 +29,7 @@ from errno import EWOULDBLOCK from errno import ENOBUFS -from OpenSSL import SSL +from OpenSSL import SSL, __version__ as _sslversion from zope.interface import implements @@ -38,6 +39,11 @@ from twisted.internet.main import CONNECTION_DONE, CONNECTION_LOST from twisted.internet._ssl import _TLSDelayed +warnings.warn( + "Support for pyOpenSSL %s is deprecated. " + "Upgrade to pyOpenSSL 0.10 or newer." % (_sslversion,), + category=DeprecationWarning, + stacklevel=100) class _TLSMixin: _socketShutdownMethod = 'sock_shutdown' diff -Nru twisted-11.1.0/twisted/internet/_pollingfile.py twisted-12.1.0/twisted/internet/_pollingfile.py --- twisted-11.1.0/twisted/internet/_pollingfile.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/internet/_pollingfile.py 2012-04-14 00:21:00.000000000 +0000 @@ -234,16 +234,39 @@ pass self.lostCallback() + def writeSequence(self, seq): + """ + Append a C{list} or C{tuple} of bytes to the output buffer. + + @param seq: C{list} or C{tuple} of C{str} instances to be appended to + the output buffer. + + @raise TypeError: If C{seq} contains C{unicode}. + """ + if unicode in map(type, seq): + raise TypeError("Unicode not allowed in output buffer.") self.outQueue.extend(seq) + def write(self, data): + """ + Append some bytes to the output buffer. + + @param data: C{str} to be appended to the output buffer. + @type data: C{str}. + + @raise TypeError: If C{data} is C{unicode} instead of C{str}. + """ + if isinstance(data, unicode): + raise TypeError("Unicode not allowed in output buffer.") if self.disconnecting: return self.outQueue.append(data) if sum(map(len, self.outQueue)) > FULL_BUFFER_SIZE: self.bufferFull() + def checkWork(self): numBytesWritten = 0 if not self.outQueue: @@ -258,8 +281,6 @@ while self.outQueue: data = self.outQueue.pop(0) errCode = 0 - if isinstance(data, unicode): - raise TypeError("unicode not allowed") try: errCode, nBytesWritten = win32file.WriteFile(self.writePipe, data, None) diff -Nru twisted-11.1.0/twisted/internet/posixbase.py twisted-12.1.0/twisted/internet/posixbase.py --- twisted-11.1.0/twisted/internet/posixbase.py 2011-10-16 20:13:26.000000000 +0000 +++ twisted-12.1.0/twisted/internet/posixbase.py 2012-05-04 18:49:18.000000000 +0000 @@ -16,7 +16,8 @@ from twisted.python.compat import set from twisted.internet.interfaces import IReactorUNIX, IReactorUNIXDatagram -from twisted.internet.interfaces import IReactorTCP, IReactorUDP, IReactorSSL, _IReactorArbitrary +from twisted.internet.interfaces import ( + IReactorTCP, IReactorUDP, IReactorSSL, _IReactorArbitrary, IReactorSocket) from twisted.internet.interfaces import IReactorProcess, IReactorMulticast from twisted.internet.interfaces import IHalfCloseableDescriptor from twisted.internet import error @@ -233,14 +234,11 @@ -class PosixReactorBase(_SignalReactorMixin, ReactorBase): - """ - A basis for reactors that use file descriptors. - @ivar _childWaker: C{None} or a reference to the L{_SIGCHLDWaker} - which is used to properly notice child process termination. +class _DisconnectSelectableMixin(object): + """ + Mixin providing the C{_disconnectSelectable} method. """ - implements(_IReactorArbitrary, IReactorTCP, IReactorUDP, IReactorMulticast) def _disconnectSelectable(self, selectable, why, isRead, faildict={ error.ConnectionDone: failure.Failure(error.ConnectionDone()), @@ -265,6 +263,22 @@ self.removeWriter(selectable) selectable.connectionLost(failure.Failure(why)) + + +class PosixReactorBase(_SignalReactorMixin, _DisconnectSelectableMixin, + ReactorBase): + """ + A basis for reactors that use file descriptors. + + @ivar _childWaker: C{None} or a reference to the L{_SIGCHLDWaker} + which is used to properly notice child process termination. + """ + implements(_IReactorArbitrary, IReactorTCP, IReactorUDP, IReactorMulticast) + + # Callable that creates a waker, overrideable so that subclasses can + # substitute their own implementation: + _wakerFactory = _Waker + def installWaker(self): """ Install a `waker' to allow threads and signals to wake up the IO thread. @@ -273,7 +287,7 @@ the reactor. On Windows we use a pair of sockets. """ if not self.waker: - self.waker = _Waker(self) + self.waker = self._wakerFactory(self) self._internalReaders.add(self.waker) self.addReader(self.waker) @@ -422,6 +436,25 @@ return p + # IReactorSocket (but not on Windows) + def adoptStreamPort(self, fileDescriptor, addressFamily, factory): + """ + Create a new L{IListeningPort} from an already-initialized socket. + + This just dispatches to a suitable port implementation (eg from + L{IReactorTCP}, etc) based on the specified C{addressFamily}. + + @see: L{twisted.internet.interfaces.IReactorSocket.adoptStreamPort} + """ + if addressFamily not in (socket.AF_INET, socket.AF_INET6): + raise error.UnsupportedAddressFamily(addressFamily) + + p = tcp.Port._fromListeningDescriptor( + self, fileDescriptor, addressFamily, factory) + p.startListening() + return p + + # IReactorTCP def listenTCP(self, port, factory, backlog=50, interface=''): @@ -601,5 +634,7 @@ classImplements(PosixReactorBase, IReactorUNIX, IReactorUNIXDatagram) if processEnabled: classImplements(PosixReactorBase, IReactorProcess) +if getattr(socket, 'fromfd', None) is not None: + classImplements(PosixReactorBase, IReactorSocket) __all__ = ["PosixReactorBase"] diff -Nru twisted-11.1.0/twisted/internet/_posixstdio.py twisted-12.1.0/twisted/internet/_posixstdio.py --- twisted-11.1.0/twisted/internet/_posixstdio.py 2010-05-14 16:34:24.000000000 +0000 +++ twisted-12.1.0/twisted/internet/_posixstdio.py 2012-05-04 18:49:18.000000000 +0000 @@ -11,7 +11,7 @@ Maintainer: James Y Knight """ -import warnings, errno, os +import warnings from zope.interface import implements from twisted.internet import process, error, interfaces @@ -23,31 +23,20 @@ class StandardIO(object): - implements(interfaces.ITransport, interfaces.IProducer, interfaces.IConsumer, interfaces.IHalfCloseableDescriptor) + implements(interfaces.ITransport, interfaces.IProducer, + interfaces.IConsumer, interfaces.IHalfCloseableDescriptor) + _reader = None _writer = None disconnected = False disconnecting = False - def __init__(self, proto, stdin=0, stdout=1): - from twisted.internet import reactor + def __init__(self, proto, stdin=0, stdout=1, reactor=None): + if reactor is None: + from twisted.internet import reactor self.protocol = proto self._writer = process.ProcessWriter(reactor, self, 'write', stdout) - try: - self._writer.startReading() - except IOError, e: - if e.errno == errno.EPERM: - # epoll will reject certain file descriptors by raising - # EPERM. Most commonly, this means stdout was redirected to - # a regular file. - raise RuntimeError( - "This reactor does not support this type of file " - "descriptor (fd %d, mode %d) (for example, epollreactor " - "does not support normal files. See #4429)." % ( - stdout, os.fstat(stdout).st_mode)) - raise - self._reader = process.ProcessReader(reactor, self, 'read', stdin) self._reader.startReading() self.protocol.makeConnection(self) diff -Nru twisted-11.1.0/twisted/internet/protocol.py twisted-12.1.0/twisted/internet/protocol.py --- twisted-11.1.0/twisted/internet/protocol.py 2011-10-22 03:14:14.000000000 +0000 +++ twisted-12.1.0/twisted/internet/protocol.py 2012-05-12 13:55:41.000000000 +0000 @@ -623,7 +623,8 @@ def processEnded(self, reason): """ - This will be called when the subprocess is finished. + Called when the child process exits and all file descriptors + associated with it have been closed. @type reason: L{twisted.python.failure.Failure} """ diff -Nru twisted-11.1.0/twisted/internet/reactor.py twisted-12.1.0/twisted/internet/reactor.py --- twisted-11.1.0/twisted/internet/reactor.py 2011-05-05 02:48:02.000000000 +0000 +++ twisted-12.1.0/twisted/internet/reactor.py 2012-05-14 22:39:50.000000000 +0000 @@ -6,10 +6,10 @@ applications using Twisted. The reactor provides APIs for networking, threading, dispatching events, and more. -The default reactor is based on C{select(2)} and will be installed if this -module is imported without another reactor being explicitly installed. -Regardless of which reactor is installed, importing this module is the correct -way to get a reference to it. +The default reactor depends on the platform and will be installed if this +module is imported without another reactor being explicitly installed +beforehand. Regardless of which reactor is installed, importing this module is +the correct way to get a reference to it. New application code should prefer to pass and accept the reactor as a parameter where it is needed, rather than relying on being able to import this diff -Nru twisted-11.1.0/twisted/internet/ssl.py twisted-12.1.0/twisted/internet/ssl.py --- twisted-11.1.0/twisted/internet/ssl.py 2011-10-11 12:01:26.000000000 +0000 +++ twisted-12.1.0/twisted/internet/ssl.py 2012-01-22 00:48:15.000000000 +0000 @@ -159,6 +159,10 @@ tcp.Port.__init__(self, port, factory, backlog, interface, reactor) self.ctxFactory = ctxFactory + # Force some parameter checking in pyOpenSSL. It's better to fail now + # than after we've set up the transport. + ctxFactory.getContext() + def _getLogPrefix(self, factory): """ @@ -174,6 +178,10 @@ self.contextFactory = contextFactory tcp.Connector.__init__(self, host, port, factory, timeout, bindAddress, reactor) + # Force some parameter checking in pyOpenSSL. It's better to fail now + # than after we've set up the transport. + contextFactory.getContext() + def _makeTransport(self): return Client(self.host, self.port, self.bindAddress, self.contextFactory, self, self.reactor) diff -Nru twisted-11.1.0/twisted/internet/task.py twisted-12.1.0/twisted/internet/task.py --- twisted-11.1.0/twisted/internet/task.py 2011-08-13 23:57:43.000000000 +0000 +++ twisted-12.1.0/twisted/internet/task.py 2012-01-15 21:19:39.000000000 +0000 @@ -36,13 +36,20 @@ something else, but it probably ought to be set *before* calling L{start}. + @type running: C{bool} + @ivar running: A flag which is C{True} while C{f} is scheduled to be called + (or is currently being called). It is set to C{True} when L{start} is + called and set to C{False} when L{stop} is called or if C{f} raises an + exception. In either case, it will be C{False} by the time the + C{Deferred} returned by L{start} fires its callback or errback. + @type _expectNextCallAt: C{float} @ivar _expectNextCallAt: The time at which this instance most recently scheduled itself to run. @type _realLastTime: C{float} - @ivar _realLastTime: When counting skips, the time at which the skip counter - was last invoked. + @ivar _realLastTime: When counting skips, the time at which the skip + counter was last invoked. @type _runAtStart: C{bool} @ivar _runAtStart: A flag indicating whether the 'now' argument was passed diff -Nru twisted-11.1.0/twisted/internet/tcp.py twisted-12.1.0/twisted/internet/tcp.py --- twisted-11.1.0/twisted/internet/tcp.py 2011-10-31 22:29:28.000000000 +0000 +++ twisted-12.1.0/twisted/internet/tcp.py 2012-04-26 13:46:20.000000000 +0000 @@ -85,16 +85,20 @@ from os import strerror + from errno import errorcode # Twisted Imports from twisted.internet import base, address, fdesc from twisted.internet.task import deferLater from twisted.python import log, failure, reflect -from twisted.python.util import unsignedID +from twisted.python.util import unsignedID, untilConcludes from twisted.internet.error import CannotListenError from twisted.internet import abstract, main, interfaces, error +# Not all platforms have, or support, this flag. +_AI_NUMERICSERV = getattr(socket, "AI_NUMERICSERV", 0) + class _SocketCloser(object): @@ -108,7 +112,8 @@ skt = self.socket try: if orderly: - getattr(skt, self._socketShutdownMethod)(2) + if self._socketShutdownMethod is not None: + getattr(skt, self._socketShutdownMethod)(2) else: # Set SO_LINGER to 1,0 which, by convention, causes a # connection reset to be sent when close is called, @@ -194,6 +199,11 @@ return else: return main.CONNECTION_LOST + + return self._dataReceived(data) + + + def _dataReceived(self, data): if not data: return main.CONNECTION_DONE rval = self.protocol.dataReceived(data) @@ -217,14 +227,14 @@ connection is lost, an exception is returned. Otherwise, the number of bytes successfully written is returned. """ + # Limit length of buffer to try to send, because some OSes are too + # stupid to do so themselves (ahem windows) + limitedData = buffer(data, 0, self.SEND_LIMIT) + try: - # Limit length of buffer to try to send, because some OSes are too - # stupid to do so themselves (ahem windows) - return self.socket.send(buffer(data, 0, self.SEND_LIMIT)) + return untilConcludes(self.socket.send, limitedData) except socket.error, se: - if se.args[0] == EINTR: - return self.writeSomeData(data) - elif se.args[0] in (EWOULDBLOCK, ENOBUFS): + if se.args[0] in (EWOULDBLOCK, ENOBUFS): return 0 else: return main.CONNECTION_LOST @@ -299,30 +309,124 @@ -class BaseClient(_TLSClientMixin, Connection): + +class _BaseBaseClient(object): """ - A base class for client TCP (and similiar) sockets. + Code shared with other (non-POSIX) reactors for management of general + outgoing connections. + + Requirements upon subclasses are documented as instance variables rather + than abstract methods, in order to avoid MRO confusion, since this base is + mixed in to unfortunately weird and distinctive multiple-inheritance + hierarchies and many of these attributes are provided by peer classes + rather than descendant classes in those hierarchies. + + @ivar addressFamily: The address family constant (C{socket.AF_INET}, + C{socket.AF_INET6}, C{socket.AF_UNIX}) of the underlying socket of this + client connection. + @type addressFamily: C{int} + + @ivar socketType: The socket type constant (C{socket.SOCK_STREAM} or + C{socket.SOCK_DGRAM}) of the underlying socket. + @type socketType: C{int} + + @ivar _requiresResolution: A flag indicating whether the address of this + client will require name resolution. C{True} if the hostname of said + address indicates a name that must be resolved by hostname lookup, + C{False} if it indicates an IP address literal. + @type _requiresResolution: C{bool} + + @cvar _commonConnection: Subclasses must provide this attribute, which + indicates the L{Connection}-alike class to invoke C{__init__} and + C{connectionLost} on. + @type _commonConnection: C{type} + + @ivar _stopReadingAndWriting: Subclasses must implement in order to remove + this transport from its reactor's notifications in response to a + terminated connection attempt. + @type _stopReadingAndWriting: 0-argument callable returning C{None} + + @ivar _closeSocket: Subclasses must implement in order to close the socket + in response to a terminated connection attempt. + @type _closeSocket: 1-argument callable; see L{_SocketCloser._closeSocket} + + @ivar _collectSocketDetails: Clean up references to the attached socket in + its underlying OS resource (such as a file descriptor or file handle), + as part of post connection-failure cleanup. + @type _collectSocketDetails: 0-argument callable returning C{None}. + + @ivar reactor: The class pointed to by C{_commonConnection} should set this + attribute in its constructor. + @type reactor: L{twisted.internet.interfaces.IReactorTime}, + L{twisted.internet.interfaces.IReactorCore}, + L{twisted.internet.interfaces.IReactorFDSet} """ - _base = Connection addressFamily = socket.AF_INET socketType = socket.SOCK_STREAM def _finishInit(self, whenDone, skt, error, reactor): """ - Called by base classes to continue to next stage of initialization. + Called by subclasses to continue to the stage of initialization where + the socket connect attempt is made. + + @param whenDone: A 0-argument callable to invoke once the connection is + set up. This is C{None} if the connection could not be prepared + due to a previous error. + + @param skt: The socket object to use to perform the connection. + @type skt: C{socket._socketobject} + + @param error: The error to fail the connection with. + + @param reactor: The reactor to use for this client. + @type reactor: L{twisted.internet.interfaces.IReactorTime} """ if whenDone: - Connection.__init__(self, skt, None, reactor) - self.doWrite = self.doConnect - self.doRead = self.doConnect + self._commonConnection.__init__(self, skt, None, reactor) reactor.callLater(0, whenDone) else: reactor.callLater(0, self.failIfNotConnected, error) - def stopConnecting(self): - """Stop attempt to connect.""" - self.failIfNotConnected(error.UserError()) + + def resolveAddress(self): + """ + Resolve the name that was passed to this L{_BaseBaseClient}, if + necessary, and then move on to attempting the connection once an + address has been determined. (The connection will be attempted + immediately within this function if either name resolution can be + synchronous or the address was an IP address literal.) + + @note: You don't want to call this method from outside, as it won't do + anything useful; it's just part of the connection bootstrapping + process. Also, although this method is on L{_BaseBaseClient} for + historical reasons, it's not used anywhere except for L{Client} + itself. + + @return: C{None} + """ + if self._requiresResolution: + d = self.reactor.resolve(self.addr[0]) + d.addCallback(lambda n: (n,) + self.addr[1:]) + d.addCallbacks(self._setRealAddress, self.failIfNotConnected) + else: + self._setRealAddress(self.addr) + + + def _setRealAddress(self, address): + """ + Set the resolved address of this L{_BaseBaseClient} and initiate the + connection attempt. + + @param address: Depending on whether this is an IPv4 or IPv6 connection + attempt, a 2-tuple of C{(host, port)} or a 4-tuple of C{(host, + port, flow, scope)}. At this point it is a fully resolved address, + and the 'host' portion will always be an IP address, not a DNS + name. + """ + self.realAddress = address + self.doConnect() + def failIfNotConnected(self, err): """ @@ -334,19 +438,84 @@ not hasattr(self, "connector")): return + self._stopReadingAndWriting() + try: + self._closeSocket(True) + except AttributeError: + pass + else: + self._collectSocketDetails() self.connector.connectionFailed(failure.Failure(err)) + del self.connector + + + def stopConnecting(self): + """ + If a connection attempt is still outstanding (i.e. no connection is + yet established), immediately stop attempting to connect. + """ + self.failIfNotConnected(error.UserError()) + + + def connectionLost(self, reason): + """ + Invoked by lower-level logic when it's time to clean the socket up. + Depending on the state of the connection, either inform the attached + L{Connector} that the connection attempt has failed, or inform the + connected L{IProtocol} that the established connection has been lost. + + @param reason: the reason that the connection was terminated + @type reason: L{Failure} + """ + if not self.connected: + self.failIfNotConnected(error.ConnectError(string=reason)) + else: + self._commonConnection.connectionLost(self, reason) + self.connector.connectionLost(reason) + + + +class BaseClient(_BaseBaseClient, _TLSClientMixin, Connection): + """ + A base class for client TCP (and similiar) sockets. + + @ivar realAddress: The address object that will be used for socket.connect; + this address is an address tuple (the number of elements dependent upon + the address family) which does not contain any names which need to be + resolved. + @type realAddress: C{tuple} + + @ivar _base: L{Connection}, which is the base class of this class which has + all of the useful file descriptor methods. This is used by + L{_TLSServerMixin} to call the right methods to directly manipulate the + transport, as is necessary for writing TLS-encrypted bytes (whereas + those methods on L{Server} will go through another layer of TLS if it + has been enabled). + """ + + _base = Connection + _commonConnection = Connection + + def _stopReadingAndWriting(self): + """ + Implement the POSIX-ish (i.e. + L{twisted.internet.interfaces.IReactorFDSet}) method of detaching this + socket from the reactor for L{_BaseBaseClient}. + """ if hasattr(self, "reactor"): # this doesn't happen if we failed in __init__ self.stopReading() self.stopWriting() - del self.connector - try: - self._closeSocket(True) - except AttributeError: - pass - else: - del self.socket, self.fileno + + def _collectSocketDetails(self): + """ + Clean up references to the socket and its file descriptor. + + @see: L{_BaseBaseClient} + """ + del self.socket, self.fileno + def createInternetSocket(self): """(internal) Create a non-blocking socket using @@ -357,22 +526,16 @@ fdesc._setCloseOnExec(s.fileno()) return s - def resolveAddress(self): - if abstract.isIPAddress(self.addr[0]): - self._setRealAddress(self.addr[0]) - else: - d = self.reactor.resolve(self.addr[0]) - d.addCallbacks(self._setRealAddress, self.failIfNotConnected) - - def _setRealAddress(self, address): - self.realAddress = (address, self.addr[1]) - self.doConnect() def doConnect(self): - """I connect the socket. + """ + Initiate the outgoing connection attempt. - Then, call the protocol's makeConnection, and start waiting for data. + @note: Applications do not need to call this method; it will be invoked + internally as part of L{IReactorTCP.connectTCP}. """ + self.doWrite = self.doConnect + self.doRead = self.doConnect if not hasattr(self, "connector"): # this happens when connection failed but doConnect # was scheduled via a callLater in self._finishInit @@ -383,7 +546,6 @@ self.failIfNotConnected(error.getConnectError((err, strerror(err)))) return - # doConnect gets called twice. The first time we actually need to # start the connection attempt. The second time we don't really # want to (SO_ERROR above will have taken care of any errors, and if @@ -418,7 +580,18 @@ self.stopWriting() self._connectDone() + def _connectDone(self): + """ + This is a hook for when a connection attempt has succeeded. + + Here, we build the protocol from the + L{twisted.internet.protocol.ClientFactory} that was passed in, compute + a log string, begin reading so as to send traffic to the newly built + protocol, and finally hook up the protocol itself. + + This hook is overridden by L{ssl.Client} to initiate the TLS protocol. + """ self.protocol = self.connector.buildProtocol(self.getPeer()) self.connected = 1 logPrefix = self._getLogPrefix(self.protocol) @@ -426,16 +599,64 @@ self.startReading() self.protocol.makeConnection(self) - def connectionLost(self, reason): - if not self.connected: - self.failIfNotConnected(error.ConnectError(string=reason)) - else: - Connection.connectionLost(self, reason) - self.connector.connectionLost(reason) -class Client(BaseClient): - """A TCP client.""" +_NUMERIC_ONLY = socket.AI_NUMERICHOST | _AI_NUMERICSERV + +def _resolveIPv6(ip, port): + """ + Resolve an IPv6 literal into an IPv6 address. + + This is necessary to resolve any embedded scope identifiers to the relevant + C{sin6_scope_id} for use with C{socket.connect()}, C{socket.listen()}, or + C{socket.bind()}; see U{RFC 3493 } for + more information. + + @param ip: An IPv6 address literal. + @type ip: C{str} + + @param port: A port number. + @type port: C{int} + + @return: a 4-tuple of C{(host, port, flow, scope)}, suitable for use as an + IPv6 address. + + @raise socket.gaierror: if either the IP or port is not numeric as it + should be. + """ + return socket.getaddrinfo(ip, port, 0, 0, 0, _NUMERIC_ONLY)[0][4] + + + +class _BaseTCPClient(object): + """ + Code shared with other (non-POSIX) reactors for management of outgoing TCP + connections (both TCPv4 and TCPv6). + + @note: In order to be functional, this class must be mixed into the same + hierarchy as L{_BaseBaseClient}. It would subclass L{_BaseBaseClient} + directly, but the class hierarchy here is divided in strange ways out + of the need to share code along multiple axes; specifically, with the + IOCP reactor and also with UNIX clients in other reactors. + + @ivar _addressType: The Twisted _IPAddress implementation for this client + @type _addressType: L{IPv4Address} or L{IPv6Address} + + @ivar connector: The L{Connector} which is driving this L{_BaseTCPClient}'s + connection attempt. + + @ivar addr: The address that this socket will be connecting to. + @type addr: If IPv4, a 2-C{tuple} of C{(str host, int port)}. If IPv6, a + 4-C{tuple} of (C{str host, int port, int ignored, int scope}). + + @ivar createInternetSocket: Subclasses must implement this as a method to + create a python socket object of the appropriate address family and + socket type. + @type createInternetSocket: 0-argument callable returning + C{socket._socketobject}. + """ + + _addressType = address.IPv4Address def __init__(self, host, port, bindAddress, connector, reactor=None): # BaseClient.__init__ is invoked later @@ -446,6 +667,15 @@ err = None skt = None + if abstract.isIPAddress(host): + self._requiresResolution = False + elif abstract.isIPv6Address(host): + self._requiresResolution = False + self.addr = _resolveIPv6(host, port) + self.addressFamily = socket.AF_INET6 + self._addressType = address.IPv6Address + else: + self._requiresResolution = True try: skt = self.createInternetSocket() except socket.error, se: @@ -453,31 +683,52 @@ whenDone = None if whenDone and bindAddress is not None: try: - skt.bind(bindAddress) + if abstract.isIPv6Address(bindAddress[0]): + bindinfo = _resolveIPv6(*bindAddress) + else: + bindinfo = bindAddress + skt.bind(bindinfo) except socket.error, se: err = error.ConnectBindError(se.args[0], se.args[1]) whenDone = None self._finishInit(whenDone, skt, err, reactor) + def getHost(self): - """Returns an IPv4Address. + """ + Returns an L{IPv4Address} or L{IPv6Address}. This indicates the address from which I am connecting. """ - return address.IPv4Address('TCP', *self.socket.getsockname()) + return self._addressType('TCP', *self.socket.getsockname()[:2]) + def getPeer(self): - """Returns an IPv4Address. + """ + Returns an L{IPv4Address} or L{IPv6Address}. This indicates the address that I am connected to. """ - return address.IPv4Address('TCP', *self.realAddress) + # an ipv6 realAddress has more than two elements, but the IPv6Address + # constructor still only takes two. + return self._addressType('TCP', *self.realAddress[:2]) + def __repr__(self): s = '<%s to %s at %x>' % (self.__class__, self.addr, unsignedID(self)) return s + +class Client(_BaseTCPClient, BaseClient): + """ + A transport for a TCP protocol; either TCPv4 or TCPv6. + + Do not create these directly; use L{IReactorTCP.connectTCP}. + """ + + + class Server(_TLSServerMixin, Connection): """ Serverside socket-stream connection class. @@ -494,6 +745,8 @@ """ _base = Connection + _addressType = address.IPv4Address + def __init__(self, sock, protocol, client, server, sessionno, reactor): """ Server(sock, protocol, client, server, sessionno) @@ -503,6 +756,8 @@ instance of Port, and a session number. """ Connection.__init__(self, sock, protocol, reactor) + if len(client) != 2: + self._addressType = address.IPv6Address self.server = server self.client = client self.sessionno = sessionno @@ -523,19 +778,24 @@ """ return self.repstr + def getHost(self): - """Returns an IPv4Address. + """ + Returns an L{IPv4Address} or L{IPv6Address}. This indicates the server's address. """ - return address.IPv4Address('TCP', *self.socket.getsockname()) + host, port = self.socket.getsockname()[:2] + return self._addressType('TCP', host, port) + def getPeer(self): - """Returns an IPv4Address. + """ + Returns an L{IPv4Address} or L{IPv6Address}. This indicates the client's address. """ - return address.IPv4Address('TCP', *self.client) + return self._addressType('TCP', *self.client[:2]) @@ -568,11 +828,15 @@ this port. Normally this is C{"TCP"}, since this is a TCP port, but when the TLS implementation re-uses this class it overrides the value with C{"TLS"}. Only used for logging. + + @ivar _preexistingSocket: If not C{None}, a L{socket.socket} instance which + was created and initialized outside of the reactor and will be used to + listen for connections (instead of a new socket being created by this + L{Port}). """ implements(interfaces.IListeningPort) - addressFamily = socket.AF_INET socketType = socket.SOCK_STREAM transport = Server @@ -586,6 +850,13 @@ # value when we are actually listening. _realPortNumber = None + # An externally initialized socket that we will use, rather than creating + # our own. + _preexistingSocket = None + + addressFamily = socket.AF_INET + _addressType = address.IPv4Address + def __init__(self, port, factory, backlog=50, interface='', reactor=None): """Initialize with a numeric port to listen on. """ @@ -593,12 +864,40 @@ self.port = port self.factory = factory self.backlog = backlog + if abstract.isIPv6Address(interface): + self.addressFamily = socket.AF_INET6 + self._addressType = address.IPv6Address self.interface = interface + + @classmethod + def _fromListeningDescriptor(cls, reactor, fd, addressFamily, factory): + """ + Create a new L{Port} based on an existing listening I{SOCK_STREAM} + I{AF_INET} socket. + + Arguments are the same as to L{Port.__init__}, except where noted. + + @param fd: An integer file descriptor associated with a listening + socket. The socket must be in non-blocking mode. Any additional + attributes desired, such as I{FD_CLOEXEC}, must also be set already. + + @param addressFamily: The address family (sometimes called I{domain}) of + the existing socket. For example, L{socket.AF_INET}. + + @return: A new instance of C{cls} wrapping the socket given by C{fd}. + """ + port = socket.fromfd(fd, addressFamily, cls.socketType) + interface = port.getsockname()[0] + self = cls(None, factory, None, interface, reactor) + self._preexistingSocket = port + return self + + def __repr__(self): if self._realPortNumber is not None: - return "<%s of %s on %s>" % (self.__class__, self.factory.__class__, - self._realPortNumber) + return "<%s of %s on %s>" % (self.__class__, + self.factory.__class__, self._realPortNumber) else: return "<%s of %s (not listening)>" % (self.__class__, self.factory.__class__) @@ -615,11 +914,24 @@ This is called on unserialization, and must be called after creating a server to begin listening on the specified port. """ - try: - skt = self.createInternetSocket() - skt.bind((self.interface, self.port)) - except socket.error, le: - raise CannotListenError, (self.interface, self.port, le) + if self._preexistingSocket is None: + # Create a new socket and make it listen + try: + skt = self.createInternetSocket() + if self.addressFamily == socket.AF_INET6: + addr = _resolveIPv6(self.interface, self.port) + else: + addr = (self.interface, self.port) + skt.bind(addr) + except socket.error, le: + raise CannotListenError, (self.interface, self.port, le) + skt.listen(self.backlog) + else: + # Re-use the externally specified socket + skt = self._preexistingSocket + self._preexistingSocket = None + # Avoid shutting it down at the end. + self._socketShutdownMethod = None # Make sure that if we listened on port 0, we update that to # reflect what the OS actually assigned us. @@ -628,10 +940,9 @@ log.msg("%s starting on %s" % ( self._getLogPrefix(self.factory), self._realPortNumber)) - # The order of the next 6 lines is kind of bizarre. If no one + # The order of the next 5 lines is kind of bizarre. If no one # can explain it, perhaps we should re-arrange them. self.factory.doStart() - skt.listen(self.backlog) self.connected = True self.socket = skt self.fileno = self.socket.fileno @@ -640,8 +951,9 @@ self.startReading() - def _buildAddr(self, (host, port)): - return address._ServerFactoryIPv4Address('TCP', host, port) + def _buildAddr(self, address): + host, port = address[:2] + return self._addressType('TCP', host, port) def doRead(self): @@ -763,27 +1075,56 @@ """ return reflect.qual(self.factory.__class__) - def getHost(self): - """Returns an IPv4Address. - This indicates the server's address. + def getHost(self): + """ + Return an L{IPv4Address} or L{IPv6Address} indicating the listening + address of this port. """ - return address.IPv4Address('TCP', *self.socket.getsockname()) + host, port = self.socket.getsockname()[:2] + return self._addressType('TCP', host, port) + + class Connector(base.BaseConnector): + """ + A L{Connector} provides of L{twisted.internet.interfaces.IConnector} for + all POSIX-style reactors. + + @ivar _addressType: the type returned by L{Connector.getDestination}. + Either L{IPv4Address} or L{IPv6Address}, depending on the type of + address. + @type _addressType: C{type} + """ + _addressType = address.IPv4Address + def __init__(self, host, port, factory, timeout, bindAddress, reactor=None): - self.host = host if isinstance(port, types.StringTypes): try: port = socket.getservbyname(port, 'tcp') except socket.error, e: raise error.ServiceNameUnknownError(string="%s (%r)" % (e, port)) - self.port = port + self.host, self.port = host, port + if abstract.isIPv6Address(host): + self._addressType = address.IPv6Address self.bindAddress = bindAddress base.BaseConnector.__init__(self, factory, timeout, reactor) + def _makeTransport(self): + """ + Create a L{Client} bound to this L{Connector}. + + @return: a new L{Client} + @rtype: L{Client} + """ return Client(self.host, self.port, self.bindAddress, self, self.reactor) + def getDestination(self): - return address.IPv4Address('TCP', self.host, self.port) + """ + @see: L{twisted.internet.interfaces.IConnector.getDestination}. + """ + return self._addressType('TCP', self.host, self.port) + + diff -Nru twisted-11.1.0/twisted/internet/test/connectionmixins.py twisted-12.1.0/twisted/internet/test/connectionmixins.py --- twisted-11.1.0/twisted/internet/test/connectionmixins.py 2011-11-02 13:15:43.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/connectionmixins.py 2012-04-12 03:14:29.000000000 +0000 @@ -1,3 +1,4 @@ +# -*- test-case-name: twisted.internet.test.test_tcp -*- # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. @@ -5,14 +6,31 @@ Various helpers for tests for connection-oriented transports. """ +import socket + from gc import collect from weakref import ref +from zope.interface import implements +from zope.interface.verify import verifyObject + from twisted.python import context, log -from twisted.python.reflect import fullyQualifiedName +from twisted.python.failure import Failure +from twisted.python.runtime import platform from twisted.python.log import ILogContext, msg, err -from twisted.internet.defer import Deferred, gatherResults -from twisted.internet.protocol import ServerFactory, Protocol +from twisted.internet.defer import Deferred, gatherResults, succeed, fail +from twisted.internet.interfaces import ( + IConnector, IResolverSimple, IReactorFDSet) +from twisted.internet.protocol import ClientFactory, Protocol, ServerFactory +from twisted.test.test_tcp import ClosingProtocol +from twisted.trial.unittest import SkipTest +from twisted.internet.error import DNSLookupError +from twisted.internet.interfaces import ITLSTransport +from twisted.internet.test.reactormixins import ConnectableProtocol +from twisted.internet.test.reactormixins import runProtocolsWithReactor +from twisted.internet.test.reactormixins import needsRunningReactor + + def serverFactoryFor(protocol): """ @@ -29,6 +47,47 @@ # ServerFactory is good enough for client endpoints, too. factoryFor = serverFactoryFor + + +def findFreePort(interface='127.0.0.1', family=socket.AF_INET, + type=socket.SOCK_STREAM): + """ + Ask the platform to allocate a free port on the specified interface, then + release the socket and return the address which was allocated. + + @param interface: The local address to try to bind the port on. + @type interface: C{str} + + @param type: The socket type which will use the resulting port. + + @return: A two-tuple of address and port, like that returned by + L{socket.getsockname}. + """ + addr = socket.getaddrinfo(interface, 0)[0][4] + probe = socket.socket(family, type) + try: + probe.bind(addr) + return probe.getsockname() + finally: + probe.close() + + + +def _getWriters(reactor): + """ + Like L{IReactorFDSet.getWriters}, but with support for IOCP reactor as + well. + """ + if IReactorFDSet.providedBy(reactor): + return reactor.getWriters() + elif 'IOCP' in reactor.__class__.__name__: + return reactor.handles + else: + # Cannot tell what is going on. + raise Exception("Cannot find writers on %r" % (reactor,)) + + + class _AcceptOneClient(ServerFactory): """ This factory fires a L{Deferred} with a protocol instance shortly after it @@ -36,6 +95,7 @@ connected to a transport). @ivar reactor: The reactor used to schedule the I{shortly}. + @ivar result: A L{Deferred} which will be fired with the protocol instance. """ def __init__(self, reactor, result): @@ -50,7 +110,61 @@ -class ClosingLaterProtocol(Protocol): +class _SimplePullProducer(object): + """ + A pull producer which writes one byte whenever it is resumed. For use by + L{test_unregisterProducerAfterDisconnect}. + """ + def __init__(self, consumer): + self.consumer = consumer + + + def stopProducing(self): + pass + + + def resumeProducing(self): + log.msg("Producer.resumeProducing") + self.consumer.write('x') + + + +class Stop(ClientFactory): + """ + A client factory which stops a reactor when a connection attempt fails. + """ + failReason = None + + def __init__(self, reactor): + self.reactor = reactor + + + def clientConnectionFailed(self, connector, reason): + self.failReason = reason + msg("Stop(CF) cCFailed: %s" % (reason.getErrorMessage(),)) + self.reactor.stop() + + + +class FakeResolver(object): + """ + A resolver implementation based on a C{dict} mapping names to addresses. + """ + implements(IResolverSimple) + + def __init__(self, names): + self.names = names + + + def getHostByName(self, name, timeout): + try: + return succeed(self.names[name]) + except KeyError: + return fail(DNSLookupError("FakeResolver couldn't find " + name)) + + + +class ClosingLaterProtocol(ConnectableProtocol): """ ClosingLaterProtocol exchanges one byte with its peer and then disconnects itself. This is mostly a work-around for the fact that connectionMade is @@ -82,46 +196,9 @@ This mixin defines test methods which should apply to most L{ITransport} implementations. """ - def serverEndpoint(self, reactor): - """ - Return an object providing L{IStreamServerEndpoint} for use in creating - a server to use to establish the connection type to be tested. - """ - raise NotImplementedError("%s.serverEndpoint() not implemented" % ( - fullyQualifiedName(self.__class__),)) - - def clientEndpoint(self, reactor, serverAddress): - """ - Return an object providing L{IStreamClientEndpoint} for use in creating - a client to use to establish the connection type to be tested. - """ - raise NotImplementedError("%s.clientEndpoint() not implemented" % ( - fullyQualifiedName(self.__class__),)) - - - def loopback(self, reactor, clientProtocol, serverProtocol): - """ - Create a loopback connection of the type to be tested, using - C{clientProtocol} and C{serverProtocol} to handle each end of the - connection. - - @return: A L{Deferred} which fires when the connection is established. - The result is a two-tuple of the client protocol instance and - server protocol instance. - """ - accepted = Deferred() - factory = _AcceptOneClient(reactor, accepted) - factory.protocol = serverProtocol - server = self.serverEndpoint(reactor) - listening = server.listen(factory) - def startedListening(port): - address = port.getHost() - client = self.clientEndpoint(reactor, address) - return gatherResults([ - client.connect(factoryFor(clientProtocol)), accepted]) - listening.addCallback(startedListening) - return listening + # This should be a reactormixins.EndpointCreator instance. + endpoints = None def test_logPrefix(self): @@ -129,35 +206,30 @@ Client and server transports implement L{ILoggingContext.logPrefix} to return a message reflecting the protocol they are running. """ - class CustomLogPrefixProtocol(Protocol): + class CustomLogPrefixProtocol(ConnectableProtocol): def __init__(self, prefix): self._prefix = prefix - self.system = Deferred() + self.system = None + + def connectionMade(self): + self.transport.write("a") def logPrefix(self): return self._prefix def dataReceived(self, bytes): - self.system.callback(context.get(ILogContext)["system"]) - - reactor = self.buildReactor() - d = self.loopback( - reactor, - lambda: CustomLogPrefixProtocol("Custom Client"), - lambda: CustomLogPrefixProtocol("Custom Server")) - def connected((client, server)): - client.transport.write("foo") - server.transport.write("bar") - return gatherResults([client.system, server.system]) - d.addCallback(connected) - - def gotSystem((client, server)): - self.assertIn("Custom Client", client) - self.assertIn("Custom Server", server) - d.addCallback(gotSystem) - d.addErrback(err) - d.addCallback(lambda ignored: reactor.stop()) - self.runReactor(reactor) + self.system = context.get(ILogContext)["system"] + self.transport.write("b") + # Only close connection if both sides have received data, so + # that both sides have system set. + if "b" in bytes: + self.transport.loseConnection() + + client = CustomLogPrefixProtocol("Custom Client") + server = CustomLogPrefixProtocol("Custom Server") + runProtocolsWithReactor(self, server, client, self.endpoints) + self.assertIn("Custom Client", client.system) + self.assertIn("Custom Server", server.system) def test_writeAfterDisconnect(self): @@ -171,21 +243,19 @@ serverConnectionLostDeferred = Deferred() protocol = lambda: ClosingLaterProtocol(serverConnectionLostDeferred) - portDeferred = self.serverEndpoint(reactor).listen( + portDeferred = self.endpoints.server(reactor).listen( serverFactoryFor(protocol)) def listening(port): msg("Listening on %r" % (port.getHost(),)) - endpoint = self.clientEndpoint(reactor, port.getHost()) + endpoint = self.endpoints.client(reactor, port.getHost()) lostConnectionDeferred = Deferred() - protocol = lambda: ClosingLaterProtocol( - lostConnectionDeferred) + protocol = lambda: ClosingLaterProtocol(lostConnectionDeferred) client = endpoint.connect(factoryFor(protocol)) def write(proto): msg("About to write to %r" % (proto,)) proto.transport.write('x') - client.addCallbacks( - write, lostConnectionDeferred.errback) + client.addCallbacks(write, lostConnectionDeferred.errback) def disconnected(proto): msg("%r disconnected" % (proto,)) @@ -199,9 +269,11 @@ lostConnectionDeferred, serverConnectionLostDeferred]) - portDeferred.addCallback(listening) - portDeferred.addErrback(err) - portDeferred.addCallback(lambda ignored: reactor.stop()) + def onListen(): + portDeferred.addCallback(listening) + portDeferred.addErrback(err) + portDeferred.addCallback(lambda ignored: reactor.stop()) + needsRunningReactor(reactor, onListen) self.runReactor(reactor) self.assertEqual(finished, [True, True]) @@ -209,19 +281,19 @@ def test_protocolGarbageAfterLostConnection(self): """ - After the connection a protocol is being used for is closed, the reactor - discards all of its references to the protocol. + After the connection a protocol is being used for is closed, the + reactor discards all of its references to the protocol. """ lostConnectionDeferred = Deferred() clientProtocol = ClosingLaterProtocol(lostConnectionDeferred) clientRef = ref(clientProtocol) reactor = self.buildReactor() - portDeferred = self.serverEndpoint(reactor).listen( + portDeferred = self.endpoints.server(reactor).listen( serverFactoryFor(Protocol)) def listening(port): msg("Listening on %r" % (port.getHost(),)) - endpoint = self.clientEndpoint(reactor, port.getHost()) + endpoint = self.endpoints.client(reactor, port.getHost()) client = endpoint.connect(factoryFor(lambda: clientProtocol)) def disconnect(proto): @@ -231,9 +303,11 @@ client.addErrback(lostConnectionDeferred.errback) return lostConnectionDeferred - portDeferred.addCallback(listening) - portDeferred.addErrback(err) - portDeferred.addCallback(lambda ignored: reactor.stop()) + def onListening(): + portDeferred.addCallback(listening) + portDeferred.addErrback(err) + portDeferred.addBoth(lambda ignored: reactor.stop()) + needsRunningReactor(reactor, onListening) self.runReactor(reactor) @@ -254,3 +328,322 @@ log.addObserver(loggedMessages.append) self.addCleanup(log.removeObserver, loggedMessages.append) return loggedMessages + + + +class BrokenContextFactory(object): + """ + A context factory with a broken C{getContext} method, for exercising the + error handling for such a case. + """ + message = "Some path was wrong maybe" + + def getContext(self): + raise ValueError(self.message) + + + +class TCPClientTestsMixin(object): + """ + This mixin defines tests applicable to TCP client implementations. Classes + which mix this in must provide all of the documented instance variables in + order to specify how the test works. These are documented as instance + variables rather than declared as methods due to some peculiar inheritance + ordering concerns, but they are effectively abstract methods. + + This must be mixed in to a L{ReactorBuilder + } subclass, as it + depends on several of its methods. + + @ivar endpoints: A L{twisted.internet.test.reactormixins.EndpointCreator} + instance. + + @ivar interface: An IP address literal to locally bind a socket to as well + as to connect to. This can be any valid interface for the local host. + @type interface: C{str} + + @ivar port: An unused local listening port to listen on and connect to. + This will be used in conjunction with the C{interface}. (Depending on + what they're testing, some tests will locate their own port with + L{findFreePort} instead.) + @type port: C{int} + + @ivar family: an address family constant, such as L{socket.AF_INET}, + L{socket.AF_INET6}, or L{socket.AF_UNIX}, which indicates the address + family of the transport type under test. + @type family: C{int} + + @ivar addressClass: the L{twisted.internet.interfaces.IAddress} implementor + associated with the transport type under test. Must also be a + 3-argument callable which produces an instance of same. + @type addressClass: C{type} + + @ivar fakeDomainName: A fake domain name to use, to simulate hostname + resolution and to distinguish between hostnames and IP addresses where + necessary. + @type fakeDomainName: C{str} + """ + + def test_interface(self): + """ + L{IReactorTCP.connectTCP} returns an object providing L{IConnector}. + """ + reactor = self.buildReactor() + connector = reactor.connectTCP(self.interface, self.port, + ClientFactory()) + self.assertTrue(verifyObject(IConnector, connector)) + + + def test_clientConnectionFailedStopsReactor(self): + """ + The reactor can be stopped by a client factory's + C{clientConnectionFailed} method. + """ + host, port = findFreePort(self.interface, self.family)[:2] + reactor = self.buildReactor() + needsRunningReactor( + reactor, lambda: reactor.connectTCP(host, port, Stop(reactor))) + self.runReactor(reactor) + + + def test_addresses(self): + """ + A client's transport's C{getHost} and C{getPeer} return L{IPv4Address} + instances which have the dotted-quad string form of the resolved + adddress of the local and remote endpoints of the connection + respectively as their C{host} attribute, not the hostname originally + passed in to L{connectTCP + }, if a hostname + was used. + """ + host, port = findFreePort(self.interface, self.family)[:2] + reactor = self.buildReactor() + fakeDomain = self.fakeDomainName + reactor.installResolver(FakeResolver({fakeDomain: self.interface})) + + server = reactor.listenTCP( + 0, serverFactoryFor(Protocol), interface=host) + serverAddress = server.getHost() + + addresses = {'host': None, 'peer': None} + class CheckAddress(Protocol): + def makeConnection(self, transport): + addresses['host'] = transport.getHost() + addresses['peer'] = transport.getPeer() + reactor.stop() + + clientFactory = Stop(reactor) + clientFactory.protocol = CheckAddress + + def connectMe(): + reactor.connectTCP( + fakeDomain, server.getHost().port, clientFactory, + bindAddress=(self.interface, port)) + needsRunningReactor(reactor, connectMe) + + self.runReactor(reactor) + + if clientFactory.failReason: + self.fail(clientFactory.failReason.getTraceback()) + + self.assertEqual( + addresses['host'], + self.addressClass('TCP', self.interface, port)) + self.assertEqual( + addresses['peer'], + self.addressClass('TCP', self.interface, serverAddress.port)) + + + def test_connectEvent(self): + """ + This test checks that we correctly get notifications event for a + client. This ought to prevent a regression under Windows using the + GTK2 reactor. See #3925. + """ + reactor = self.buildReactor() + + server = reactor.listenTCP(0, serverFactoryFor(Protocol), + interface=self.interface) + connected = [] + + class CheckConnection(Protocol): + def connectionMade(self): + connected.append(self) + reactor.stop() + + clientFactory = Stop(reactor) + clientFactory.protocol = CheckConnection + + needsRunningReactor(reactor, lambda: reactor.connectTCP( + self.interface, server.getHost().port, clientFactory)) + + reactor.run() + + self.assertTrue(connected) + + + def test_unregisterProducerAfterDisconnect(self): + """ + If a producer is unregistered from a L{ITCPTransport} provider after + the transport has been disconnected (by the peer) and after + L{ITCPTransport.loseConnection} has been called, the transport is not + re-added to the reactor as a writer as would be necessary if the + transport were still connected. + """ + reactor = self.buildReactor() + port = reactor.listenTCP(0, serverFactoryFor(ClosingProtocol), + interface=self.interface) + + finished = Deferred() + finished.addErrback(log.err) + finished.addCallback(lambda ign: reactor.stop()) + + writing = [] + + class ClientProtocol(Protocol): + """ + Protocol to connect, register a producer, try to lose the + connection, wait for the server to disconnect from us, and then + unregister the producer. + """ + def connectionMade(self): + log.msg("ClientProtocol.connectionMade") + self.transport.registerProducer( + _SimplePullProducer(self.transport), False) + self.transport.loseConnection() + + def connectionLost(self, reason): + log.msg("ClientProtocol.connectionLost") + self.unregister() + writing.append(self.transport in _getWriters(reactor)) + finished.callback(None) + + def unregister(self): + log.msg("ClientProtocol unregister") + self.transport.unregisterProducer() + + clientFactory = ClientFactory() + clientFactory.protocol = ClientProtocol + reactor.connectTCP(self.interface, port.getHost().port, clientFactory) + self.runReactor(reactor) + self.assertFalse(writing[0], + "Transport was writing after unregisterProducer.") + + + def test_disconnectWhileProducing(self): + """ + If L{ITCPTransport.loseConnection} is called while a producer is + registered with the transport, the connection is closed after the + producer is unregistered. + """ + reactor = self.buildReactor() + + # For some reason, pyobject/pygtk will not deliver the close + # notification that should happen after the unregisterProducer call in + # this test. The selectable is in the write notification set, but no + # notification ever arrives. Probably for the same reason #5233 led + # win32eventreactor to be broken. + skippedReactors = ["Glib2Reactor", "Gtk2Reactor"] + reactorClassName = reactor.__class__.__name__ + if reactorClassName in skippedReactors and platform.isWindows(): + raise SkipTest( + "A pygobject/pygtk bug disables this functionality on Windows.") + + class Producer: + def resumeProducing(self): + log.msg("Producer.resumeProducing") + + port = reactor.listenTCP(0, serverFactoryFor(Protocol), + interface=self.interface) + + finished = Deferred() + finished.addErrback(log.err) + finished.addCallback(lambda ign: reactor.stop()) + + class ClientProtocol(Protocol): + """ + Protocol to connect, register a producer, try to lose the + connection, unregister the producer, and wait for the connection to + actually be lost. + """ + def connectionMade(self): + log.msg("ClientProtocol.connectionMade") + self.transport.registerProducer(Producer(), False) + self.transport.loseConnection() + # Let the reactor tick over, in case synchronously calling + # loseConnection and then unregisterProducer is the same as + # synchronously calling unregisterProducer and then + # loseConnection (as it is in several reactors). + reactor.callLater(0, reactor.callLater, 0, self.unregister) + + def unregister(self): + log.msg("ClientProtocol unregister") + self.transport.unregisterProducer() + # This should all be pretty quick. Fail the test + # if we don't get a connectionLost event really + # soon. + reactor.callLater( + 1.0, finished.errback, + Failure(Exception("Connection was not lost"))) + + def connectionLost(self, reason): + log.msg("ClientProtocol.connectionLost") + finished.callback(None) + + clientFactory = ClientFactory() + clientFactory.protocol = ClientProtocol + reactor.connectTCP(self.interface, port.getHost().port, clientFactory) + self.runReactor(reactor) + # If the test failed, we logged an error already and trial + # will catch it. + + + def test_badContext(self): + """ + If the context factory passed to L{ITCPTransport.startTLS} raises an + exception from its C{getContext} method, that exception is raised by + L{ITCPTransport.startTLS}. + """ + reactor = self.buildReactor() + + brokenFactory = BrokenContextFactory() + results = [] + + serverFactory = ServerFactory() + serverFactory.protocol = Protocol + + port = reactor.listenTCP(0, serverFactory, interface=self.interface) + endpoint = self.endpoints.client(reactor, port.getHost()) + + clientFactory = ClientFactory() + clientFactory.protocol = Protocol + connectDeferred = endpoint.connect(clientFactory) + + def connected(protocol): + if not ITLSTransport.providedBy(protocol.transport): + results.append("skip") + else: + results.append(self.assertRaises(ValueError, + protocol.transport.startTLS, + brokenFactory)) + + def connectFailed(failure): + results.append(failure) + + def whenRun(): + connectDeferred.addCallback(connected) + connectDeferred.addErrback(connectFailed) + connectDeferred.addBoth(lambda ign: reactor.stop()) + needsRunningReactor(reactor, whenRun) + + self.runReactor(reactor) + + self.assertEqual(len(results), 1, + "more than one callback result: %s" % (results,)) + + if isinstance(results[0], Failure): + # self.fail(Failure) + results[0].raiseException() + if results[0] == "skip": + raise SkipTest("Reactor does not support ITLSTransport") + self.assertEqual(BrokenContextFactory.message, str(results[0])) diff -Nru twisted-11.1.0/twisted/internet/test/_posixifaces.py twisted-12.1.0/twisted/internet/test/_posixifaces.py --- twisted-11.1.0/twisted/internet/test/_posixifaces.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/_posixifaces.py 2011-12-11 03:20:29.000000000 +0000 @@ -0,0 +1,131 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +POSIX implementation of local network interface enumeration. +""" + +import sys, socket + +from socket import AF_INET, AF_INET6, inet_ntop +from ctypes import ( + CDLL, POINTER, Structure, c_char_p, c_ushort, c_int, + c_uint32, c_uint8, c_void_p, c_ubyte, pointer, cast) +from ctypes.util import find_library + +libc = CDLL(find_library("c")) + +if sys.platform == 'darwin': + _sockaddrCommon = [ + ("sin_len", c_uint8), + ("sin_family", c_uint8), + ] +else: + _sockaddrCommon = [ + ("sin_family", c_ushort), + ] + + + +class in_addr(Structure): + _fields_ = [ + ("in_addr", c_ubyte * 4), + ] + + + +class in6_addr(Structure): + _fields_ = [ + ("in_addr", c_ubyte * 16), + ] + + + +class sockaddr(Structure): + _fields_ = _sockaddrCommon + [ + ("sin_port", c_ushort), + ] + + + +class sockaddr_in(Structure): + _fields_ = _sockaddrCommon + [ + ("sin_port", c_ushort), + ("sin_addr", in_addr), + ] + + + +class sockaddr_in6(Structure): + _fields_ = _sockaddrCommon + [ + ("sin_port", c_ushort), + ("sin_flowinfo", c_uint32), + ("sin_addr", in6_addr), + ] + + + +class ifaddrs(Structure): + pass + +ifaddrs_p = POINTER(ifaddrs) +ifaddrs._fields_ = [ + ('ifa_next', ifaddrs_p), + ('ifa_name', c_char_p), + ('ifa_flags', c_uint32), + ('ifa_addr', POINTER(sockaddr)), + ('ifa_netmask', POINTER(sockaddr)), + ('ifa_dstaddr', POINTER(sockaddr)), + ('ifa_data', c_void_p)] + +getifaddrs = libc.getifaddrs +getifaddrs.argtypes = [POINTER(ifaddrs_p)] +getifaddrs.restype = c_int + +freeifaddrs = libc.freeifaddrs +freeifaddrs.argtypes = [ifaddrs_p] + +def _interfaces(): + """ + Call C{getifaddrs(3)} and return a list of tuples of interface name, address + family, and human-readable address representing its results. + """ + ifaddrs = ifaddrs_p() + if getifaddrs(pointer(ifaddrs)) < 0: + raise OSError() + results = [] + try: + while ifaddrs: + if ifaddrs[0].ifa_addr: + family = ifaddrs[0].ifa_addr[0].sin_family + if family == AF_INET: + addr = cast(ifaddrs[0].ifa_addr, POINTER(sockaddr_in)) + elif family == AF_INET6: + addr = cast(ifaddrs[0].ifa_addr, POINTER(sockaddr_in6)) + else: + addr = None + + if addr: + packed = ''.join(map(chr, addr[0].sin_addr.in_addr[:])) + results.append(( + ifaddrs[0].ifa_name, + family, + inet_ntop(family, packed))) + + ifaddrs = ifaddrs[0].ifa_next + finally: + freeifaddrs(ifaddrs) + return results + + + +def posixGetLinkLocalIPv6Addresses(): + """ + Return a list of strings in colon-hex format representing all the link local + IPv6 addresses available on the system, as reported by I{getifaddrs(3)}. + """ + retList = [] + for (interface, family, address) in _interfaces(): + if family == socket.AF_INET6 and address.startswith('fe80:'): + retList.append('%s%%%s' % (address, interface)) + return retList diff -Nru twisted-11.1.0/twisted/internet/test/reactormixins.py twisted-12.1.0/twisted/internet/test/reactormixins.py --- twisted-11.1.0/twisted/internet/test/reactormixins.py 2011-08-28 15:09:23.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/reactormixins.py 2012-04-12 03:14:29.000000000 +0000 @@ -7,9 +7,10 @@ __metaclass__ = type -import signal +import os, signal, time -from twisted.internet.defer import TimeoutError +from twisted.internet.defer import TimeoutError, Deferred, gatherResults +from twisted.internet.protocol import ClientFactory, Protocol from twisted.trial.unittest import TestCase, SkipTest from twisted.python.runtime import platform from twisted.python.reflect import namedAny, fullyQualifiedName @@ -23,6 +24,159 @@ from twisted.internet import process + +def needsRunningReactor(reactor, thunk): + """ + Various functions within these tests need an already-running reactor at + some point. They need to stop the reactor when the test has completed, and + that means calling reactor.stop(). However, reactor.stop() raises an + exception if the reactor isn't already running, so if the L{Deferred} that + a particular API under test returns fires synchronously (as especially an + endpoint's C{connect()} method may do, if the connect is to a local + interface address) then the test won't be able to stop the reactor being + tested and finish. So this calls C{thunk} only once C{reactor} is running. + + (This is just an alias for + L{twisted.internet.interfaces.IReactorCore.callWhenRunning} on the given + reactor parameter, in order to centrally reference the above paragraph and + repeating it everywhere as a comment.) + + @param reactor: the L{twisted.internet.interfaces.IReactorCore} under test + + @param thunk: a 0-argument callable, which eventually finishes the test in + question, probably in a L{Deferred} callback. + """ + reactor.callWhenRunning(thunk) + + + +class ConnectableProtocol(Protocol): + """ + A protocol to be used with L{runProtocolsWithReactor}. + + The protocol and its pair should eventually disconnect from each other. + + @ivar reactor: The reactor used in this test. + + @ivar disconnectReason: The L{Failure} passed to C{connectionLost}. + + @ivar _done: A L{Deferred} which will be fired when the connection is + lost. + """ + + disconnectReason = None + + def _setAttributes(self, reactor, done): + """ + Set attributes on the protocol that are known only externally; this + will be called by L{runProtocolsWithReactor} when this protocol is + instantiated. + + @param reactor: The reactor used in this test. + + @param done: A L{Deferred} which will be fired when the connection is + lost. + """ + self.reactor = reactor + self._done = done + + + def connectionLost(self, reason): + self.disconnectReason = reason + self._done.callback(None) + del self._done + + + +class EndpointCreator: + """ + Create client and server endpoints that know how to connect to each other. + """ + + def server(self, reactor): + """ + Return an object providing C{IStreamServerEndpoint} for use in creating + a server to use to establish the connection type to be tested. + """ + raise NotImplementedError() + + + def client(self, reactor, serverAddress): + """ + Return an object providing C{IStreamClientEndpoint} for use in creating + a client to use to establish the connection type to be tested. + """ + raise NotImplementedError() + + + +class _SingleProtocolFactory(ClientFactory): + """ + Factory to be used by L{runProtocolsWithReactor}. + + It always returns the same protocol (i.e. is intended for only a single connection). + """ + + def __init__(self, protocol): + self._protocol = protocol + + + def buildProtocol(self, addr): + return self._protocol + + + +def runProtocolsWithReactor(reactorBuilder, serverProtocol, clientProtocol, + endpointCreator): + """ + Connect two protocols using endpoints and a new reactor instance. + + A new reactor will be created and run, with the client and server protocol + instances connected to each other using the given endpoint creator. The + protocols should run through some set of tests, then disconnect; when both + have disconnected the reactor will be stopped and the function will + return. + + @param reactorBuilder: A L{ReactorBuilder} instance. + + @param serverProtocol: A L{ConnectableProtocol} that will be the server. + + @param clientProtocol: A L{ConnectableProtocol} that will be the client. + + @param endpointCreator: An instance of L{EndpointCreator}. + + @return: The reactor run by this test. + """ + reactor = reactorBuilder.buildReactor() + serverProtocol._setAttributes(reactor, Deferred()) + clientProtocol._setAttributes(reactor, Deferred()) + serverFactory = _SingleProtocolFactory(serverProtocol) + clientFactory = _SingleProtocolFactory(clientProtocol) + + # Listen on a port: + serverEndpoint = endpointCreator.server(reactor) + d = serverEndpoint.listen(serverFactory) + + # Connect to the port: + def gotPort(p): + clientEndpoint = endpointCreator.client( + reactor, p.getHost()) + return clientEndpoint.connect(clientFactory) + d.addCallback(gotPort) + + # Stop reactor when both connections are lost: + def failed(result): + log.err(result, "Connection setup failed.") + disconnected = gatherResults([serverProtocol._done, clientProtocol._done]) + d.addCallback(lambda _: disconnected) + d.addErrback(failed) + d.addCallback(lambda _: needsRunningReactor(reactor, reactor.stop)) + + reactorBuilder.runReactor(reactor) + return reactor + + + class ReactorBuilder: """ L{TestCase} mixin which provides a reactor-creation API. This mixin @@ -57,19 +211,29 @@ # since no one really wants to use it on other platforms. _reactors.extend([ "twisted.internet.gtk2reactor.PortableGtkReactor", + "twisted.internet.gireactor.PortableGIReactor", + "twisted.internet.gtk3reactor.PortableGtk3Reactor", "twisted.internet.win32eventreactor.Win32Reactor", "twisted.internet.iocpreactor.reactor.IOCPReactor"]) else: _reactors.extend([ "twisted.internet.glib2reactor.Glib2Reactor", "twisted.internet.gtk2reactor.Gtk2Reactor", - "twisted.internet.kqreactor.KQueueReactor"]) + "twisted.internet.gireactor.GIReactor", + "twisted.internet.gtk3reactor.Gtk3Reactor"]) if platform.isMacOSX(): _reactors.append("twisted.internet.cfreactor.CFReactor") else: _reactors.extend([ "twisted.internet.pollreactor.PollReactor", "twisted.internet.epollreactor.EPollReactor"]) + if not platform.isLinux(): + # Presumably Linux is not going to start supporting kqueue, so + # skip even trying this configuration. + _reactors.extend([ + # Support KQueue on non-OS-X POSIX platforms for now. + "twisted.internet.kqreactor.KQueueReactor", + ]) reactorFactory = None originalHandler = None @@ -93,12 +257,25 @@ if self.originalHandler is not None: signal.signal(signal.SIGCHLD, self.originalHandler) if process is not None: + begin = time.time() while process.reapProcessHandlers: log.msg( "ReactorBuilder.tearDown reaping some processes %r" % ( process.reapProcessHandlers,)) process.reapAllProcesses() + # The process should exit on its own. However, if it + # doesn't, we're stuck in this loop forever. To avoid + # hanging the test suite, eventually give the process some + # help exiting and move on. + time.sleep(0.001) + if time.time() - begin > 60: + for pid in process.reapProcessHandlers: + os.kill(pid, signal.SIGKILL) + raise Exception( + "Timeout waiting for child processes to exit: %r" % ( + process.reapProcessHandlers,)) + def unbuildReactor(self, reactor): """ diff -Nru twisted-11.1.0/twisted/internet/test/test_abstract.py twisted-12.1.0/twisted/internet/test/test_abstract.py --- twisted-11.1.0/twisted/internet/test/test_abstract.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_abstract.py 2011-12-11 03:20:29.000000000 +0000 @@ -0,0 +1,56 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Tests for L{twisted.internet.abstract}, a collection of APIs for implementing +reactors. +""" + +from twisted.trial.unittest import TestCase + +from twisted.internet.abstract import isIPv6Address + +class IPv6AddressTests(TestCase): + """ + Tests for L{isIPv6Address}, a function for determining if a particular + string is an IPv6 address literal. + """ + def test_empty(self): + """ + The empty string is not an IPv6 address literal. + """ + self.assertFalse(isIPv6Address("")) + + + def test_colon(self): + """ + A single C{":"} is not an IPv6 address literal. + """ + self.assertFalse(isIPv6Address(":")) + + + def test_loopback(self): + """ + C{"::1"} is the IPv6 loopback address literal. + """ + self.assertTrue(isIPv6Address("::1")) + + + def test_scopeID(self): + """ + An otherwise valid IPv6 address literal may also include a C{"%"} + followed by an arbitrary scope identifier. + """ + self.assertTrue(isIPv6Address("fe80::1%eth0")) + self.assertTrue(isIPv6Address("fe80::2%1")) + self.assertTrue(isIPv6Address("fe80::3%en2")) + + + def test_invalidWithScopeID(self): + """ + An otherwise invalid IPv6 address literal is still invalid with a + trailing scope identifier. + """ + self.assertFalse(isIPv6Address("%eth0")) + self.assertFalse(isIPv6Address(":%eth0")) + self.assertFalse(isIPv6Address("hello%eth0")) diff -Nru twisted-11.1.0/twisted/internet/test/test_address.py twisted-12.1.0/twisted/internet/test/test_address.py --- twisted-11.1.0/twisted/internet/test/test_address.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_address.py 2012-04-24 21:19:37.000000000 +0000 @@ -89,7 +89,10 @@ when a different name is passed in """ self.assertFalse(self.buildAddress() == self.buildDifferentAddress()) + self.assertFalse(self.buildDifferentAddress() == self.buildAddress()) + self.assertTrue(self.buildAddress() != self.buildDifferentAddress()) + self.assertTrue(self.buildDifferentAddress() != self.buildAddress()) def assertDeprecations(self, testMethod, message): @@ -131,10 +134,12 @@ If a value is passed for the C{_bwHack} parameter to L{IPv4Address}, a deprecation warning is emitted. """ + # Construct this for warning side-effects, disregard the actual object. + IPv4Address("TCP", "127.0.0.3", 0, _bwHack="TCP") + message = ( "twisted.internet.address.IPv4Address._bwHack is deprecated " "since Twisted 11.0") - address = IPv4Address("TCP", "127.0.0.3", 0, _bwHack="TCP") return self.assertDeprecations(self.test_bwHackDeprecation, message) @@ -161,10 +166,12 @@ If a value is passed for the C{_bwHack} parameter to L{IPv4Address}, a deprecation warning is emitted. """ + # Construct this for warning side-effects, disregard the actual object. + IPv4Address("UDP", "127.0.0.3", 0, _bwHack="UDP") + message = ( "twisted.internet.address.IPv4Address._bwHack is deprecated " "since Twisted 11.0") - address = IPv4Address("UDP", "127.0.0.3", 0, _bwHack="UDP") return self.assertDeprecations(self.test_bwHackDeprecation, message) @@ -201,6 +208,8 @@ os.symlink(os.path.abspath(self._socketAddress), linkName) self.assertTrue( UNIXAddress(self._socketAddress) == UNIXAddress(linkName)) + self.assertTrue( + UNIXAddress(linkName) == UNIXAddress(self._socketAddress)) test_comparisonOfLinkedFiles.skip = symlinkSkip @@ -221,8 +230,63 @@ If a value is passed for the C{_bwHack} parameter to L{UNIXAddress}, a deprecation warning is emitted. """ + # Construct this for warning side-effects, disregard the actual object. + UNIXAddress(self.mktemp(), _bwHack='UNIX') + message = ( "twisted.internet.address.UNIXAddress._bwHack is deprecated " "since Twisted 11.0") - address = UNIXAddress(self.mktemp(), _bwHack='UNIX') return self.assertDeprecations(self.test_bwHackDeprecation, message) + + + +class EmptyUNIXAddressTestCase(unittest.TestCase, AddressTestCaseMixin): + """ + Tests for L{UNIXAddress} operations involving a C{None} address. + """ + addressArgSpec = (("name", "%r"),) + + def setUp(self): + self._socketAddress = self.mktemp() + + + def buildAddress(self): + """ + Create an arbitrary new L{UNIXAddress} instance. A new instance is + created for each call, but always for the same address. + """ + return UNIXAddress(self._socketAddress) + + + def buildDifferentAddress(self): + """ + Like L{buildAddress}, but with a fixed address of C{None}. + """ + return UNIXAddress(None) + + + def test_comparisonOfLinkedFiles(self): + """ + A UNIXAddress referring to a C{None} address does not compare equal to a + UNIXAddress referring to a symlink. + """ + linkName = self.mktemp() + self.fd = open(self._socketAddress, 'w') + os.symlink(os.path.abspath(self._socketAddress), linkName) + self.assertTrue( + UNIXAddress(self._socketAddress) != UNIXAddress(None)) + self.assertTrue( + UNIXAddress(None) != UNIXAddress(self._socketAddress)) + test_comparisonOfLinkedFiles.skip = symlinkSkip + + + def test_emptyHash(self): + """ + C{__hash__} can be used to get a hash of an address, even one referring + to C{None} rather than a real path. + """ + addr = self.buildDifferentAddress() + d = {addr: True} + self.assertTrue(d[self.buildDifferentAddress()]) + + diff -Nru twisted-11.1.0/twisted/internet/test/test_core.py twisted-12.1.0/twisted/internet/test/test_core.py --- twisted-11.1.0/twisted/internet/test/test_core.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_core.py 2012-05-12 13:55:41.000000000 +0000 @@ -134,15 +134,15 @@ reactor.addSystemEventTrigger("before", "startup", beforeStartup) reactor.addSystemEventTrigger("after", "startup", afterStartup) - sawPhase = [None] + sawPhase = [] def fakeSignal(signum, action): - sawPhase[0] = phase[0] + sawPhase.append(phase[0]) self.patch(signal, 'signal', fakeSignal) reactor.callWhenRunning(reactor.stop) self.assertEqual(phase[0], None) - self.assertEqual(sawPhase[0], None) + self.assertEqual(sawPhase, []) self.runReactor(reactor) - self.assertEqual(sawPhase[0], "before") + self.assertIn("before", sawPhase) self.assertEqual(phase[0], "after") diff -Nru twisted-11.1.0/twisted/internet/test/test_default.py twisted-12.1.0/twisted/internet/test/test_default.py --- twisted-11.1.0/twisted/internet/test/test_default.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_default.py 2012-05-08 00:03:40.000000000 +0000 @@ -5,17 +5,12 @@ Tests for L{twisted.internet.default}. """ -try: - from select import poll -except ImportError: - pollSkip = "select.poll() unavailable on this platform" -else: - pollSkip = None - +import select from twisted.trial.unittest import TestCase from twisted.python.runtime import Platform from twisted.internet.default import _getInstallFunction +unix = Platform('posix', 'other') linux = Platform('posix', 'linux2') windows = Platform('nt', 'win32') osx = Platform('posix', 'darwin') @@ -24,17 +19,44 @@ class PollReactorTests(TestCase): """ Tests for the cases of L{twisted.internet.default._getInstallFunction} - in which it picks the poll(2)-based reactor. + in which it picks the poll(2) or epoll(7)-based reactors. """ - skip = pollSkip + + def assertIsPoll(self, install): + """ + Assert the given function will install the poll() reactor, or select() + if poll() is unavailable. + """ + if hasattr(select, "poll"): + self.assertEqual( + install.__module__, 'twisted.internet.pollreactor') + else: + self.assertEqual( + install.__module__, 'twisted.internet.selectreactor') + + + def test_unix(self): + """ + L{_getInstallFunction} chooses the poll reactor on arbitrary Unix + platforms, falling back to select(2) if it is unavailable. + """ + install = _getInstallFunction(unix) + self.assertIsPoll(install) + def test_linux(self): """ - L{_getInstallFunction} chooses the poll reactor on Linux. + L{_getInstallFunction} chooses the epoll reactor on Linux, or poll if + epoll is unavailable. """ install = _getInstallFunction(linux) - self.assertEqual( - install.__module__, 'twisted.internet.pollreactor') + try: + from twisted.internet import epollreactor + except ImportError: + self.assertIsPoll(install) + else: + self.assertEqual( + install.__module__, 'twisted.internet.epollreactor') diff -Nru twisted-11.1.0/twisted/internet/test/test_endpoints.py twisted-12.1.0/twisted/internet/test/test_endpoints.py --- twisted-11.1.0/twisted/internet/test/test_endpoints.py 2011-10-11 11:43:33.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_endpoints.py 2012-04-26 13:46:20.000000000 +0000 @@ -7,15 +7,20 @@ """ from errno import EPERM +from socket import AF_INET, AF_INET6 from zope.interface import implements +from zope.interface.verify import verifyObject from twisted.trial import unittest -from twisted.internet import error, interfaces +from twisted.internet import error, interfaces, defer from twisted.internet import endpoints from twisted.internet.address import IPv4Address, UNIXAddress from twisted.internet.protocol import ClientFactory, Protocol -from twisted.test.proto_helpers import MemoryReactor, RaisingMemoryReactor +from twisted.test.proto_helpers import ( + MemoryReactor, RaisingMemoryReactor, StringTransport) from twisted.python.failure import Failure +from twisted.python.systemd import ListenFDs +from twisted.plugin import getPlugins from twisted import plugins from twisted.python.modules import getModule @@ -70,8 +75,14 @@ class TestHalfCloseableProtocol(TestProtocol): """ - A Protocol that implements L{IHalfCloseableProtocol} and records that - its C{readConnectionLost} and {writeConnectionLost} methods. + A Protocol that implements L{IHalfCloseableProtocol} and records whether its + C{readConnectionLost} and {writeConnectionLost} methods are called. + + @ivar readLost: A C{bool} indicating whether C{readConnectionLost} has been + called. + + @ivar writeLost: A C{bool} indicating whether C{writeConnectionLost} has + been called. """ implements(interfaces.IHalfCloseableProtocol) @@ -90,6 +101,26 @@ +class TestFileDescriptorReceiverProtocol(TestProtocol): + """ + A Protocol that implements L{IFileDescriptorReceiver} and records how its + C{fileDescriptorReceived} method is called. + + @ivar receivedDescriptors: A C{list} containing all of the file descriptors + passed to C{fileDescriptorReceived} calls made on this instance. + """ + implements(interfaces.IFileDescriptorReceiver) + + def connectionMade(self): + TestProtocol.connectionMade(self) + self.receivedDescriptors = [] + + + def fileDescriptorReceived(self, descriptor): + self.receivedDescriptors.append(descriptor) + + + class TestFactory(ClientFactory): """ Simple factory to be used both when connecting and listening. It contains @@ -111,7 +142,7 @@ C{doStart} method, allowing application-specific setup and logging. """ factory = ClientFactory() - wf = endpoints._WrappingFactory(factory, None) + wf = endpoints._WrappingFactory(factory) wf.doStart() self.assertEqual(1, factory.numPorts) @@ -123,7 +154,7 @@ """ factory = ClientFactory() factory.numPorts = 3 - wf = endpoints._WrappingFactory(factory, None) + wf = endpoints._WrappingFactory(factory) wf.doStop() self.assertEqual(2, factory.numPorts) @@ -143,7 +174,7 @@ raise ValueError("My protocol is poorly defined.") - wf = endpoints._WrappingFactory(BogusFactory(), None) + wf = endpoints._WrappingFactory(BogusFactory()) wf.buildProtocol(None) @@ -161,7 +192,7 @@ returned from the wrapped C{logPrefix} method is returned from L{_WrappingProtocol.logPrefix}. """ - wf = endpoints._WrappingFactory(TestFactory(), None) + wf = endpoints._WrappingFactory(TestFactory()) wp = wf.buildProtocol(None) self.assertEqual(wp.logPrefix(), "A Test Protocol") @@ -175,7 +206,7 @@ pass factory = TestFactory() factory.protocol = NoProtocol - wf = endpoints._WrappingFactory(factory, None) + wf = endpoints._WrappingFactory(factory) wp = wf.buildProtocol(None) self.assertEqual(wp.logPrefix(), "NoProtocol") @@ -185,7 +216,7 @@ The wrapped C{Protocol}'s C{dataReceived} will get called when our C{_WrappingProtocol}'s C{dataReceived} gets called. """ - wf = endpoints._WrappingFactory(TestFactory(), None) + wf = endpoints._WrappingFactory(TestFactory()) p = wf.buildProtocol(None) p.makeConnection(None) @@ -201,7 +232,7 @@ Our transport is properly hooked up to the wrappedProtocol when a connection is made. """ - wf = endpoints._WrappingFactory(TestFactory(), None) + wf = endpoints._WrappingFactory(TestFactory()) p = wf.buildProtocol(None) dummyTransport = object() @@ -219,7 +250,7 @@ L{_WrappingProtocol.connectionLost} is called. """ tf = TestFactory() - wf = endpoints._WrappingFactory(tf, None) + wf = endpoints._WrappingFactory(tf) p = wf.buildProtocol(None) p.connectionLost("fail") @@ -232,7 +263,7 @@ Calls to L{_WrappingFactory.clientConnectionLost} should errback the L{_WrappingFactory._onConnection} L{Deferred} """ - wf = endpoints._WrappingFactory(TestFactory(), None) + wf = endpoints._WrappingFactory(TestFactory()) expectedFailure = Failure(error.ConnectError(string="fail")) wf.clientConnectionFailed( @@ -248,10 +279,46 @@ self.assertEqual(errors, [expectedFailure]) + def test_wrappingProtocolFileDescriptorReceiver(self): + """ + Our L{_WrappingProtocol} should be an L{IFileDescriptorReceiver} if the + wrapped protocol is. + """ + connectedDeferred = None + applicationProtocol = TestFileDescriptorReceiverProtocol() + wrapper = endpoints._WrappingProtocol( + connectedDeferred, applicationProtocol) + self.assertTrue(interfaces.IFileDescriptorReceiver.providedBy(wrapper)) + self.assertTrue(verifyObject(interfaces.IFileDescriptorReceiver, wrapper)) + + + def test_wrappingProtocolNotFileDescriptorReceiver(self): + """ + Our L{_WrappingProtocol} does not provide L{IHalfCloseableProtocol} if + the wrapped protocol doesn't. + """ + tp = TestProtocol() + p = endpoints._WrappingProtocol(None, tp) + self.assertFalse(interfaces.IFileDescriptorReceiver.providedBy(p)) + + + def test_wrappedProtocolFileDescriptorReceived(self): + """ + L{_WrappingProtocol.fileDescriptorReceived} calls the wrapped protocol's + C{fileDescriptorReceived} method. + """ + wrappedProtocol = TestFileDescriptorReceiverProtocol() + wrapper = endpoints._WrappingProtocol( + defer.Deferred(), wrappedProtocol) + wrapper.makeConnection(StringTransport()) + wrapper.fileDescriptorReceived(42) + self.assertEqual(wrappedProtocol.receivedDescriptors, [42]) + + def test_wrappingProtocolHalfCloseable(self): """ - Our L{_WrappingProtocol} should be an L{IHalfCloseableProtocol} if - the C{wrappedProtocol} is. + Our L{_WrappingProtocol} should be an L{IHalfCloseableProtocol} if the + C{wrappedProtocol} is. """ cd = object() hcp = TestHalfCloseableProtocol() @@ -294,11 +361,10 @@ -class EndpointTestCaseMixin(object): +class ClientEndpointTestCaseMixin(object): """ - Generic test methods to be mixed into all endpoint test classes. + Generic test methods to be mixed into all client endpoint test classes. """ - def retrieveConnectedFactory(self, reactor): """ Retrieve a single factory that has connected using the given reactor. @@ -391,6 +457,11 @@ d.addErrback(checkFailure) d.cancel() + # When canceled, the connector will immediately notify its factory that + # the connection attempt has failed due to a UserError. + attemptFactory = self.retrieveConnectedFactory(mreactor) + attemptFactory.clientConnectionFailed(None, Failure(error.UserError())) + # This should be a feature of MemoryReactor: . self.assertEqual(len(receivedFailures), 1) @@ -400,6 +471,32 @@ self.assertEqual(failure.value.address, address) + def test_endpointConnectNonDefaultArgs(self): + """ + The endpoint should pass it's connectArgs parameter to the reactor's + listen methods. + """ + factory = object() + + mreactor = MemoryReactor() + + ep, expectedArgs, ignoredHost = self.createClientEndpoint( + mreactor, factory, + **self.connectArgs()) + + ep.connect(factory) + + expectedClients = self.expectedClients(mreactor) + + self.assertEqual(len(expectedClients), 1) + self.assertConnectArgs(expectedClients[0], expectedArgs) + + + +class ServerEndpointTestCaseMixin(object): + """ + Generic test methods to be mixed into all client endpoint test classes. + """ def test_endpointListenSuccess(self): """ An endpoint can listen and returns a deferred that gets called back @@ -449,27 +546,6 @@ self.assertEqual(receivedExceptions, [exception]) - def test_endpointConnectNonDefaultArgs(self): - """ - The endpoint should pass it's connectArgs parameter to the reactor's - listen methods. - """ - factory = object() - - mreactor = MemoryReactor() - - ep, expectedArgs, ignoredHost = self.createClientEndpoint( - mreactor, factory, - **self.connectArgs()) - - ep.connect(factory) - - expectedClients = self.expectedClients(mreactor) - - self.assertEqual(len(expectedClients), 1) - self.assertConnectArgs(expectedClients[0], expectedArgs) - - def test_endpointListenNonDefaultArgs(self): """ The endpoint should pass it's listenArgs parameter to the reactor's @@ -491,8 +567,15 @@ -class TCP4EndpointsTestCase(EndpointTestCaseMixin, - unittest.TestCase): +class EndpointTestCaseMixin(ServerEndpointTestCaseMixin, + ClientEndpointTestCaseMixin): + """ + Generic test methods to be mixed into all endpoint test classes. + """ + + + +class TCP4EndpointsTestCase(EndpointTestCaseMixin, unittest.TestCase): """ Tests for TCP Endpoints. """ @@ -1110,9 +1193,9 @@ def test_tcp(self): """ - When passed a TCP strports description, L{endpointClient} returns a - L{TCP4ClientEndpoint} instance initialized with the values from the - string. + When passed a TCP strports description, L{endpoints.clientFromString} + returns a L{TCP4ClientEndpoint} instance initialized with the values + from the string. """ reactor = object() client = endpoints.clientFromString( @@ -1126,6 +1209,53 @@ self.assertEqual(client._bindAddress, "10.0.0.2") + def test_tcpPositionalArgs(self): + """ + When passed a TCP strports description using positional arguments, + L{endpoints.clientFromString} returns a L{TCP4ClientEndpoint} instance + initialized with the values from the string. + """ + reactor = object() + client = endpoints.clientFromString( + reactor, + "tcp:example.com:1234:timeout=7:bindAddress=10.0.0.2") + self.assertIsInstance(client, endpoints.TCP4ClientEndpoint) + self.assertIdentical(client._reactor, reactor) + self.assertEqual(client._host, "example.com") + self.assertEqual(client._port, 1234) + self.assertEqual(client._timeout, 7) + self.assertEqual(client._bindAddress, "10.0.0.2") + + + def test_tcpHostPositionalArg(self): + """ + When passed a TCP strports description specifying host as a positional + argument, L{endpoints.clientFromString} returns a L{TCP4ClientEndpoint} + instance initialized with the values from the string. + """ + reactor = object() + + client = endpoints.clientFromString( + reactor, + "tcp:example.com:port=1234:timeout=7:bindAddress=10.0.0.2") + self.assertEqual(client._host, "example.com") + self.assertEqual(client._port, 1234) + + + def test_tcpPortPositionalArg(self): + """ + When passed a TCP strports description specifying port as a positional + argument, L{endpoints.clientFromString} returns a L{TCP4ClientEndpoint} + instance initialized with the values from the string. + """ + reactor = object() + client = endpoints.clientFromString( + reactor, + "tcp:host=example.com:1234:timeout=7:bindAddress=10.0.0.2") + self.assertEqual(client._host, "example.com") + self.assertEqual(client._port, 1234) + + def test_tcpDefaults(self): """ A TCP strports description may omit I{timeout} or I{bindAddress} to @@ -1141,9 +1271,9 @@ def test_unix(self): """ - When passed a UNIX strports description, L{endpointClient} returns a - L{UNIXClientEndpoint} instance initialized with the values from the - string. + When passed a UNIX strports description, L{endpoints.clientFromString} + returns a L{UNIXClientEndpoint} instance initialized with the values + from the string. """ reactor = object() client = endpoints.clientFromString( @@ -1166,6 +1296,23 @@ self.assertEqual(client._checkPID, False) + def test_unixPathPositionalArg(self): + """ + When passed a UNIX strports description specifying path as a positional + argument, L{endpoints.clientFromString} returns a L{UNIXClientEndpoint} + instance initialized with the values from the string. + """ + reactor = object() + client = endpoints.clientFromString( + reactor, + "unix:/var/foo/bar:lockfile=1:timeout=9") + self.assertIsInstance(client, endpoints.UNIXClientEndpoint) + self.assertIdentical(client._reactor, reactor) + self.assertEqual(client._path, "/var/foo/bar") + self.assertEqual(client._timeout, 9) + self.assertEqual(client._checkPID, True) + + def test_typeFromPlugin(self): """ L{endpoints.clientFromString} looks up plugins of type @@ -1242,6 +1389,28 @@ expectedCerts) + def test_sslPositionalArgs(self): + """ + When passed an SSL strports description, L{clientFromString} returns a + L{SSL4ClientEndpoint} instance initialized with the values from the + string. + """ + reactor = object() + client = endpoints.clientFromString( + reactor, + "ssl:example.net:4321:privateKey=%s:" + "certKey=%s:bindAddress=10.0.0.3:timeout=3:caCertsDir=%s" % + (escapedPEMPathName, + escapedPEMPathName, + escapedCAsPathName)) + self.assertIsInstance(client, endpoints.SSL4ClientEndpoint) + self.assertIdentical(client._reactor, reactor) + self.assertEqual(client._host, "example.net") + self.assertEqual(client._port, 4321) + self.assertEqual(client._timeout, 3) + self.assertEqual(client._bindAddress, "10.0.0.3") + + def test_unreadableCertificate(self): """ If a certificate in the directory is unreadable, @@ -1277,3 +1446,201 @@ self.assertEqual(certOptions.verify, False) ctx = certOptions.getContext() self.assertIsInstance(ctx, ContextType) + + + +class AdoptedStreamServerEndpointTestCase(ServerEndpointTestCaseMixin, + unittest.TestCase): + """ + Tests for adopted socket-based stream server endpoints. + """ + def _createStubbedAdoptedEndpoint(self, reactor, fileno, addressFamily): + """ + Create an L{AdoptedStreamServerEndpoint} which may safely be used with + an invalid file descriptor. This is convenient for a number of unit + tests. + """ + e = endpoints.AdoptedStreamServerEndpoint(reactor, fileno, addressFamily) + # Stub out some syscalls which would fail, given our invalid file + # descriptor. + e._close = lambda fd: None + e._setNonBlocking = lambda fd: None + return e + + + def createServerEndpoint(self, reactor, factory): + """ + Create a new L{AdoptedStreamServerEndpoint} for use by a test. + + @return: A three-tuple: + - The endpoint + - A tuple of the arguments expected to be passed to the underlying + reactor method + - An IAddress object which will match the result of + L{IListeningPort.getHost} on the port returned by the endpoint. + """ + fileno = 12 + addressFamily = AF_INET + endpoint = self._createStubbedAdoptedEndpoint( + reactor, fileno, addressFamily) + # Magic numbers come from the implementation of MemoryReactor + address = IPv4Address("TCP", "0.0.0.0", 1234) + return (endpoint, (fileno, addressFamily, factory), address) + + + def expectedServers(self, reactor): + """ + @return: The ports which were actually adopted by C{reactor} via calls + to its L{IReactorSocket.adoptStreamPort} implementation. + """ + return reactor.adoptedPorts + + + def listenArgs(self): + """ + @return: A C{dict} of additional keyword arguments to pass to the + C{createServerEndpoint}. + """ + return {} + + + def test_singleUse(self): + """ + L{AdoptedStreamServerEndpoint.listen} can only be used once. The file + descriptor given is closed after the first use, and subsequent calls to + C{listen} return a L{Deferred} that fails with L{AlreadyListened}. + """ + reactor = MemoryReactor() + endpoint = self._createStubbedAdoptedEndpoint(reactor, 13, AF_INET) + endpoint.listen(object()) + d = self.assertFailure(endpoint.listen(object()), error.AlreadyListened) + def listenFailed(ignored): + self.assertEqual(1, len(reactor.adoptedPorts)) + d.addCallback(listenFailed) + return d + + + def test_descriptionNonBlocking(self): + """ + L{AdoptedStreamServerEndpoint.listen} sets the file description given to + it to non-blocking. + """ + reactor = MemoryReactor() + endpoint = self._createStubbedAdoptedEndpoint(reactor, 13, AF_INET) + events = [] + def setNonBlocking(fileno): + events.append(("setNonBlocking", fileno)) + endpoint._setNonBlocking = setNonBlocking + + d = endpoint.listen(object()) + def listened(ignored): + self.assertEqual([("setNonBlocking", 13)], events) + d.addCallback(listened) + return d + + + def test_descriptorClosed(self): + """ + L{AdoptedStreamServerEndpoint.listen} closes its file descriptor after + adding it to the reactor with L{IReactorSocket.adoptStreamPort}. + """ + reactor = MemoryReactor() + endpoint = self._createStubbedAdoptedEndpoint(reactor, 13, AF_INET) + events = [] + def close(fileno): + events.append(("close", fileno, len(reactor.adoptedPorts))) + endpoint._close = close + + d = endpoint.listen(object()) + def listened(ignored): + self.assertEqual([("close", 13, 1)], events) + d.addCallback(listened) + return d + + + +class SystemdEndpointPluginTests(unittest.TestCase): + """ + Unit tests for the systemd stream server endpoint and endpoint string + description parser. + + @see: U{systemd} + """ + + _parserClass = endpoints._SystemdParser + + def test_pluginDiscovery(self): + """ + L{endpoints._SystemdParser} is found as a plugin for + L{interfaces.IStreamServerEndpointStringParser} interface. + """ + parsers = list(getPlugins( + interfaces.IStreamServerEndpointStringParser)) + for p in parsers: + if isinstance(p, self._parserClass): + break + else: + self.fail("Did not find systemd parser in %r" % (parsers,)) + + + def test_interface(self): + """ + L{endpoints._SystemdParser} instances provide + L{interfaces.IStreamServerEndpointStringParser}. + """ + parser = self._parserClass() + self.assertTrue(verifyObject( + interfaces.IStreamServerEndpointStringParser, parser)) + + + def _parseStreamServerTest(self, addressFamily, addressFamilyString): + """ + Helper for unit tests for L{endpoints._SystemdParser.parseStreamServer} + for different address families. + + Handling of the address family given will be verify. If there is a + problem a test-failing exception will be raised. + + @param addressFamily: An address family constant, like L{socket.AF_INET}. + + @param addressFamilyString: A string which should be recognized by the + parser as representing C{addressFamily}. + """ + reactor = object() + descriptors = [5, 6, 7, 8, 9] + index = 3 + + parser = self._parserClass() + parser._sddaemon = ListenFDs(descriptors) + + server = parser.parseStreamServer( + reactor, domain=addressFamilyString, index=str(index)) + self.assertIdentical(server.reactor, reactor) + self.assertEqual(server.addressFamily, addressFamily) + self.assertEqual(server.fileno, descriptors[index]) + + + def test_parseStreamServerINET(self): + """ + IPv4 can be specified using the string C{"INET"}. + """ + self._parseStreamServerTest(AF_INET, "INET") + + + def test_parseStreamServerINET6(self): + """ + IPv6 can be specified using the string C{"INET6"}. + """ + self._parseStreamServerTest(AF_INET6, "INET6") + + + def test_parseStreamServerUNIX(self): + """ + A UNIX domain socket can be specified using the string C{"UNIX"}. + """ + try: + from socket import AF_UNIX + except ImportError: + raise unittest.SkipTest("Platform lacks AF_UNIX support") + else: + self._parseStreamServerTest(AF_UNIX, "UNIX") diff -Nru twisted-11.1.0/twisted/internet/test/test_epollreactor.py twisted-12.1.0/twisted/internet/test/test_epollreactor.py --- twisted-11.1.0/twisted/internet/test/test_epollreactor.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_epollreactor.py 2012-05-04 18:49:18.000000000 +0000 @@ -0,0 +1,246 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Tests for L{twisted.internet.epollreactor}. +""" + +from twisted.trial.unittest import TestCase +try: + from twisted.internet.epollreactor import _ContinuousPolling +except ImportError: + _ContinuousPolling = None +from twisted.internet.task import Clock +from twisted.internet.error import ConnectionDone + + + +class Descriptor(object): + """ + Records reads and writes, as if it were a C{FileDescriptor}. + """ + + def __init__(self): + self.events = [] + + + def fileno(self): + return 1 + + + def doRead(self): + self.events.append("read") + + + def doWrite(self): + self.events.append("write") + + + def connectionLost(self, reason): + reason.trap(ConnectionDone) + self.events.append("lost") + + + +class ContinuousPollingTests(TestCase): + """ + L{_ContinuousPolling} can be used to read and write from C{FileDescriptor} + objects. + """ + + def test_addReader(self): + """ + Adding a reader when there was previously no reader starts up a + C{LoopingCall}. + """ + poller = _ContinuousPolling(Clock()) + self.assertEqual(poller._loop, None) + reader = object() + self.assertFalse(poller.isReading(reader)) + poller.addReader(reader) + self.assertNotEqual(poller._loop, None) + self.assertTrue(poller._loop.running) + self.assertIdentical(poller._loop.clock, poller._reactor) + self.assertTrue(poller.isReading(reader)) + + + def test_addWriter(self): + """ + Adding a writer when there was previously no writer starts up a + C{LoopingCall}. + """ + poller = _ContinuousPolling(Clock()) + self.assertEqual(poller._loop, None) + writer = object() + self.assertFalse(poller.isWriting(writer)) + poller.addWriter(writer) + self.assertNotEqual(poller._loop, None) + self.assertTrue(poller._loop.running) + self.assertIdentical(poller._loop.clock, poller._reactor) + self.assertTrue(poller.isWriting(writer)) + + + def test_removeReader(self): + """ + Removing a reader stops the C{LoopingCall}. + """ + poller = _ContinuousPolling(Clock()) + reader = object() + poller.addReader(reader) + poller.removeReader(reader) + self.assertEqual(poller._loop, None) + self.assertEqual(poller._reactor.getDelayedCalls(), []) + self.assertFalse(poller.isReading(reader)) + + + def test_removeWriter(self): + """ + Removing a writer stops the C{LoopingCall}. + """ + poller = _ContinuousPolling(Clock()) + writer = object() + poller.addWriter(writer) + poller.removeWriter(writer) + self.assertEqual(poller._loop, None) + self.assertEqual(poller._reactor.getDelayedCalls(), []) + self.assertFalse(poller.isWriting(writer)) + + + def test_removeUnknown(self): + """ + Removing unknown readers and writers silently does nothing. + """ + poller = _ContinuousPolling(Clock()) + poller.removeWriter(object()) + poller.removeReader(object()) + + + def test_multipleReadersAndWriters(self): + """ + Adding multiple readers and writers results in a single + C{LoopingCall}. + """ + poller = _ContinuousPolling(Clock()) + writer = object() + poller.addWriter(writer) + self.assertNotEqual(poller._loop, None) + poller.addWriter(object()) + self.assertNotEqual(poller._loop, None) + poller.addReader(object()) + self.assertNotEqual(poller._loop, None) + poller.addReader(object()) + poller.removeWriter(writer) + self.assertNotEqual(poller._loop, None) + self.assertTrue(poller._loop.running) + self.assertEqual(len(poller._reactor.getDelayedCalls()), 1) + + + def test_readerPolling(self): + """ + Adding a reader causes its C{doRead} to be called every 1 + milliseconds. + """ + reactor = Clock() + poller = _ContinuousPolling(reactor) + desc = Descriptor() + poller.addReader(desc) + self.assertEqual(desc.events, []) + reactor.advance(0.00001) + self.assertEqual(desc.events, ["read"]) + reactor.advance(0.00001) + self.assertEqual(desc.events, ["read", "read"]) + reactor.advance(0.00001) + self.assertEqual(desc.events, ["read", "read", "read"]) + + + def test_writerPolling(self): + """ + Adding a writer causes its C{doWrite} to be called every 1 + milliseconds. + """ + reactor = Clock() + poller = _ContinuousPolling(reactor) + desc = Descriptor() + poller.addWriter(desc) + self.assertEqual(desc.events, []) + reactor.advance(0.001) + self.assertEqual(desc.events, ["write"]) + reactor.advance(0.001) + self.assertEqual(desc.events, ["write", "write"]) + reactor.advance(0.001) + self.assertEqual(desc.events, ["write", "write", "write"]) + + + def test_connectionLostOnRead(self): + """ + If a C{doRead} returns a value indicating disconnection, + C{connectionLost} is called on it. + """ + reactor = Clock() + poller = _ContinuousPolling(reactor) + desc = Descriptor() + desc.doRead = lambda: ConnectionDone() + poller.addReader(desc) + self.assertEqual(desc.events, []) + reactor.advance(0.001) + self.assertEqual(desc.events, ["lost"]) + + + def test_connectionLostOnWrite(self): + """ + If a C{doWrite} returns a value indicating disconnection, + C{connectionLost} is called on it. + """ + reactor = Clock() + poller = _ContinuousPolling(reactor) + desc = Descriptor() + desc.doWrite = lambda: ConnectionDone() + poller.addWriter(desc) + self.assertEqual(desc.events, []) + reactor.advance(0.001) + self.assertEqual(desc.events, ["lost"]) + + + def test_removeAll(self): + """ + L{_ContinuousPolling.removeAll} removes all descriptors and returns + the readers and writers. + """ + poller = _ContinuousPolling(Clock()) + reader = object() + writer = object() + both = object() + poller.addReader(reader) + poller.addReader(both) + poller.addWriter(writer) + poller.addWriter(both) + removed = poller.removeAll() + self.assertEqual(poller.getReaders(), []) + self.assertEqual(poller.getWriters(), []) + self.assertEqual(len(removed), 3) + self.assertEqual(set(removed), set([reader, writer, both])) + + + def test_getReaders(self): + """ + L{_ContinuousPolling.getReaders} returns a list of the read + descriptors. + """ + poller = _ContinuousPolling(Clock()) + reader = object() + poller.addReader(reader) + self.assertIn(reader, poller.getReaders()) + + + def test_getWriters(self): + """ + L{_ContinuousPolling.getWriters} returns a list of the write + descriptors. + """ + poller = _ContinuousPolling(Clock()) + writer = object() + poller.addWriter(writer) + self.assertIn(writer, poller.getWriters()) + + if _ContinuousPolling is None: + skip = "epoll not supported in this environment." diff -Nru twisted-11.1.0/twisted/internet/test/test_fdset.py twisted-12.1.0/twisted/internet/test/test_fdset.py --- twisted-11.1.0/twisted/internet/test/test_fdset.py 2011-11-02 13:15:43.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_fdset.py 2012-01-23 22:55:41.000000000 +0000 @@ -286,7 +286,7 @@ reactor = self.buildReactor() name = reactor.__class__.__name__ - if name in ('EPollReactor', 'CFReactor'): + if name in ('EPollReactor', 'KQueueReactor', 'CFReactor'): # Closing a file descriptor immediately removes it from the epoll # set without generating a notification. That means epollreactor # will not call any methods on Victim after the close, so there's diff -Nru twisted-11.1.0/twisted/internet/test/test_filedescriptor.py twisted-12.1.0/twisted/internet/test/test_filedescriptor.py --- twisted-11.1.0/twisted/internet/test/test_filedescriptor.py 2011-10-28 15:35:02.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_filedescriptor.py 2012-03-15 20:18:28.000000000 +0000 @@ -5,14 +5,17 @@ Whitebox tests for L{twisted.internet.abstract.FileDescriptor}. """ +from zope.interface.verify import verifyClass + from twisted.internet.abstract import FileDescriptor +from twisted.internet.interfaces import IPushProducer from twisted.trial.unittest import TestCase -class FileDescriptorWriteSequenceTests(TestCase): +class FileDescriptorTests(TestCase): """ - Tests for L{FileDescriptor.writeSequence}. + Tests for L{FileDescriptor}. """ def test_writeWithUnicodeRaisesException(self): """ @@ -29,3 +32,10 @@ fileDescriptor = FileDescriptor() self.assertRaises( TypeError, fileDescriptor.writeSequence, ['foo', u'bar', 'baz']) + + + def test_implementInterfaceIPushProducer(self): + """ + L{FileDescriptor} should implement L{IPushProducer}. + """ + self.assertTrue(verifyClass(IPushProducer, FileDescriptor)) diff -Nru twisted-11.1.0/twisted/internet/test/test_glibbase.py twisted-12.1.0/twisted/internet/test/test_glibbase.py --- twisted-11.1.0/twisted/internet/test/test_glibbase.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_glibbase.py 2012-03-13 14:46:45.000000000 +0000 @@ -0,0 +1,66 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Tests for twisted.internet.glibbase. +""" + +import sys +from twisted.trial.unittest import TestCase +from twisted.internet._glibbase import ensureNotImported + + + +class EnsureNotImportedTests(TestCase): + """ + L{ensureNotImported} protects against unwanted past and future imports. + """ + + def test_ensureWhenNotImported(self): + """ + If the specified modules have never been imported, and import + prevention is requested, L{ensureNotImported} makes sure they will not + be imported in the future. + """ + modules = {} + self.patch(sys, "modules", modules) + ensureNotImported(["m1", "m2"], "A message.", + preventImports=["m1", "m2", "m3"]) + self.assertEquals(modules, {"m1": None, "m2": None, "m3": None}) + + + def test_ensureWhenNotImportedDontPrevent(self): + """ + If the specified modules have never been imported, and import + prevention is not requested, L{ensureNotImported} has no effect. + """ + modules = {} + self.patch(sys, "modules", modules) + ensureNotImported(["m1", "m2"], "A message.") + self.assertEquals(modules, {}) + + + def test_ensureWhenFailedToImport(self): + """ + If the specified modules have been set to C{None} in C{sys.modules}, + L{ensureNotImported} does not complain. + """ + modules = {"m2": None} + self.patch(sys, "modules", modules) + ensureNotImported(["m1", "m2"], "A message.", preventImports=["m1", "m2"]) + self.assertEquals(modules, {"m1": None, "m2": None}) + + + def test_ensureFailsWhenImported(self): + """ + If one of the specified modules has been previously imported, + L{ensureNotImported} raises an exception. + """ + module = object() + modules = {"m2": module} + self.patch(sys, "modules", modules) + e = self.assertRaises(ImportError, ensureNotImported, + ["m1", "m2"], "A message.", + preventImports=["m1", "m2"]) + self.assertEquals(modules, {"m2": module}) + self.assertEquals(e.args, ("A message.",)) diff -Nru twisted-11.1.0/twisted/internet/test/test_gtk3reactor.py twisted-12.1.0/twisted/internet/test/test_gtk3reactor.py --- twisted-11.1.0/twisted/internet/test/test_gtk3reactor.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_gtk3reactor.py 2012-05-12 22:44:21.000000000 +0000 @@ -0,0 +1,152 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +GI/GTK3 reactor tests. +""" + +try: + from twisted.internet import gireactor, gtk3reactor + from gi.repository import Gtk, Gio +except ImportError: + gireactor = None + +from twisted.internet.error import ReactorAlreadyRunning +from twisted.trial.unittest import TestCase, SkipTest +from twisted.internet.test.reactormixins import ReactorBuilder + + + +class GtkApplicationRegistration(ReactorBuilder, TestCase): + """ + GtkApplication and GApplication are supported by + L{twisted.internet.gtk3reactor} and L{twisted.internet.gireactor}. + + We inherit from L{ReactorBuilder} in order to use some of its + reactor-running infrastructure, but don't need its test-creation + functionality. + """ + if gireactor is None: + skip = "gtk3/gi not importable" + + + def runReactor(self, app, reactor): + """ + Register the app, run the reactor, make sure app was activated, and + that reactor was running, and that reactor can be stopped. + """ + if not hasattr(app, "quit"): + raise SkipTest("Version of PyGObject is too old.") + + result = [] + def stop(): + result.append("stopped") + reactor.stop() + def activate(widget): + result.append("activated") + reactor.callLater(0, stop) + app.connect('activate', activate) + + # We want reactor.stop() to *always* stop the event loop, even if + # someone has called hold() on the application and never done the + # corresponding release() -- for more details see + # http://developer.gnome.org/gio/unstable/GApplication.html. + app.hold() + + reactor.registerGApplication(app) + ReactorBuilder.runReactor(self, reactor) + self.assertEqual(result, ["activated", "stopped"]) + + + def test_gApplicationActivate(self): + """ + L{Gio.Application} instances can be registered with a gireactor. + """ + reactor = gireactor.GIReactor(useGtk=False) + self.addCleanup(self.unbuildReactor, reactor) + app = Gio.Application( + application_id='com.twistedmatrix.trial.gireactor', + flags=Gio.ApplicationFlags.FLAGS_NONE) + + self.runReactor(app, reactor) + + + def test_gtkApplicationActivate(self): + """ + L{Gtk.Application} instances can be registered with a gtk3reactor. + """ + reactor = gtk3reactor.Gtk3Reactor() + self.addCleanup(self.unbuildReactor, reactor) + app = Gtk.Application( + application_id='com.twistedmatrix.trial.gtk3reactor', + flags=Gio.ApplicationFlags.FLAGS_NONE) + + self.runReactor(app, reactor) + + + def test_portable(self): + """ + L{gireactor.PortableGIReactor} doesn't support application + registration at this time. + """ + reactor = gireactor.PortableGIReactor() + self.addCleanup(self.unbuildReactor, reactor) + app = Gio.Application( + application_id='com.twistedmatrix.trial.gireactor', + flags=Gio.ApplicationFlags.FLAGS_NONE) + self.assertRaises(NotImplementedError, + reactor.registerGApplication, app) + + + def test_noQuit(self): + """ + Older versions of PyGObject lack C{Application.quit}, and so won't + allow registration. + """ + reactor = gireactor.GIReactor(useGtk=False) + self.addCleanup(self.unbuildReactor, reactor) + # An app with no "quit" method: + app = object() + exc = self.assertRaises(RuntimeError, reactor.registerGApplication, app) + self.assertTrue(exc.args[0].startswith( + "Application registration is not")) + + + def test_cantRegisterAfterRun(self): + """ + It is not possible to register a C{Application} after the reactor has + already started. + """ + reactor = gireactor.GIReactor(useGtk=False) + self.addCleanup(self.unbuildReactor, reactor) + app = Gio.Application( + application_id='com.twistedmatrix.trial.gireactor', + flags=Gio.ApplicationFlags.FLAGS_NONE) + + def tryRegister(): + exc = self.assertRaises(ReactorAlreadyRunning, + reactor.registerGApplication, app) + self.assertEqual(exc.args[0], + "Can't register application after reactor was started.") + reactor.stop() + reactor.callLater(0, tryRegister) + ReactorBuilder.runReactor(self, reactor) + + + def test_cantRegisterTwice(self): + """ + It is not possible to register more than one C{Application}. + """ + reactor = gireactor.GIReactor(useGtk=False) + self.addCleanup(self.unbuildReactor, reactor) + app = Gio.Application( + application_id='com.twistedmatrix.trial.gireactor', + flags=Gio.ApplicationFlags.FLAGS_NONE) + reactor.registerGApplication(app) + app2 = Gio.Application( + application_id='com.twistedmatrix.trial.gireactor2', + flags=Gio.ApplicationFlags.FLAGS_NONE) + exc = self.assertRaises(RuntimeError, + reactor.registerGApplication, app2) + self.assertEqual(exc.args[0], + "Can't register more than one application instance.") diff -Nru twisted-11.1.0/twisted/internet/test/test_iocp.py twisted-12.1.0/twisted/internet/test/test_iocp.py --- twisted-11.1.0/twisted/internet/test/test_iocp.py 2011-11-02 00:53:45.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_iocp.py 2012-03-15 20:18:28.000000000 +0000 @@ -14,12 +14,14 @@ from twisted.trial import unittest from twisted.python.log import msg +from twisted.internet.interfaces import IPushProducer try: from twisted.internet.iocpreactor import iocpsupport as _iocp, tcp, udp from twisted.internet.iocpreactor.reactor import IOCPReactor, EVENTS_PER_LOOP, KEY_NORMAL from twisted.internet.iocpreactor.interfaces import IReadWriteHandle from twisted.internet.iocpreactor.const import SO_UPDATE_ACCEPT_CONTEXT + from twisted.internet.iocpreactor.abstract import FileHandle except ImportError: skip = 'This test only applies to IOCPReactor' @@ -113,8 +115,15 @@ """ Verify that IOCP socket-representing classes implement IReadWriteHandle """ - verifyClass(IReadWriteHandle, tcp.Connection) - verifyClass(IReadWriteHandle, udp.Port) + self.assertTrue(verifyClass(IReadWriteHandle, tcp.Connection)) + self.assertTrue(verifyClass(IReadWriteHandle, udp.Port)) + + + def test_fileHandleInterfaces(self): + """ + Verify that L{Filehandle} implements L{IPushProducer}. + """ + self.assertTrue(verifyClass(IPushProducer, FileHandle)) def test_maxEventsPerIteration(self): diff -Nru twisted-11.1.0/twisted/internet/test/test_newtls.py twisted-12.1.0/twisted/internet/test/test_newtls.py --- twisted-11.1.0/twisted/internet/test/test_newtls.py 2011-11-02 12:47:09.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_newtls.py 2012-04-12 03:14:29.000000000 +0000 @@ -6,7 +6,14 @@ """ from twisted.trial import unittest +from twisted.internet.test.reactormixins import ReactorBuilder, runProtocolsWithReactor +from twisted.internet.test.reactormixins import ConnectableProtocol +from twisted.internet.test.test_tls import SSLCreator, TLSMixin +from twisted.internet.test.test_tls import StartTLSClientCreator +from twisted.internet.test.test_tls import ContextGeneratingMixin +from twisted.internet.test.test_tcp import TCPCreator try: + from twisted.protocols import tls from twisted.internet import _newtls except ImportError: _newtls = None @@ -43,3 +50,145 @@ notDefault = object() bypass.loseConnection(notDefault) self.assertEqual(result, [default, notDefault]) + + + +class FakeProducer(object): + """ + A producer that does nothing. + """ + + def pauseProducing(self): + pass + + + def resumeProducing(self): + pass + + + def stopProducing(self): + pass + + + +class ProducerProtocol(ConnectableProtocol): + """ + Register a producer, unregister it, and verify the producer hooks up to + innards of C{TLSMemoryBIOProtocol}. + """ + + def __init__(self, producer, result): + self.producer = producer + self.result = result + + + def connectionMade(self): + if not isinstance(self.transport.protocol, + tls.TLSMemoryBIOProtocol): + # Either the test or the code have a bug... + raise RuntimeError("TLSMemoryBIOProtocol not hooked up.") + + self.transport.registerProducer(self.producer, True) + # The producer was registered with the TLSMemoryBIOProtocol: + self.result.append(self.transport.protocol._producer._producer) + + self.transport.unregisterProducer() + # The producer was unregistered from the TLSMemoryBIOProtocol: + self.result.append(self.transport.protocol._producer) + self.transport.loseConnection() + + + +class ProducerTestsMixin(ReactorBuilder, TLSMixin, ContextGeneratingMixin): + """ + Test the new TLS code integrates C{TLSMemoryBIOProtocol} correctly. + """ + + if not _newtls: + skip = "Could not import twisted.internet._newtls" + + def test_producerSSLFromStart(self): + """ + C{registerProducer} and C{unregisterProducer} on TLS transports + created as SSL from the get go are passed to the + C{TLSMemoryBIOProtocol}, not the underlying transport directly. + """ + result = [] + producer = FakeProducer() + + runProtocolsWithReactor(self, ConnectableProtocol(), + ProducerProtocol(producer, result), + SSLCreator()) + self.assertEqual(result, [producer, None]) + + + def test_producerAfterStartTLS(self): + """ + C{registerProducer} and C{unregisterProducer} on TLS transports + created by C{startTLS} are passed to the C{TLSMemoryBIOProtocol}, not + the underlying transport directly. + """ + result = [] + producer = FakeProducer() + + runProtocolsWithReactor(self, ConnectableProtocol(), + ProducerProtocol(producer, result), + StartTLSClientCreator()) + self.assertEqual(result, [producer, None]) + + + def startTLSAfterRegisterProducer(self, streaming): + """ + When a producer is registered, and then startTLS is called, + the producer is re-registered with the C{TLSMemoryBIOProtocol}. + """ + clientContext = self.getClientContext() + serverContext = self.getServerContext() + result = [] + producer = FakeProducer() + + class RegisterTLSProtocol(ConnectableProtocol): + def connectionMade(self): + self.transport.registerProducer(producer, streaming) + self.transport.startTLS(serverContext) + # Store TLSMemoryBIOProtocol and underlying transport producer + # status: + if streaming: + # _ProducerMembrane -> producer: + result.append(self.transport.protocol._producer._producer) + result.append(self.transport.producer._producer) + else: + # _ProducerMembrane -> _PullToPush -> producer: + result.append( + self.transport.protocol._producer._producer._producer) + result.append(self.transport.producer._producer._producer) + self.transport.unregisterProducer() + self.transport.loseConnection() + + class StartTLSProtocol(ConnectableProtocol): + def connectionMade(self): + self.transport.startTLS(clientContext) + + runProtocolsWithReactor(self, RegisterTLSProtocol(), + StartTLSProtocol(), TCPCreator()) + self.assertEqual(result, [producer, producer]) + + + def test_startTLSAfterRegisterProducerStreaming(self): + """ + When a streaming producer is registered, and then startTLS is called, + the producer is re-registered with the C{TLSMemoryBIOProtocol}. + """ + self.startTLSAfterRegisterProducer(True) + + + def test_startTLSAfterRegisterProducerNonStreaming(self): + """ + When a non-streaming producer is registered, and then startTLS is + called, the producer is re-registered with the + C{TLSMemoryBIOProtocol}. + """ + self.startTLSAfterRegisterProducer(False) + + +globals().update(ProducerTestsMixin.makeTestCaseClasses()) diff -Nru twisted-11.1.0/twisted/internet/test/test_pollingfile.py twisted-12.1.0/twisted/internet/test/test_pollingfile.py --- twisted-11.1.0/twisted/internet/test/test_pollingfile.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_pollingfile.py 2012-04-14 00:21:00.000000000 +0000 @@ -20,20 +20,27 @@ Tests for L{_pollingfile._PollableWritePipe}. """ - def test_checkWorkUnicode(self): + def test_writeUnicode(self): """ - When one tries to pass unicode to L{_pollingfile._PollableWritePipe}, a - C{TypeError} is raised instead of passing the data to C{WriteFile} - call which is going to mangle it. + L{_pollingfile._PollableWritePipe.write} raises a C{TypeError} if an + attempt is made to append unicode data to the output buffer. """ p = _pollingfile._PollableWritePipe(1, lambda: None) - p.write("test") - p.checkWork() + self.assertRaises(TypeError, p.write, u"test") + + + def test_writeSequenceUnicode(self): + """ + L{_pollingfile._PollableWritePipe.writeSequence} raises a C{TypeError} + if unicode data is part of the data sequence to be appended to the + output buffer. + """ + p = _pollingfile._PollableWritePipe(1, lambda: None) + self.assertRaises(TypeError, p.writeSequence, [u"test"]) + self.assertRaises(TypeError, p.writeSequence, (u"test", )) - p.write(u"test") - self.assertRaises(TypeError, p.checkWork) if _pollingfile is None: - TestPollableWritePipe.skip = "_pollingfile is only avalable under Windows." + TestPollableWritePipe.skip = "Test will run only on Windows." diff -Nru twisted-11.1.0/twisted/internet/test/test_process.py twisted-12.1.0/twisted/internet/test/test_process.py --- twisted-11.1.0/twisted/internet/test/test_process.py 2011-10-02 02:01:47.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_process.py 2012-05-12 13:55:41.000000000 +0000 @@ -384,6 +384,33 @@ self.runReactor(reactor) + def test_timeleyProcessExited(self): + """ + If a spawned process exits, C{processExited} will be called in a + timely manner. + """ + reactor = self.buildReactor() + + class ExitingProtocol(ProcessProtocol): + exited = False + + def processExited(protoSelf, reason): + protoSelf.exited = True + reactor.stop() + self.assertEqual(reason.value.exitCode, 0) + + protocol = ExitingProtocol() + reactor.callWhenRunning( + reactor.spawnProcess, protocol, sys.executable, + [sys.executable, "-c", "raise SystemExit(0)"], + usePTY=self.usePTY) + + # This will timeout if processExited isn't called: + self.runReactor(reactor, timeout=30) + self.assertEqual(protocol.exited, True) + + + class ProcessTestsBuilder(ProcessTestsBuilderBase): """ Builder defining tests relating to L{IReactorProcess} for child processes diff -Nru twisted-11.1.0/twisted/internet/test/test_socket.py twisted-12.1.0/twisted/internet/test/test_socket.py --- twisted-11.1.0/twisted/internet/test/test_socket.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_socket.py 2012-04-18 11:46:14.000000000 +0000 @@ -0,0 +1,96 @@ + +import errno, socket + +from twisted.python.log import err +from twisted.internet.interfaces import IReactorSocket +from twisted.internet.error import ( + UnsupportedAddressFamily, UnsupportedSocketType) +from twisted.internet.protocol import ServerFactory +from twisted.internet.test.reactormixins import ( + ReactorBuilder, needsRunningReactor) + + +class AdoptStreamPortErrorsTestsBuilder(ReactorBuilder): + """ + Builder for testing L{IReactorSocket} implementations. + + Generally only tests for failure cases are found here. Success cases for + this interface are tested elsewhere. For example, the success case for + I{AF_INET} is in L{twisted.internet.test.test_tcp}, since that case should + behave exactly the same as L{IReactorTCP.listenTCP}. + """ + requiredInterfaces = [IReactorSocket] + + def test_invalidDescriptor(self): + """ + An implementation of L{IReactorSocket.adoptStreamPort} raises + L{socket.error} if passed an integer which is not associated with a + socket. + """ + reactor = self.buildReactor() + + probe = socket.socket() + fileno = probe.fileno() + probe.close() + + exc = self.assertRaises( + socket.error, + reactor.adoptStreamPort, fileno, socket.AF_INET, ServerFactory()) + self.assertEqual(exc.args[0], errno.EBADF) + + + def test_invalidAddressFamily(self): + """ + An implementation of L{IReactorSocket.adoptStreamPort} raises + L{UnsupportedAddressFamily} if passed an address family it does not + support. + """ + reactor = self.buildReactor() + + port = socket.socket() + port.listen(1) + self.addCleanup(port.close) + + arbitrary = 2 ** 16 + 7 + + self.assertRaises( + UnsupportedAddressFamily, + reactor.adoptStreamPort, port.fileno(), arbitrary, ServerFactory()) + + + def test_stopOnlyCloses(self): + """ + When the L{IListeningPort} returned by L{IReactorSocket.adoptStreamPort} + is stopped using C{stopListening}, the underlying socket is closed but + not shutdown. This allows another process which still has a reference + to it to continue accepting connections over it. + """ + reactor = self.buildReactor() + + portSocket = socket.socket() + self.addCleanup(portSocket.close) + + portSocket.listen(1) + portSocket.setblocking(False) + + # The file descriptor is duplicated by adoptStreamPort + port = reactor.adoptStreamPort( + portSocket.fileno(), portSocket.family, ServerFactory()) + d = port.stopListening() + def stopped(ignored): + # Should still be possible to accept a connection on portSocket. If + # it was shutdown, the exception would be EINVAL instead. + exc = self.assertRaises(socket.error, portSocket.accept) + self.assertEqual(exc.args[0], errno.EAGAIN) + d.addCallback(stopped) + d.addErrback(err, "Failed to accept on original port.") + + needsRunningReactor( + reactor, + lambda: d.addCallback(lambda ignored: reactor.stop())) + + reactor.run() + + + +globals().update(AdoptStreamPortErrorsTestsBuilder.makeTestCaseClasses()) diff -Nru twisted-11.1.0/twisted/internet/test/test_stdio.py twisted-12.1.0/twisted/internet/test/test_stdio.py --- twisted-11.1.0/twisted/internet/test/test_stdio.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_stdio.py 2012-05-04 18:49:18.000000000 +0000 @@ -0,0 +1,195 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Tests for L{twisted.internet.stdio}. +""" + +from twisted.python.runtime import platform +from twisted.internet.test.reactormixins import ReactorBuilder +from twisted.internet.protocol import Protocol +if not platform.isWindows(): + from twisted.internet._posixstdio import StandardIO + + + +class StdioFilesTests(ReactorBuilder): + """ + L{StandardIO} supports reading and writing to filesystem files. + """ + + def setUp(self): + path = self.mktemp() + file(path, "w").close() + self.extraFile = file(path, "r+") + + + def test_addReader(self): + """ + Adding a filesystem file reader to a reactor will make sure it is + polled. + """ + reactor = self.buildReactor() + + class DataProtocol(Protocol): + data = "" + def dataReceived(self, data): + self.data += data + # It'd be better to stop reactor on connectionLost, but that + # fails on FreeBSD, probably due to + # http://bugs.python.org/issue9591: + if self.data == "hello!": + reactor.stop() + + path = self.mktemp() + f = file(path, "w") + f.write("hello!") + f.close() + f = file(path, "r") + + # Read bytes from a file, deliver them to a protocol instance: + protocol = DataProtocol() + StandardIO(protocol, stdin=f.fileno(), + stdout=self.extraFile.fileno(), + reactor=reactor) + + self.runReactor(reactor) + self.assertEqual(protocol.data, "hello!") + + + def test_addWriter(self): + """ + Adding a filesystem file writer to a reactor will make sure it is + polled. + """ + reactor = self.buildReactor() + + class DisconnectProtocol(Protocol): + def connectionLost(self, reason): + reactor.stop() + + path = self.mktemp() + f = file(path, "w") + + # Write bytes to a transport, hopefully have them written to a file: + protocol = DisconnectProtocol() + StandardIO(protocol, stdout=f.fileno(), + stdin=self.extraFile.fileno(), reactor=reactor) + protocol.transport.write("hello") + protocol.transport.write(", world") + protocol.transport.loseConnection() + + self.runReactor(reactor) + f.close() + f = file(path, "r") + self.assertEqual(f.read(), "hello, world") + f.close() + + + def test_removeReader(self): + """ + Removing a filesystem file reader from a reactor will make sure it is + no longer polled. + """ + reactor = self.buildReactor() + self.addCleanup(self.unbuildReactor, reactor) + + path = self.mktemp() + file(path, "w").close() + # Cleanup might fail if file is GCed too soon: + self.f = f = file(path, "r") + + # Have the reader added: + stdio = StandardIO(Protocol(), stdin=f.fileno(), + stdout=self.extraFile.fileno(), + reactor=reactor) + self.assertIn(stdio._reader, reactor.getReaders()) + stdio._reader.stopReading() + self.assertNotIn(stdio._reader, reactor.getReaders()) + + + def test_removeWriter(self): + """ + Removing a filesystem file writer from a reactor will make sure it is + no longer polled. + """ + reactor = self.buildReactor() + self.addCleanup(self.unbuildReactor, reactor) + + # Cleanup might fail if file is GCed too soon: + self.f = f = file(self.mktemp(), "w") + + # Have the reader added: + protocol = Protocol() + stdio = StandardIO(protocol, stdout=f.fileno(), + stdin=self.extraFile.fileno(), + reactor=reactor) + protocol.transport.write("hello") + self.assertIn(stdio._writer, reactor.getWriters()) + stdio._writer.stopWriting() + self.assertNotIn(stdio._writer, reactor.getWriters()) + + + def test_removeAll(self): + """ + Calling C{removeAll} on a reactor includes descriptors that are + filesystem files. + """ + reactor = self.buildReactor() + self.addCleanup(self.unbuildReactor, reactor) + + path = self.mktemp() + file(path, "w").close() + # Cleanup might fail if file is GCed too soon: + self.f = f = file(path, "r") + + # Have the reader added: + stdio = StandardIO(Protocol(), stdin=f.fileno(), + stdout=self.extraFile.fileno(), reactor=reactor) + # And then removed: + removed = reactor.removeAll() + self.assertIn(stdio._reader, removed) + self.assertNotIn(stdio._reader, reactor.getReaders()) + + + def test_getReaders(self): + """ + C{reactor.getReaders} includes descriptors that are filesystem files. + """ + reactor = self.buildReactor() + self.addCleanup(self.unbuildReactor, reactor) + + path = self.mktemp() + file(path, "w").close() + # Cleanup might fail if file is GCed too soon: + self.f = f = file(path, "r") + + # Have the reader added: + stdio = StandardIO(Protocol(), stdin=f.fileno(), + stdout=self.extraFile.fileno(), reactor=reactor) + self.assertIn(stdio._reader, reactor.getReaders()) + + + def test_getWriters(self): + """ + C{reactor.getWriters} includes descriptors that are filesystem files. + """ + reactor = self.buildReactor() + self.addCleanup(self.unbuildReactor, reactor) + + # Cleanup might fail if file is GCed too soon: + self.f = f = file(self.mktemp(), "w") + + # Have the reader added: + stdio = StandardIO(Protocol(), stdout=f.fileno(), + stdin=self.extraFile.fileno(), reactor=reactor) + self.assertNotIn(stdio._writer, reactor.getWriters()) + stdio._writer.startWriting() + self.assertIn(stdio._writer, reactor.getWriters()) + + if platform.isWindows(): + skip = ("StandardIO does not accept stdout as an argument to Windows. " + "Testing redirection to a file is therefore harder.") + + +globals().update(StdioFilesTests.makeTestCaseClasses()) diff -Nru twisted-11.1.0/twisted/internet/test/test_tcp.py twisted-12.1.0/twisted/internet/test/test_tcp.py --- twisted-11.1.0/twisted/internet/test/test_tcp.py 2011-11-02 13:15:43.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_tcp.py 2012-04-12 03:14:29.000000000 +0000 @@ -2,7 +2,8 @@ # See LICENSE for details. """ -Tests for implementations of L{IReactorTCP}. +Tests for implementations of L{IReactorTCP} and the TCP parts of +L{IReactorSocket}. """ __metaclass__ = type @@ -10,122 +11,89 @@ import socket, errno from zope.interface import implements -from zope.interface.verify import verifyObject from twisted.python.runtime import platform from twisted.python.failure import Failure from twisted.python import log from twisted.trial.unittest import SkipTest, TestCase -from twisted.internet.test.reactormixins import ReactorBuilder -from twisted.internet.error import DNSLookupError, ConnectionLost +from twisted.internet.test.reactormixins import ReactorBuilder, EndpointCreator +from twisted.internet.test.reactormixins import ConnectableProtocol +from twisted.internet.test.reactormixins import runProtocolsWithReactor +from twisted.internet.error import ConnectionLost, UserError, ConnectionRefusedError from twisted.internet.error import ConnectionDone, ConnectionAborted from twisted.internet.interfaces import ( - ILoggingContext, IResolverSimple, IConnector, IReactorFDSet) -from twisted.internet.address import IPv4Address + ILoggingContext, IConnector, IReactorFDSet, IReactorSocket) +from twisted.internet.address import IPv4Address, IPv6Address from twisted.internet.defer import ( - Deferred, DeferredList, succeed, fail, maybeDeferred, gatherResults) -from twisted.internet.endpoints import TCP4ServerEndpoint, TCP4ClientEndpoint + Deferred, DeferredList, maybeDeferred, gatherResults) +from twisted.internet.endpoints import ( + TCP4ServerEndpoint, TCP4ClientEndpoint) from twisted.internet.protocol import ServerFactory, ClientFactory, Protocol -from twisted.internet.interfaces import IPushProducer, IPullProducer -from twisted.internet.protocol import ClientCreator -from twisted.internet.tcp import Connection, Server +from twisted.internet.interfaces import ( + IPushProducer, IPullProducer, IHalfCloseableProtocol) +from twisted.internet.tcp import Connection, Server, _resolveIPv6 from twisted.internet.test.connectionmixins import ( - LogObserverMixin, ConnectionTestsMixin, serverFactoryFor) + LogObserverMixin, ConnectionTestsMixin, TCPClientTestsMixin, findFreePort) from twisted.internet.test.test_core import ObjectModelIntegrationMixin from twisted.test.test_tcp import MyClientFactory, MyServerFactory -from twisted.test.test_tcp import ClosingProtocol +from twisted.test.test_tcp import ClosingFactory, ClientStartStopFactory try: - from twisted.internet.ssl import ClientContextFactory + from OpenSSL import SSL except ImportError: - ClientContextFactory = None + useSSL = False +else: + from twisted.internet.ssl import ClientContextFactory + useSSL = True -def findFreePort(interface='127.0.0.1', type=socket.SOCK_STREAM): - """ - Ask the platform to allocate a free port on the specified interface, - then release the socket and return the address which was allocated. +try: + socket.socket(socket.AF_INET6, socket.SOCK_STREAM).close() +except socket.error, e: + ipv6Skip = str(e) +else: + ipv6Skip = None - @param interface: The local address to try to bind the port on. - @type interface: C{str} - @param type: The socket type which will use the resulting port. - @return: A two-tuple of address and port, like that returned by - L{socket.getsockname}. - """ - family = socket.AF_INET - probe = socket.socket(family, type) +if platform.isWindows(): + from twisted.internet.test import _win32ifaces + getLinkLocalIPv6Addresses = _win32ifaces.win32GetLinkLocalIPv6Addresses +else: try: - probe.bind((interface, 0)) - return probe.getsockname() - finally: - probe.close() + from twisted.internet.test import _posixifaces + except ImportError: + getLinkLocalIPv6Addresses = lambda: [] + else: + getLinkLocalIPv6Addresses = _posixifaces.posixGetLinkLocalIPv6Addresses -class Stop(ClientFactory): - """ - A client factory which stops a reactor when a connection attempt fails. +def getLinkLocalIPv6Address(): """ - def __init__(self, reactor): - self.reactor = reactor + Find and return a configured link local IPv6 address including a scope + identifier using the % separation syntax. If the system has no link local + IPv6 addresses, raise L{SkipTest} instead. + @raise SkipTest: if no link local address can be found or if the + C{netifaces} module is not available. - def clientConnectionFailed(self, connector, reason): - self.reactor.stop() - - - -class FakeResolver: - """ - A resolver implementation based on a C{dict} mapping names to addresses. + @return: a C{str} giving the address """ - implements(IResolverSimple) - - def __init__(self, names): - self.names = names - - - def getHostByName(self, name, timeout): - try: - return succeed(self.names[name]) - except KeyError: - return fail(DNSLookupError("FakeResolver couldn't find " + name)) + addresses = getLinkLocalIPv6Addresses() + if addresses: + return addresses[0] + raise SkipTest("Link local IPv6 address unavailable") -class _SimplePullProducer(object): - """ - A pull producer which writes one byte whenever it is resumed. For use by - L{test_unregisterProducerAfterDisconnect}. - """ - def __init__(self, consumer): - self.consumer = consumer - - - def stopProducing(self): - pass - - - def resumeProducing(self): - log.msg("Producer.resumeProducing") - self.consumer.write('x') - - - -def _getWriters(reactor): - """ - Like L{IReactorFDSet.getWriters}, but with support for IOCP reactor as well. - """ - if IReactorFDSet.providedBy(reactor): - return reactor.getWriters() - elif 'IOCP' in reactor.__class__.__name__: - return reactor.handles +def connect(client, (host, port)): + if '%' in host or ':' in host: + address = socket.getaddrinfo(host, port)[0][4] else: - # Cannot tell what is going on. - raise Exception("Cannot find writers on %r" % (reactor,)) + address = (host, port) + client.connect(address) @@ -346,228 +314,252 @@ conn._tlsClientDefault = True conn.startTLS(ClientContextFactory(), True) self.assertTrue(conn.TLS) - if ClientContextFactory is None: + if not useSSL: test_tlsAfterStartTLS.skip = "No SSL support available" -class TCPClientTestsBuilder(ReactorBuilder, ConnectionTestsMixin): + +class TCPCreator(EndpointCreator): """ - Builder defining tests relating to L{IReactorTCP.connectTCP}. + Create IPv4 TCP endpoints for L{runProtocolsWithReactor}-based tests. """ - def serverEndpoint(self, reactor): + + interface = "127.0.0.1" + + def server(self, reactor): """ - Create a L{TCP4ServerEndpoint} listening on localhost on a - TCP/IP-selected port. + Create a server-side TCP endpoint. """ - return TCP4ServerEndpoint(reactor, 0, interface='127.0.0.1') + return TCP4ServerEndpoint(reactor, 0, interface=self.interface) - def clientEndpoint(self, reactor, serverAddress): + def client(self, reactor, serverAddress): """ - Create a L{TCP4ClientEndpoint} which will connect to localhost - on the port given by C{serverAddress}. + Create a client end point that will connect to the given address. @type serverAddress: L{IPv4Address} """ - return TCP4ClientEndpoint( - reactor, '127.0.0.1', serverAddress.port) + return TCP4ClientEndpoint(reactor, self.interface, serverAddress.port) + + + +class TCP6Creator(TCPCreator): + """ + Create IPv6 TCP endpoints for + C{ReactorBuilder.runProtocolsWithReactor}-based tests. + + The endpoint types in question here are still the TCP4 variety, since + these simply pass through IPv6 address literals to the reactor, and we are + only testing address literals, not name resolution (as name resolution has + not yet been implemented). See http://twistedmatrix.com/trac/ticket/4470 + for more specific information about new endpoint classes. The naming is + slightly misleading, but presumably if you're passing an IPv6 literal, you + know what you're asking for. + """ + def __init__(self): + self.interface = getLinkLocalIPv6Address() + - def test_interface(self): +class TCPClientTestsBase(ReactorBuilder, ConnectionTestsMixin, + TCPClientTestsMixin): + """ + Base class for builders defining tests related to L{IReactorTCP.connectTCP}. + """ + port = 1234 + + @property + def interface(self): """ - L{IReactorTCP.connectTCP} returns an object providing L{IConnector}. + Return the interface attribute from the endpoints object. """ - reactor = self.buildReactor() - connector = reactor.connectTCP("127.0.0.1", 1234, ClientFactory()) - self.assertTrue(verifyObject(IConnector, connector)) + return self.endpoints.interface - def test_clientConnectionFailedStopsReactor(self): - """ - The reactor can be stopped by a client factory's - C{clientConnectionFailed} method. + +class TCP4ClientTestsBuilder(TCPClientTestsBase): + """ + Builder configured with IPv4 parameters for tests related to L{IReactorTCP.connectTCP}. + """ + fakeDomainName = 'some-fake.domain.example.com' + family = socket.AF_INET + addressClass = IPv4Address + + endpoints = TCPCreator() + + + +class TCP6ClientTestsBuilder(TCPClientTestsBase): + """ + Builder configured with IPv6 parameters for tests related to L{IReactorTCP.connectTCP}. + """ + + if ipv6Skip: + skip = "Platform does not support ipv6" + + family = socket.AF_INET6 + addressClass = IPv6Address + + + def setUp(self): + # Only create this object here, so that it won't be created if tests + # are being skipped: + self.endpoints = TCP6Creator() + # This is used by test_addresses to test the distinction between the + # resolved name and the name on the socket itself. All the same + # invariants should hold, but giving back an IPv6 address from a + # resolver is not something the reactor can handle, so instead, we make + # it so that the connect call for the IPv6 address test simply uses an + # address literal. + self.fakeDomainName = self.endpoints.interface + + + +class TCPConnectorTestsBuilder(ReactorBuilder): + + def test_connectorIdentity(self): + """ + L{IReactorTCP.connectTCP} returns an object which provides + L{IConnector}. The destination of the connector is the address which + was passed to C{connectTCP}. The same connector object is passed to + the factory's C{startedConnecting} method as to the factory's + C{clientConnectionLost} method. """ - host, port = findFreePort() + serverFactory = ClosingFactory() reactor = self.buildReactor() - reactor.connectTCP(host, port, Stop(reactor)) + tcpPort = reactor.listenTCP(0, serverFactory, interface=self.interface) + serverFactory.port = tcpPort + portNumber = tcpPort.getHost().port + + seenConnectors = [] + seenFailures = [] + + clientFactory = ClientStartStopFactory() + clientFactory.clientConnectionLost = ( + lambda connector, reason: (seenConnectors.append(connector), + seenFailures.append(reason))) + clientFactory.startedConnecting = seenConnectors.append + + connector = reactor.connectTCP(self.interface, portNumber, + clientFactory) + self.assertTrue(IConnector.providedBy(connector)) + dest = connector.getDestination() + self.assertEqual(dest.type, "TCP") + self.assertEqual(dest.host, self.interface) + self.assertEqual(dest.port, portNumber) + + clientFactory.whenStopped.addBoth(lambda _: reactor.stop()) + self.runReactor(reactor) + seenFailures[0].trap(ConnectionDone) + self.assertEqual(seenConnectors, [connector, connector]) + - def test_addresses(self): + def test_userFail(self): """ - A client's transport's C{getHost} and C{getPeer} return L{IPv4Address} - instances which give the dotted-quad string form of the local and - remote endpoints of the connection respectively. + Calling L{IConnector.stopConnecting} in C{Factory.startedConnecting} + results in C{Factory.clientConnectionFailed} being called with + L{error.UserError} as the reason. """ - host, port = findFreePort() + serverFactory = MyServerFactory() reactor = self.buildReactor() + tcpPort = reactor.listenTCP(0, serverFactory, interface=self.interface) + portNumber = tcpPort.getHost().port - server = reactor.listenTCP( - 0, serverFactoryFor(Protocol), interface=host) - serverAddress = server.getHost() + fatalErrors = [] - addresses = {'host': None, 'peer': None} - class CheckAddress(Protocol): - def makeConnection(self, transport): - addresses['host'] = transport.getHost() - addresses['peer'] = transport.getPeer() + def startedConnecting(connector): + try: + connector.stopConnecting() + except Exception: + fatalErrors.append(Failure()) reactor.stop() - clientFactory = Stop(reactor) - clientFactory.protocol = CheckAddress - reactor.connectTCP( - 'localhost', server.getHost().port, clientFactory, - bindAddress=('127.0.0.1', port)) + clientFactory = ClientStartStopFactory() + clientFactory.startedConnecting = startedConnecting + + clientFactory.whenStopped.addBoth(lambda _: reactor.stop()) + + reactor.callWhenRunning(lambda: reactor.connectTCP(self.interface, + portNumber, + clientFactory)) - reactor.installResolver(FakeResolver({'localhost': '127.0.0.1'})) self.runReactor(reactor) - self.assertEqual( - addresses['host'], - IPv4Address('TCP', '127.0.0.1', port)) - self.assertEqual( - addresses['peer'], - IPv4Address('TCP', '127.0.0.1', serverAddress.port)) + if fatalErrors: + self.fail(fatalErrors[0].getTraceback()) + clientFactory.reason.trap(UserError) + self.assertEqual(clientFactory.failed, 1) - def test_connectEvent(self): + def test_reconnect(self): """ - This test checks that we correctly get notifications event for a - client. This ought to prevent a regression under Windows using the GTK2 - reactor. See #3925. + Calling L{IConnector.connect} in C{Factory.clientConnectionLost} causes + a new connection attempt to be made. """ + serverFactory = ClosingFactory() reactor = self.buildReactor() + tcpPort = reactor.listenTCP(0, serverFactory, interface=self.interface) + serverFactory.port = tcpPort + portNumber = tcpPort.getHost().port + + clientFactory = MyClientFactory() + + def clientConnectionLost(connector, reason): + connector.connect() + clientFactory.clientConnectionLost = clientConnectionLost + reactor.connectTCP(self.interface, portNumber, clientFactory) + + protocolMadeAndClosed = [] + def reconnectFailed(ignored): + p = clientFactory.protocol + protocolMadeAndClosed.append((p.made, p.closed)) + reactor.stop() - server = reactor.listenTCP(0, serverFactoryFor(Protocol)) - connected = [] - - class CheckConnection(Protocol): - def connectionMade(self): - connected.append(self) - reactor.stop() - - clientFactory = Stop(reactor) - clientFactory.protocol = CheckConnection - reactor.connectTCP( - '127.0.0.1', server.getHost().port, clientFactory) + clientFactory.failDeferred.addCallback(reconnectFailed) - reactor.run() + self.runReactor(reactor) - self.assertTrue(connected) + clientFactory.reason.trap(ConnectionRefusedError) + self.assertEqual(protocolMadeAndClosed, [(1, 1)]) - def test_unregisterProducerAfterDisconnect(self): - """ - If a producer is unregistered from a L{ITCPTransport} provider after the - transport has been disconnected (by the peer) and after - L{ITCPTransport.loseConnection} has been called, the transport is not - re-added to the reactor as a writer as would be necessary if the - transport were still connected. - """ - reactor = self.buildReactor() - port = reactor.listenTCP(0, serverFactoryFor(ClosingProtocol)) - finished = Deferred() - finished.addErrback(log.err) - finished.addCallback(lambda ign: reactor.stop()) +class TCP4ConnectorTestsBuilder(TCPConnectorTestsBuilder): + interface = '127.0.0.1' + family = socket.AF_INET + addressClass = IPv4Address - writing = [] - class ClientProtocol(Protocol): - """ - Protocol to connect, register a producer, try to lose the - connection, wait for the server to disconnect from us, and - then unregister the producer. - """ - def connectionMade(self): - log.msg("ClientProtocol.connectionMade") - self.transport.registerProducer( - _SimplePullProducer(self.transport), False) - self.transport.loseConnection() - def connectionLost(self, reason): - log.msg("ClientProtocol.connectionLost") - self.unregister() - writing.append(self.transport in _getWriters(reactor)) - finished.callback(None) - - def unregister(self): - log.msg("ClientProtocol unregister") - self.transport.unregisterProducer() - - clientFactory = ClientFactory() - clientFactory.protocol = ClientProtocol - reactor.connectTCP('127.0.0.1', port.getHost().port, clientFactory) - self.runReactor(reactor) - self.assertFalse( - writing[0], "Transport was writing after unregisterProducer.") +class TCP6ConnectorTestsBuilder(TCPConnectorTestsBuilder): + family = socket.AF_INET6 + addressClass = IPv6Address + if ipv6Skip: + skip = "Platform does not support ipv6" - def test_disconnectWhileProducing(self): - """ - If L{ITCPTransport.loseConnection} is called while a producer - is registered with the transport, the connection is closed - after the producer is unregistered. - """ - reactor = self.buildReactor() + def setUp(self): + self.interface = getLinkLocalIPv6Address() - # For some reason, pyobject/pygtk will not deliver the close - # notification that should happen after the unregisterProducer call in - # this test. The selectable is in the write notification set, but no - # notification ever arrives. Probably for the same reason #5233 led - # win32eventreactor to be broken. - skippedReactors = ["Glib2Reactor", "Gtk2Reactor"] - reactorClassName = reactor.__class__.__name__ - if reactorClassName in skippedReactors and platform.isWindows(): - raise SkipTest( - "A pygobject/pygtk bug disables this functionality on Windows.") - class Producer: - def resumeProducing(self): - log.msg("Producer.resumeProducing") - port = reactor.listenTCP(0, serverFactoryFor(Protocol)) +def createTestSocket(test, addressFamily, socketType): + """ + Create a socket for the duration of the given test. - finished = Deferred() - finished.addErrback(log.err) - finished.addCallback(lambda ign: reactor.stop()) + @param test: the test to add cleanup to. - class ClientProtocol(Protocol): - """ - Protocol to connect, register a producer, try to lose the - connection, unregister the producer, and wait for the connection to - actually be lost. - """ - def connectionMade(self): - log.msg("ClientProtocol.connectionMade") - self.transport.registerProducer(Producer(), False) - self.transport.loseConnection() - # Let the reactor tick over, in case synchronously calling - # loseConnection and then unregisterProducer is the same as - # synchronously calling unregisterProducer and then - # loseConnection (as it is in several reactors). - reactor.callLater(0, reactor.callLater, 0, self.unregister) - - def unregister(self): - log.msg("ClientProtocol unregister") - self.transport.unregisterProducer() - # This should all be pretty quick. Fail the test - # if we don't get a connectionLost event really - # soon. - reactor.callLater( - 1.0, finished.errback, - Failure(Exception("Connection was not lost"))) + @param addressFamily: an C{AF_*} constant - def connectionLost(self, reason): - log.msg("ClientProtocol.connectionLost") - finished.callback(None) + @param socketType: a C{SOCK_*} constant. - clientFactory = ClientFactory() - clientFactory.protocol = ClientProtocol - reactor.connectTCP('127.0.0.1', port.getHost().port, clientFactory) - self.runReactor(reactor) - # If the test failed, we logged an error already and trial - # will catch it. + @return: a socket object. + """ + skt = socket.socket(addressFamily, socketType) + test.addCleanup(skt.close) + return skt @@ -633,24 +625,64 @@ self.assertFullyNewStyle(port) - -class TCPPortTestsBuilder(ReactorBuilder, ObjectModelIntegrationMixin, - StreamTransportTestsMixin): +class ListenTCPMixin(object): """ - Tests for L{IReactorTCP.listenTCP} + Mixin which uses L{IReactorTCP.listenTCP} to hand out listening TCP ports. """ - def getListeningPort(self, reactor, factory): + def getListeningPort(self, reactor, factory, port=0, interface=''): """ Get a TCP port from a reactor. """ - return reactor.listenTCP(0, factory) + return reactor.listenTCP(port, factory, interface=interface) + + + +class SocketTCPMixin(object): + """ + Mixin which uses L{IReactorSocket.adoptStreamPort} to hand out listening TCP + ports. + """ + def getListeningPort(self, reactor, factory, port=0, interface=''): + """ + Get a TCP port from a reactor, wrapping an already-initialized file + descriptor. + """ + if IReactorSocket.providedBy(reactor): + if ':' in interface: + domain = socket.AF_INET6 + address = socket.getaddrinfo(interface, port)[0][4] + else: + domain = socket.AF_INET + address = (interface, port) + portSock = socket.socket(domain) + portSock.bind(address) + portSock.listen(3) + portSock.setblocking(False) + try: + return reactor.adoptStreamPort( + portSock.fileno(), portSock.family, factory) + finally: + # The socket should still be open; fileno will raise if it is + # not. + portSock.fileno() + # Now clean it up, because the rest of the test does not need + # it. + portSock.close() + else: + raise SkipTest("Reactor does not provide IReactorSocket") + +class TCPPortTestsMixin(object): + """ + Tests for L{IReactorTCP.listenTCP} + """ def getExpectedStartListeningLogMessage(self, port, factory): """ Get the message expected to be logged when a TCP port starts listening. """ - return "%s starting on %d" % (factory, port.getHost().port) + return "%s starting on %d" % ( + factory, port.getHost().port) def getExpectedConnectionLostLogMsg(self, port): @@ -666,11 +698,47 @@ listening port listens on an IPv4 address. """ reactor = self.buildReactor() - port = reactor.listenTCP(0, ServerFactory()) + port = self.getListeningPort(reactor, ServerFactory()) address = port.getHost() self.assertIsInstance(address, IPv4Address) + def test_portGetHostOnIPv6(self): + """ + When listening on an IPv6 address, L{IListeningPort.getHost} returns + an L{IPv6Address} with C{host} and C{port} attributes reflecting the + address the port is bound to. + """ + reactor = self.buildReactor() + host, portNumber = findFreePort( + family=socket.AF_INET6, interface='::1')[:2] + port = self.getListeningPort( + reactor, ServerFactory(), portNumber, host) + address = port.getHost() + self.assertIsInstance(address, IPv6Address) + self.assertEqual('::1', address.host) + self.assertEqual(portNumber, address.port) + if ipv6Skip: + test_portGetHostOnIPv6.skip = ipv6Skip + + + def test_portGetHostOnIPv6ScopeID(self): + """ + When a link-local IPv6 address including a scope identifier is passed as + the C{interface} argument to L{IReactorTCP.listenTCP}, the resulting + L{IListeningPort} reports its address as an L{IPv6Address} with a host + value that includes the scope identifier. + """ + linkLocal = getLinkLocalIPv6Address() + reactor = self.buildReactor() + port = self.getListeningPort(reactor, ServerFactory(), 0, linkLocal) + address = port.getHost() + self.assertIsInstance(address, IPv6Address) + self.assertEqual(linkLocal, address.host) + if ipv6Skip: + test_portGetHostOnIPv6ScopeID.skip = ipv6Skip + + def _buildProtocolAddressTest(self, client, interface): """ Connect C{client} to a server listening on C{interface} started with @@ -697,10 +765,10 @@ factory = ObserveAddress() reactor = self.buildReactor() - port = reactor.listenTCP(0, factory, interface=interface) + port = self.getListeningPort(reactor, factory, 0, interface) client.setblocking(False) try: - client.connect((port.getHost().host, port.getHost().port)) + connect(client, (port.getHost().host, port.getHost().port)) except socket.error, (errnum, message): self.assertIn(errnum, (errno.EINPROGRESS, errno.EWOULDBLOCK)) @@ -715,13 +783,42 @@ to the factory's C{buildProtocol} method giving the peer's address. """ interface = '127.0.0.1' - client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.addCleanup(client.close) + client = createTestSocket(self, socket.AF_INET, socket.SOCK_STREAM) observedAddress = self._buildProtocolAddressTest(client, interface) self.assertEqual( IPv4Address('TCP', *client.getsockname()), observedAddress) + def test_buildProtocolIPv6Address(self): + """ + When a connection is accepted to an IPv6 address, an L{IPv6Address} is + passed to the factory's C{buildProtocol} method giving the peer's + address. + """ + interface = '::1' + client = createTestSocket(self, socket.AF_INET6, socket.SOCK_STREAM) + observedAddress = self._buildProtocolAddressTest(client, interface) + self.assertEqual( + IPv6Address('TCP', *client.getsockname()[:2]), observedAddress) + if ipv6Skip: + test_buildProtocolIPv6Address.skip = ipv6Skip + + + def test_buildProtocolIPv6AddressScopeID(self): + """ + When a connection is accepted to a link-local IPv6 address, an + L{IPv6Address} is passed to the factory's C{buildProtocol} method + giving the peer's address, including a scope identifier. + """ + interface = getLinkLocalIPv6Address() + client = createTestSocket(self, socket.AF_INET6, socket.SOCK_STREAM) + observedAddress = self._buildProtocolAddressTest(client, interface) + self.assertEqual( + IPv6Address('TCP', *client.getsockname()[:2]), observedAddress) + if ipv6Skip: + test_buildProtocolIPv6AddressScopeID.skip = ipv6Skip + + def _serverGetConnectionAddressTest(self, client, interface, which): """ Connect C{client} to a server listening on C{interface} started with @@ -750,10 +847,10 @@ reactor = self.buildReactor() factory = ServerFactory() factory.protocol = ObserveAddress - port = reactor.listenTCP(0, factory, interface=interface) + port = self.getListeningPort(reactor, factory, 0, interface) client.setblocking(False) try: - client.connect((port.getHost().host, port.getHost().port)) + connect(client, (port.getHost().host, port.getHost().port)) except socket.error, (errnum, message): self.assertIn(errnum, (errno.EINPROGRESS, errno.EWOULDBLOCK)) self.runReactor(reactor) @@ -767,14 +864,46 @@ address on which the server accepted the connection. """ interface = '127.0.0.1' - client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.addCleanup(client.close) + client = createTestSocket(self, socket.AF_INET, socket.SOCK_STREAM) hostAddress = self._serverGetConnectionAddressTest( client, interface, 'getHost') self.assertEqual( IPv4Address('TCP', *client.getpeername()), hostAddress) + def test_serverGetHostOnIPv6(self): + """ + When a connection is accepted over IPv6, the server + L{ITransport.getHost} method returns an L{IPv6Address} giving the + address on which the server accepted the connection. + """ + interface = '::1' + client = createTestSocket(self, socket.AF_INET6, socket.SOCK_STREAM) + hostAddress = self._serverGetConnectionAddressTest( + client, interface, 'getHost') + self.assertEqual( + IPv6Address('TCP', *client.getpeername()[:2]), hostAddress) + if ipv6Skip: + test_serverGetHostOnIPv6.skip = ipv6Skip + + + def test_serverGetHostOnIPv6ScopeID(self): + """ + When a connection is accepted over IPv6, the server + L{ITransport.getHost} method returns an L{IPv6Address} giving the + address on which the server accepted the connection, including the scope + identifier. + """ + interface = getLinkLocalIPv6Address() + client = createTestSocket(self, socket.AF_INET6, socket.SOCK_STREAM) + hostAddress = self._serverGetConnectionAddressTest( + client, interface, 'getHost') + self.assertEqual( + IPv6Address('TCP', *client.getpeername()[:2]), hostAddress) + if ipv6Skip: + test_serverGetHostOnIPv6ScopeID.skip = ipv6Skip + + def test_serverGetPeerOnIPv4(self): """ When a connection is accepted over IPv4, the server @@ -782,19 +911,66 @@ address of the remote end of the connection. """ interface = '127.0.0.1' - client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.addCleanup(client.close) + client = createTestSocket(self, socket.AF_INET, socket.SOCK_STREAM) peerAddress = self._serverGetConnectionAddressTest( client, interface, 'getPeer') self.assertEqual( IPv4Address('TCP', *client.getsockname()), peerAddress) + def test_serverGetPeerOnIPv6(self): + """ + When a connection is accepted over IPv6, the server + L{ITransport.getPeer} method returns an L{IPv6Address} giving the + address on the remote end of the connection. + """ + interface = '::1' + client = createTestSocket(self, socket.AF_INET6, socket.SOCK_STREAM) + peerAddress = self._serverGetConnectionAddressTest( + client, interface, 'getPeer') + self.assertEqual( + IPv6Address('TCP', *client.getsockname()[:2]), peerAddress) + if ipv6Skip: + test_serverGetPeerOnIPv6.skip = ipv6Skip + + + def test_serverGetPeerOnIPv6ScopeID(self): + """ + When a connection is accepted over IPv6, the server + L{ITransport.getPeer} method returns an L{IPv6Address} giving the + address on the remote end of the connection, including the scope + identifier. + """ + interface = getLinkLocalIPv6Address() + client = createTestSocket(self, socket.AF_INET6, socket.SOCK_STREAM) + peerAddress = self._serverGetConnectionAddressTest( + client, interface, 'getPeer') + self.assertEqual( + IPv6Address('TCP', *client.getsockname()[:2]), peerAddress) + if ipv6Skip: + test_serverGetPeerOnIPv6ScopeID.skip = ipv6Skip + + + +class TCPPortTestsBuilder(ReactorBuilder, ListenTCPMixin, TCPPortTestsMixin, + ObjectModelIntegrationMixin, + StreamTransportTestsMixin): + pass + + + +class TCPFDPortTestsBuilder(ReactorBuilder, SocketTCPMixin, TCPPortTestsMixin, + ObjectModelIntegrationMixin, + StreamTransportTestsMixin): + pass + + class StopStartReadingProtocol(Protocol): """ Protocol that pauses and resumes the transport a few times """ + def connectionMade(self): self.data = '' self.pauseResumeProducing(3) @@ -826,6 +1002,7 @@ """ Builder defining tests relating to L{twisted.internet.tcp.Connection}. """ + def test_stopStartReading(self): """ This test verifies transport socket read state after multiple @@ -891,38 +1068,58 @@ The reactor needs to remember that notification until Bob resumes the transport. """ - reactor = self.buildReactor() - events = [] - class Pauser(Protocol): + class Pauser(ConnectableProtocol): + def __init__(self): + self.events = [] + def dataReceived(self, bytes): - events.append("paused") + self.events.append("paused") self.transport.pauseProducing() - reactor.callLater(0, self.resume) + self.reactor.callLater(0, self.resume) def resume(self): - events.append("resumed") + self.events.append("resumed") self.transport.resumeProducing() def connectionLost(self, reason): # This is the event you have been waiting for. - events.append("lost") - reactor.stop() + self.events.append("lost") + ConnectableProtocol.connectionLost(self, reason) - serverFactory = ServerFactory() - serverFactory.protocol = Pauser - port = reactor.listenTCP(0, serverFactory) + class Client(ConnectableProtocol): + def connectionMade(self): + self.transport.write("some bytes for you") + self.transport.loseConnection() - cc = TCP4ClientEndpoint(reactor, '127.0.0.1', port.getHost().port) - cf = ClientFactory() - cf.protocol = Protocol - clientDeferred = cc.connect(cf) - def connected(client): - client.transport.write("some bytes for you") - client.transport.loseConnection() - clientDeferred.addCallback(connected) + pauser = Pauser() + runProtocolsWithReactor(self, pauser, Client(), TCPCreator()) + self.assertEqual(pauser.events, ["paused", "resumed", "lost"]) - self.runReactor(reactor) - self.assertEqual(events, ["paused", "resumed", "lost"]) + + def test_doubleHalfClose(self): + """ + If one side half-closes its connection, and then the other side of the + connection calls C{loseWriteConnection}, and then C{loseConnection} in + {writeConnectionLost}, the connection is closed correctly. + + This rather obscure case used to fail (see ticket #3037). + """ + class ListenerProtocol(ConnectableProtocol): + implements(IHalfCloseableProtocol) + + def readConnectionLost(self): + self.transport.loseWriteConnection() + + def writeConnectionLost(self): + self.transport.loseConnection() + + class Client(ConnectableProtocol): + def connectionMade(self): + self.transport.loseConnection() + + # If test fails, reactor won't stop and we'll hit timeout: + runProtocolsWithReactor( + self, ListenerProtocol(), Client(), TCPCreator()) @@ -967,11 +1164,6 @@ reactor = self.buildReactor() port = reactor.listenTCP(0, server) - self.addCleanup(port.stopListening) - - connector = reactor.connectTCP( - "127.0.0.1", port.getHost().port, client) - self.addCleanup(connector.disconnect) def dataReceived(data): log.msg("data received: %r" % data) @@ -995,6 +1187,8 @@ reactor.stop() return result d.addBoth(stop) + + reactor.connectTCP("127.0.0.1", port.getHost().port, client) self.runReactor(reactor) @@ -1007,11 +1201,8 @@ reactor = self.buildReactor() port = reactor.listenTCP(0, server) - self.addCleanup(port.stopListening) - connector = reactor.connectTCP( - "127.0.0.1", port.getHost().port, client) - self.addCleanup(connector.disconnect) + reactor.connectTCP("127.0.0.1", port.getHost().port, client) def serverConnected(proto): log.msg("server connected %s" % proto) @@ -1040,11 +1231,6 @@ reactor = self.buildReactor() port = reactor.listenTCP(0, self.server) - self.addCleanup(port.stopListening) - - connector = reactor.connectTCP( - "127.0.0.1", port.getHost().port, self.client) - self.addCleanup(connector.disconnect) # The following could probably all be much simpler, but for #5285. @@ -1074,6 +1260,9 @@ reactor.stop() return result d1.addBoth(stop) + + reactor.connectTCP("127.0.0.1", port.getHost().port, self.client) + self.runReactor(reactor) @@ -1160,25 +1349,18 @@ self.assertEquals(producer.actions, ["resume", "resume"]) -globals().update(TCPClientTestsBuilder.makeTestCaseClasses()) +globals().update(TCP4ClientTestsBuilder.makeTestCaseClasses()) +globals().update(TCP6ClientTestsBuilder.makeTestCaseClasses()) globals().update(TCPPortTestsBuilder.makeTestCaseClasses()) +globals().update(TCPFDPortTestsBuilder.makeTestCaseClasses()) globals().update(TCPConnectionTestsBuilder.makeTestCaseClasses()) +globals().update(TCP4ConnectorTestsBuilder.makeTestCaseClasses()) +globals().update(TCP6ConnectorTestsBuilder.makeTestCaseClasses()) globals().update(WriteSequenceTests.makeTestCaseClasses()) -class AbortServerProtocol(Protocol): - """ - Generic server protocol for abortConnection() tests. - """ - - def connectionLost(self, reason): - self.factory.done.callback(reason) - del self.factory.done - - - -class ServerAbortsTwice(AbortServerProtocol): +class ServerAbortsTwice(ConnectableProtocol): """ Call abortConnection() twice. """ @@ -1189,7 +1371,7 @@ -class ServerAbortsThenLoses(AbortServerProtocol): +class ServerAbortsThenLoses(ConnectableProtocol): """ Call abortConnection() followed by loseConnection(). """ @@ -1200,7 +1382,7 @@ -class AbortServerWritingProtocol(AbortServerProtocol): +class AbortServerWritingProtocol(ConnectableProtocol): """ Protocol that writes data upon connection. """ @@ -1226,7 +1408,7 @@ -class NoReadServer(AbortServerProtocol): +class NoReadServer(ConnectableProtocol): """ Stop reading immediately on connection. @@ -1239,7 +1421,7 @@ -class EventualNoReadServer(AbortServerProtocol): +class EventualNoReadServer(ConnectableProtocol): """ Like NoReadServer, except we Wait until some bytes have been delivered before stopping reading. This means TLS handshake has finished, where @@ -1274,40 +1456,16 @@ -class AbortServerFactory(ServerFactory): - """ - Server factory for abortConnection() tests. - """ - - def __init__(self, done, serverClass, reactor): - self.done = done - self.serverClass = serverClass - self.reactor = reactor - - def buildProtocol(self, addr): - p = self.serverClass() - p.factory = self - self.proto = p - return p - - -class BaseAbortingClient(Protocol): +class BaseAbortingClient(ConnectableProtocol): """ Base class for abort-testing clients. """ - inReactorMethod = False - def __init__(self, done, reactor): - self.done = done - self.reactor = reactor - - def connectionLost(self, reason): if self.inReactorMethod: raise RuntimeError("BUG: connectionLost was called re-entrantly!") - self.done.callback(reason) - del self.done + ConnectableProtocol.connectionLost(self, reason) @@ -1367,18 +1525,13 @@ -class ProducerAbortingClient(Protocol): +class ProducerAbortingClient(ConnectableProtocol): """ Call abortConnection from doWrite, via resumeProducing. """ inReactorMethod = True - - def __init__(self, done, reactor): - self.done = done - self.reactor = reactor - self.producerStopped = False - + producerStopped = False def write(self): self.transport.write("lalala" * 127000) @@ -1407,12 +1560,11 @@ raise RuntimeError("BUG: stopProducing() was never called.") if self.inReactorMethod: raise RuntimeError("BUG: connectionLost called re-entrantly!") - self.done.callback(reason) - del self.done + ConnectableProtocol.connectionLost(self, reason) -class StreamingProducerClient(Protocol): +class StreamingProducerClient(ConnectableProtocol): """ Call abortConnection() when the other side has stopped reading. @@ -1424,14 +1576,9 @@ Since it's very difficult to know when this actually happens, we just write a lot of data, and assume at that point no more writes will happen. """ - - def __init__(self, done, reactor): - self.done = done - self.paused = False - self.reactor = reactor - self.extraWrites = 0 - self.inReactorMethod = False - + paused = False + extraWrites = 0 + inReactorMethod = False def connectionMade(self): self.write() @@ -1487,9 +1634,8 @@ def connectionLost(self, reason): # Tell server to start reading again so it knows to go away: - self.serverFactory.proto.transport.startReading() - self.done.callback(reason) - del self.done + self.otherProtocol.transport.startReading() + ConnectableProtocol.connectionLost(self, reason) @@ -1554,8 +1700,7 @@ # Base class assertion about stopProducing being called isn't valid; # if the we blew up in resumeProducing, consumers are justified in # giving up on the producer and not calling stopProducing. - self.done.callback(reason) - del self.done + ConnectableProtocol.connectionLost(self, reason) @@ -1563,6 +1708,8 @@ """ Unit tests for L{ITransport.abortConnection}. """ + # Override in subclasses, should be a EndpointCreator instance: + endpoints = None def runAbortTest(self, clientClass, serverClass, clientConnectionLostReason=None): @@ -1573,63 +1720,34 @@ We then run the reactor until both sides have disconnected, and then verify that the right exception resulted. """ - reactor = self.buildReactor() - serverDoneDeferred = Deferred() - clientDoneDeferred = Deferred() - - server = AbortServerFactory(serverDoneDeferred, serverClass, reactor) - serverport = self.listen(reactor, server) - - c = ClientCreator(reactor, clientClass, clientDoneDeferred, reactor) - d = self.connect(c, serverport) - def addServer(client): - client.serverFactory = server - d.addCallback(addServer) - - serverReason = [] - clientReason = [] - serverDoneDeferred.addBoth(serverReason.append) - clientDoneDeferred.addBoth(clientReason.append) - d.addCallback(lambda x: clientDoneDeferred) - d.addCallback(lambda x: serverDoneDeferred) - - d.addCallback(lambda x: serverport.stopListening()) - def verifyReactorIsClean(ignore): - if clientConnectionLostReason is not None: - self.flushLoggedErrors(clientConnectionLostReason) - self.assertEqual(reactor.removeAll(), []) - # The reactor always has a timeout added in buildReactor(): - delayedCalls = reactor.getDelayedCalls() - self.assertEqual(len(delayedCalls), 1, map(str, delayedCalls)) - d.addCallback(verifyReactorIsClean) - - d.addCallback(lambda ignored: reactor.stop()) - # If we get error, make sure test still exits: - def errorHandler(err): - log.err(err) - reactor.stop() - d.addErrback(errorHandler) - - self.runReactor(reactor, timeout=10) - clientExpectedExceptions = (ConnectionAborted, ConnectionLost) serverExpectedExceptions = (ConnectionLost, ConnectionDone) # In TLS tests we may get SSL.Error instead of ConnectionLost, # since we're trashing the TLS protocol layer. - try: - from OpenSSL import SSL - except ImportError: - SSL = None - if SSL: + if useSSL: clientExpectedExceptions = clientExpectedExceptions + (SSL.Error,) serverExpectedExceptions = serverExpectedExceptions + (SSL.Error,) - if clientConnectionLostReason: - self.assertIsInstance(clientReason[0].value, - (clientConnectionLostReason,) + clientExpectedExceptions) + client = clientClass() + server = serverClass() + client.otherProtocol = server + server.otherProtocol = client + reactor = runProtocolsWithReactor(self, server, client, self.endpoints) + + # Make sure everything was shutdown correctly: + self.assertEqual(reactor.removeAll(), []) + # The reactor always has a timeout added in runReactor(): + delayedCalls = reactor.getDelayedCalls() + self.assertEqual(len(delayedCalls), 1, map(str, delayedCalls)) + + if clientConnectionLostReason is not None: + self.assertIsInstance( + client.disconnectReason.value, + (clientConnectionLostReason,) + clientExpectedExceptions) else: - self.assertIsInstance(clientReason[0].value, clientExpectedExceptions) - self.assertIsInstance(serverReason[0].value, serverExpectedExceptions) + self.assertIsInstance(client.disconnectReason.value, + clientExpectedExceptions) + self.assertIsInstance(server.disconnectReason.value, serverExpectedExceptions) def test_dataReceivedAbort(self): @@ -1687,7 +1805,7 @@ connectionLost should not be called re-entrantly. """ self.runAbortTest(ProducerAbortingClient, - AbortServerProtocol) + ConnectableProtocol) def test_resumeProducingAbortLater(self): @@ -1738,6 +1856,8 @@ self.runAbortTest(DataReceivedRaisingClient, AbortServerWritingProtocol, clientConnectionLostReason=ZeroDivisionError) + errors = self.flushLoggedErrors(ZeroDivisionError) + self.assertEquals(len(errors), 1) def test_resumeProducingThrows(self): @@ -1750,9 +1870,10 @@ unexpected exceptions. """ self.runAbortTest(ResumeThrowsClient, - AbortServerProtocol, + ConnectableProtocol, clientConnectionLostReason=ZeroDivisionError) - + errors = self.flushLoggedErrors(ZeroDivisionError) + self.assertEquals(len(errors), 1) @@ -1761,19 +1882,62 @@ TCP-specific L{AbortConnectionMixin} tests. """ - def listen(self, reactor, server): + endpoints = TCPCreator() + +globals().update(AbortConnectionTestCase.makeTestCaseClasses()) + + + +class SimpleUtilityTestCase(TestCase): + """ + Simple, direct tests for helpers within L{twisted.internet.tcp}. + """ + + skip = ipv6Skip + + def test_resolveNumericHost(self): """ - Listen with the given protocol factory. + L{_resolveIPv6} raises a L{socket.gaierror} (L{socket.EAI_NONAME}) when + invoked with a non-numeric host. (In other words, it is passing + L{socket.AI_NUMERICHOST} to L{socket.getaddrinfo} and will not + accidentally block if it receives bad input.) """ - return reactor.listenTCP(0, server, interface="127.0.0.1") + err = self.assertRaises(socket.gaierror, _resolveIPv6, "localhost", 1) + self.assertEqual(err.args[0], socket.EAI_NONAME) - def connect(self, clientcreator, serverport, *a, **k): + def test_resolveNumericService(self): """ - Connect a client to the listening server port. Return the resulting - Deferred. + L{_resolveIPv6} raises a L{socket.gaierror} (L{socket.EAI_NONAME}) when + invoked with a non-numeric port. (In other words, it is passing + L{socket.AI_NUMERICSERV} to L{socket.getaddrinfo} and will not + accidentally block if it receives bad input.) """ - return clientcreator.connectTCP(serverport.getHost().host, - serverport.getHost().port) + err = self.assertRaises(socket.gaierror, _resolveIPv6, "::1", "http") + self.assertEqual(err.args[0], socket.EAI_NONAME) + + if platform.isWindows(): + test_resolveNumericService.skip = ("The AI_NUMERICSERV flag is not " + "supported by Microsoft providers.") + # http://msdn.microsoft.com/en-us/library/windows/desktop/ms738520.aspx + + + def test_resolveIPv6(self): + """ + L{_resolveIPv6} discovers the flow info and scope ID of an IPv6 + address. + """ + result = _resolveIPv6("::1", 2) + self.assertEqual(len(result), 4) + # We can't say anything more useful about these than that they're + # integers, because the whole point of getaddrinfo is that you can never + # know a-priori know _anything_ about the network interfaces of the + # computer that you're on and you have to ask it. + self.assertIsInstance(result[2], int) # flow info + self.assertIsInstance(result[3], int) # scope id + # but, luckily, IP presentation format and what it means to be a port + # number are a little better specified. + self.assertEqual(result[:2], ("::1", 2)) + + -globals().update(AbortConnectionTestCase.makeTestCaseClasses()) diff -Nru twisted-11.1.0/twisted/internet/test/test_threads.py twisted-12.1.0/twisted/internet/test/test_threads.py --- twisted-11.1.0/twisted/internet/test/test_threads.py 2011-06-13 23:20:22.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_threads.py 2011-12-08 03:37:41.000000000 +0000 @@ -8,7 +8,7 @@ __metaclass__ = type from weakref import ref -import gc +import gc, threading from twisted.python.threadable import isInIOThread from twisted.internet.test.reactormixins import ReactorBuilder @@ -104,6 +104,24 @@ self.assertTrue(after - before < 30) + def test_callFromThread(self): + """ + A function scheduled with L{IReactorThreads.callFromThread} invoked + from another thread is run in the reactor thread. + """ + reactor = self.buildReactor() + result = [] + + def threadCall(): + result.append(threading.currentThread()) + reactor.stop() + reactor.callLater(0, reactor.callInThread, + reactor.callFromThread, threadCall) + self.runReactor(reactor, 5) + + self.assertEquals(result, [threading.currentThread()]) + + def test_stopThreadPool(self): """ When the reactor stops, L{ReactorBase._stopThreadPool} drops the diff -Nru twisted-11.1.0/twisted/internet/test/test_time.py twisted-12.1.0/twisted/internet/test/test_time.py --- twisted-11.1.0/twisted/internet/test/test_time.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_time.py 2011-12-08 03:37:41.000000000 +0000 @@ -7,6 +7,7 @@ __metaclass__ = type +from twisted.python.runtime import platform from twisted.internet.test.reactormixins import ReactorBuilder @@ -23,4 +24,38 @@ reactor.run() + +class GlibTimeTestsBuilder(ReactorBuilder): + """ + Builder for defining tests relating to L{IReactorTime} for reactors based + off glib. + """ + if platform.isWindows(): + _reactors = ["twisted.internet.gtk2reactor.PortableGtkReactor"] + else: + _reactors = ["twisted.internet.glib2reactor.Glib2Reactor", + "twisted.internet.gtk2reactor.Gtk2Reactor"] + + def test_timeout_add(self): + """ + A C{reactor.callLater} call scheduled from a C{gobject.timeout_add} + call is run on time. + """ + import gobject + reactor = self.buildReactor() + + result = [] + def gschedule(): + reactor.callLater(0, callback) + return 0 + def callback(): + result.append(True) + reactor.stop() + + reactor.callWhenRunning(gobject.timeout_add, 10, gschedule) + self.runReactor(reactor, 5) + self.assertEqual(result, [True]) + + globals().update(TimeTestsBuilder.makeTestCaseClasses()) +globals().update(GlibTimeTestsBuilder.makeTestCaseClasses()) diff -Nru twisted-11.1.0/twisted/internet/test/test_tls.py twisted-12.1.0/twisted/internet/test/test_tls.py --- twisted-11.1.0/twisted/internet/test/test_tls.py 2011-10-15 21:21:45.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_tls.py 2012-05-12 10:07:03.000000000 +0000 @@ -7,9 +7,11 @@ __metaclass__ = type +import sys, operator + from zope.interface import implements -from twisted.internet.test.reactormixins import ReactorBuilder +from twisted.internet.test.reactormixins import ReactorBuilder, EndpointCreator from twisted.internet.protocol import ServerFactory, ClientFactory, Protocol from twisted.internet.interfaces import ( IReactorSSL, ITLSTransport, IStreamClientEndpoint) @@ -18,13 +20,14 @@ SSL4ServerEndpoint, SSL4ClientEndpoint, TCP4ClientEndpoint) from twisted.internet.error import ConnectionClosed from twisted.internet.task import Cooperator -from twisted.trial.unittest import SkipTest +from twisted.trial.unittest import TestCase, SkipTest from twisted.python.runtime import platform from twisted.internet.test.test_core import ObjectModelIntegrationMixin -from twisted.internet.test.test_tcp import StreamTransportTestsMixin +from twisted.internet.test.test_tcp import ( + StreamTransportTestsMixin, AbortConnectionMixin) from twisted.internet.test.connectionmixins import ConnectionTestsMixin -from twisted.internet.test.test_tcp import AbortConnectionMixin +from twisted.internet.test.connectionmixins import BrokenContextFactory try: from OpenSSL.crypto import FILETYPE_PEM @@ -120,22 +123,27 @@ immediately start TLS on it. Return a L{Deferred} which fires with the protocol instance. """ - d = self.wrapped.connect(factory) - def connected(protocol): - protocol.transport.startTLS(self.contextFactory) - return protocol - d.addCallback(connected) - return d + # This would be cleaner when we have ITransport.switchProtocol, which + # will be added with ticket #3204: + class WrapperFactory(ServerFactory): + def buildProtocol(wrapperSelf, addr): + protocol = factory.buildProtocol(addr) + def connectionMade(orig=protocol.connectionMade): + protocol.transport.startTLS(self.contextFactory) + orig() + protocol.connectionMade = connectionMade + return protocol + + return self.wrapped.connect(WrapperFactory()) -class StartTLSClientTestsMixin(TLSMixin, ReactorBuilder, ConnectionTestsMixin, - ContextGeneratingMixin): +class StartTLSClientCreator(EndpointCreator, ContextGeneratingMixin): """ - Tests for TLS connections established using L{ITLSTransport.startTLS} (as - opposed to L{IReactorSSL.connectSSL} or L{IReactorSSL.listenSSL}). + Create L{ITLSTransport.startTLS} endpoint for the client, and normal SSL + for server just because it's easier. """ - def serverEndpoint(self, reactor): + def server(self, reactor): """ Construct an SSL server endpoint. This should be be constructing a TCP server endpoint which immediately calls C{startTLS} instead, but that @@ -144,7 +152,7 @@ return SSL4ServerEndpoint(reactor, 0, self.getServerContext()) - def clientEndpoint(self, reactor, serverAddress): + def client(self, reactor, serverAddress): """ Construct a TCP client endpoint wrapped to immediately start TLS. """ @@ -155,20 +163,50 @@ -class SSLClientTestsMixin(TLSMixin, ReactorBuilder, ContextGeneratingMixin, - ConnectionTestsMixin): +class BadContextTestsMixin(object): """ - Mixin defining tests relating to L{ITLSTransport}. + Mixin for L{ReactorBuilder} subclasses which defines a helper for testing + the handling of broken context factories. """ + def _testBadContext(self, useIt): + """ + Assert that the exception raised by a broken context factory's + C{getContext} method is raised by some reactor method. If it is not, an + exception will be raised to fail the test. + + @param useIt: A two-argument callable which will be called with a + reactor and a broken context factory and which is expected to raise + the same exception as the broken context factory's C{getContext} + method. + """ + reactor = self.buildReactor() + exc = self.assertRaises( + ValueError, useIt, reactor, BrokenContextFactory()) + self.assertEqual(BrokenContextFactory.message, str(exc)) - def serverEndpoint(self, reactor): + + +class StartTLSClientTestsMixin(TLSMixin, ReactorBuilder, ConnectionTestsMixin): + """ + Tests for TLS connections established using L{ITLSTransport.startTLS} (as + opposed to L{IReactorSSL.connectSSL} or L{IReactorSSL.listenSSL}). + """ + endpoints = StartTLSClientCreator() + + + +class SSLCreator(EndpointCreator, ContextGeneratingMixin): + """ + Create SSL endpoints. + """ + def server(self, reactor): """ Create an SSL server endpoint on a TCP/IP-stack allocated port. """ return SSL4ServerEndpoint(reactor, 0, self.getServerContext()) - def clientEndpoint(self, reactor, serverAddress): + def client(self, reactor, serverAddress): """ Create an SSL client endpoint which will connect localhost on the port given by C{serverAddress}. @@ -180,6 +218,25 @@ ClientContextFactory()) +class SSLClientTestsMixin(TLSMixin, ReactorBuilder, ContextGeneratingMixin, + ConnectionTestsMixin, BadContextTestsMixin): + """ + Mixin defining tests relating to L{ITLSTransport}. + """ + endpoints = SSLCreator() + + def test_badContext(self): + """ + If the context factory passed to L{IReactorSSL.connectSSL} raises an + exception from its C{getContext} method, that exception is raised by + L{IReactorSSL.connectSSL}. + """ + def useIt(reactor, contextFactory): + return reactor.connectSSL( + "127.0.0.1", 1234, ClientFactory(), contextFactory) + self._testBadContext(useIt) + + def test_disconnectAfterWriteAfterStartTLS(self): """ L{ITCPTransport.loseConnection} ends a connection which was set up with @@ -257,7 +314,7 @@ class TLSPortTestsBuilder(TLSMixin, ContextGeneratingMixin, - ObjectModelIntegrationMixin, + ObjectModelIntegrationMixin, BadContextTestsMixin, StreamTransportTestsMixin, ReactorBuilder): """ Tests for L{IReactorSSL.listenSSL} @@ -283,6 +340,18 @@ return "(TLS Port %s Closed)" % (port.getHost().port,) + def test_badContext(self): + """ + If the context factory passed to L{IReactorSSL.listenSSL} raises an + exception from its C{getContext} method, that exception is raised by + L{IReactorSSL.listenSSL}. + """ + def useIt(reactor, contextFactory): + return reactor.listenSSL(0, ServerFactory(), contextFactory) + self._testBadContext(useIt) + + + globals().update(SSLClientTestsMixin.makeTestCaseClasses()) globals().update(StartTLSClientTestsMixin.makeTestCaseClasses()) globals().update(TLSPortTestsBuilder().makeTestCaseClasses()) @@ -290,7 +359,11 @@ class AbortSSLConnectionTest(ReactorBuilder, AbortConnectionMixin, ContextGeneratingMixin): + """ + C{abortConnection} tests using SSL. + """ requiredInterfaces = (IReactorSSL,) + endpoints = SSLCreator() def buildReactor(self): reactor = ReactorBuilder.buildReactor(self) @@ -310,25 +383,50 @@ def setUp(self): if FILETYPE_PEM is None: raise SkipTest("OpenSSL not available.") - self.serverContext = self.getServerContext() - self.clientContext = self.getClientContext() - self.clientContext.method = self.serverContext.method - - - def listen(self, reactor, server): - """ - Listen using SSL. - """ - return reactor.listenSSL( - 0, server, self.serverContext, interface="127.0.0.1") +globals().update(AbortSSLConnectionTest.makeTestCaseClasses()) - def connect(self, clientcreator, serverport): +class OldTLSDeprecationTest(TestCase): + """ + Tests for the deprecation of L{twisted.internet._oldtls}, the implementation + module for L{IReactorSSL} used when only an old version of pyOpenSSL is + available. + """ + def test_warning(self): """ - Connect using SSL. + The use of L{twisted.internet._oldtls} is deprecated, and emits a + L{DeprecationWarning}. """ - return clientcreator.connectSSL( - serverport.getHost().host, serverport.getHost().port, - self.clientContext) + # Since _oldtls depends on OpenSSL, just skip this test if it isn't + # installed on the system. Faking it would be error prone. + try: + import OpenSSL + except ImportError: + raise SkipTest("OpenSSL not available.") -globals().update(AbortSSLConnectionTest.makeTestCaseClasses()) + # Change the apparent version of OpenSSL to one support for which is + # deprecated. And have it change back again after the test. + self.patch(OpenSSL, '__version__', '0.5') + + # If the module was already imported, the import statement below won't + # execute its top-level code. Take it out of sys.modules so the import + # system re-evaluates it. Arrange to put the original back afterwards. + # Also handle the case where it hasn't yet been imported. + try: + oldtls = sys.modules['twisted.internet._oldtls'] + except KeyError: + self.addCleanup(sys.modules.pop, 'twisted.internet._oldtls') + else: + del sys.modules['twisted.internet._oldtls'] + self.addCleanup( + operator.setitem, sys.modules, 'twisted.internet._oldtls', + oldtls) + + # The actual test. + import twisted.internet._oldtls + warnings = self.flushWarnings() + self.assertEqual(warnings[0]['category'], DeprecationWarning) + self.assertEqual( + warnings[0]['message'], + "Support for pyOpenSSL 0.5 is deprecated. " + "Upgrade to pyOpenSSL 0.10 or newer.") diff -Nru twisted-11.1.0/twisted/internet/test/test_udp_internals.py twisted-12.1.0/twisted/internet/test/test_udp_internals.py --- twisted-11.1.0/twisted/internet/test/test_udp_internals.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_udp_internals.py 2011-11-10 00:36:47.000000000 +0000 @@ -0,0 +1,165 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Tests for the internal implementation details of L{twisted.internet.udp}. +""" + +import socket + +from twisted.trial import unittest +from twisted.internet.protocol import DatagramProtocol +from twisted.internet import udp +from twisted.python.runtime import platformType + +if platformType == 'win32': + from errno import WSAEWOULDBLOCK as EWOULDBLOCK + from errno import WSAECONNREFUSED as ECONNREFUSED +else: + from errno import EWOULDBLOCK + from errno import ECONNREFUSED + + + +class StringUDPSocket(object): + """ + A fake UDP socket object, which returns a fixed sequence of strings and/or + socket errors. Useful for testing. + + @ivar retvals: A C{list} containing either strings or C{socket.error}s. + + @ivar connectedAddr: The address the socket is connected to. + """ + + def __init__(self, retvals): + self.retvals = retvals + self.connectedAddr = None + + + def connect(self, addr): + self.connectedAddr = addr + + + def recvfrom(self, size): + """ + Return (or raise) the next value from C{self.retvals}. + """ + ret = self.retvals.pop(0) + if isinstance(ret, socket.error): + raise ret + return ret, None + + + +class KeepReads(DatagramProtocol): + """ + Accumulate reads in a list. + """ + + def __init__(self): + self.reads = [] + + + def datagramReceived(self, data, addr): + self.reads.append(data) + + + +class ErrorsTestCase(unittest.TestCase): + """ + Error handling tests for C{udp.Port}. + """ + + def test_socketReadNormal(self): + """ + Socket reads with some good data followed by a socket error which can + be ignored causes reading to stop, and no log messages to be logged. + """ + # Add a fake error to the list of ignorables: + udp._sockErrReadIgnore.append(-7000) + self.addCleanup(udp._sockErrReadIgnore.remove, -7000) + + protocol = KeepReads() + port = udp.Port(None, protocol) + + # Normal result, no errors + port.socket = StringUDPSocket( + ["result", "123", socket.error(-7000), "456", + socket.error(-7000)]) + port.doRead() + # Read stops on error: + self.assertEqual(protocol.reads, ["result", "123"]) + port.doRead() + self.assertEqual(protocol.reads, ["result", "123", "456"]) + + + def test_readImmediateError(self): + """ + If the socket is unconnected, socket reads with an immediate + connection refusal are ignored, and reading stops. The protocol's + C{connectionRefused} method is not called. + """ + # Add a fake error to the list of those that count as connection + # refused: + udp._sockErrReadRefuse.append(-6000) + self.addCleanup(udp._sockErrReadRefuse.remove, -6000) + + protocol = KeepReads() + # Fail if connectionRefused is called: + protocol.connectionRefused = lambda: 1/0 + + port = udp.Port(None, protocol) + + # Try an immediate "connection refused" + port.socket = StringUDPSocket(["a", socket.error(-6000), "b", + socket.error(EWOULDBLOCK)]) + port.doRead() + # Read stops on error: + self.assertEqual(protocol.reads, ["a"]) + # Read again: + port.doRead() + self.assertEqual(protocol.reads, ["a", "b"]) + + + def test_connectedReadImmediateError(self): + """ + If the socket connected, socket reads with an immediate + connection refusal are ignored, and reading stops. The protocol's + C{connectionRefused} method is called. + """ + # Add a fake error to the list of those that count as connection + # refused: + udp._sockErrReadRefuse.append(-6000) + self.addCleanup(udp._sockErrReadRefuse.remove, -6000) + + protocol = KeepReads() + refused = [] + protocol.connectionRefused = lambda: refused.append(True) + + port = udp.Port(None, protocol) + port.socket = StringUDPSocket(["a", socket.error(-6000), "b", + socket.error(EWOULDBLOCK)]) + port.connect("127.0.0.1", 9999) + + # Read stops on error: + port.doRead() + self.assertEqual(protocol.reads, ["a"]) + self.assertEqual(refused, [True]) + + # Read again: + port.doRead() + self.assertEqual(protocol.reads, ["a", "b"]) + self.assertEqual(refused, [True]) + + + def test_readUnknownError(self): + """ + Socket reads with an unknown socket error are raised. + """ + protocol = KeepReads() + port = udp.Port(None, protocol) + + # Some good data, followed by an unknown error + port.socket = StringUDPSocket(["good", socket.error(-1337)]) + self.assertRaises(socket.error, port.doRead) + self.assertEqual(protocol.reads, ["good"]) diff -Nru twisted-11.1.0/twisted/internet/test/test_unix.py twisted-12.1.0/twisted/internet/test/test_unix.py --- twisted-11.1.0/twisted/internet/test/test_unix.py 2011-11-02 13:15:43.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/test_unix.py 2012-04-26 13:46:20.000000000 +0000 @@ -6,29 +6,47 @@ """ from stat import S_IMODE -from os import stat -from sys import platform +from os import stat, close from tempfile import mktemp +from socket import AF_INET, SOCK_STREAM, socket +from pprint import pformat try: from socket import AF_UNIX except ImportError: AF_UNIX = None +from zope.interface import implements from zope.interface.verify import verifyObject +from twisted.python.log import addObserver, removeObserver, err +from twisted.python.failure import Failure from twisted.python.hashlib import md5 -from twisted.internet.interfaces import IConnector +from twisted.python.runtime import platform +from twisted.internet.interfaces import IConnector, IFileDescriptorReceiver +from twisted.internet.error import ConnectionClosed, FileDescriptorOverrun from twisted.internet.address import UNIXAddress from twisted.internet.endpoints import UNIXServerEndpoint, UNIXClientEndpoint +from twisted.internet.defer import Deferred, fail +from twisted.internet.task import LoopingCall from twisted.internet import interfaces from twisted.internet.protocol import ( ServerFactory, ClientFactory, DatagramProtocol) -from twisted.internet.test.reactormixins import ReactorBuilder +from twisted.internet.test.reactormixins import ReactorBuilder, EndpointCreator from twisted.internet.test.test_core import ObjectModelIntegrationMixin from twisted.internet.test.test_tcp import StreamTransportTestsMixin +from twisted.internet.test.reactormixins import ( + ConnectableProtocol, runProtocolsWithReactor) from twisted.internet.test.connectionmixins import ConnectionTestsMixin +try: + from twisted.python import sendmsg +except ImportError: + sendmsgSkip = ( + "sendmsg extension unavailable, extended UNIX features disabled") +else: + sendmsgSkip = None + class UNIXFamilyMixin: """ @@ -59,11 +77,12 @@ return md5(case.mktemp()).hexdigest() -class UNIXTestsBuilder(UNIXFamilyMixin, ReactorBuilder, ConnectionTestsMixin): + +class UNIXCreator(EndpointCreator): """ - Builder defining tests relating to L{IReactorUNIX}. + Create UNIX socket end points. """ - def serverEndpoint(self, reactor): + def server(self, reactor): """ Construct a UNIX server endpoint. """ @@ -72,13 +91,125 @@ return UNIXServerEndpoint(reactor, path) - def clientEndpoint(self, reactor, serverAddress): + def client(self, reactor, serverAddress): """ Construct a UNIX client endpoint. """ return UNIXClientEndpoint(reactor, serverAddress.name) + +class SendFileDescriptor(ConnectableProtocol): + """ + L{SendFileDescriptorAndBytes} sends a file descriptor and optionally some + normal bytes and then closes its connection. + + @ivar reason: The reason the connection was lost, after C{connectionLost} + is called. + """ + reason = None + + def __init__(self, fd, data): + """ + @param fd: A C{int} giving a file descriptor to send over the + connection. + + @param data: A C{str} giving data to send over the connection, or + C{None} if no data is to be sent. + """ + self.fd = fd + self.data = data + + + def connectionMade(self): + """ + Send C{self.fd} and, if it is not C{None}, C{self.data}. Then close the + connection. + """ + self.transport.sendFileDescriptor(self.fd) + if self.data: + self.transport.write(self.data) + self.transport.loseConnection() + + + def connectionLost(self, reason): + ConnectableProtocol.connectionLost(self, reason) + self.reason = reason + + + +class ReceiveFileDescriptor(ConnectableProtocol): + """ + L{ReceiveFileDescriptor} provides an API for waiting for file descriptors to + be received. + + @ivar reason: The reason the connection was lost, after C{connectionLost} + is called. + + @ivar waiting: A L{Deferred} which fires with a file descriptor once one is + received, or with a failure if the connection is lost with no descriptor + arriving. + """ + implements(IFileDescriptorReceiver) + + reason = None + waiting = None + + def waitForDescriptor(self): + """ + Return a L{Deferred} which will fire with the next file descriptor + received, or with a failure if the connection is or has already been + lost. + """ + if self.reason is None: + self.waiting = Deferred() + return self.waiting + else: + return fail(self.reason) + + + def fileDescriptorReceived(self, descriptor): + """ + Fire the waiting Deferred, initialized by C{waitForDescriptor}, with the + file descriptor just received. + """ + self.waiting.callback(descriptor) + self.waiting = None + + + def dataReceived(self, data): + """ + Fail the waiting Deferred, if it has not already been fired by + C{fileDescriptorReceived}. The bytes sent along with a file descriptor + are guaranteed to be delivered to the protocol's C{dataReceived} method + only after the file descriptor has been delivered to the protocol's + C{fileDescriptorReceived}. + """ + if self.waiting is not None: + self.waiting.errback(Failure(Exception( + "Received bytes (%r) before descriptor." % (data,)))) + self.waiting = None + + + def connectionLost(self, reason): + """ + Fail the waiting Deferred, initialized by C{waitForDescriptor}, if there + is one. + """ + ConnectableProtocol.connectionLost(self, reason) + if self.waiting is not None: + self.waiting.errback(reason) + self.waiting = None + self.reason = reason + + + +class UNIXTestsBuilder(UNIXFamilyMixin, ReactorBuilder, ConnectionTestsMixin): + """ + Builder defining tests relating to L{IReactorUNIX}. + """ + endpoints = UNIXCreator() + def test_interface(self): """ L{IReactorUNIX.connectUNIX} returns an object providing L{IConnector}. @@ -107,7 +238,7 @@ reactor = self.buildReactor() port = reactor.listenUNIX('\0' + path, ServerFactory()) self.assertEqual(port.getHost(), UNIXAddress('\0' + path)) - if platform != 'linux2': + if not platform.isLinux(): test_listenOnLinuxAbstractNamespace.skip = ( 'Abstract namespace UNIX sockets only supported on Linux.') @@ -122,11 +253,239 @@ connector = reactor.connectUNIX('\0' + path, ClientFactory()) self.assertEqual( connector.getDestination(), UNIXAddress('\0' + path)) - if platform != 'linux2': + if not platform.isLinux(): test_connectToLinuxAbstractNamespace.skip = ( 'Abstract namespace UNIX sockets only supported on Linux.') + def test_addresses(self): + """ + A client's transport's C{getHost} and C{getPeer} return L{UNIXAddress} + instances which have the filesystem path of the host and peer ends of + the connection. + """ + class SaveAddress(ConnectableProtocol): + def makeConnection(self, transport): + self.addresses = dict( + host=transport.getHost(), peer=transport.getPeer()) + transport.loseConnection() + + server = SaveAddress() + client = SaveAddress() + + runProtocolsWithReactor(self, server, client, self.endpoints) + + self.assertEqual(server.addresses['host'], client.addresses['peer']) + self.assertEqual(server.addresses['peer'], client.addresses['host']) + + + def test_sendFileDescriptor(self): + """ + L{IUNIXTransport.sendFileDescriptor} accepts an integer file descriptor + and sends a copy of it to the process reading from the connection. + """ + from socket import fromfd + + s = socket() + s.bind(('', 0)) + server = SendFileDescriptor(s.fileno(), "junk") + + client = ReceiveFileDescriptor() + d = client.waitForDescriptor() + def checkDescriptor(descriptor): + received = fromfd(descriptor, AF_INET, SOCK_STREAM) + # Thanks for the free dup, fromfd() + close(descriptor) + + # If the sockets have the same local address, they're probably the + # same. + self.assertEqual(s.getsockname(), received.getsockname()) + + # But it would be cheating for them to be identified by the same + # file descriptor. The point was to get a copy, as we might get if + # there were two processes involved here. + self.assertNotEqual(s.fileno(), received.fileno()) + d.addCallback(checkDescriptor) + d.addErrback(err, "Sending file descriptor encountered a problem") + d.addBoth(lambda ignored: server.transport.loseConnection()) + + runProtocolsWithReactor(self, server, client, self.endpoints) + if sendmsgSkip is not None: + test_sendFileDescriptor.skip = sendmsgSkip + + + def test_sendFileDescriptorTriggersPauseProducing(self): + """ + If a L{IUNIXTransport.sendFileDescriptor} call fills up the send buffer, + any registered producer is paused. + """ + class DoesNotRead(ConnectableProtocol): + def connectionMade(self): + self.transport.pauseProducing() + + class SendsManyFileDescriptors(ConnectableProtocol): + paused = False + + def connectionMade(self): + self.socket = socket() + self.transport.registerProducer(self, True) + def sender(): + self.transport.sendFileDescriptor(self.socket.fileno()) + self.transport.write("x") + self.task = LoopingCall(sender) + self.task.clock = self.transport.reactor + self.task.start(0).addErrback(err, "Send loop failure") + + def stopProducing(self): + self._disconnect() + + def resumeProducing(self): + self._disconnect() + + def pauseProducing(self): + self.paused = True + self.transport.unregisterProducer() + self._disconnect() + + def _disconnect(self): + self.task.stop() + self.transport.abortConnection() + self.other.transport.abortConnection() + + server = SendsManyFileDescriptors() + client = DoesNotRead() + server.other = client + runProtocolsWithReactor(self, server, client, self.endpoints) + + self.assertTrue( + server.paused, "sendFileDescriptor producer was not paused") + if sendmsgSkip is not None: + test_sendFileDescriptorTriggersPauseProducing.skip = sendmsgSkip + + + def test_fileDescriptorOverrun(self): + """ + If L{IUNIXTransport.sendFileDescriptor} is used to queue a greater + number of file descriptors than the number of bytes sent using + L{ITransport.write}, the connection is closed and the protocol connected + to the transport has its C{connectionLost} method called with a failure + wrapping L{FileDescriptorOverrun}. + """ + cargo = socket() + server = SendFileDescriptor(cargo.fileno(), None) + + client = ReceiveFileDescriptor() + d = self.assertFailure( + client.waitForDescriptor(), ConnectionClosed) + d.addErrback( + err, "Sending file descriptor encountered unexpected problem") + d.addBoth(lambda ignored: server.transport.loseConnection()) + + runProtocolsWithReactor(self, server, client, self.endpoints) + + self.assertIsInstance(server.reason.value, FileDescriptorOverrun) + if sendmsgSkip is not None: + test_fileDescriptorOverrun.skip = sendmsgSkip + + + def test_avoidLeakingFileDescriptors(self): + """ + If associated with a protocol which does not provide + L{IFileDescriptorReceiver}, file descriptors received by the + L{IUNIXTransport} implementation are closed and a warning is emitted. + """ + # To verify this, establish a connection. Send one end of the + # connection over the IUNIXTransport implementation. After the copy + # should no longer exist, close the original. If the opposite end of + # the connection decides the connection is closed, the copy does not + # exist. + from socket import socketpair + probeClient, probeServer = socketpair() + + events = [] + addObserver(events.append) + self.addCleanup(removeObserver, events.append) + + class RecordEndpointAddresses(SendFileDescriptor): + def connectionMade(self): + self.hostAddress = self.transport.getHost() + self.peerAddress = self.transport.getPeer() + SendFileDescriptor.connectionMade(self) + + server = RecordEndpointAddresses(probeClient.fileno(), "junk") + client = ConnectableProtocol() + + runProtocolsWithReactor(self, server, client, self.endpoints) + + # Get rid of the original reference to the socket. + probeClient.close() + + # A non-blocking recv will return "" if the connection is closed, as + # desired. If the connection has not been closed, because the duplicate + # file descriptor is still open, it will fail with EAGAIN instead. + probeServer.setblocking(False) + self.assertEqual("", probeServer.recv(1024)) + + # This is a surprising circumstance, so it should be logged. + format = ( + "%(protocolName)s (on %(hostAddress)r) does not " + "provide IFileDescriptorReceiver; closing file " + "descriptor received (from %(peerAddress)r).") + clsName = "ConnectableProtocol" + + # Reverse host and peer, since the log event is from the client + # perspective. + expectedEvent = dict(hostAddress=server.peerAddress, + peerAddress=server.hostAddress, + protocolName=clsName, + format=format) + + for logEvent in events: + for k, v in expectedEvent.iteritems(): + if v != logEvent.get(k): + break + else: + # No mismatches were found, stop looking at events + break + else: + # No fully matching events were found, fail the test. + self.fail( + "Expected event (%s) not found in logged events (%s)" % ( + expectedEvent, pformat(events,))) + if sendmsgSkip is not None: + test_avoidLeakingFileDescriptors.skip = sendmsgSkip + + + def test_descriptorDeliveredBeforeBytes(self): + """ + L{IUNIXTransport.sendFileDescriptor} sends file descriptors before + L{ITransport.write} sends normal bytes. + """ + class RecordEvents(ConnectableProtocol): + implements(IFileDescriptorReceiver) + + def connectionMade(self): + ConnectableProtocol.connectionMade(self) + self.events = [] + + def fileDescriptorReceived(innerSelf, descriptor): + self.addCleanup(close, descriptor) + innerSelf.events.append(type(descriptor)) + + def dataReceived(self, data): + self.events.extend(data) + + cargo = socket() + server = SendFileDescriptor(cargo.fileno(), "junk") + client = RecordEvents() + + runProtocolsWithReactor(self, server, client, self.endpoints) + + self.assertEqual([int, "j", "u", "n", "k"], client.events) + if sendmsgSkip is not None: + test_descriptorDeliveredBeforeBytes.skip = sendmsgSkip + + class UNIXDatagramTestsBuilder(UNIXFamilyMixin, ReactorBuilder): """ @@ -153,7 +512,7 @@ reactor = self.buildReactor() port = reactor.listenUNIXDatagram('\0' + path, DatagramProtocol()) self.assertEqual(port.getHost(), UNIXAddress('\0' + path)) - if platform != 'linux2': + if not platform.isLinux(): test_listenOnLinuxAbstractNamespace.skip = ( 'Abstract namespace UNIX sockets only supported on Linux.') diff -Nru twisted-11.1.0/twisted/internet/test/_win32ifaces.py twisted-12.1.0/twisted/internet/test/_win32ifaces.py --- twisted-11.1.0/twisted/internet/test/_win32ifaces.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/internet/test/_win32ifaces.py 2011-12-12 17:13:08.000000000 +0000 @@ -0,0 +1,119 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Windows implementation of local network interface enumeration. +""" + +from socket import socket, AF_INET6, SOCK_STREAM +from ctypes import ( + WinDLL, byref, create_string_buffer, c_int, c_void_p, + POINTER, Structure, cast, string_at) + +WS2_32 = WinDLL('ws2_32') + +SOCKET = c_int +DWORD = c_int +LPVOID = c_void_p +LPSOCKADDR = c_void_p +LPWSAPROTOCOL_INFO = c_void_p +LPTSTR = c_void_p +LPDWORD = c_void_p +LPWSAOVERLAPPED = c_void_p +LPWSAOVERLAPPED_COMPLETION_ROUTINE = c_void_p + +# http://msdn.microsoft.com/en-us/library/ms741621(v=VS.85).aspx +# int WSAIoctl( +# __in SOCKET s, +# __in DWORD dwIoControlCode, +# __in LPVOID lpvInBuffer, +# __in DWORD cbInBuffer, +# __out LPVOID lpvOutBuffer, +# __in DWORD cbOutBuffer, +# __out LPDWORD lpcbBytesReturned, +# __in LPWSAOVERLAPPED lpOverlapped, +# __in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine +# ); +WSAIoctl = WS2_32.WSAIoctl +WSAIoctl.argtypes = [ + SOCKET, DWORD, LPVOID, DWORD, LPVOID, DWORD, LPDWORD, + LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE] +WSAIoctl.restype = c_int + +# http://msdn.microsoft.com/en-us/library/ms741516(VS.85).aspx +# INT WSAAPI WSAAddressToString( +# __in LPSOCKADDR lpsaAddress, +# __in DWORD dwAddressLength, +# __in_opt LPWSAPROTOCOL_INFO lpProtocolInfo, +# __inout LPTSTR lpszAddressString, +# __inout LPDWORD lpdwAddressStringLength +# ); +WSAAddressToString = WS2_32.WSAAddressToStringA +WSAAddressToString.argtypes = [ + LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFO, LPTSTR, LPDWORD] +WSAAddressToString.restype = c_int + + +SIO_ADDRESS_LIST_QUERY = 0x48000016 +WSAEFAULT = 10014 + +class SOCKET_ADDRESS(Structure): + _fields_ = [('lpSockaddr', c_void_p), + ('iSockaddrLength', c_int)] + + + +def make_SAL(ln): + class SOCKET_ADDRESS_LIST(Structure): + _fields_ = [('iAddressCount', c_int), + ('Address', SOCKET_ADDRESS * ln)] + return SOCKET_ADDRESS_LIST + + + +def win32GetLinkLocalIPv6Addresses(): + """ + Return a list of strings in colon-hex format representing all the link local + IPv6 addresses available on the system, as reported by + I{WSAIoctl}/C{SIO_ADDRESS_LIST_QUERY}. + """ + s = socket(AF_INET6, SOCK_STREAM) + size = 4096 + retBytes = c_int() + for i in range(2): + buf = create_string_buffer(size) + ret = WSAIoctl( + s.fileno(), + SIO_ADDRESS_LIST_QUERY, 0, 0, buf, size, byref(retBytes), 0, 0) + + # WSAIoctl might fail with WSAEFAULT, which means there was not enough + # space in the buffer we gave it. There's no way to check the errno + # until Python 2.6, so we don't even try. :/ Maybe if retBytes is still + # 0 another error happened, though. + if ret and retBytes.value: + size = retBytes.value + else: + break + + # If it failed, then we'll just have to give up. Still no way to see why. + if ret: + raise RuntimeError("WSAIoctl failure") + + addrList = cast(buf, POINTER(make_SAL(0))) + addrCount = addrList[0].iAddressCount + addrList = cast(buf, POINTER(make_SAL(addrCount))) + + addressStringBufLength = 1024 + addressStringBuf = create_string_buffer(addressStringBufLength) + + retList = [] + for i in range(addrList[0].iAddressCount): + retBytes.value = addressStringBufLength + addr = addrList[0].Address[i] + ret = WSAAddressToString( + addr.lpSockaddr, addr.iSockaddrLength, 0, addressStringBuf, + byref(retBytes)) + if ret: + raise RuntimeError("WSAAddressToString failure") + retList.append(string_at(addressStringBuf)) + return [addr for addr in retList if '%' in addr] diff -Nru twisted-11.1.0/twisted/internet/udp.py twisted-12.1.0/twisted/internet/udp.py --- twisted-11.1.0/twisted/internet/udp.py 2011-10-16 19:41:49.000000000 +0000 +++ twisted-12.1.0/twisted/internet/udp.py 2011-11-10 00:36:47.000000000 +0000 @@ -7,7 +7,12 @@ Please do not use this module directly. -Maintainer: Itamar Shtull-Trauring +@var _sockErrReadIgnore: list of symbolic error constants (from the C{errno} + module) representing socket errors where the error is temporary and can be + ignored. + +@var _sockErrReadRefuse: list of symbolic error constants (from the C{errno} + module) representing socket errors that indicate connection refused. """ # System Imports @@ -20,14 +25,25 @@ from twisted.python.runtime import platformType if platformType == 'win32': - from errno import WSAEWOULDBLOCK as EWOULDBLOCK - from errno import WSAEINTR as EINTR - from errno import WSAEMSGSIZE as EMSGSIZE - from errno import WSAECONNREFUSED as ECONNREFUSED - from errno import WSAECONNRESET - EAGAIN = EWOULDBLOCK + from errno import WSAEWOULDBLOCK + from errno import WSAEINTR, WSAEMSGSIZE, WSAETIMEDOUT + from errno import WSAECONNREFUSED, WSAECONNRESET, WSAENETRESET + from errno import WSAEINPROGRESS + + # Classify read and write errors + _sockErrReadIgnore = [WSAEINTR, WSAEWOULDBLOCK, WSAEMSGSIZE, WSAEINPROGRESS] + _sockErrReadRefuse = [WSAECONNREFUSED, WSAECONNRESET, WSAENETRESET, + WSAETIMEDOUT] + + # POSIX-compatible write errors + EMSGSIZE = WSAEMSGSIZE + ECONNREFUSED = WSAECONNREFUSED + EAGAIN = WSAEWOULDBLOCK + EINTR = WSAEINTR else: from errno import EWOULDBLOCK, EINTR, EMSGSIZE, ECONNREFUSED, EAGAIN + _sockErrReadIgnore = [EAGAIN, EINTR, EWOULDBLOCK] + _sockErrReadRefuse = [ECONNREFUSED] # Twisted Imports from twisted.internet import base, defer, address @@ -118,13 +134,13 @@ data, addr = self.socket.recvfrom(self.maxPacketSize) except socket.error, se: no = se.args[0] - if no in (EAGAIN, EINTR, EWOULDBLOCK): + if no in _sockErrReadIgnore: return - if (no == ECONNREFUSED) or (platformType == "win32" and no == WSAECONNRESET): + if no in _sockErrReadRefuse: if self._connectedAddr: self.protocol.connectionRefused() - else: - raise + return + raise else: read += len(data) try: diff -Nru twisted-11.1.0/twisted/internet/unix.py twisted-12.1.0/twisted/internet/unix.py --- twisted-11.1.0/twisted/internet/unix.py 2011-10-11 12:01:26.000000000 +0000 +++ twisted-12.1.0/twisted/internet/unix.py 2012-04-26 13:46:20.000000000 +0000 @@ -12,8 +12,8 @@ """ # System imports -import os, sys, stat, socket -from errno import EINTR, EMSGSIZE, EAGAIN, EWOULDBLOCK, ECONNREFUSED +import os, sys, stat, socket, struct +from errno import EINTR, EMSGSIZE, EAGAIN, EWOULDBLOCK, ECONNREFUSED, ENOBUFS from zope.interface import implements, implementsOnly, implementedBy @@ -21,20 +21,190 @@ raise ImportError("UNIX sockets not supported on this platform") # Twisted imports -from twisted.internet import base, tcp, udp, error, interfaces, protocol, address +from twisted.internet import main, base, tcp, udp, error, interfaces, protocol, address from twisted.internet.error import CannotListenError +from twisted.python.util import untilConcludes from twisted.python import lockfile, log, reflect, failure +try: + from twisted.python import sendmsg +except ImportError: + sendmsg = None + + +def _ancillaryDescriptor(fd): + """ + Pack an integer into an ancillary data structure suitable for use with + L{sendmsg.send1msg}. + """ + packed = struct.pack("i", fd) + return [(socket.SOL_SOCKET, sendmsg.SCM_RIGHTS, packed)] + + + +class _SendmsgMixin(object): + """ + Mixin for stream-oriented UNIX transports which uses sendmsg and recvmsg to + offer additional functionality, such as copying file descriptors into other + processes. + + @ivar _writeSomeDataBase: The class which provides the basic implementation + of C{writeSomeData}. Ultimately this should be a subclass of + L{twisted.internet.abstract.FileDescriptor}. Subclasses which mix in + L{_SendmsgMixin} must define this. + + @ivar _sendmsgQueue: A C{list} of C{int} holding file descriptors which are + currently buffered before being sent. + + @ivar _fileDescriptorBufferSize: An C{int} giving the maximum number of file + descriptors to accept and queue for sending before pausing the + registered producer, if there is one. + """ + implements(interfaces.IUNIXTransport) + + _writeSomeDataBase = None + _fileDescriptorBufferSize = 64 + + def __init__(self): + self._sendmsgQueue = [] + + + def _isSendBufferFull(self): + """ + Determine whether the user-space send buffer for this transport is full + or not. + + This extends the base determination by adding consideration of how many + file descriptors need to be sent using L{sendmsg.send1msg}. When there + are more than C{self._fileDescriptorBufferSize}, the buffer is + considered full. + + @return: C{True} if it is full, C{False} otherwise. + """ + # There must be some bytes in the normal send buffer, checked by + # _writeSomeDataBase._isSendBufferFull, in order to send file + # descriptors from _sendmsgQueue. That means that the buffer will + # eventually be considered full even without this additional logic. + # However, since we send only one byte per file descriptor, having lots + # of elements in _sendmsgQueue incurs more overhead and perhaps slows + # things down. Anyway, try this for now, maybe rethink it later. + return ( + len(self._sendmsgQueue) > self._fileDescriptorBufferSize + or self._writeSomeDataBase._isSendBufferFull(self)) + + + def sendFileDescriptor(self, fileno): + """ + Queue the given file descriptor to be sent and start trying to send it. + """ + self._sendmsgQueue.append(fileno) + self._maybePauseProducer() + self.startWriting() + + + def writeSomeData(self, data): + """ + Send as much of C{data} as possible. Also send any pending file + descriptors. + """ + # Make it a programming error to send more file descriptors than you + # send regular bytes. Otherwise, due to the limitation mentioned below, + # we could end up with file descriptors left, but no bytes to send with + # them, therefore no way to send those file descriptors. + if len(self._sendmsgQueue) > len(data): + return error.FileDescriptorOverrun() + + # If there are file descriptors to send, try sending them first, using a + # little bit of data from the stream-oriented write buffer too. It is + # not possible to send a file descriptor without sending some regular + # data. + index = 0 + try: + while index < len(self._sendmsgQueue): + fd = self._sendmsgQueue[index] + try: + untilConcludes( + sendmsg.send1msg, self.socket.fileno(), data[index], 0, + _ancillaryDescriptor(fd)) + except socket.error, se: + if se.args[0] in (EWOULDBLOCK, ENOBUFS): + return index + else: + return main.CONNECTION_LOST + else: + index += 1 + finally: + del self._sendmsgQueue[:index] + + # Hand the remaining data to the base implementation. Avoid slicing in + # favor of a buffer, in case that happens to be any faster. + limitedData = buffer(data, index) + result = self._writeSomeDataBase.writeSomeData(self, limitedData) + try: + return index + result + except TypeError: + return result + + + def doRead(self): + """ + Calls L{IFileDescriptorReceiver.fileDescriptorReceived} and + L{IProtocol.dataReceived} with all available data. + + This reads up to C{self.bufferSize} bytes of data from its socket, then + dispatches the data to protocol callbacks to be handled. If the + connection is not lost through an error in the underlying recvmsg(), + this function will return the result of the dataReceived call. + """ + try: + data, flags, ancillary = untilConcludes( + sendmsg.recv1msg, self.socket.fileno(), 0, self.bufferSize) + except socket.error, se: + if se.args[0] == EWOULDBLOCK: + return + else: + return main.CONNECTION_LOST + + if ancillary: + fd = struct.unpack('i', ancillary[0][2])[0] + if interfaces.IFileDescriptorReceiver.providedBy(self.protocol): + self.protocol.fileDescriptorReceived(fd) + else: + log.msg( + format=( + "%(protocolName)s (on %(hostAddress)r) does not " + "provide IFileDescriptorReceiver; closing file " + "descriptor received (from %(peerAddress)r)."), + hostAddress=self.getHost(), peerAddress=self.getPeer(), + protocolName=self._getLogPrefix(self.protocol), + ) + os.close(fd) + + return self._dataReceived(data) + +if sendmsg is None: + class _SendmsgMixin(object): + """ + Behaviorless placeholder used when L{twisted.python.sendmsg} is not + available, preventing L{IUNIXTransport} from being supported. + """ + + + +class Server(_SendmsgMixin, tcp.Server): + + _writeSomeDataBase = tcp.Server -class Server(tcp.Server): def __init__(self, sock, protocol, client, server, sessionno, reactor): + _SendmsgMixin.__init__(self) tcp.Server.__init__(self, sock, protocol, (client, None), server, sessionno, reactor) + def getHost(self): return address.UNIXAddress(self.socket.getsockname()) def getPeer(self): - return address.UNIXAddress(self.hostname) + return address.UNIXAddress(self.hostname or None) @@ -149,12 +319,15 @@ -class Client(tcp.BaseClient): +class Client(_SendmsgMixin, tcp.BaseClient): """A client for Unix sockets.""" addressFamily = socket.AF_UNIX socketType = socket.SOCK_STREAM + _writeSomeDataBase = tcp.BaseClient + def __init__(self, filename, connector, reactor=None, checkPID = 0): + _SendmsgMixin.__init__(self) self.connector = connector self.realAddress = self.addr = filename if checkPID and not lockfile.isLocked(filename + ".lock"): diff -Nru twisted-11.1.0/twisted/internet/win32eventreactor.py twisted-12.1.0/twisted/internet/win32eventreactor.py --- twisted-11.1.0/twisted/internet/win32eventreactor.py 2011-11-02 13:15:43.000000000 +0000 +++ twisted-12.1.0/twisted/internet/win32eventreactor.py 2011-12-22 18:40:35.000000000 +0000 @@ -248,7 +248,7 @@ handles = self._events.keys() or [self.dummyEvent] timeout = int(timeout * 1000) - val = MsgWaitForMultipleObjects(handles, 0, timeout, QS_ALLINPUT | QS_ALLEVENTS) + val = MsgWaitForMultipleObjects(handles, 0, timeout, QS_ALLINPUT) if val == WAIT_TIMEOUT: return elif val == WAIT_OBJECT_0 + len(handles): diff -Nru twisted-11.1.0/twisted/persisted/__init__.py twisted-12.1.0/twisted/persisted/__init__.py --- twisted-11.1.0/twisted/persisted/__init__.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/persisted/__init__.py 2012-03-10 15:22:17.000000000 +0000 @@ -4,12 +4,3 @@ """ Twisted Persisted: utilities for managing persistence. """ - - -from twisted.python import versions, deprecate - -deprecate.deprecatedModuleAttribute(versions.Version('twisted', 11, 0, 0), - "Use a different persistence library. This one " - "is no longer maintained.", - __name__, 'journal') - diff -Nru twisted-11.1.0/twisted/persisted/journal/base.py twisted-12.1.0/twisted/persisted/journal/base.py --- twisted-11.1.0/twisted/persisted/journal/base.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/persisted/journal/base.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,226 +0,0 @@ -# -*- test-case-name: twisted.test.test_journal -*- -# -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -# - - -"""Basic classes and interfaces for journal.""" - -from __future__ import nested_scopes - -# system imports -import os, time - -try: - import cPickle as pickle -except ImportError: - import pickle - -# twisted imports -from zope.interface import implements, Interface - - -class Journal: - """All commands to the system get routed through here. - - Subclasses should implement the actual snapshotting capability. - """ - - def __init__(self, log, journaledService): - self.log = log - self.journaledService = journaledService - self.latestIndex = self.log.getCurrentIndex() - - def updateFromLog(self): - """Run all commands from log that haven't been run yet. - - This method should be run on startup to ensure the snapshot - is up-to-date. - """ - snapshotIndex = self.getLastSnapshot() - if snapshotIndex < self.latestIndex: - for cmdtime, command in self.log.getCommandsSince(snapshotIndex + 1): - command.execute(self.journaledService, cmdtime) - - def executeCommand(self, command): - """Log and execute a command.""" - runTime = time.time() - d = self.log.logCommand(command, runTime) - d.addCallback(self._reallyExecute, command, runTime) - return d - - def _reallyExecute(self, index, command, runTime): - """Callback called when logging command is done.""" - result = command.execute(self.journaledService, runTime) - self.latestIndex = index - return result - - def getLastSnapshot(self): - """Return command index of the last snapshot taken.""" - raise NotImplementedError - - def sync(self, *args, **kwargs): - """Save journal to disk, returns Deferred of finish status. - - Subclasses may choose whatever signature is appropriate, or may - not implement this at all. - """ - raise NotImplementedError - - - -class MemoryJournal(Journal): - """Prevayler-like journal that dumps from memory to disk.""" - - def __init__(self, log, journaledService, path, loadedCallback): - self.path = path - if os.path.exists(path): - try: - self.lastSync, obj = pickle.load(open(path, "rb")) - except (IOError, OSError, pickle.UnpicklingError): - self.lastSync, obj = 0, None - loadedCallback(obj) - else: - self.lastSync = 0 - loadedCallback(None) - Journal.__init__(self, log, journaledService) - - def getLastSnapshot(self): - return self.lastSync - - def sync(self, obj): - # make this more reliable at some point - f = open(self.path, "wb") - pickle.dump((self.latestIndex, obj), f, 1) - f.close() - self.lastSync = self.latestIndex - - -class ICommand(Interface): - """A serializable command which interacts with a journaled service.""" - - def execute(journaledService, runTime): - """Run the command and return result.""" - - -class ICommandLog(Interface): - """Interface for command log.""" - - def logCommand(command, runTime): - """Add a command and its run time to the log. - - @return: Deferred of command index. - """ - - def getCurrentIndex(): - """Return index of last command that was logged.""" - - def getCommandsSince(index): - """Return commands who's index >= the given one. - - @return: list of (time, command) tuples, sorted with ascending times. - """ - - -class LoadingService: - """Base class for journalled service used with Wrappables.""" - - def loadObject(self, objType, objId): - """Return object of specified type and id.""" - raise NotImplementedError - - -class Wrappable: - """Base class for objects used with LoadingService.""" - - objectType = None # override in base class - - def getUid(self): - """Return uid for loading with LoadingService.loadObject""" - raise NotImplementedError - - -class WrapperCommand: - - implements(ICommand) - - def __init__(self, methodName, obj, args=(), kwargs={}): - self.obj = obj - self.objId = obj.getUid() - self.objType = obj.objectType - self.methodName = methodName - self.args = args - self.kwargs = kwargs - - def execute(self, svc, commandTime): - if not hasattr(self, "obj"): - obj = svc.loadObject(self.objType, self.objId) - else: - obj = self.obj - return getattr(obj, self.methodName)(*self.args, **self.kwargs) - - def __getstate__(self): - d = self.__dict__.copy() - del d["obj"] - return d - - -def command(methodName, cmdClass=WrapperCommand): - """Wrap a method so it gets turned into command automatically. - - For use with Wrappables. - - Usage:: - - | class Foo(Wrappable): - | objectType = "foo" - | def getUid(self): - | return self.id - | def _bar(self, x): - | return x + 1 - | - | bar = command('_bar') - - The resulting callable will have signature identical to wrapped - function, except that it expects journal as first argument, and - returns a Deferred. - """ - def wrapper(obj, journal, *args, **kwargs): - return journal.executeCommand(cmdClass(methodName, obj, args, kwargs)) - return wrapper - - -class ServiceWrapperCommand: - - implements(ICommand) - - def __init__(self, methodName, args=(), kwargs={}): - self.methodName = methodName - self.args = args - self.kwargs = kwargs - - def execute(self, svc, commandTime): - return getattr(svc, self.methodName)(*self.args, **self.kwargs) - - def __repr__(self): - return "" % (self.methodName, self.args, self.kwargs) - - def __cmp__(self, other): - if hasattr(other, "__dict__"): - return cmp(self.__dict__, other.__dict__) - else: - return 0 - - -def serviceCommand(methodName, cmdClass=ServiceWrapperCommand): - """Wrap methods into commands for a journalled service. - - The resulting callable will have signature identical to wrapped - function, except that it expects journal as first argument, and - returns a Deferred. - """ - def wrapper(obj, journal, *args, **kwargs): - return journal.executeCommand(cmdClass(methodName, args, kwargs)) - return wrapper diff -Nru twisted-11.1.0/twisted/persisted/journal/__init__.py twisted-12.1.0/twisted/persisted/journal/__init__.py --- twisted-11.1.0/twisted/persisted/journal/__init__.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/persisted/journal/__init__.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - - -""" -Command-journalling persistence framework inspired by Prevayler. - -This package is deprecated since Twisted 11.0. - -Maintainer: Itamar Shtull-Trauring -""" - diff -Nru twisted-11.1.0/twisted/persisted/journal/picklelog.py twisted-12.1.0/twisted/persisted/journal/picklelog.py --- twisted-11.1.0/twisted/persisted/journal/picklelog.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/persisted/journal/picklelog.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -# -# -*- test-case-name: twisted.test.test_journal -*- - -"""Logging that uses pickles. - -TODO: add log that logs to a file. -""" - -# twisted imports -from twisted.persisted import dirdbm -from twisted.internet import defer -from zope.interface import implements - -# sibling imports -import base - - -class DirDBMLog: - """Log pickles to DirDBM directory.""" - - implements(base.ICommandLog) - - def __init__(self, logPath): - self.db = dirdbm.Shelf(logPath) - indexs = map(int, self.db.keys()) - if indexs: - self.currentIndex = max(indexs) - else: - self.currentIndex = 0 - - def logCommand(self, command, time): - """Log a command.""" - self.currentIndex += 1 - self.db[str(self.currentIndex)] = (time, command) - return defer.succeed(1) - - def getCurrentIndex(self): - """Return index of last command logged.""" - return self.currentIndex - - def getCommandsSince(self, index): - result = [] - for i in range(index, self.currentIndex + 1): - result.append(self.db[str(i)]) - return result diff -Nru twisted-11.1.0/twisted/persisted/journal/rowjournal.py twisted-12.1.0/twisted/persisted/journal/rowjournal.py --- twisted-11.1.0/twisted/persisted/journal/rowjournal.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/persisted/journal/rowjournal.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,99 +0,0 @@ -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -# - -"""Journal using twisted.enterprise.row RDBMS support. - -You're going to need the following table in your database:: - - | CREATE TABLE journalinfo - | ( - | commandIndex int - | ); - | INSERT INTO journalinfo VALUES (0); - -""" - -from __future__ import nested_scopes - -# twisted imports -from twisted.internet import defer - -# sibling imports -import base - - -# constants for command list -INSERT, DELETE, UPDATE = range(3) - - -class RowJournal(base.Journal): - """Journal that stores data 'snapshot' in using twisted.enterprise.row. - - Use this as the reflector instead of the original reflector. - - It may block on creation, if it has to run recovery. - """ - - def __init__(self, log, journaledService, reflector): - self.reflector = reflector - self.commands = [] - self.syncing = 0 - base.Journal.__init__(self, log, journaledService) - - def updateRow(self, obj): - """Mark on object for updating when sync()ing.""" - self.commands.append((UPDATE, obj)) - - def insertRow(self, obj): - """Mark on object for inserting when sync()ing.""" - self.commands.append((INSERT, obj)) - - def deleteRow(self, obj): - """Mark on object for deleting when sync()ing.""" - self.commands.append((DELETE, obj)) - - def loadObjectsFrom(self, tableName, parentRow=None, data=None, whereClause=None, forceChildren=0): - """Flush all objects to the database and then load objects.""" - d = self.sync() - d.addCallback(lambda result: self.reflector.loadObjectsFrom( - tableName, parentRow=parentRow, data=data, whereClause=whereClause, - forceChildren=forceChildren)) - return d - - def sync(self): - """Commit changes to database.""" - if self.syncing: - raise ValueError, "sync already in progress" - comandMap = {INSERT : self.reflector.insertRowSQL, - UPDATE : self.reflector.updateRowSQL, - DELETE : self.reflector.deleteRowSQL} - sqlCommands = [] - for kind, obj in self.commands: - sqlCommands.append(comandMap[kind](obj)) - self.commands = [] - if sqlCommands: - self.syncing = 1 - d = self.reflector.dbpool.runInteraction(self._sync, self.latestIndex, sqlCommands) - d.addCallback(self._syncDone) - return d - else: - return defer.succeed(1) - - def _sync(self, txn, index, commands): - """Do the actual database synchronization.""" - for c in commands: - txn.execute(c) - txn.update("UPDATE journalinfo SET commandIndex = %d" % index) - - def _syncDone(self, result): - self.syncing = 0 - return result - - def getLastSnapshot(self): - """Return command index of last snapshot.""" - conn = self.reflector.dbpool.connect() - cursor = conn.cursor() - cursor.execute("SELECT commandIndex FROM journalinfo") - return cursor.fetchall()[0][0] diff -Nru twisted-11.1.0/twisted/plugins/cred_sshkeys.py twisted-12.1.0/twisted/plugins/cred_sshkeys.py --- twisted-11.1.0/twisted/plugins/cred_sshkeys.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/plugins/cred_sshkeys.py 2012-03-12 21:35:11.000000000 +0000 @@ -0,0 +1,51 @@ +# -*- test-case-name: twisted.test.test_strcred -*- +# +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Cred plugin for ssh key login +""" + +from zope.interface import implements + +from twisted import plugin +from twisted.cred.strcred import ICheckerFactory +from twisted.cred.credentials import ISSHPrivateKey + + +sshKeyCheckerFactoryHelp = """ +This allows SSH public key authentication, based on public keys listed in +authorized_keys and authorized_keys2 files in user .ssh/ directories. +""" + + +try: + from twisted.conch.checkers import SSHPublicKeyDatabase + + class SSHKeyCheckerFactory(object): + """ + Generates checkers that will authenticate a SSH public key + """ + implements(ICheckerFactory, plugin.IPlugin) + authType = 'sshkey' + authHelp = sshKeyCheckerFactoryHelp + argStringFormat = 'No argstring required.' + credentialInterfaces = SSHPublicKeyDatabase.credentialInterfaces + + + def generateChecker(self, argstring=''): + """ + This checker factory ignores the argument string. Everything + needed to authenticate users is pulled out of the public keys + listed in user .ssh/ directories. + """ + return SSHPublicKeyDatabase() + + + + theSSHKeyCheckerFactory = SSHKeyCheckerFactory() + +except ImportError: + # if checkers can't be imported, then there should be no SSH cred plugin + pass diff -Nru twisted-11.1.0/twisted/plugins/twisted_core.py twisted-12.1.0/twisted/plugins/twisted_core.py --- twisted-11.1.0/twisted/plugins/twisted_core.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/plugins/twisted_core.py 2012-04-04 21:03:05.000000000 +0000 @@ -0,0 +1,6 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +from twisted.internet.endpoints import _SystemdParser + +systemdEndpointParser = _SystemdParser() diff -Nru twisted-11.1.0/twisted/plugins/twisted_reactors.py twisted-12.1.0/twisted/plugins/twisted_reactors.py --- twisted-11.1.0/twisted/plugins/twisted_reactors.py 2011-05-05 02:48:02.000000000 +0000 +++ twisted-12.1.0/twisted/plugins/twisted_reactors.py 2012-01-25 03:20:58.000000000 +0000 @@ -11,6 +11,10 @@ 'select', 'twisted.internet.selectreactor', 'select(2)-based reactor.') wx = Reactor( 'wx', 'twisted.internet.wxreactor', 'wxPython integration reactor.') +gi = Reactor( + 'gi', 'twisted.internet.gireactor', 'GObject Introspection integration reactor.') +gtk3 = Reactor( + 'gtk3', 'twisted.internet.gtk3reactor', 'Gtk3 integration reactor.') gtk = Reactor( 'gtk', 'twisted.internet.gtkreactor', 'Gtk1 integration reactor.') gtk2 = Reactor( diff -Nru twisted-11.1.0/twisted/protocols/amp.py twisted-12.1.0/twisted/protocols/amp.py --- twisted-11.1.0/twisted/protocols/amp.py 2011-09-23 12:30:19.000000000 +0000 +++ twisted-12.1.0/twisted/protocols/amp.py 2012-05-09 18:58:59.000000000 +0000 @@ -178,6 +178,7 @@ from cStringIO import StringIO from struct import pack import decimal, datetime +from itertools import count from zope.interface import Interface, implements @@ -187,6 +188,7 @@ from twisted.python.failure import Failure from twisted.python import log, filepath +from twisted.internet.interfaces import IFileDescriptorReceiver from twisted.internet.main import CONNECTION_LOST from twisted.internet.error import PeerVerifyError, ConnectionLost from twisted.internet.error import ConnectionClosed @@ -1473,6 +1475,74 @@ objects, self.subargs, Box(), proto ).serialize() for objects in inObject]) + + +class Descriptor(Integer): + """ + Encode and decode file descriptors for exchange over a UNIX domain socket. + + This argument type requires an AMP connection set up over an + L{IUNIXTransport} provider (for + example, the kind of connection created by + L{IReactorUNIX.connectUNIX} + and L{UNIXClientEndpoint}). + + There is no correspondence between the integer value of the file descriptor + on the sending and receiving sides, therefore an alternate approach is taken + to matching up received descriptors with particular L{Descriptor} + parameters. The argument is encoded to an ordinal (unique per connection) + for inclusion in the AMP command or response box. The descriptor itself is + sent using + L{IUNIXTransport.sendFileDescriptor}. + The receiver uses the order in which file descriptors are received and the + ordinal value to come up with the received copy of the descriptor. + """ + def fromStringProto(self, inString, proto): + """ + Take a unique identifier associated with a file descriptor which must + have been received by now and use it to look up that descriptor in a + dictionary where they are kept. + + @param inString: The base representation (as a byte string) of an + ordinal indicating which file descriptor corresponds to this usage + of this argument. + @type inString: C{str} + + @param proto: The protocol used to receive this descriptor. This + protocol must be connected via a transport providing + L{IUNIXTransport}. + @type proto: L{BinaryBoxProtocol} + + @return: The file descriptor represented by C{inString}. + @rtype: C{int} + """ + return proto._getDescriptor(int(inString)) + + + def toStringProto(self, inObject, proto): + """ + Send C{inObject}, an integer file descriptor, over C{proto}'s connection + and return a unique identifier which will allow the receiver to + associate the file descriptor with this argument. + + @param inObject: A file descriptor to duplicate over an AMP connection + as the value for this argument. + @type inObject: C{int} + + @param proto: The protocol which will be used to send this descriptor. + This protocol must be connected via a transport providing + L{IUNIXTransport}. + + @return: A byte string which can be used by the receiver to reconstruct + the file descriptor. + @type: C{str} + """ + identifier = proto._sendFileDescriptor(inObject) + outString = Integer.toStringProto(self, identifier, proto) + return outString + + + class Command: """ Subclass me to specify an AMP Command. @@ -1929,9 +1999,61 @@ -class BinaryBoxProtocol(StatefulStringProtocol, Int16StringReceiver): +class _DescriptorExchanger(object): + """ + L{_DescriptorExchanger} is a mixin for L{BinaryBoxProtocol} which adds + support for receiving file descriptors, a feature offered by + L{IUNIXTransport}. + + @ivar _descriptors: Temporary storage for all file descriptors received. + Values in this dictionary are the file descriptors (as integers). Keys + in this dictionary are ordinals giving the order in which each + descriptor was received. The ordering information is used to allow + L{Descriptor} to determine which is the correct descriptor for any + particular usage of that argument type. + @type _descriptors: C{dict} + + @ivar _sendingDescriptorCounter: A no-argument callable which returns the + ordinals, starting from 0. This is used to construct values for + C{_sendFileDescriptor}. + + @ivar _receivingDescriptorCounter: A no-argument callable which returns the + ordinals, starting from 0. This is used to construct values for + C{fileDescriptorReceived}. + """ + implements(IFileDescriptorReceiver) + + def __init__(self): + self._descriptors = {} + self._getDescriptor = self._descriptors.pop + self._sendingDescriptorCounter = count().next + self._receivingDescriptorCounter = count().next + + + def _sendFileDescriptor(self, descriptor): + """ + Assign and return the next ordinal to the given descriptor after sending + the descriptor over this protocol's transport. + """ + self.transport.sendFileDescriptor(descriptor) + return self._sendingDescriptorCounter() + + + def fileDescriptorReceived(self, descriptor): + """ + Collect received file descriptors to be claimed later by L{Descriptor}. + + @param descriptor: The received file descriptor. + @type descriptor: C{int} + """ + self._descriptors[self._receivingDescriptorCounter()] = descriptor + + + +class BinaryBoxProtocol(StatefulStringProtocol, Int16StringReceiver, + _DescriptorExchanger): """ - A protocol for receving L{Box}es - key/value pairs - via length-prefixed + A protocol for receiving L{AmpBox}es - key/value pairs - via length-prefixed strings. A box is composed of: - any number of key-value pairs, described by: @@ -1958,7 +2080,7 @@ than allowed by the protocol was received. @ivar boxReceiver: an L{IBoxReceiver} provider, whose L{ampBoxReceived} - method will be invoked for each L{Box} that is received. + method will be invoked for each L{AmpBox} that is received. """ implements(IBoxSender) @@ -1977,6 +2099,7 @@ innerProtocolClientFactory = None def __init__(self, boxReceiver): + _DescriptorExchanger.__init__(self) self.boxReceiver = boxReceiver diff -Nru twisted-11.1.0/twisted/protocols/ftp.py twisted-12.1.0/twisted/protocols/ftp.py --- twisted-11.1.0/twisted/protocols/ftp.py 2011-09-18 20:08:09.000000000 +0000 +++ twisted-12.1.0/twisted/protocols/ftp.py 2012-01-15 18:31:09.000000000 +0000 @@ -1027,6 +1027,17 @@ def ftp_RETR(self, path): + """ + This command causes the content of a file to be sent over the data + transfer channel. If the path is to a folder, an error will be raised. + + @type path: C{str} + @param path: The path to the file which should be transferred over the + data transfer channel. + + @rtype: L{Deferred} + @return: a L{Deferred} which will be fired when the transfer is done. + """ if self.dtpInstance is None: raise BadCmdSequenceError('PORT or PASV required before RETR') @@ -1071,7 +1082,7 @@ return d def ebOpened(err): - if not err.check(PermissionDeniedError, FileNotFoundError, IsNotADirectoryError): + if not err.check(PermissionDeniedError, FileNotFoundError, IsADirectoryError): log.msg("Unexpected error attempting to open file for transmission:") log.err(err) if err.check(FTPCmdError): diff -Nru twisted-11.1.0/twisted/protocols/htb.py twisted-12.1.0/twisted/protocols/htb.py --- twisted-11.1.0/twisted/protocols/htb.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/protocols/htb.py 2012-01-17 02:37:22.000000000 +0000 @@ -74,12 +74,13 @@ return allowable def drip(self): - """Let some of the bucket drain. + """ + Let some of the bucket drain. How much of the bucket drains depends on how long it has been since I was last called. - @returns: True if I am now empty. + @returns: C{True} if the bucket is empty after this drip. @returntype: bool """ if self.parentBucket is not None: @@ -87,13 +88,12 @@ if self.rate is None: self.content = 0 - return True else: now = time() deltaT = now - self.lastDrip self.content = long(max(0, self.content - deltaT * self.rate)) self.lastDrip = now - return False + return self.content == 0 class IBucketFilter(Interface): diff -Nru twisted-11.1.0/twisted/protocols/test/test_tls.py twisted-12.1.0/twisted/protocols/test/test_tls.py --- twisted-11.1.0/twisted/protocols/test/test_tls.py 2011-10-15 21:43:38.000000000 +0000 +++ twisted-12.1.0/twisted/protocols/test/test_tls.py 2012-01-22 16:03:52.000000000 +0000 @@ -151,6 +151,8 @@ L{TLSMemoryBIOFactory.doStart} and L{TLSMemoryBIOFactory.doStop} do not log any messages. """ + contextFactory = DefaultOpenSSLContextFactory(certPath, certPath) + logs = [] logger = logs.append log.addObserver(logger) @@ -159,7 +161,7 @@ # Disable logging on the wrapped factory: wrappedFactory.doStart = lambda: None wrappedFactory.doStop = lambda: None - factory = TLSMemoryBIOFactory(None, False, wrappedFactory) + factory = TLSMemoryBIOFactory(contextFactory, False, wrappedFactory) factory.doStart() factory.doStop() self.assertEqual(logs, []) @@ -171,7 +173,8 @@ with a short string (C{"TLS"}) indicating the wrapping, rather than its full class name. """ - factory = TLSMemoryBIOFactory(None, False, ServerFactory()) + contextFactory = DefaultOpenSSLContextFactory(certPath, certPath) + factory = TLSMemoryBIOFactory(contextFactory, False, ServerFactory()) self.assertEqual("ServerFactory (TLS)", factory.logPrefix()) @@ -183,7 +186,8 @@ class NoFactory(object): pass - factory = TLSMemoryBIOFactory(None, False, NoFactory()) + contextFactory = DefaultOpenSSLContextFactory(certPath, certPath) + factory = TLSMemoryBIOFactory(contextFactory, False, NoFactory()) self.assertEqual("NoFactory (TLS)", factory.logPrefix()) @@ -1132,6 +1136,52 @@ self.assertTrue(verifyObject(IPushProducer, membrane)) + def registerProducerAfterConnectionLost(self, streaming): + """ + If a producer is registered after the transport has disconnected, the + producer is not used, and its stopProducing method is called. + """ + clientProtocol, tlsProtocol = buildTLSProtocol() + clientProtocol.connectionLost = lambda reason: reason.trap(Error) + + class Producer(object): + stopped = False + + def resumeProducing(self): + return 1/0 # this should never be called + + def stopProducing(self): + self.stopped = True + + # Disconnect the transport: + tlsProtocol.connectionLost(Failure(ConnectionDone())) + + # Register the producer; startProducing should not be called, but + # stopProducing will: + producer = Producer() + tlsProtocol.registerProducer(producer, False) + self.assertIdentical(tlsProtocol.transport.producer, None) + self.assertEqual(producer.stopped, True) + + + def test_streamingProducerAfterConnectionLost(self): + """ + If a streaming producer is registered after the transport has + disconnected, the producer is not used, and its stopProducing method + is called. + """ + self.registerProducerAfterConnectionLost(True) + + + def test_nonStreamingProducerAfterConnectionLost(self): + """ + If a non-streaming producer is registered after the transport has + disconnected, the producer is not used, and its stopProducing method + is called. + """ + self.registerProducerAfterConnectionLost(False) + + class NonStreamingProducer(object): """ diff -Nru twisted-11.1.0/twisted/protocols/tls.py twisted-12.1.0/twisted/protocols/tls.py --- twisted-11.1.0/twisted/protocols/tls.py 2011-10-15 21:43:38.000000000 +0000 +++ twisted-12.1.0/twisted/protocols/tls.py 2012-01-22 16:03:52.000000000 +0000 @@ -538,6 +538,11 @@ def registerProducer(self, producer, streaming): + # If we've already disconnected, nothing to do here: + if self._lostTLSConnection: + producer.stopProducing() + return + # If we received a non-streaming producer, wrap it so it becomes a # streaming producer: if not streaming: @@ -578,12 +583,16 @@ protocol = TLSMemoryBIOProtocol noisy = False # disable unnecessary logging. - + def __init__(self, contextFactory, isClient, wrappedFactory): WrappingFactory.__init__(self, wrappedFactory) self._contextFactory = contextFactory self._isClient = isClient + # Force some parameter checking in pyOpenSSL. It's better to fail now + # than after we've set up the transport. + contextFactory.getContext() + def logPrefix(self): """ diff -Nru twisted-11.1.0/twisted/python/components.py twisted-12.1.0/twisted/python/components.py --- twisted-11.1.0/twisted/python/components.py 2011-08-20 12:54:04.000000000 +0000 +++ twisted-12.1.0/twisted/python/components.py 2012-03-07 17:34:52.000000000 +0000 @@ -28,9 +28,6 @@ interface. """ -# system imports -import warnings - # zope3 imports from zope.interface import interface, declarations from zope.interface.adapter import AdapterRegistry @@ -40,11 +37,6 @@ from twisted.persisted import styles -class ComponentsDeprecationWarning(DeprecationWarning): - """ - Nothing emits this warning anymore. - """ - # Twisted's global adapter registry globalRegistry = AdapterRegistry() @@ -143,27 +135,6 @@ _addHook(globalRegistry) -## backwardsCompatImplements and fixClassImplements should probably stick around for another -## release cycle. No harm doing so in any case. - -def backwardsCompatImplements(klass): - """DEPRECATED. - - Does nothing. Previously handled backwards compat from a - zope.interface using class to a class wanting old twisted - components interface behaviors. - """ - warnings.warn("components.backwardsCompatImplements doesn't do anything in Twisted 2.3, stop calling it.", ComponentsDeprecationWarning, stacklevel=2) - -def fixClassImplements(klass): - """DEPRECATED. - - Does nothing. Previously converted class from __implements__ to - zope implementation. - """ - warnings.warn("components.fixClassImplements doesn't do anything in Twisted 2.3, stop calling it.", ComponentsDeprecationWarning, stacklevel=2) - - def getRegistry(): """Returns the Twisted global C{zope.interface.adapter.AdapterRegistry} instance. @@ -461,12 +432,7 @@ __all__ = [ # Sticking around: - "ComponentsDeprecationWarning", "registerAdapter", "getAdapterFactory", "Adapter", "Componentized", "ReprableComponentized", "getRegistry", "proxyForInterface", - - # Deprecated: - "backwardsCompatImplements", - "fixClassImplements", ] diff -Nru twisted-11.1.0/twisted/python/constants.py twisted-12.1.0/twisted/python/constants.py --- twisted-11.1.0/twisted/python/constants.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/python/constants.py 2012-03-11 09:04:58.000000000 +0000 @@ -0,0 +1,377 @@ +# -*- test-case-name: twisted.python.test.test_constants -*- +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Symbolic constant support, including collections and constants with text, +numeric, and bit flag values. +""" + +__all__ = [ + 'NamedConstant', 'ValueConstant', 'FlagConstant', + 'Names', 'Values', 'Flags'] + +from itertools import count +from operator import and_, or_, xor + +_unspecified = object() +_constantOrder = count().next + + +class _Constant(object): + """ + @ivar _index: A C{int} allocated from a shared counter in order to keep + track of the order in which L{_Constant}s are instantiated. + + @ivar name: A C{str} giving the name of this constant; only set once the + constant is initialized by L{_ConstantsContainer}. + + @ivar _container: The L{_ConstantsContainer} subclass this constant belongs + to; only set once the constant is initialized by that subclass. + """ + def __init__(self): + self._index = _constantOrder() + + + def __get__(self, oself, cls): + """ + Ensure this constant has been initialized before returning it. + """ + cls._initializeEnumerants() + return self + + + def __repr__(self): + """ + Return text identifying both which constant this is and which collection + it belongs to. + """ + return "<%s=%s>" % (self._container.__name__, self.name) + + + def _realize(self, container, name, value): + """ + Complete the initialization of this L{_Constant}. + + @param container: The L{_ConstantsContainer} subclass this constant is + part of. + + @param name: The name of this constant in its container. + + @param value: The value of this constant; not used, as named constants + have no value apart from their identity. + """ + self._container = container + self.name = name + + + +class _EnumerantsInitializer(object): + """ + L{_EnumerantsInitializer} is a descriptor used to initialize a cache of + objects representing named constants for a particular L{_ConstantsContainer} + subclass. + """ + def __get__(self, oself, cls): + """ + Trigger the initialization of the enumerants cache on C{cls} and then + return it. + """ + cls._initializeEnumerants() + return cls._enumerants + + + +class _ConstantsContainer(object): + """ + L{_ConstantsContainer} is a class with attributes used as symbolic + constants. It is up to subclasses to specify what kind of constants are + allowed. + + @cvar _constantType: Specified by a L{_ConstantsContainer} subclass to + specify the type of constants allowed by that subclass. + + @cvar _enumerantsInitialized: A C{bool} tracking whether C{_enumerants} has + been initialized yet or not. + + @cvar _enumerants: A C{dict} mapping the names of constants (eg + L{NamedConstant} instances) found in the class definition to those + instances. This is initialized via the L{_EnumerantsInitializer} + descriptor the first time it is accessed. + """ + _constantType = None + + _enumerantsInitialized = False + _enumerants = _EnumerantsInitializer() + + def __new__(cls): + """ + Classes representing constants containers are not intended to be + instantiated. + + The class object itself is used directly. + """ + raise TypeError("%s may not be instantiated." % (cls.__name__,)) + + + def _initializeEnumerants(cls): + """ + Find all of the L{NamedConstant} instances in the definition of C{cls}, + initialize them with constant values, and build a mapping from their + names to them to attach to C{cls}. + """ + if not cls._enumerantsInitialized: + constants = [] + for (name, descriptor) in cls.__dict__.iteritems(): + if isinstance(descriptor, cls._constantType): + constants.append((descriptor._index, name, descriptor)) + enumerants = {} + constants.sort() + for (index, enumerant, descriptor) in constants: + value = cls._constantFactory(enumerant, descriptor) + descriptor._realize(cls, enumerant, value) + enumerants[enumerant] = descriptor + # Replace the _enumerants descriptor with the result so future + # access will go directly to the values. The _enumerantsInitialized + # flag is still necessary because NamedConstant.__get__ may also + # call this method. + cls._enumerants = enumerants + cls._enumerantsInitialized = True + _initializeEnumerants = classmethod(_initializeEnumerants) + + + def _constantFactory(cls, name, descriptor): + """ + Construct the value for a new constant to add to this container. + + @param name: The name of the constant to create. + + @return: L{NamedConstant} instances have no value apart from identity, + so return a meaningless dummy value. + """ + return _unspecified + _constantFactory = classmethod(_constantFactory) + + + def lookupByName(cls, name): + """ + Retrieve a constant by its name or raise a C{ValueError} if there is no + constant associated with that name. + + @param name: A C{str} giving the name of one of the constants defined by + C{cls}. + + @raise ValueError: If C{name} is not the name of one of the constants + defined by C{cls}. + + @return: The L{NamedConstant} associated with C{name}. + """ + if name in cls._enumerants: + return getattr(cls, name) + raise ValueError(name) + lookupByName = classmethod(lookupByName) + + + def iterconstants(cls): + """ + Iteration over a L{Names} subclass results in all of the constants it + contains. + + @return: an iterator the elements of which are the L{NamedConstant} + instances defined in the body of this L{Names} subclass. + """ + constants = cls._enumerants.values() + constants.sort(key=lambda descriptor: descriptor._index) + return iter(constants) + iterconstants = classmethod(iterconstants) + + + +class NamedConstant(_Constant): + """ + L{NamedConstant} defines an attribute to be a named constant within a + collection defined by a L{Names} subclass. + + L{NamedConstant} is only for use in the definition of L{Names} + subclasses. Do not instantiate L{NamedConstant} elsewhere and do not + subclass it. + """ + + + +class Names(_ConstantsContainer): + """ + A L{Names} subclass contains constants which differ only in their names and + identities. + """ + _constantType = NamedConstant + + + +class ValueConstant(_Constant): + """ + L{ValueConstant} defines an attribute to be a named constant within a + collection defined by a L{Values} subclass. + + L{ValueConstant} is only for use in the definition of L{Values} subclasses. + Do not instantiate L{ValueConstant} elsewhere and do not subclass it. + """ + def __init__(self, value): + _Constant.__init__(self) + self.value = value + + + +class Values(_ConstantsContainer): + """ + A L{Values} subclass contains constants which are associated with arbitrary + values. + """ + _constantType = ValueConstant + + def lookupByValue(cls, value): + """ + Retrieve a constant by its value or raise a C{ValueError} if there is no + constant associated with that value. + + @param value: The value of one of the constants defined by C{cls}. + + @raise ValueError: If C{value} is not the value of one of the constants + defined by C{cls}. + + @return: The L{ValueConstant} associated with C{value}. + """ + for constant in cls.iterconstants(): + if constant.value == value: + return constant + raise ValueError(value) + lookupByValue = classmethod(lookupByValue) + + + +def _flagOp(op, left, right): + """ + Implement a binary operator for a L{FlagConstant} instance. + + @param op: A two-argument callable implementing the binary operation. For + example, C{operator.or_}. + + @param left: The left-hand L{FlagConstant} instance. + @param right: The right-hand L{FlagConstant} instance. + + @return: A new L{FlagConstant} instance representing the result of the + operation. + """ + value = op(left.value, right.value) + names = op(left.names, right.names) + result = FlagConstant() + result._realize(left._container, names, value) + return result + + + +class FlagConstant(_Constant): + """ + L{FlagConstant} defines an attribute to be a flag constant within a + collection defined by a L{Flags} subclass. + + L{FlagConstant} is only for use in the definition of L{Flags} subclasses. + Do not instantiate L{FlagConstant} elsewhere and do not subclass it. + """ + def __init__(self, value=_unspecified): + _Constant.__init__(self) + self.value = value + + + def _realize(self, container, names, value): + """ + Complete the initialization of this L{FlagConstant}. + + This implementation differs from other C{_realize} implementations in + that a L{FlagConstant} may have several names which apply to it, due to + flags being combined with various operators. + + @param container: The L{Flags} subclass this constant is part of. + + @param names: When a single-flag value is being initialized, a C{str} + giving the name of that flag. This is the case which happens when a + L{Flags} subclass is being initialized and L{FlagConstant} instances + from its body are being realized. Otherwise, a C{set} of C{str} + giving names of all the flags set on this L{FlagConstant} instance. + This is the case when two flags are combined using C{|}, for + example. + """ + if isinstance(names, str): + name = names + names = set([names]) + elif len(names) == 1: + (name,) = names + else: + name = "{" + ",".join(sorted(names)) + "}" + _Constant._realize(self, container, name, value) + self.value = value + self.names = names + + + def __or__(self, other): + """ + Define C{|} on two L{FlagConstant} instances to create a new + L{FlagConstant} instance with all flags set in either instance set. + """ + return _flagOp(or_, self, other) + + + def __and__(self, other): + """ + Define C{&} on two L{FlagConstant} instances to create a new + L{FlagConstant} instance with only flags set in both instances set. + """ + return _flagOp(and_, self, other) + + + def __xor__(self, other): + """ + Define C{^} on two L{FlagConstant} instances to create a new + L{FlagConstant} instance with only flags set on exactly one instance + set. + """ + return _flagOp(xor, self, other) + + + def __invert__(self): + """ + Define C{~} on a L{FlagConstant} instance to create a new + L{FlagConstant} instance with all flags not set on this instance set. + """ + result = FlagConstant() + result._realize(self._container, set(), 0) + for flag in self._container.iterconstants(): + if flag.value & self.value == 0: + result |= flag + return result + + + +class Flags(Values): + """ + A L{Flags} subclass contains constants which can be combined using the + common bitwise operators (C{|}, C{&}, etc) similar to a I{bitvector} from a + language like C. + """ + _constantType = FlagConstant + + _value = 1 + + def _constantFactory(cls, name, descriptor): + """ + For L{FlagConstant} instances with no explicitly defined value, assign + the next power of two as its value. + """ + if descriptor.value is _unspecified: + value = cls._value + cls._value <<= 1 + else: + value = descriptor.value + cls._value = value << 1 + return value + _constantFactory = classmethod(_constantFactory) diff -Nru twisted-11.1.0/twisted/python/dist.py twisted-12.1.0/twisted/python/dist.py --- twisted-11.1.0/twisted/python/dist.py 2011-09-26 16:28:23.000000000 +0000 +++ twisted-12.1.0/twisted/python/dist.py 2011-11-20 15:19:42.000000000 +0000 @@ -6,7 +6,7 @@ Maintainer: Christopher Armstrong """ -from distutils.command import build_scripts, install_data, build_ext, build_py +from distutils.command import build_scripts, install_data, build_ext from distutils.errors import CompileError from distutils import core from distutils.core import Extension @@ -83,8 +83,6 @@ kw['cmdclass'] = { 'install_data': install_data_twisted, 'build_scripts': build_scripts_twisted} - if sys.version_info[:3] < (2, 3, 0): - kw['cmdclass']['build_py'] = build_py_twisted if "conditionalExtensions" in kw: extensions = kw["conditionalExtensions"] @@ -262,20 +260,6 @@ ## Helpers and distutil tweaks -class build_py_twisted(build_py.build_py): - """ - Changes behavior in Python 2.2 to support simultaneous specification of - `packages' and `py_modules'. - """ - def run(self): - if self.py_modules: - self.build_modules() - if self.packages: - self.build_packages() - self.byte_compile(self.get_outputs(include_bytecode=0)) - - - class build_scripts_twisted(build_scripts.build_scripts): """Renames scripts so they end with '.py' on Windows.""" diff -Nru twisted-11.1.0/twisted/python/_epoll.c twisted-12.1.0/twisted/python/_epoll.c --- twisted-11.1.0/twisted/python/_epoll.c 2011-03-14 17:51:06.000000000 +0000 +++ twisted-12.1.0/twisted/python/_epoll.c 2012-02-19 19:24:21.000000000 +0000 @@ -1,4 +1,4 @@ -/* Generated by Cython 0.14.1 on Tue Mar 8 19:42:56 2011 */ +/* Generated by Cython 0.15.1 on Fri Feb 17 23:33:28 2012 */ #define PY_SSIZE_T_CLEAN #include "Python.h" @@ -46,7 +46,7 @@ #define PY_SSIZE_T_MIN INT_MIN #define PY_FORMAT_SIZE_T "" #define PyInt_FromSsize_t(z) PyInt_FromLong(z) - #define PyInt_AsSsize_t(o) PyInt_AsLong(o) + #define PyInt_AsSsize_t(o) __Pyx_PyInt_AsInt(o) #define PyNumber_Index(o) PyNumber_Int(o) #define PyIndex_Check(o) PyNumber_Check(o) #define PyErr_WarnEx(category, message, stacklevel) PyErr_Warn(category, message) @@ -159,6 +159,15 @@ #define PyBoolObject PyLongObject #endif +#if PY_VERSION_HEX < 0x03020000 + typedef long Py_hash_t; + #define __Pyx_PyInt_FromHash_t PyInt_FromLong + #define __Pyx_PyInt_AsHash_t PyInt_AsLong +#else + #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t + #define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t +#endif + #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) @@ -209,22 +218,28 @@ #define __Pyx_DOCSTR(n) (n) #endif -#ifdef __cplusplus -#define __PYX_EXTERN_C extern "C" -#else -#define __PYX_EXTERN_C extern +#ifndef __PYX_EXTERN_C + #ifdef __cplusplus + #define __PYX_EXTERN_C extern "C" + #else + #define __PYX_EXTERN_C extern + #endif #endif #if defined(WIN32) || defined(MS_WINDOWS) #define _USE_MATH_DEFINES #endif #include +#define __PYX_HAVE__twisted__python___epoll #define __PYX_HAVE_API__twisted__python___epoll #include "stdio.h" #include "errno.h" #include "string.h" #include "stdint.h" #include "sys/epoll.h" +#ifdef _OPENMP +#include +#endif /* _OPENMP */ #ifdef PYREX_WITHOUT_ASSERTIONS #define CYTHON_WITHOUT_ASSERTIONS @@ -267,6 +282,7 @@ #define __Pyx_PyBytes_FromUString(s) PyBytes_FromString((char*)s) #define __Pyx_PyBytes_AsUString(s) ((unsigned char*) PyBytes_AsString(s)) +#define __Pyx_Owned_Py_None(b) (Py_INCREF(Py_None), Py_None) #define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False)) static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x); @@ -279,17 +295,17 @@ #ifdef __GNUC__ -/* Test for GCC > 2.95 */ -#if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)) -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) -#else /* __GNUC__ > 2 ... */ -#define likely(x) (x) -#define unlikely(x) (x) -#endif /* __GNUC__ > 2 ... */ + /* Test for GCC > 2.95 */ + #if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)) + #define likely(x) __builtin_expect(!!(x), 1) + #define unlikely(x) __builtin_expect(!!(x), 0) + #else /* __GNUC__ > 2 ... */ + #define likely(x) (x) + #define unlikely(x) (x) + #endif /* __GNUC__ > 2 ... */ #else /* __GNUC__ */ -#define likely(x) (x) -#define unlikely(x) (x) + #define likely(x) (x) + #define unlikely(x) (x) #endif /* __GNUC__ */ static PyObject *__pyx_m; @@ -306,22 +322,23 @@ "_epoll.pyx", }; -/* Type declarations */ +/*--- Type declarations ---*/ +struct __pyx_obj_7twisted_6python_6_epoll_epoll; -/* "twisted/python/_epoll.pyx":68 - * cdef extern void PyEval_RestoreThread(PyThreadState*) +/* "twisted/python/_epoll.pyx":106 + * free(events) * * cdef class epoll: # <<<<<<<<<<<<<< * """ * Represent a set of file descriptors being monitored for events. */ - struct __pyx_obj_7twisted_6python_6_epoll_epoll { PyObject_HEAD int fd; int initialized; }; + #ifndef CYTHON_REFNANNY #define CYTHON_REFNANNY 0 #endif @@ -336,40 +353,39 @@ void (*FinishContext)(void**); } __Pyx_RefNannyAPIStruct; static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; - static __Pyx_RefNannyAPIStruct * __Pyx_RefNannyImportAPI(const char *modname) { - PyObject *m = NULL, *p = NULL; - void *r = NULL; - m = PyImport_ImportModule((char *)modname); - if (!m) goto end; - p = PyObject_GetAttrString(m, (char *)"RefNannyAPI"); - if (!p) goto end; - r = PyLong_AsVoidPtr(p); - end: - Py_XDECREF(p); - Py_XDECREF(m); - return (__Pyx_RefNannyAPIStruct *)r; - } - #define __Pyx_RefNannySetupContext(name) void *__pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) + static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); /*proto*/ + #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; + #define __Pyx_RefNannySetupContext(name) __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) #define __Pyx_RefNannyFinishContext() __Pyx_RefNanny->FinishContext(&__pyx_refnanny) - #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r);} } while(0) + #define __Pyx_XINCREF(r) do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0) + #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0) + #define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0) + #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0) #else + #define __Pyx_RefNannyDeclarations #define __Pyx_RefNannySetupContext(name) #define __Pyx_RefNannyFinishContext() #define __Pyx_INCREF(r) Py_INCREF(r) #define __Pyx_DECREF(r) Py_DECREF(r) #define __Pyx_GOTREF(r) #define __Pyx_GIVEREF(r) + #define __Pyx_XINCREF(r) Py_XINCREF(r) #define __Pyx_XDECREF(r) Py_XDECREF(r) + #define __Pyx_XGOTREF(r) + #define __Pyx_XGIVEREF(r) #endif /* CYTHON_REFNANNY */ -#define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);} } while(0) -#define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r);} } while(0) static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/ +static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/ +static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/ + +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); /*proto*/ + static void __Pyx_RaiseDoubleKeywordsError( const char* func_name, PyObject* kw_name); /*proto*/ @@ -378,11 +394,6 @@ static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/ -static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/ -static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/ - -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/ - static CYTHON_INLINE unsigned char __Pyx_PyInt_AsUnsignedChar(PyObject *); static CYTHON_INLINE unsigned short __Pyx_PyInt_AsUnsignedShort(PyObject *); @@ -415,16 +426,20 @@ static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject *); -static void __Pyx_AddTraceback(const char *funcname); /*proto*/ +static int __Pyx_check_binary_version(void); + +static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno, + int __pyx_lineno, const char *__pyx_filename); /*proto*/ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/ -/* Module declarations from twisted.python._epoll */ +/* Module declarations from 'twisted.python._epoll' */ static PyTypeObject *__pyx_ptype_7twisted_6python_6_epoll_epoll = 0; +static PyObject *__pyx_f_7twisted_6python_6_epoll_call_epoll_wait(int, unsigned int, int); /*proto*/ #define __Pyx_MODULE_NAME "twisted.python._epoll" -static int __pyx_module_is_main_twisted__python___epoll = 0; +int __pyx_module_is_main_twisted__python___epoll = 0; -/* Implementation of twisted.python._epoll */ +/* Implementation of 'twisted.python._epoll' */ static PyObject *__pyx_builtin_IOError; static char __pyx_k_1[] = "\nInterface to epoll I/O event notification facility.\n"; static char __pyx_k__ET[] = "ET"; @@ -436,26 +451,45 @@ static char __pyx_k__MSG[] = "MSG"; static char __pyx_k__OUT[] = "OUT"; static char __pyx_k__PRI[] = "PRI"; -static char __pyx_k__data[] = "data"; static char __pyx_k__size[] = "size"; static char __pyx_k__RDBAND[] = "RDBAND"; static char __pyx_k__RDNORM[] = "RDNORM"; static char __pyx_k__WRBAND[] = "WRBAND"; static char __pyx_k__WRNORM[] = "WRNORM"; -static char __pyx_k__append[] = "append"; static char __pyx_k__events[] = "events"; static char __pyx_k__CTL_ADD[] = "CTL_ADD"; static char __pyx_k__CTL_DEL[] = "CTL_DEL"; static char __pyx_k__CTL_MOD[] = "CTL_MOD"; +static char __pyx_k__EPOLLET[] = "EPOLLET"; +static char __pyx_k__EPOLLIN[] = "EPOLLIN"; static char __pyx_k__IOError[] = "IOError"; static char __pyx_k__timeout[] = "timeout"; +static char __pyx_k__EPOLLERR[] = "EPOLLERR"; +static char __pyx_k__EPOLLHUP[] = "EPOLLHUP"; +static char __pyx_k__EPOLLMSG[] = "EPOLLMSG"; +static char __pyx_k__EPOLLOUT[] = "EPOLLOUT"; +static char __pyx_k__EPOLLPRI[] = "EPOLLPRI"; static char __pyx_k____main__[] = "__main__"; static char __pyx_k____test__[] = "__test__"; static char __pyx_k__maxevents[] = "maxevents"; -static char __pyx_k__initialized[] = "initialized"; +static char __pyx_k__EPOLLRDBAND[] = "EPOLLRDBAND"; +static char __pyx_k__EPOLLRDNORM[] = "EPOLLRDNORM"; +static char __pyx_k__EPOLLWRBAND[] = "EPOLLWRBAND"; +static char __pyx_k__EPOLLWRNORM[] = "EPOLLWRNORM"; static PyObject *__pyx_n_s__CTL_ADD; static PyObject *__pyx_n_s__CTL_DEL; static PyObject *__pyx_n_s__CTL_MOD; +static PyObject *__pyx_n_s__EPOLLERR; +static PyObject *__pyx_n_s__EPOLLET; +static PyObject *__pyx_n_s__EPOLLHUP; +static PyObject *__pyx_n_s__EPOLLIN; +static PyObject *__pyx_n_s__EPOLLMSG; +static PyObject *__pyx_n_s__EPOLLOUT; +static PyObject *__pyx_n_s__EPOLLPRI; +static PyObject *__pyx_n_s__EPOLLRDBAND; +static PyObject *__pyx_n_s__EPOLLRDNORM; +static PyObject *__pyx_n_s__EPOLLWRBAND; +static PyObject *__pyx_n_s__EPOLLWRNORM; static PyObject *__pyx_n_s__ERR; static PyObject *__pyx_n_s__ET; static PyObject *__pyx_n_s__HUP; @@ -470,77 +504,335 @@ static PyObject *__pyx_n_s__WRNORM; static PyObject *__pyx_n_s____main__; static PyObject *__pyx_n_s____test__; -static PyObject *__pyx_n_s__append; -static PyObject *__pyx_n_s__data; static PyObject *__pyx_n_s__events; static PyObject *__pyx_n_s__fd; -static PyObject *__pyx_n_s__initialized; static PyObject *__pyx_n_s__maxevents; static PyObject *__pyx_n_s__op; static PyObject *__pyx_n_s__size; static PyObject *__pyx_n_s__timeout; -/* "twisted/python/_epoll.pyx":76 +/* "twisted/python/_epoll.pyx":68 + * cdef extern void PyEval_RestoreThread(PyThreadState*) + * + * cdef call_epoll_wait(int fd, unsigned int maxevents, int timeout_msec): # <<<<<<<<<<<<<< + * """ + * Wait for an I/O event, wrap epoll_wait(2). + */ + +static PyObject *__pyx_f_7twisted_6python_6_epoll_call_epoll_wait(int __pyx_v_fd, unsigned int __pyx_v_maxevents, int __pyx_v_timeout_msec) { + struct epoll_event *__pyx_v_events; + int __pyx_v_result; + int __pyx_v_nbytes; + PyThreadState *__pyx_v__save; + PyObject *__pyx_v_results = NULL; + long __pyx_v_i; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + int __pyx_t_5; + int __pyx_t_6; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("call_epoll_wait"); + + /* "twisted/python/_epoll.pyx":89 + * cdef PyThreadState *_save + * + * nbytes = sizeof(epoll_event) * maxevents # <<<<<<<<<<<<<< + * events = malloc(nbytes) + * memset(events, 0, nbytes) + */ + __pyx_v_nbytes = ((sizeof(struct epoll_event)) * __pyx_v_maxevents); + + /* "twisted/python/_epoll.pyx":90 + * + * nbytes = sizeof(epoll_event) * maxevents + * events = malloc(nbytes) # <<<<<<<<<<<<<< + * memset(events, 0, nbytes) + * try: + */ + __pyx_v_events = ((struct epoll_event *)malloc(__pyx_v_nbytes)); + + /* "twisted/python/_epoll.pyx":91 + * nbytes = sizeof(epoll_event) * maxevents + * events = malloc(nbytes) + * memset(events, 0, nbytes) # <<<<<<<<<<<<<< + * try: + * _save = PyEval_SaveThread() + */ + memset(__pyx_v_events, 0, __pyx_v_nbytes); + + /* "twisted/python/_epoll.pyx":92 + * events = malloc(nbytes) + * memset(events, 0, nbytes) + * try: # <<<<<<<<<<<<<< + * _save = PyEval_SaveThread() + * result = epoll_wait(fd, events, maxevents, timeout_msec) + */ + /*try:*/ { + + /* "twisted/python/_epoll.pyx":93 + * memset(events, 0, nbytes) + * try: + * _save = PyEval_SaveThread() # <<<<<<<<<<<<<< + * result = epoll_wait(fd, events, maxevents, timeout_msec) + * PyEval_RestoreThread(_save) + */ + __pyx_v__save = PyEval_SaveThread(); + + /* "twisted/python/_epoll.pyx":94 + * try: + * _save = PyEval_SaveThread() + * result = epoll_wait(fd, events, maxevents, timeout_msec) # <<<<<<<<<<<<<< + * PyEval_RestoreThread(_save) + * + */ + __pyx_v_result = epoll_wait(__pyx_v_fd, __pyx_v_events, __pyx_v_maxevents, __pyx_v_timeout_msec); + + /* "twisted/python/_epoll.pyx":95 + * _save = PyEval_SaveThread() + * result = epoll_wait(fd, events, maxevents, timeout_msec) + * PyEval_RestoreThread(_save) # <<<<<<<<<<<<<< + * + * if result == -1: + */ + PyEval_RestoreThread(__pyx_v__save); + + /* "twisted/python/_epoll.pyx":97 + * PyEval_RestoreThread(_save) + * + * if result == -1: # <<<<<<<<<<<<<< + * raise IOError(errno, strerror(errno)) + * results = [] + */ + __pyx_t_1 = (__pyx_v_result == -1); + if (__pyx_t_1) { + + /* "twisted/python/_epoll.pyx":98 + * + * if result == -1: + * raise IOError(errno, strerror(errno)) # <<<<<<<<<<<<<< + * results = [] + * for i from 0 <= i < result: + */ + __pyx_t_2 = PyInt_FromLong(errno); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L4;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = PyBytes_FromString(strerror(errno)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L4;} + __Pyx_GOTREF(((PyObject *)__pyx_t_3)); + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L4;} + __Pyx_GOTREF(((PyObject *)__pyx_t_4)); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_4, 1, ((PyObject *)__pyx_t_3)); + __Pyx_GIVEREF(((PyObject *)__pyx_t_3)); + __pyx_t_2 = 0; + __pyx_t_3 = 0; + __pyx_t_3 = PyObject_Call(__pyx_builtin_IOError, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L4;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0; + __Pyx_Raise(__pyx_t_3, 0, 0, 0); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L4;} + goto __pyx_L6; + } + __pyx_L6:; + + /* "twisted/python/_epoll.pyx":99 + * if result == -1: + * raise IOError(errno, strerror(errno)) + * results = [] # <<<<<<<<<<<<<< + * for i from 0 <= i < result: + * results.append((events[i].data.fd, events[i].events)) + */ + __pyx_t_3 = PyList_New(0); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 99; __pyx_clineno = __LINE__; goto __pyx_L4;} + __Pyx_GOTREF(((PyObject *)__pyx_t_3)); + __pyx_v_results = __pyx_t_3; + __pyx_t_3 = 0; + + /* "twisted/python/_epoll.pyx":100 + * raise IOError(errno, strerror(errno)) + * results = [] + * for i from 0 <= i < result: # <<<<<<<<<<<<<< + * results.append((events[i].data.fd, events[i].events)) + * return results + */ + __pyx_t_5 = __pyx_v_result; + for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_5; __pyx_v_i++) { + + /* "twisted/python/_epoll.pyx":101 + * results = [] + * for i from 0 <= i < result: + * results.append((events[i].data.fd, events[i].events)) # <<<<<<<<<<<<<< + * return results + * finally: + */ + if (unlikely(((PyObject *)__pyx_v_results) == Py_None)) { + PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", "append"); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L4;} + } + __pyx_t_3 = PyInt_FromLong((__pyx_v_events[__pyx_v_i]).data.fd); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L4;} + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PyInt_FromLong(((int)(__pyx_v_events[__pyx_v_i]).events)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L4;} + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L4;} + __Pyx_GOTREF(((PyObject *)__pyx_t_2)); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); + __pyx_t_3 = 0; + __pyx_t_4 = 0; + __pyx_t_6 = PyList_Append(__pyx_v_results, ((PyObject *)__pyx_t_2)); if (unlikely(__pyx_t_6 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L4;} + __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0; + } + + /* "twisted/python/_epoll.pyx":102 + * for i from 0 <= i < result: + * results.append((events[i].data.fd, events[i].events)) + * return results # <<<<<<<<<<<<<< + * finally: + * free(events) + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(((PyObject *)__pyx_v_results)); + __pyx_r = ((PyObject *)__pyx_v_results); + goto __pyx_L3; + } + + /* "twisted/python/_epoll.pyx":104 + * return results + * finally: + * free(events) # <<<<<<<<<<<<<< + * + * cdef class epoll: + */ + /*finally:*/ { + int __pyx_why; + PyObject *__pyx_exc_type, *__pyx_exc_value, *__pyx_exc_tb; + int __pyx_exc_lineno; + __pyx_exc_type = 0; __pyx_exc_value = 0; __pyx_exc_tb = 0; __pyx_exc_lineno = 0; + __pyx_why = 0; goto __pyx_L5; + __pyx_L3: __pyx_exc_type = 0; __pyx_exc_value = 0; __pyx_exc_tb = 0; __pyx_exc_lineno = 0; + __pyx_why = 3; goto __pyx_L5; + __pyx_L4: { + __pyx_why = 4; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_ErrFetch(&__pyx_exc_type, &__pyx_exc_value, &__pyx_exc_tb); + __pyx_exc_lineno = __pyx_lineno; + goto __pyx_L5; + } + __pyx_L5:; + free(__pyx_v_events); + switch (__pyx_why) { + case 3: goto __pyx_L0; + case 4: { + __Pyx_ErrRestore(__pyx_exc_type, __pyx_exc_value, __pyx_exc_tb); + __pyx_lineno = __pyx_exc_lineno; + __pyx_exc_type = 0; + __pyx_exc_value = 0; + __pyx_exc_tb = 0; + goto __pyx_L1_error; + } + } + } + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_AddTraceback("twisted.python._epoll.call_epoll_wait", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_results); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "twisted/python/_epoll.pyx":114 * cdef int initialized * - * def __init__(self, int size): # <<<<<<<<<<<<<< - * self.fd = epoll_create(size) - * if self.fd == -1: + * def __init__(self, int size=1023): # <<<<<<<<<<<<<< + * """ + * The constructor arguments are compatible with select.poll.__init__. */ static int __pyx_pf_7twisted_6python_6_epoll_5epoll___init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static char __pyx_doc_7twisted_6python_6_epoll_5epoll___init__[] = "\n The constructor arguments are compatible with select.poll.__init__.\n "; +struct wrapperbase __pyx_wrapperbase_7twisted_6python_6_epoll_5epoll___init__; static int __pyx_pf_7twisted_6python_6_epoll_5epoll___init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { int __pyx_v_size; int __pyx_r; + __Pyx_RefNannyDeclarations int __pyx_t_1; PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; PyObject *__pyx_t_4 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__size,0}; __Pyx_RefNannySetupContext("__init__"); - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); + { PyObject* values[1] = {0}; - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 0: - values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__size); - if (likely(values[0])) kw_args--; - else goto __pyx_L5_argtuple_error; - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "__init__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - } - __pyx_v_size = __Pyx_PyInt_AsInt(values[0]); if (unlikely((__pyx_v_size == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - } else if (PyTuple_GET_SIZE(__pyx_args) != 1) { - goto __pyx_L5_argtuple_error; - } else { - __pyx_v_size = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_size == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + if (kw_args > 0) { + PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__size); + if (value) { values[0] = value; kw_args--; } + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "__init__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } else { + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + } + if (values[0]) { + __pyx_v_size = __Pyx_PyInt_AsInt(values[0]); if (unlikely((__pyx_v_size == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } else { + __pyx_v_size = ((int)1023); + } } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("__init__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __Pyx_RaiseArgtupleInvalid("__init__", 0, 0, 1, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __pyx_L3_error:; - __Pyx_AddTraceback("twisted.python._epoll.epoll.__init__"); + __Pyx_AddTraceback("twisted.python._epoll.epoll.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return -1; __pyx_L4_argument_unpacking_done:; - /* "twisted/python/_epoll.pyx":77 - * - * def __init__(self, int size): + /* "twisted/python/_epoll.pyx":118 + * The constructor arguments are compatible with select.poll.__init__. + * """ * self.fd = epoll_create(size) # <<<<<<<<<<<<<< * if self.fd == -1: * raise IOError(errno, strerror(errno)) */ ((struct __pyx_obj_7twisted_6python_6_epoll_epoll *)__pyx_v_self)->fd = epoll_create(__pyx_v_size); - /* "twisted/python/_epoll.pyx":78 - * def __init__(self, int size): + /* "twisted/python/_epoll.pyx":119 + * """ * self.fd = epoll_create(size) * if self.fd == -1: # <<<<<<<<<<<<<< * raise IOError(errno, strerror(errno)) @@ -549,18 +841,18 @@ __pyx_t_1 = (((struct __pyx_obj_7twisted_6python_6_epoll_epoll *)__pyx_v_self)->fd == -1); if (__pyx_t_1) { - /* "twisted/python/_epoll.pyx":79 + /* "twisted/python/_epoll.pyx":120 * self.fd = epoll_create(size) * if self.fd == -1: * raise IOError(errno, strerror(errno)) # <<<<<<<<<<<<<< * self.initialized = 1 * */ - __pyx_t_2 = PyInt_FromLong(errno); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = PyInt_FromLong(errno); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyBytes_FromString(strerror(errno)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = PyBytes_FromString(strerror(errno)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(((PyObject *)__pyx_t_3)); - __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(((PyObject *)__pyx_t_4)); PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2); __Pyx_GIVEREF(__pyx_t_2); @@ -568,17 +860,17 @@ __Pyx_GIVEREF(((PyObject *)__pyx_t_3)); __pyx_t_2 = 0; __pyx_t_3 = 0; - __pyx_t_3 = PyObject_Call(__pyx_builtin_IOError, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = PyObject_Call(__pyx_builtin_IOError, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0; - __Pyx_Raise(__pyx_t_3, 0, 0); + __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;} goto __pyx_L6; } __pyx_L6:; - /* "twisted/python/_epoll.pyx":80 + /* "twisted/python/_epoll.pyx":121 * if self.fd == -1: * raise IOError(errno, strerror(errno)) * self.initialized = 1 # <<<<<<<<<<<<<< @@ -593,14 +885,14 @@ __Pyx_XDECREF(__pyx_t_2); __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_4); - __Pyx_AddTraceback("twisted.python._epoll.epoll.__init__"); + __Pyx_AddTraceback("twisted.python._epoll.epoll.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = -1; __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } -/* "twisted/python/_epoll.pyx":82 +/* "twisted/python/_epoll.pyx":123 * self.initialized = 1 * * def __dealloc__(self): # <<<<<<<<<<<<<< @@ -610,9 +902,10 @@ static void __pyx_pf_7twisted_6python_6_epoll_5epoll_1__dealloc__(PyObject *__pyx_v_self); /*proto*/ static void __pyx_pf_7twisted_6python_6_epoll_5epoll_1__dealloc__(PyObject *__pyx_v_self) { + __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__dealloc__"); - /* "twisted/python/_epoll.pyx":83 + /* "twisted/python/_epoll.pyx":124 * * def __dealloc__(self): * if self.initialized: # <<<<<<<<<<<<<< @@ -621,7 +914,7 @@ */ if (((struct __pyx_obj_7twisted_6python_6_epoll_epoll *)__pyx_v_self)->initialized) { - /* "twisted/python/_epoll.pyx":84 + /* "twisted/python/_epoll.pyx":125 * def __dealloc__(self): * if self.initialized: * close(self.fd) # <<<<<<<<<<<<<< @@ -630,7 +923,7 @@ */ close(((struct __pyx_obj_7twisted_6python_6_epoll_epoll *)__pyx_v_self)->fd); - /* "twisted/python/_epoll.pyx":85 + /* "twisted/python/_epoll.pyx":126 * if self.initialized: * close(self.fd) * self.initialized = 0 # <<<<<<<<<<<<<< @@ -645,7 +938,7 @@ __Pyx_RefNannyFinishContext(); } -/* "twisted/python/_epoll.pyx":87 +/* "twisted/python/_epoll.pyx":128 * self.initialized = 0 * * def close(self): # <<<<<<<<<<<<<< @@ -657,13 +950,17 @@ static char __pyx_doc_7twisted_6python_6_epoll_5epoll_2close[] = "\n Close the epoll file descriptor.\n "; static PyObject *__pyx_pf_7twisted_6python_6_epoll_5epoll_2close(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations int __pyx_t_1; PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; PyObject *__pyx_t_4 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; __Pyx_RefNannySetupContext("close"); - /* "twisted/python/_epoll.pyx":91 + /* "twisted/python/_epoll.pyx":132 * Close the epoll file descriptor. * """ * if self.initialized: # <<<<<<<<<<<<<< @@ -672,7 +969,7 @@ */ if (((struct __pyx_obj_7twisted_6python_6_epoll_epoll *)__pyx_v_self)->initialized) { - /* "twisted/python/_epoll.pyx":92 + /* "twisted/python/_epoll.pyx":133 * """ * if self.initialized: * if close(self.fd) == -1: # <<<<<<<<<<<<<< @@ -682,18 +979,18 @@ __pyx_t_1 = (close(((struct __pyx_obj_7twisted_6python_6_epoll_epoll *)__pyx_v_self)->fd) == -1); if (__pyx_t_1) { - /* "twisted/python/_epoll.pyx":93 + /* "twisted/python/_epoll.pyx":134 * if self.initialized: * if close(self.fd) == -1: * raise IOError(errno, strerror(errno)) # <<<<<<<<<<<<<< * self.initialized = 0 * */ - __pyx_t_2 = PyInt_FromLong(errno); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_2 = PyInt_FromLong(errno); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyBytes_FromString(strerror(errno)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = PyBytes_FromString(strerror(errno)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(((PyObject *)__pyx_t_3)); - __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(((PyObject *)__pyx_t_4)); PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2); __Pyx_GIVEREF(__pyx_t_2); @@ -701,17 +998,17 @@ __Pyx_GIVEREF(((PyObject *)__pyx_t_3)); __pyx_t_2 = 0; __pyx_t_3 = 0; - __pyx_t_3 = PyObject_Call(__pyx_builtin_IOError, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_3 = PyObject_Call(__pyx_builtin_IOError, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0; - __Pyx_Raise(__pyx_t_3, 0, 0); + __Pyx_Raise(__pyx_t_3, 0, 0, 0); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;} goto __pyx_L6; } __pyx_L6:; - /* "twisted/python/_epoll.pyx":94 + /* "twisted/python/_epoll.pyx":135 * if close(self.fd) == -1: * raise IOError(errno, strerror(errno)) * self.initialized = 0 # <<<<<<<<<<<<<< @@ -729,7 +1026,7 @@ __Pyx_XDECREF(__pyx_t_2); __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_4); - __Pyx_AddTraceback("twisted.python._epoll.epoll.close"); + __Pyx_AddTraceback("twisted.python._epoll.epoll.close", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); @@ -737,7 +1034,7 @@ return __pyx_r; } -/* "twisted/python/_epoll.pyx":96 +/* "twisted/python/_epoll.pyx":137 * self.initialized = 0 * * def fileno(self): # <<<<<<<<<<<<<< @@ -749,18 +1046,22 @@ static char __pyx_doc_7twisted_6python_6_epoll_5epoll_3fileno[] = "\n Return the epoll file descriptor number.\n "; static PyObject *__pyx_pf_7twisted_6python_6_epoll_5epoll_3fileno(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; __Pyx_RefNannySetupContext("fileno"); - /* "twisted/python/_epoll.pyx":100 + /* "twisted/python/_epoll.pyx":141 * Return the epoll file descriptor number. * """ * return self.fd # <<<<<<<<<<<<<< * - * def _control(self, int op, int fd, int events): + * def register(self, int fd, int events): */ __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PyInt_FromLong(((struct __pyx_obj_7twisted_6python_6_epoll_epoll *)__pyx_v_self)->fd); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyInt_FromLong(((struct __pyx_obj_7twisted_6python_6_epoll_epoll *)__pyx_v_self)->fd); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 141; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; @@ -770,7 +1071,7 @@ goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("twisted.python._epoll.epoll.fileno"); + __Pyx_AddTraceback("twisted.python._epoll.epoll.fileno", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); @@ -778,141 +1079,143 @@ return __pyx_r; } -/* "twisted/python/_epoll.pyx":102 +/* "twisted/python/_epoll.pyx":143 * return self.fd * - * def _control(self, int op, int fd, int events): # <<<<<<<<<<<<<< + * def register(self, int fd, int events): # <<<<<<<<<<<<<< * """ - * Modify the monitored state of a particular file descriptor. + * Add (register) a file descriptor to be monitored by self. */ -static PyObject *__pyx_pf_7twisted_6python_6_epoll_5epoll_4_control(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static char __pyx_doc_7twisted_6python_6_epoll_5epoll_4_control[] = "\n Modify the monitored state of a particular file descriptor.\n \n Wrap epoll_ctl(2).\n\n @type op: C{int}\n @param op: One of CTL_ADD, CTL_DEL, or CTL_MOD\n\n @type fd: C{int}\n @param fd: File descriptor to modify\n\n @type events: C{int}\n @param events: A bit set of IN, OUT, PRI, ERR, HUP, and ET.\n\n @raise IOError: Raised if the underlying epoll_ctl() call fails.\n "; -static PyObject *__pyx_pf_7twisted_6python_6_epoll_5epoll_4_control(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - int __pyx_v_op; +static PyObject *__pyx_pf_7twisted_6python_6_epoll_5epoll_4register(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static char __pyx_doc_7twisted_6python_6_epoll_5epoll_4register[] = "\n Add (register) a file descriptor to be monitored by self.\n\n This method is compatible with select.epoll.register in Python 2.6.\n\n Wrap epoll_ctl(2).\n\n @type fd: C{int}\n @param fd: File descriptor to modify\n\n @type events: C{int}\n @param events: A bit set of IN, OUT, PRI, ERR, HUP, and ET.\n\n @raise IOError: Raised if the underlying epoll_ctl() call fails.\n "; +static PyObject *__pyx_pf_7twisted_6python_6_epoll_5epoll_4register(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { int __pyx_v_fd; int __pyx_v_events; int __pyx_v_result; struct epoll_event __pyx_v_evt; PyObject *__pyx_r = NULL; - int __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; PyObject *__pyx_t_4 = NULL; - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__op,&__pyx_n_s__fd,&__pyx_n_s__events,0}; - __Pyx_RefNannySetupContext("_control"); - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); - PyObject* values[3] = {0,0,0}; - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 0: - values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__op); - if (likely(values[0])) kw_args--; - else goto __pyx_L5_argtuple_error; - case 1: - values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__fd); - if (likely(values[1])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("_control", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - } - case 2: - values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__events); - if (likely(values[2])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("_control", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "_control") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - } - __pyx_v_op = __Pyx_PyInt_AsInt(values[0]); if (unlikely((__pyx_v_op == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __pyx_v_fd = __Pyx_PyInt_AsInt(values[1]); if (unlikely((__pyx_v_fd == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __pyx_v_events = __Pyx_PyInt_AsInt(values[2]); if (unlikely((__pyx_v_events == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { - goto __pyx_L5_argtuple_error; - } else { - __pyx_v_op = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_op == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __pyx_v_fd = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_fd == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __pyx_v_events = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 2)); if (unlikely((__pyx_v_events == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + PyObject *__pyx_t_5 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__fd,&__pyx_n_s__events,0}; + __Pyx_RefNannySetupContext("register"); + { + PyObject* values[2] = {0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__fd); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__events); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("register", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 143; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "register") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 143; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + } + __pyx_v_fd = __Pyx_PyInt_AsInt(values[0]); if (unlikely((__pyx_v_fd == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 143; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_v_events = __Pyx_PyInt_AsInt(values[1]); if (unlikely((__pyx_v_events == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 143; __pyx_clineno = __LINE__; goto __pyx_L3_error;} } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("_control", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __Pyx_RaiseArgtupleInvalid("register", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 143; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __pyx_L3_error:; - __Pyx_AddTraceback("twisted.python._epoll.epoll._control"); + __Pyx_AddTraceback("twisted.python._epoll.epoll.register", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; - /* "twisted/python/_epoll.pyx":121 + /* "twisted/python/_epoll.pyx":161 * cdef int result * cdef epoll_event evt * evt.events = events # <<<<<<<<<<<<<< * evt.data.fd = fd - * result = epoll_ctl(self.fd, op, fd, &evt) + * result = epoll_ctl(self.fd, CTL_ADD, fd, &evt) */ __pyx_v_evt.events = __pyx_v_events; - /* "twisted/python/_epoll.pyx":122 + /* "twisted/python/_epoll.pyx":162 * cdef epoll_event evt * evt.events = events * evt.data.fd = fd # <<<<<<<<<<<<<< - * result = epoll_ctl(self.fd, op, fd, &evt) + * result = epoll_ctl(self.fd, CTL_ADD, fd, &evt) * if result == -1: */ __pyx_v_evt.data.fd = __pyx_v_fd; - /* "twisted/python/_epoll.pyx":123 + /* "twisted/python/_epoll.pyx":163 * evt.events = events * evt.data.fd = fd - * result = epoll_ctl(self.fd, op, fd, &evt) # <<<<<<<<<<<<<< + * result = epoll_ctl(self.fd, CTL_ADD, fd, &evt) # <<<<<<<<<<<<<< * if result == -1: * raise IOError(errno, strerror(errno)) */ - __pyx_v_result = epoll_ctl(((struct __pyx_obj_7twisted_6python_6_epoll_epoll *)__pyx_v_self)->fd, __pyx_v_op, __pyx_v_fd, (&__pyx_v_evt)); + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__CTL_ADD); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 163; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyInt_AsInt(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 163; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_result = epoll_ctl(((struct __pyx_obj_7twisted_6python_6_epoll_epoll *)__pyx_v_self)->fd, __pyx_t_2, __pyx_v_fd, (&__pyx_v_evt)); - /* "twisted/python/_epoll.pyx":124 + /* "twisted/python/_epoll.pyx":164 * evt.data.fd = fd - * result = epoll_ctl(self.fd, op, fd, &evt) + * result = epoll_ctl(self.fd, CTL_ADD, fd, &evt) * if result == -1: # <<<<<<<<<<<<<< * raise IOError(errno, strerror(errno)) * */ - __pyx_t_1 = (__pyx_v_result == -1); - if (__pyx_t_1) { + __pyx_t_3 = (__pyx_v_result == -1); + if (__pyx_t_3) { - /* "twisted/python/_epoll.pyx":125 - * result = epoll_ctl(self.fd, op, fd, &evt) + /* "twisted/python/_epoll.pyx":165 + * result = epoll_ctl(self.fd, CTL_ADD, fd, &evt) * if result == -1: * raise IOError(errno, strerror(errno)) # <<<<<<<<<<<<<< * - * def wait(self, unsigned int maxevents, int timeout): + * def unregister(self, int fd): */ - __pyx_t_2 = PyInt_FromLong(errno); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 125; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyBytes_FromString(strerror(errno)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 125; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_3)); - __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 125; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyInt_FromLong(errno); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 165; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = PyBytes_FromString(strerror(errno)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 165; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(((PyObject *)__pyx_t_4)); - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2); - __Pyx_GIVEREF(__pyx_t_2); - PyTuple_SET_ITEM(__pyx_t_4, 1, ((PyObject *)__pyx_t_3)); - __Pyx_GIVEREF(((PyObject *)__pyx_t_3)); - __pyx_t_2 = 0; - __pyx_t_3 = 0; - __pyx_t_3 = PyObject_Call(__pyx_builtin_IOError, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 125; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0; - __Pyx_Raise(__pyx_t_3, 0, 0); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 125; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 165; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_5)); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_5, 1, ((PyObject *)__pyx_t_4)); + __Pyx_GIVEREF(((PyObject *)__pyx_t_4)); + __pyx_t_1 = 0; + __pyx_t_4 = 0; + __pyx_t_4 = PyObject_Call(__pyx_builtin_IOError, ((PyObject *)__pyx_t_5), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 165; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 165; __pyx_clineno = __LINE__; goto __pyx_L1_error;} goto __pyx_L6; } __pyx_L6:; @@ -920,10 +1223,10 @@ __pyx_r = Py_None; __Pyx_INCREF(Py_None); goto __pyx_L0; __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_4); - __Pyx_AddTraceback("twisted.python._epoll.epoll._control"); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("twisted.python._epoll.epoll.register", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); @@ -931,299 +1234,618 @@ return __pyx_r; } -/* "twisted/python/_epoll.pyx":127 +/* "twisted/python/_epoll.pyx":167 * raise IOError(errno, strerror(errno)) * - * def wait(self, unsigned int maxevents, int timeout): # <<<<<<<<<<<<<< + * def unregister(self, int fd): # <<<<<<<<<<<<<< * """ - * Wait for an I/O event, wrap epoll_wait(2). + * Remove (unregister) a file descriptor monitored by self. */ -static PyObject *__pyx_pf_7twisted_6python_6_epoll_5epoll_5wait(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static char __pyx_doc_7twisted_6python_6_epoll_5epoll_5wait[] = "\n Wait for an I/O event, wrap epoll_wait(2).\n\n @type maxevents: C{int}\n @param maxevents: Maximum number of events returned.\n\n @type timeout: C{int}\n @param timeout: Maximum time waiting for events. 0 makes it return\n immediately whereas -1 makes it wait indefinitely.\n \n @raise IOError: Raised if the underlying epoll_wait() call fails.\n "; -static PyObject *__pyx_pf_7twisted_6python_6_epoll_5epoll_5wait(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - unsigned int __pyx_v_maxevents; - int __pyx_v_timeout; - struct epoll_event *__pyx_v_events; - int __pyx_v_result; - int __pyx_v_nbytes; +static PyObject *__pyx_pf_7twisted_6python_6_epoll_5epoll_5unregister(PyObject *__pyx_v_self, PyObject *__pyx_arg_fd); /*proto*/ +static char __pyx_doc_7twisted_6python_6_epoll_5epoll_5unregister[] = "\n Remove (unregister) a file descriptor monitored by self.\n\n This method is compatible with select.epoll.unregister in Python 2.6.\n\n Wrap epoll_ctl(2).\n\n @type fd: C{int}\n @param fd: File descriptor to modify\n\n @raise IOError: Raised if the underlying epoll_ctl() call fails.\n "; +static PyObject *__pyx_pf_7twisted_6python_6_epoll_5epoll_5unregister(PyObject *__pyx_v_self, PyObject *__pyx_arg_fd) { int __pyx_v_fd; - PyThreadState *__pyx_v__save; - PyObject *__pyx_v_results; - long __pyx_v_i; + int __pyx_v_result; + struct epoll_event __pyx_v_evt; PyObject *__pyx_r = NULL; - int __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; PyObject *__pyx_t_4 = NULL; - int __pyx_t_5; - int __pyx_t_6; - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__maxevents,&__pyx_n_s__timeout,0}; - __Pyx_RefNannySetupContext("wait"); - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args = PyDict_Size(__pyx_kwds); - PyObject* values[2] = {0,0}; - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 0: - values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__maxevents); - if (likely(values[0])) kw_args--; - else goto __pyx_L5_argtuple_error; - case 1: - values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__timeout); - if (likely(values[1])) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("wait", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "wait") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - } - __pyx_v_maxevents = __Pyx_PyInt_AsUnsignedInt(values[0]); if (unlikely((__pyx_v_maxevents == (unsigned int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __pyx_v_timeout = __Pyx_PyInt_AsInt(values[1]); if (unlikely((__pyx_v_timeout == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { - goto __pyx_L5_argtuple_error; - } else { - __pyx_v_maxevents = __Pyx_PyInt_AsUnsignedInt(PyTuple_GET_ITEM(__pyx_args, 0)); if (unlikely((__pyx_v_maxevents == (unsigned int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L3_error;} - __pyx_v_timeout = __Pyx_PyInt_AsInt(PyTuple_GET_ITEM(__pyx_args, 1)); if (unlikely((__pyx_v_timeout == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + PyObject *__pyx_t_5 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("unregister"); + assert(__pyx_arg_fd); { + __pyx_v_fd = __Pyx_PyInt_AsInt(__pyx_arg_fd); if (unlikely((__pyx_v_fd == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 167; __pyx_clineno = __LINE__; goto __pyx_L3_error;} } goto __pyx_L4_argument_unpacking_done; - __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("wait", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L3_error;} __pyx_L3_error:; - __Pyx_AddTraceback("twisted.python._epoll.epoll.wait"); + __Pyx_AddTraceback("twisted.python._epoll.epoll.unregister", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; - __pyx_v_results = ((PyObject*)Py_None); __Pyx_INCREF(Py_None); - /* "twisted/python/_epoll.pyx":146 - * cdef PyThreadState *_save - * - * nbytes = sizeof(epoll_event) * maxevents # <<<<<<<<<<<<<< - * events = malloc(nbytes) - * memset(events, 0, nbytes) + /* "twisted/python/_epoll.pyx":183 + * cdef epoll_event evt + * # We don't have to fill evt.events for CTL_DEL. + * evt.data.fd = fd # <<<<<<<<<<<<<< + * result = epoll_ctl(self.fd, CTL_DEL, fd, &evt) + * if result == -1: */ - __pyx_v_nbytes = ((sizeof(struct epoll_event)) * __pyx_v_maxevents); + __pyx_v_evt.data.fd = __pyx_v_fd; - /* "twisted/python/_epoll.pyx":147 - * - * nbytes = sizeof(epoll_event) * maxevents - * events = malloc(nbytes) # <<<<<<<<<<<<<< - * memset(events, 0, nbytes) - * try: + /* "twisted/python/_epoll.pyx":184 + * # We don't have to fill evt.events for CTL_DEL. + * evt.data.fd = fd + * result = epoll_ctl(self.fd, CTL_DEL, fd, &evt) # <<<<<<<<<<<<<< + * if result == -1: + * raise IOError(errno, strerror(errno)) */ - __pyx_v_events = ((struct epoll_event *)malloc(__pyx_v_nbytes)); + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__CTL_DEL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyInt_AsInt(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_result = epoll_ctl(((struct __pyx_obj_7twisted_6python_6_epoll_epoll *)__pyx_v_self)->fd, __pyx_t_2, __pyx_v_fd, (&__pyx_v_evt)); - /* "twisted/python/_epoll.pyx":148 - * nbytes = sizeof(epoll_event) * maxevents - * events = malloc(nbytes) - * memset(events, 0, nbytes) # <<<<<<<<<<<<<< - * try: - * fd = self.fd + /* "twisted/python/_epoll.pyx":185 + * evt.data.fd = fd + * result = epoll_ctl(self.fd, CTL_DEL, fd, &evt) + * if result == -1: # <<<<<<<<<<<<<< + * raise IOError(errno, strerror(errno)) + * */ - memset(__pyx_v_events, 0, __pyx_v_nbytes); + __pyx_t_3 = (__pyx_v_result == -1); + if (__pyx_t_3) { - /* "twisted/python/_epoll.pyx":149 - * events = malloc(nbytes) - * memset(events, 0, nbytes) - * try: # <<<<<<<<<<<<<< - * fd = self.fd + /* "twisted/python/_epoll.pyx":186 + * result = epoll_ctl(self.fd, CTL_DEL, fd, &evt) + * if result == -1: + * raise IOError(errno, strerror(errno)) # <<<<<<<<<<<<<< * + * def modify(self, int fd, int events): */ - /*try:*/ { + __pyx_t_1 = PyInt_FromLong(errno); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 186; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = PyBytes_FromString(strerror(errno)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 186; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_4)); + __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 186; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_5)); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_5, 1, ((PyObject *)__pyx_t_4)); + __Pyx_GIVEREF(((PyObject *)__pyx_t_4)); + __pyx_t_1 = 0; + __pyx_t_4 = 0; + __pyx_t_4 = PyObject_Call(__pyx_builtin_IOError, ((PyObject *)__pyx_t_5), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 186; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 186; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L5; + } + __pyx_L5:; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("twisted.python._epoll.epoll.unregister", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} - /* "twisted/python/_epoll.pyx":150 - * memset(events, 0, nbytes) - * try: - * fd = self.fd # <<<<<<<<<<<<<< +/* "twisted/python/_epoll.pyx":188 + * raise IOError(errno, strerror(errno)) * - * _save = PyEval_SaveThread() + * def modify(self, int fd, int events): # <<<<<<<<<<<<<< + * """ + * Modify the modified state of a file descriptor monitored by self. */ - __pyx_v_fd = ((struct __pyx_obj_7twisted_6python_6_epoll_epoll *)__pyx_v_self)->fd; - /* "twisted/python/_epoll.pyx":152 - * fd = self.fd - * - * _save = PyEval_SaveThread() # <<<<<<<<<<<<<< - * result = epoll_wait(fd, events, maxevents, timeout) - * PyEval_RestoreThread(_save) +static PyObject *__pyx_pf_7twisted_6python_6_epoll_5epoll_6modify(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static char __pyx_doc_7twisted_6python_6_epoll_5epoll_6modify[] = "\n Modify the modified state of a file descriptor monitored by self.\n\n This method is compatible with select.epoll.modify in Python 2.6.\n\n Wrap epoll_ctl(2).\n\n @type fd: C{int}\n @param fd: File descriptor to modify\n\n @type events: C{int}\n @param events: A bit set of IN, OUT, PRI, ERR, HUP, and ET.\n\n @raise IOError: Raised if the underlying epoll_ctl() call fails.\n "; +static PyObject *__pyx_pf_7twisted_6python_6_epoll_5epoll_6modify(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + int __pyx_v_fd; + int __pyx_v_events; + int __pyx_v_result; + struct epoll_event __pyx_v_evt; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__fd,&__pyx_n_s__events,0}; + __Pyx_RefNannySetupContext("modify"); + { + PyObject* values[2] = {0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__fd); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__events); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("modify", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 188; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "modify") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 188; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + } + __pyx_v_fd = __Pyx_PyInt_AsInt(values[0]); if (unlikely((__pyx_v_fd == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 188; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_v_events = __Pyx_PyInt_AsInt(values[1]); if (unlikely((__pyx_v_events == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 188; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("modify", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 188; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("twisted.python._epoll.epoll.modify", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + + /* "twisted/python/_epoll.pyx":206 + * cdef int result + * cdef epoll_event evt + * evt.events = events # <<<<<<<<<<<<<< + * evt.data.fd = fd + * result = epoll_ctl(self.fd, CTL_MOD, fd, &evt) */ - __pyx_v__save = PyEval_SaveThread(); + __pyx_v_evt.events = __pyx_v_events; - /* "twisted/python/_epoll.pyx":153 - * - * _save = PyEval_SaveThread() - * result = epoll_wait(fd, events, maxevents, timeout) # <<<<<<<<<<<<<< - * PyEval_RestoreThread(_save) + /* "twisted/python/_epoll.pyx":207 + * cdef epoll_event evt + * evt.events = events + * evt.data.fd = fd # <<<<<<<<<<<<<< + * result = epoll_ctl(self.fd, CTL_MOD, fd, &evt) + * if result == -1: + */ + __pyx_v_evt.data.fd = __pyx_v_fd; + + /* "twisted/python/_epoll.pyx":208 + * evt.events = events + * evt.data.fd = fd + * result = epoll_ctl(self.fd, CTL_MOD, fd, &evt) # <<<<<<<<<<<<<< + * if result == -1: + * raise IOError(errno, strerror(errno)) + */ + __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__CTL_MOD); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 208; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyInt_AsInt(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 208; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_result = epoll_ctl(((struct __pyx_obj_7twisted_6python_6_epoll_epoll *)__pyx_v_self)->fd, __pyx_t_2, __pyx_v_fd, (&__pyx_v_evt)); + + /* "twisted/python/_epoll.pyx":209 + * evt.data.fd = fd + * result = epoll_ctl(self.fd, CTL_MOD, fd, &evt) + * if result == -1: # <<<<<<<<<<<<<< + * raise IOError(errno, strerror(errno)) * */ - __pyx_v_result = epoll_wait(__pyx_v_fd, __pyx_v_events, __pyx_v_maxevents, __pyx_v_timeout); + __pyx_t_3 = (__pyx_v_result == -1); + if (__pyx_t_3) { - /* "twisted/python/_epoll.pyx":154 - * _save = PyEval_SaveThread() - * result = epoll_wait(fd, events, maxevents, timeout) - * PyEval_RestoreThread(_save) # <<<<<<<<<<<<<< + /* "twisted/python/_epoll.pyx":210 + * result = epoll_ctl(self.fd, CTL_MOD, fd, &evt) + * if result == -1: + * raise IOError(errno, strerror(errno)) # <<<<<<<<<<<<<< * - * if result == -1: + * def _control(self, int op, int fd, int events): */ - PyEval_RestoreThread(__pyx_v__save); + __pyx_t_1 = PyInt_FromLong(errno); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = PyBytes_FromString(strerror(errno)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_4)); + __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_5)); + PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_5, 1, ((PyObject *)__pyx_t_4)); + __Pyx_GIVEREF(((PyObject *)__pyx_t_4)); + __pyx_t_1 = 0; + __pyx_t_4 = 0; + __pyx_t_4 = PyObject_Call(__pyx_builtin_IOError, ((PyObject *)__pyx_t_5), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L6; + } + __pyx_L6:; + + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("twisted.python._epoll.epoll.modify", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} - /* "twisted/python/_epoll.pyx":156 - * PyEval_RestoreThread(_save) +/* "twisted/python/_epoll.pyx":212 + * raise IOError(errno, strerror(errno)) * - * if result == -1: # <<<<<<<<<<<<<< - * raise IOError(errno, strerror(errno)) - * results = [] + * def _control(self, int op, int fd, int events): # <<<<<<<<<<<<<< + * """ + * Modify the monitored state of a particular file descriptor. */ - __pyx_t_1 = (__pyx_v_result == -1); - if (__pyx_t_1) { - /* "twisted/python/_epoll.pyx":157 +static PyObject *__pyx_pf_7twisted_6python_6_epoll_5epoll_7_control(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static char __pyx_doc_7twisted_6python_6_epoll_5epoll_7_control[] = "\n Modify the monitored state of a particular file descriptor.\n \n Wrap epoll_ctl(2).\n\n @type op: C{int}\n @param op: One of CTL_ADD, CTL_DEL, or CTL_MOD\n\n @type fd: C{int}\n @param fd: File descriptor to modify\n\n @type events: C{int}\n @param events: A bit set of IN, OUT, PRI, ERR, HUP, and ET.\n\n @raise IOError: Raised if the underlying epoll_ctl() call fails.\n "; +static PyObject *__pyx_pf_7twisted_6python_6_epoll_5epoll_7_control(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + int __pyx_v_op; + int __pyx_v_fd; + int __pyx_v_events; + int __pyx_v_result; + struct epoll_event __pyx_v_evt; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__op,&__pyx_n_s__fd,&__pyx_n_s__events,0}; + __Pyx_RefNannySetupContext("_control"); + { + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__op); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__fd); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("_control", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + case 2: + values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__events); + if (likely(values[2])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("_control", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "_control") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + } + __pyx_v_op = __Pyx_PyInt_AsInt(values[0]); if (unlikely((__pyx_v_op == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_v_fd = __Pyx_PyInt_AsInt(values[1]); if (unlikely((__pyx_v_fd == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_v_events = __Pyx_PyInt_AsInt(values[2]); if (unlikely((__pyx_v_events == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("_control", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("twisted.python._epoll.epoll._control", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + + /* "twisted/python/_epoll.pyx":231 + * cdef int result + * cdef epoll_event evt + * evt.events = events # <<<<<<<<<<<<<< + * evt.data.fd = fd + * result = epoll_ctl(self.fd, op, fd, &evt) + */ + __pyx_v_evt.events = __pyx_v_events; + + /* "twisted/python/_epoll.pyx":232 + * cdef epoll_event evt + * evt.events = events + * evt.data.fd = fd # <<<<<<<<<<<<<< + * result = epoll_ctl(self.fd, op, fd, &evt) + * if result == -1: + */ + __pyx_v_evt.data.fd = __pyx_v_fd; + + /* "twisted/python/_epoll.pyx":233 + * evt.events = events + * evt.data.fd = fd + * result = epoll_ctl(self.fd, op, fd, &evt) # <<<<<<<<<<<<<< + * if result == -1: + * raise IOError(errno, strerror(errno)) + */ + __pyx_v_result = epoll_ctl(((struct __pyx_obj_7twisted_6python_6_epoll_epoll *)__pyx_v_self)->fd, __pyx_v_op, __pyx_v_fd, (&__pyx_v_evt)); + + /* "twisted/python/_epoll.pyx":234 + * evt.data.fd = fd + * result = epoll_ctl(self.fd, op, fd, &evt) + * if result == -1: # <<<<<<<<<<<<<< + * raise IOError(errno, strerror(errno)) * - * if result == -1: - * raise IOError(errno, strerror(errno)) # <<<<<<<<<<<<<< - * results = [] - * for i from 0 <= i < result: */ - __pyx_t_2 = PyInt_FromLong(errno); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L7;} - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyBytes_FromString(strerror(errno)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L7;} - __Pyx_GOTREF(((PyObject *)__pyx_t_3)); - __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L7;} - __Pyx_GOTREF(((PyObject *)__pyx_t_4)); - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2); - __Pyx_GIVEREF(__pyx_t_2); - PyTuple_SET_ITEM(__pyx_t_4, 1, ((PyObject *)__pyx_t_3)); - __Pyx_GIVEREF(((PyObject *)__pyx_t_3)); - __pyx_t_2 = 0; - __pyx_t_3 = 0; - __pyx_t_3 = PyObject_Call(__pyx_builtin_IOError, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L7;} - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0; - __Pyx_Raise(__pyx_t_3, 0, 0); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - {__pyx_filename = __pyx_f[0]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L7;} - goto __pyx_L9; - } - __pyx_L9:; + __pyx_t_1 = (__pyx_v_result == -1); + if (__pyx_t_1) { - /* "twisted/python/_epoll.pyx":158 - * if result == -1: - * raise IOError(errno, strerror(errno)) - * results = [] # <<<<<<<<<<<<<< - * for i from 0 <= i < result: - * results.append((events[i].data.fd, events[i].events)) + /* "twisted/python/_epoll.pyx":235 + * result = epoll_ctl(self.fd, op, fd, &evt) + * if result == -1: + * raise IOError(errno, strerror(errno)) # <<<<<<<<<<<<<< + * + * def wait(self, unsigned int maxevents, int timeout): */ - __pyx_t_3 = PyList_New(0); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 158; __pyx_clineno = __LINE__; goto __pyx_L7;} + __pyx_t_2 = PyInt_FromLong(errno); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = PyBytes_FromString(strerror(errno)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(((PyObject *)__pyx_t_3)); - __Pyx_DECREF(((PyObject *)__pyx_v_results)); - __pyx_v_results = __pyx_t_3; + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(((PyObject *)__pyx_t_4)); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_4, 1, ((PyObject *)__pyx_t_3)); + __Pyx_GIVEREF(((PyObject *)__pyx_t_3)); + __pyx_t_2 = 0; __pyx_t_3 = 0; + __pyx_t_3 = PyObject_Call(__pyx_builtin_IOError, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0; + __Pyx_Raise(__pyx_t_3, 0, 0, 0); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + {__pyx_filename = __pyx_f[0]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + goto __pyx_L6; + } + __pyx_L6:; - /* "twisted/python/_epoll.pyx":159 - * raise IOError(errno, strerror(errno)) - * results = [] - * for i from 0 <= i < result: # <<<<<<<<<<<<<< - * results.append((events[i].data.fd, events[i].events)) - * return results - */ - __pyx_t_5 = __pyx_v_result; - for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_5; __pyx_v_i++) { + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_AddTraceback("twisted.python._epoll.epoll._control", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} - /* "twisted/python/_epoll.pyx":160 - * results = [] - * for i from 0 <= i < result: - * results.append((events[i].data.fd, events[i].events)) # <<<<<<<<<<<<<< - * return results - * finally: +/* "twisted/python/_epoll.pyx":237 + * raise IOError(errno, strerror(errno)) + * + * def wait(self, unsigned int maxevents, int timeout): # <<<<<<<<<<<<<< + * """ + * Wait for an I/O event, wrap epoll_wait(2). */ - if (unlikely(__pyx_v_results == Py_None)) { - PyErr_SetString(PyExc_AttributeError, "'NoneType' object has no attribute 'append'"); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L7;} + +static PyObject *__pyx_pf_7twisted_6python_6_epoll_5epoll_8wait(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static char __pyx_doc_7twisted_6python_6_epoll_5epoll_8wait[] = "\n Wait for an I/O event, wrap epoll_wait(2).\n\n @type maxevents: C{int}\n @param maxevents: Maximum number of events returned.\n\n @type timeout: C{int}\n @param timeout: Maximum time in milliseconds waiting for events. 0\n makes it return immediately whereas -1 makes it wait indefinitely.\n \n @raise IOError: Raised if the underlying epoll_wait() call fails.\n "; +static PyObject *__pyx_pf_7twisted_6python_6_epoll_5epoll_8wait(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + unsigned int __pyx_v_maxevents; + int __pyx_v_timeout; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__maxevents,&__pyx_n_s__timeout,0}; + __Pyx_RefNannySetupContext("wait"); + { + PyObject* values[2] = {0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; } - __pyx_t_3 = PyInt_FromLong((__pyx_v_events[__pyx_v_i]).data.fd); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L7;} - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_4 = PyInt_FromLong(((int)(__pyx_v_events[__pyx_v_i]).events)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L7;} - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L7;} - __Pyx_GOTREF(((PyObject *)__pyx_t_2)); - PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_3); - __Pyx_GIVEREF(__pyx_t_3); - PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_4); - __Pyx_GIVEREF(__pyx_t_4); - __pyx_t_3 = 0; - __pyx_t_4 = 0; - __pyx_t_6 = PyList_Append(__pyx_v_results, ((PyObject *)__pyx_t_2)); if (unlikely(__pyx_t_6 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L7;} - __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0; + kw_args = PyDict_Size(__pyx_kwds); + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__maxevents); + if (likely(values[0])) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__timeout); + if (likely(values[1])) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("wait", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 237; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "wait") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 237; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); } + __pyx_v_maxevents = __Pyx_PyInt_AsUnsignedInt(values[0]); if (unlikely((__pyx_v_maxevents == (unsigned int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 237; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_v_timeout = __Pyx_PyInt_AsInt(values[1]); if (unlikely((__pyx_v_timeout == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 237; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("wait", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 237; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("twisted.python._epoll.epoll.wait", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; - /* "twisted/python/_epoll.pyx":161 - * for i from 0 <= i < result: - * results.append((events[i].data.fd, events[i].events)) - * return results # <<<<<<<<<<<<<< - * finally: - * free(events) + /* "twisted/python/_epoll.pyx":250 + * @raise IOError: Raised if the underlying epoll_wait() call fails. + * """ + * return call_epoll_wait(self.fd, maxevents, timeout) # <<<<<<<<<<<<<< + * + * def poll(self, float timeout=-1, unsigned int maxevents=1024): */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(((PyObject *)__pyx_v_results)); - __pyx_r = ((PyObject *)__pyx_v_results); - goto __pyx_L6; - } + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __pyx_f_7twisted_6python_6_epoll_call_epoll_wait(((struct __pyx_obj_7twisted_6python_6_epoll_epoll *)__pyx_v_self)->fd, __pyx_v_maxevents, __pyx_v_timeout); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 250; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; - /* "twisted/python/_epoll.pyx":163 - * return results - * finally: - * free(events) # <<<<<<<<<<<<<< + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("twisted.python._epoll.epoll.wait", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "twisted/python/_epoll.pyx":252 + * return call_epoll_wait(self.fd, maxevents, timeout) * - * CTL_ADD = EPOLL_CTL_ADD + * def poll(self, float timeout=-1, unsigned int maxevents=1024): # <<<<<<<<<<<<<< + * """ + * Wait for an I/O event, wrap epoll_wait(2). */ - /*finally:*/ { - int __pyx_why; - PyObject *__pyx_exc_type, *__pyx_exc_value, *__pyx_exc_tb; - int __pyx_exc_lineno; - __pyx_exc_type = 0; __pyx_exc_value = 0; __pyx_exc_tb = 0; __pyx_exc_lineno = 0; - __pyx_why = 0; goto __pyx_L8; - __pyx_L6: __pyx_exc_type = 0; __pyx_exc_value = 0; __pyx_exc_tb = 0; __pyx_exc_lineno = 0; - __pyx_why = 3; goto __pyx_L8; - __pyx_L7: { - __pyx_why = 4; - __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_ErrFetch(&__pyx_exc_type, &__pyx_exc_value, &__pyx_exc_tb); - __pyx_exc_lineno = __pyx_lineno; - goto __pyx_L8; - } - __pyx_L8:; - free(__pyx_v_events); - switch (__pyx_why) { - case 3: goto __pyx_L0; - case 4: { - __Pyx_ErrRestore(__pyx_exc_type, __pyx_exc_value, __pyx_exc_tb); - __pyx_lineno = __pyx_exc_lineno; - __pyx_exc_type = 0; - __pyx_exc_value = 0; - __pyx_exc_tb = 0; - goto __pyx_L1_error; + +static PyObject *__pyx_pf_7twisted_6python_6_epoll_5epoll_9poll(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static char __pyx_doc_7twisted_6python_6_epoll_5epoll_9poll[] = "\n Wait for an I/O event, wrap epoll_wait(2).\n\n This method is compatible with select.epoll.poll in Python 2.6.\n\n @type maxevents: C{int}\n @param maxevents: Maximum number of events returned.\n\n @type timeout: C{int}\n @param timeout: Maximum time waiting for events. 0 makes it return\n immediately whereas -1 makes it wait indefinitely.\n \n @raise IOError: Raised if the underlying epoll_wait() call fails.\n "; +static PyObject *__pyx_pf_7twisted_6python_6_epoll_5epoll_9poll(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + float __pyx_v_timeout; + unsigned int __pyx_v_maxevents; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__timeout,&__pyx_n_s__maxevents,0}; + __Pyx_RefNannySetupContext("poll"); + { + PyObject* values[2] = {0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 0: + if (kw_args > 0) { + PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__timeout); + if (value) { values[0] = value; kw_args--; } + } + case 1: + if (kw_args > 0) { + PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__maxevents); + if (value) { values[1] = value; kw_args--; } + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, PyTuple_GET_SIZE(__pyx_args), "poll") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 252; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } + } else { + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; } } + if (values[0]) { + __pyx_v_timeout = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_timeout == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 252; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } else { + __pyx_v_timeout = ((float)-1.0); + } + if (values[1]) { + __pyx_v_maxevents = __Pyx_PyInt_AsUnsignedInt(values[1]); if (unlikely((__pyx_v_maxevents == (unsigned int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 252; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + } else { + __pyx_v_maxevents = ((unsigned int)1024); + } } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("poll", 0, 0, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 252; __pyx_clineno = __LINE__; goto __pyx_L3_error;} + __pyx_L3_error:; + __Pyx_AddTraceback("twisted.python._epoll.epoll.poll", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + + /* "twisted/python/_epoll.pyx":267 + * @raise IOError: Raised if the underlying epoll_wait() call fails. + * """ + * return call_epoll_wait(self.fd, maxevents, (timeout * 1000.0)) # <<<<<<<<<<<<<< + * + * + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __pyx_f_7twisted_6python_6_epoll_call_epoll_wait(((struct __pyx_obj_7twisted_6python_6_epoll_epoll *)__pyx_v_self)->fd, __pyx_v_maxevents, ((int)(__pyx_v_timeout * 1000.0))); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 267; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; __pyx_r = Py_None; __Pyx_INCREF(Py_None); goto __pyx_L0; __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_AddTraceback("twisted.python._epoll.epoll.wait"); + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("twisted.python._epoll.epoll.poll", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; - __Pyx_DECREF(__pyx_v_results); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; @@ -1251,8 +1873,12 @@ static PyMethodDef __pyx_methods_7twisted_6python_6_epoll_epoll[] = { {__Pyx_NAMESTR("close"), (PyCFunction)__pyx_pf_7twisted_6python_6_epoll_5epoll_2close, METH_NOARGS, __Pyx_DOCSTR(__pyx_doc_7twisted_6python_6_epoll_5epoll_2close)}, {__Pyx_NAMESTR("fileno"), (PyCFunction)__pyx_pf_7twisted_6python_6_epoll_5epoll_3fileno, METH_NOARGS, __Pyx_DOCSTR(__pyx_doc_7twisted_6python_6_epoll_5epoll_3fileno)}, - {__Pyx_NAMESTR("_control"), (PyCFunction)__pyx_pf_7twisted_6python_6_epoll_5epoll_4_control, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7twisted_6python_6_epoll_5epoll_4_control)}, - {__Pyx_NAMESTR("wait"), (PyCFunction)__pyx_pf_7twisted_6python_6_epoll_5epoll_5wait, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7twisted_6python_6_epoll_5epoll_5wait)}, + {__Pyx_NAMESTR("register"), (PyCFunction)__pyx_pf_7twisted_6python_6_epoll_5epoll_4register, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7twisted_6python_6_epoll_5epoll_4register)}, + {__Pyx_NAMESTR("unregister"), (PyCFunction)__pyx_pf_7twisted_6python_6_epoll_5epoll_5unregister, METH_O, __Pyx_DOCSTR(__pyx_doc_7twisted_6python_6_epoll_5epoll_5unregister)}, + {__Pyx_NAMESTR("modify"), (PyCFunction)__pyx_pf_7twisted_6python_6_epoll_5epoll_6modify, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7twisted_6python_6_epoll_5epoll_6modify)}, + {__Pyx_NAMESTR("_control"), (PyCFunction)__pyx_pf_7twisted_6python_6_epoll_5epoll_7_control, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7twisted_6python_6_epoll_5epoll_7_control)}, + {__Pyx_NAMESTR("wait"), (PyCFunction)__pyx_pf_7twisted_6python_6_epoll_5epoll_8wait, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7twisted_6python_6_epoll_5epoll_8wait)}, + {__Pyx_NAMESTR("poll"), (PyCFunction)__pyx_pf_7twisted_6python_6_epoll_5epoll_9poll, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7twisted_6python_6_epoll_5epoll_9poll)}, {0, 0, 0, 0} }; @@ -1432,6 +2058,17 @@ {&__pyx_n_s__CTL_ADD, __pyx_k__CTL_ADD, sizeof(__pyx_k__CTL_ADD), 0, 0, 1, 1}, {&__pyx_n_s__CTL_DEL, __pyx_k__CTL_DEL, sizeof(__pyx_k__CTL_DEL), 0, 0, 1, 1}, {&__pyx_n_s__CTL_MOD, __pyx_k__CTL_MOD, sizeof(__pyx_k__CTL_MOD), 0, 0, 1, 1}, + {&__pyx_n_s__EPOLLERR, __pyx_k__EPOLLERR, sizeof(__pyx_k__EPOLLERR), 0, 0, 1, 1}, + {&__pyx_n_s__EPOLLET, __pyx_k__EPOLLET, sizeof(__pyx_k__EPOLLET), 0, 0, 1, 1}, + {&__pyx_n_s__EPOLLHUP, __pyx_k__EPOLLHUP, sizeof(__pyx_k__EPOLLHUP), 0, 0, 1, 1}, + {&__pyx_n_s__EPOLLIN, __pyx_k__EPOLLIN, sizeof(__pyx_k__EPOLLIN), 0, 0, 1, 1}, + {&__pyx_n_s__EPOLLMSG, __pyx_k__EPOLLMSG, sizeof(__pyx_k__EPOLLMSG), 0, 0, 1, 1}, + {&__pyx_n_s__EPOLLOUT, __pyx_k__EPOLLOUT, sizeof(__pyx_k__EPOLLOUT), 0, 0, 1, 1}, + {&__pyx_n_s__EPOLLPRI, __pyx_k__EPOLLPRI, sizeof(__pyx_k__EPOLLPRI), 0, 0, 1, 1}, + {&__pyx_n_s__EPOLLRDBAND, __pyx_k__EPOLLRDBAND, sizeof(__pyx_k__EPOLLRDBAND), 0, 0, 1, 1}, + {&__pyx_n_s__EPOLLRDNORM, __pyx_k__EPOLLRDNORM, sizeof(__pyx_k__EPOLLRDNORM), 0, 0, 1, 1}, + {&__pyx_n_s__EPOLLWRBAND, __pyx_k__EPOLLWRBAND, sizeof(__pyx_k__EPOLLWRBAND), 0, 0, 1, 1}, + {&__pyx_n_s__EPOLLWRNORM, __pyx_k__EPOLLWRNORM, sizeof(__pyx_k__EPOLLWRNORM), 0, 0, 1, 1}, {&__pyx_n_s__ERR, __pyx_k__ERR, sizeof(__pyx_k__ERR), 0, 0, 1, 1}, {&__pyx_n_s__ET, __pyx_k__ET, sizeof(__pyx_k__ET), 0, 0, 1, 1}, {&__pyx_n_s__HUP, __pyx_k__HUP, sizeof(__pyx_k__HUP), 0, 0, 1, 1}, @@ -1446,11 +2083,8 @@ {&__pyx_n_s__WRNORM, __pyx_k__WRNORM, sizeof(__pyx_k__WRNORM), 0, 0, 1, 1}, {&__pyx_n_s____main__, __pyx_k____main__, sizeof(__pyx_k____main__), 0, 0, 1, 1}, {&__pyx_n_s____test__, __pyx_k____test__, sizeof(__pyx_k____test__), 0, 0, 1, 1}, - {&__pyx_n_s__append, __pyx_k__append, sizeof(__pyx_k__append), 0, 0, 1, 1}, - {&__pyx_n_s__data, __pyx_k__data, sizeof(__pyx_k__data), 0, 0, 1, 1}, {&__pyx_n_s__events, __pyx_k__events, sizeof(__pyx_k__events), 0, 0, 1, 1}, {&__pyx_n_s__fd, __pyx_k__fd, sizeof(__pyx_k__fd), 0, 0, 1, 1}, - {&__pyx_n_s__initialized, __pyx_k__initialized, sizeof(__pyx_k__initialized), 0, 0, 1, 1}, {&__pyx_n_s__maxevents, __pyx_k__maxevents, sizeof(__pyx_k__maxevents), 0, 0, 1, 1}, {&__pyx_n_s__op, __pyx_k__op, sizeof(__pyx_k__op), 0, 0, 1, 1}, {&__pyx_n_s__size, __pyx_k__size, sizeof(__pyx_k__size), 0, 0, 1, 1}, @@ -1458,13 +2092,14 @@ {0, 0, 0, 0, 0, 0, 0} }; static int __Pyx_InitCachedBuiltins(void) { - __pyx_builtin_IOError = __Pyx_GetName(__pyx_b, __pyx_n_s__IOError); if (!__pyx_builtin_IOError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_builtin_IOError = __Pyx_GetName(__pyx_b, __pyx_n_s__IOError); if (!__pyx_builtin_IOError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;} return 0; __pyx_L1_error:; return -1; } static int __Pyx_InitCachedConstants(void) { + __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants"); __Pyx_RefNannyFinishContext(); return 0; @@ -1486,8 +2121,8 @@ #endif { PyObject *__pyx_t_1 = NULL; + __Pyx_RefNannyDeclarations #if CYTHON_REFNANNY - void* __pyx_refnanny = NULL; __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); if (!__Pyx_RefNanny) { PyErr_Clear(); @@ -1495,8 +2130,9 @@ if (!__Pyx_RefNanny) Py_FatalError("failed to import 'refnanny' module"); } - __pyx_refnanny = __Pyx_RefNanny->SetupContext("PyMODINIT_FUNC PyInit__epoll(void)", __LINE__, __FILE__); #endif + __Pyx_RefNannySetupContext("PyMODINIT_FUNC PyInit__epoll(void)"); + if ( __Pyx_check_binary_version() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} #ifdef __pyx_binding_PyCFunctionType_USED @@ -1532,180 +2168,232 @@ /*--- Constants init code ---*/ if (unlikely(__Pyx_InitCachedConstants() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} /*--- Global init code ---*/ + /*--- Variable export code ---*/ /*--- Function export code ---*/ /*--- Type init code ---*/ - if (PyType_Ready(&__pyx_type_7twisted_6python_6_epoll_epoll) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - if (__Pyx_SetAttrString(__pyx_m, "epoll", (PyObject *)&__pyx_type_7twisted_6python_6_epoll_epoll) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyType_Ready(&__pyx_type_7twisted_6python_6_epoll_epoll) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 106; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + { + PyObject *wrapper = __Pyx_GetAttrString((PyObject *)&__pyx_type_7twisted_6python_6_epoll_epoll, "__init__"); if (unlikely(!wrapper)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 106; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (Py_TYPE(wrapper) == &PyWrapperDescr_Type) { + __pyx_wrapperbase_7twisted_6python_6_epoll_5epoll___init__ = *((PyWrapperDescrObject *)wrapper)->d_base; + __pyx_wrapperbase_7twisted_6python_6_epoll_5epoll___init__.doc = __pyx_doc_7twisted_6python_6_epoll_5epoll___init__; + ((PyWrapperDescrObject *)wrapper)->d_base = &__pyx_wrapperbase_7twisted_6python_6_epoll_5epoll___init__; + } + } + if (__Pyx_SetAttrString(__pyx_m, "epoll", (PyObject *)&__pyx_type_7twisted_6python_6_epoll_epoll) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 106; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __pyx_ptype_7twisted_6python_6_epoll_epoll = &__pyx_type_7twisted_6python_6_epoll_epoll; /*--- Type import code ---*/ + /*--- Variable import code ---*/ /*--- Function import code ---*/ /*--- Execution code ---*/ - /* "twisted/python/_epoll.pyx":165 - * free(events) + /* "twisted/python/_epoll.pyx":270 + * * * CTL_ADD = EPOLL_CTL_ADD # <<<<<<<<<<<<<< * CTL_DEL = EPOLL_CTL_DEL * CTL_MOD = EPOLL_CTL_MOD */ - __pyx_t_1 = PyInt_FromLong(EPOLL_CTL_ADD); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 165; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyInt_FromLong(EPOLL_CTL_ADD); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 270; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__CTL_ADD, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 165; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__CTL_ADD, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 270; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "twisted/python/_epoll.pyx":166 + /* "twisted/python/_epoll.pyx":271 * * CTL_ADD = EPOLL_CTL_ADD * CTL_DEL = EPOLL_CTL_DEL # <<<<<<<<<<<<<< * CTL_MOD = EPOLL_CTL_MOD * */ - __pyx_t_1 = PyInt_FromLong(EPOLL_CTL_DEL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyInt_FromLong(EPOLL_CTL_DEL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 271; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__CTL_DEL, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__CTL_DEL, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 271; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "twisted/python/_epoll.pyx":167 + /* "twisted/python/_epoll.pyx":272 * CTL_ADD = EPOLL_CTL_ADD * CTL_DEL = EPOLL_CTL_DEL * CTL_MOD = EPOLL_CTL_MOD # <<<<<<<<<<<<<< * - * IN = EPOLLIN + * IN = EPOLLIN = c_EPOLLIN */ - __pyx_t_1 = PyInt_FromLong(EPOLL_CTL_MOD); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 167; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyInt_FromLong(EPOLL_CTL_MOD); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__CTL_MOD, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 167; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__CTL_MOD, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "twisted/python/_epoll.pyx":169 + /* "twisted/python/_epoll.pyx":274 * CTL_MOD = EPOLL_CTL_MOD * - * IN = EPOLLIN # <<<<<<<<<<<<<< - * OUT = EPOLLOUT - * PRI = EPOLLPRI + * IN = EPOLLIN = c_EPOLLIN # <<<<<<<<<<<<<< + * OUT = EPOLLOUT = c_EPOLLOUT + * PRI = EPOLLPRI = c_EPOLLPRI */ - __pyx_t_1 = PyInt_FromLong(EPOLLIN); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyInt_FromLong(EPOLLIN); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 274; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__IN, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 274; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyInt_FromLong(EPOLLIN); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 274; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__IN, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__EPOLLIN, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 274; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "twisted/python/_epoll.pyx":170 + /* "twisted/python/_epoll.pyx":275 * - * IN = EPOLLIN - * OUT = EPOLLOUT # <<<<<<<<<<<<<< - * PRI = EPOLLPRI - * ERR = EPOLLERR + * IN = EPOLLIN = c_EPOLLIN + * OUT = EPOLLOUT = c_EPOLLOUT # <<<<<<<<<<<<<< + * PRI = EPOLLPRI = c_EPOLLPRI + * ERR = EPOLLERR = c_EPOLLERR */ - __pyx_t_1 = PyInt_FromLong(EPOLLOUT); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 170; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyInt_FromLong(EPOLLOUT); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__OUT, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 170; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__OUT, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyInt_FromLong(EPOLLOUT); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__EPOLLOUT, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "twisted/python/_epoll.pyx":171 - * IN = EPOLLIN - * OUT = EPOLLOUT - * PRI = EPOLLPRI # <<<<<<<<<<<<<< - * ERR = EPOLLERR - * HUP = EPOLLHUP + /* "twisted/python/_epoll.pyx":276 + * IN = EPOLLIN = c_EPOLLIN + * OUT = EPOLLOUT = c_EPOLLOUT + * PRI = EPOLLPRI = c_EPOLLPRI # <<<<<<<<<<<<<< + * ERR = EPOLLERR = c_EPOLLERR + * HUP = EPOLLHUP = c_EPOLLHUP */ - __pyx_t_1 = PyInt_FromLong(EPOLLPRI); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 171; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyInt_FromLong(EPOLLPRI); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__PRI, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyInt_FromLong(EPOLLPRI); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__PRI, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 171; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__EPOLLPRI, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "twisted/python/_epoll.pyx":172 - * OUT = EPOLLOUT - * PRI = EPOLLPRI - * ERR = EPOLLERR # <<<<<<<<<<<<<< - * HUP = EPOLLHUP - * ET = EPOLLET + /* "twisted/python/_epoll.pyx":277 + * OUT = EPOLLOUT = c_EPOLLOUT + * PRI = EPOLLPRI = c_EPOLLPRI + * ERR = EPOLLERR = c_EPOLLERR # <<<<<<<<<<<<<< + * HUP = EPOLLHUP = c_EPOLLHUP + * ET = EPOLLET = c_EPOLLET */ - __pyx_t_1 = PyInt_FromLong(EPOLLERR); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyInt_FromLong(EPOLLERR); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__ERR, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyInt_FromLong(EPOLLERR); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__ERR, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__EPOLLERR, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "twisted/python/_epoll.pyx":173 - * PRI = EPOLLPRI - * ERR = EPOLLERR - * HUP = EPOLLHUP # <<<<<<<<<<<<<< - * ET = EPOLLET + /* "twisted/python/_epoll.pyx":278 + * PRI = EPOLLPRI = c_EPOLLPRI + * ERR = EPOLLERR = c_EPOLLERR + * HUP = EPOLLHUP = c_EPOLLHUP # <<<<<<<<<<<<<< + * ET = EPOLLET = c_EPOLLET * */ - __pyx_t_1 = PyInt_FromLong(EPOLLHUP); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyInt_FromLong(EPOLLHUP); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__HUP, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__HUP, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyInt_FromLong(EPOLLHUP); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__EPOLLHUP, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "twisted/python/_epoll.pyx":174 - * ERR = EPOLLERR - * HUP = EPOLLHUP - * ET = EPOLLET # <<<<<<<<<<<<<< + /* "twisted/python/_epoll.pyx":279 + * ERR = EPOLLERR = c_EPOLLERR + * HUP = EPOLLHUP = c_EPOLLHUP + * ET = EPOLLET = c_EPOLLET # <<<<<<<<<<<<<< * - * RDNORM = EPOLLRDNORM + * RDNORM = EPOLLRDNORM = c_EPOLLRDNORM */ - __pyx_t_1 = PyInt_FromLong(EPOLLET); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyInt_FromLong(EPOLLET); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__ET, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyInt_FromLong(EPOLLET); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__ET, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__EPOLLET, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "twisted/python/_epoll.pyx":176 - * ET = EPOLLET + /* "twisted/python/_epoll.pyx":281 + * ET = EPOLLET = c_EPOLLET * - * RDNORM = EPOLLRDNORM # <<<<<<<<<<<<<< - * RDBAND = EPOLLRDBAND - * WRNORM = EPOLLWRNORM + * RDNORM = EPOLLRDNORM = c_EPOLLRDNORM # <<<<<<<<<<<<<< + * RDBAND = EPOLLRDBAND = c_EPOLLRDBAND + * WRNORM = EPOLLWRNORM = c_EPOLLWRNORM */ - __pyx_t_1 = PyInt_FromLong(EPOLLRDNORM); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 176; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyInt_FromLong(EPOLLRDNORM); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 281; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__RDNORM, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 281; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyInt_FromLong(EPOLLRDNORM); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 281; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__RDNORM, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 176; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__EPOLLRDNORM, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 281; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "twisted/python/_epoll.pyx":177 + /* "twisted/python/_epoll.pyx":282 * - * RDNORM = EPOLLRDNORM - * RDBAND = EPOLLRDBAND # <<<<<<<<<<<<<< - * WRNORM = EPOLLWRNORM - * WRBAND = EPOLLWRBAND + * RDNORM = EPOLLRDNORM = c_EPOLLRDNORM + * RDBAND = EPOLLRDBAND = c_EPOLLRDBAND # <<<<<<<<<<<<<< + * WRNORM = EPOLLWRNORM = c_EPOLLWRNORM + * WRBAND = EPOLLWRBAND = c_EPOLLWRBAND */ - __pyx_t_1 = PyInt_FromLong(EPOLLRDBAND); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyInt_FromLong(EPOLLRDBAND); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 282; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__RDBAND, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__RDBAND, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 282; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyInt_FromLong(EPOLLRDBAND); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 282; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__EPOLLRDBAND, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 282; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "twisted/python/_epoll.pyx":178 - * RDNORM = EPOLLRDNORM - * RDBAND = EPOLLRDBAND - * WRNORM = EPOLLWRNORM # <<<<<<<<<<<<<< - * WRBAND = EPOLLWRBAND - * MSG = EPOLLMSG + /* "twisted/python/_epoll.pyx":283 + * RDNORM = EPOLLRDNORM = c_EPOLLRDNORM + * RDBAND = EPOLLRDBAND = c_EPOLLRDBAND + * WRNORM = EPOLLWRNORM = c_EPOLLWRNORM # <<<<<<<<<<<<<< + * WRBAND = EPOLLWRBAND = c_EPOLLWRBAND + * MSG = EPOLLMSG = c_EPOLLMSG */ - __pyx_t_1 = PyInt_FromLong(EPOLLWRNORM); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyInt_FromLong(EPOLLWRNORM); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 283; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__WRNORM, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 283; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyInt_FromLong(EPOLLWRNORM); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 283; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__WRNORM, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__EPOLLWRNORM, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 283; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "twisted/python/_epoll.pyx":179 - * RDBAND = EPOLLRDBAND - * WRNORM = EPOLLWRNORM - * WRBAND = EPOLLWRBAND # <<<<<<<<<<<<<< - * MSG = EPOLLMSG - * + /* "twisted/python/_epoll.pyx":284 + * RDBAND = EPOLLRDBAND = c_EPOLLRDBAND + * WRNORM = EPOLLWRNORM = c_EPOLLWRNORM + * WRBAND = EPOLLWRBAND = c_EPOLLWRBAND # <<<<<<<<<<<<<< + * MSG = EPOLLMSG = c_EPOLLMSG */ - __pyx_t_1 = PyInt_FromLong(EPOLLWRBAND); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyInt_FromLong(EPOLLWRBAND); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 284; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__WRBAND, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 284; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyInt_FromLong(EPOLLWRBAND); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 284; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__WRBAND, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 179; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__EPOLLWRBAND, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 284; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "twisted/python/_epoll.pyx":180 - * WRNORM = EPOLLWRNORM - * WRBAND = EPOLLWRBAND - * MSG = EPOLLMSG # <<<<<<<<<<<<<< - * + /* "twisted/python/_epoll.pyx":285 + * WRNORM = EPOLLWRNORM = c_EPOLLWRNORM + * WRBAND = EPOLLWRBAND = c_EPOLLWRBAND + * MSG = EPOLLMSG = c_EPOLLMSG # <<<<<<<<<<<<<< */ - __pyx_t_1 = PyInt_FromLong(EPOLLMSG); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 180; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyInt_FromLong(EPOLLMSG); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 285; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_GOTREF(__pyx_t_1); + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__MSG, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 285; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyInt_FromLong(EPOLLMSG); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 285; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__MSG, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 180; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyObject_SetAttr(__pyx_m, __pyx_n_s__EPOLLMSG, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 285; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; /* "twisted/python/_epoll.pyx":1 @@ -1721,7 +2409,7 @@ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); if (__pyx_m) { - __Pyx_AddTraceback("init twisted.python._epoll"); + __Pyx_AddTraceback("init twisted.python._epoll", __pyx_clineno, __pyx_lineno, __pyx_filename); Py_DECREF(__pyx_m); __pyx_m = 0; } else if (!PyErr_Occurred()) { PyErr_SetString(PyExc_ImportError, "init twisted.python._epoll"); @@ -1734,137 +2422,38 @@ return __pyx_m; #endif } - -/* Runtime support code */ + +/* Runtime support code */ + +#if CYTHON_REFNANNY +static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { + PyObject *m = NULL, *p = NULL; + void *r = NULL; + m = PyImport_ImportModule((char *)modname); + if (!m) goto end; + p = PyObject_GetAttrString(m, (char *)"RefNannyAPI"); + if (!p) goto end; + r = PyLong_AsVoidPtr(p); +end: + Py_XDECREF(p); + Py_XDECREF(m); + return (__Pyx_RefNannyAPIStruct *)r; +} +#endif /* CYTHON_REFNANNY */ static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) { PyObject *result; result = PyObject_GetAttr(dict, name); - if (!result) - PyErr_SetObject(PyExc_NameError, name); - return result; -} - -static void __Pyx_RaiseDoubleKeywordsError( - const char* func_name, - PyObject* kw_name) -{ - PyErr_Format(PyExc_TypeError, - #if PY_MAJOR_VERSION >= 3 - "%s() got multiple values for keyword argument '%U'", func_name, kw_name); - #else - "%s() got multiple values for keyword argument '%s'", func_name, - PyString_AS_STRING(kw_name)); - #endif -} - -static int __Pyx_ParseOptionalKeywords( - PyObject *kwds, - PyObject **argnames[], - PyObject *kwds2, - PyObject *values[], - Py_ssize_t num_pos_args, - const char* function_name) -{ - PyObject *key = 0, *value = 0; - Py_ssize_t pos = 0; - PyObject*** name; - PyObject*** first_kw_arg = argnames + num_pos_args; - - while (PyDict_Next(kwds, &pos, &key, &value)) { - name = first_kw_arg; - while (*name && (**name != key)) name++; - if (*name) { - values[name-argnames] = value; - } else { - #if PY_MAJOR_VERSION < 3 - if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) { - #else - if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) { - #endif - goto invalid_keyword_type; - } else { - for (name = first_kw_arg; *name; name++) { - #if PY_MAJOR_VERSION >= 3 - if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) && - PyUnicode_Compare(**name, key) == 0) break; - #else - if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) && - _PyString_Eq(**name, key)) break; - #endif - } - if (*name) { - values[name-argnames] = value; - } else { - /* unexpected keyword found */ - for (name=argnames; name != first_kw_arg; name++) { - if (**name == key) goto arg_passed_twice; - #if PY_MAJOR_VERSION >= 3 - if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) && - PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice; - #else - if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) && - _PyString_Eq(**name, key)) goto arg_passed_twice; - #endif - } - if (kwds2) { - if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; - } else { - goto invalid_keyword; - } - } - } + if (!result) { + if (dict != __pyx_b) { + PyErr_Clear(); + result = PyObject_GetAttr(__pyx_b, name); + } + if (!result) { + PyErr_SetObject(PyExc_NameError, name); } } - return 0; -arg_passed_twice: - __Pyx_RaiseDoubleKeywordsError(function_name, **name); - goto bad; -invalid_keyword_type: - PyErr_Format(PyExc_TypeError, - "%s() keywords must be strings", function_name); - goto bad; -invalid_keyword: - PyErr_Format(PyExc_TypeError, - #if PY_MAJOR_VERSION < 3 - "%s() got an unexpected keyword argument '%s'", - function_name, PyString_AsString(key)); - #else - "%s() got an unexpected keyword argument '%U'", - function_name, key); - #endif -bad: - return -1; -} - -static void __Pyx_RaiseArgtupleInvalid( - const char* func_name, - int exact, - Py_ssize_t num_min, - Py_ssize_t num_max, - Py_ssize_t num_found) -{ - Py_ssize_t num_expected; - const char *number, *more_or_less; - - if (num_found < num_min) { - num_expected = num_min; - more_or_less = "at least"; - } else { - num_expected = num_max; - more_or_less = "at most"; - } - if (exact) { - more_or_less = "exactly"; - } - number = (num_expected == 1) ? "" : "s"; - PyErr_Format(PyExc_TypeError, - #if PY_VERSION_HEX < 0x02050000 - "%s() takes %s %d positional argument%s (%d given)", - #else - "%s() takes %s %zd positional argument%s (%zd given)", - #endif - func_name, more_or_less, num_expected, number, num_found); + return result; } static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) { @@ -1895,7 +2484,8 @@ #if PY_MAJOR_VERSION < 3 -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) { +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { + /* cause is unused */ Py_XINCREF(type); Py_XINCREF(value); Py_XINCREF(tb); @@ -1962,7 +2552,7 @@ #else /* Python 3+ */ -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) { +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { if (tb == Py_None) { tb = 0; } else if (tb && !PyTraceBack_Check(tb)) { @@ -1987,6 +2577,29 @@ goto bad; } + if (cause) { + PyObject *fixed_cause; + if (PyExceptionClass_Check(cause)) { + fixed_cause = PyObject_CallObject(cause, NULL); + if (fixed_cause == NULL) + goto bad; + } + else if (PyExceptionInstance_Check(cause)) { + fixed_cause = cause; + Py_INCREF(fixed_cause); + } + else { + PyErr_SetString(PyExc_TypeError, + "exception causes must derive from " + "BaseException"); + goto bad; + } + if (!value) { + value = PyObject_CallObject(type, NULL); + } + PyException_SetCause(value, fixed_cause); + } + PyErr_SetObject(type, value); if (tb) { @@ -2004,6 +2617,124 @@ } #endif +static void __Pyx_RaiseDoubleKeywordsError( + const char* func_name, + PyObject* kw_name) +{ + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION >= 3 + "%s() got multiple values for keyword argument '%U'", func_name, kw_name); + #else + "%s() got multiple values for keyword argument '%s'", func_name, + PyString_AS_STRING(kw_name)); + #endif +} + +static int __Pyx_ParseOptionalKeywords( + PyObject *kwds, + PyObject **argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + const char* function_name) +{ + PyObject *key = 0, *value = 0; + Py_ssize_t pos = 0; + PyObject*** name; + PyObject*** first_kw_arg = argnames + num_pos_args; + + while (PyDict_Next(kwds, &pos, &key, &value)) { + name = first_kw_arg; + while (*name && (**name != key)) name++; + if (*name) { + values[name-argnames] = value; + } else { + #if PY_MAJOR_VERSION < 3 + if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) { + #else + if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) { + #endif + goto invalid_keyword_type; + } else { + for (name = first_kw_arg; *name; name++) { + #if PY_MAJOR_VERSION >= 3 + if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) && + PyUnicode_Compare(**name, key) == 0) break; + #else + if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) && + _PyString_Eq(**name, key)) break; + #endif + } + if (*name) { + values[name-argnames] = value; + } else { + /* unexpected keyword found */ + for (name=argnames; name != first_kw_arg; name++) { + if (**name == key) goto arg_passed_twice; + #if PY_MAJOR_VERSION >= 3 + if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) && + PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice; + #else + if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) && + _PyString_Eq(**name, key)) goto arg_passed_twice; + #endif + } + if (kwds2) { + if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; + } else { + goto invalid_keyword; + } + } + } + } + } + return 0; +arg_passed_twice: + __Pyx_RaiseDoubleKeywordsError(function_name, **name); + goto bad; +invalid_keyword_type: + PyErr_Format(PyExc_TypeError, + "%s() keywords must be strings", function_name); + goto bad; +invalid_keyword: + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION < 3 + "%s() got an unexpected keyword argument '%s'", + function_name, PyString_AsString(key)); + #else + "%s() got an unexpected keyword argument '%U'", + function_name, key); + #endif +bad: + return -1; +} + +static void __Pyx_RaiseArgtupleInvalid( + const char* func_name, + int exact, + Py_ssize_t num_min, + Py_ssize_t num_max, + Py_ssize_t num_found) +{ + Py_ssize_t num_expected; + const char *more_or_less; + + if (num_found < num_min) { + num_expected = num_min; + more_or_less = "at least"; + } else { + num_expected = num_max; + more_or_less = "at most"; + } + if (exact) { + more_or_less = "exactly"; + } + PyErr_Format(PyExc_TypeError, + "%s() takes %s %"PY_FORMAT_SIZE_T"d positional argument%s (%"PY_FORMAT_SIZE_T"d given)", + func_name, more_or_less, num_expected, + (num_expected == 1) ? "" : "s", num_found); +} + static CYTHON_INLINE unsigned char __Pyx_PyInt_AsUnsignedChar(PyObject* x) { const unsigned char neg_one = (unsigned char)-1, const_zero = 0; const int is_unsigned = neg_one > const_zero; @@ -2215,9 +2946,9 @@ "can't convert negative value to unsigned long"); return (unsigned long)-1; } - return PyLong_AsUnsignedLong(x); + return (unsigned long)PyLong_AsUnsignedLong(x); } else { - return PyLong_AsLong(x); + return (unsigned long)PyLong_AsLong(x); } } else { unsigned long val; @@ -2250,9 +2981,9 @@ "can't convert negative value to unsigned PY_LONG_LONG"); return (unsigned PY_LONG_LONG)-1; } - return PyLong_AsUnsignedLongLong(x); + return (unsigned PY_LONG_LONG)PyLong_AsUnsignedLongLong(x); } else { - return PyLong_AsLongLong(x); + return (unsigned PY_LONG_LONG)PyLong_AsLongLong(x); } } else { unsigned PY_LONG_LONG val; @@ -2285,9 +3016,9 @@ "can't convert negative value to long"); return (long)-1; } - return PyLong_AsUnsignedLong(x); + return (long)PyLong_AsUnsignedLong(x); } else { - return PyLong_AsLong(x); + return (long)PyLong_AsLong(x); } } else { long val; @@ -2320,9 +3051,9 @@ "can't convert negative value to PY_LONG_LONG"); return (PY_LONG_LONG)-1; } - return PyLong_AsUnsignedLongLong(x); + return (PY_LONG_LONG)PyLong_AsUnsignedLongLong(x); } else { - return PyLong_AsLongLong(x); + return (PY_LONG_LONG)PyLong_AsLongLong(x); } } else { PY_LONG_LONG val; @@ -2355,9 +3086,9 @@ "can't convert negative value to signed long"); return (signed long)-1; } - return PyLong_AsUnsignedLong(x); + return (signed long)PyLong_AsUnsignedLong(x); } else { - return PyLong_AsLong(x); + return (signed long)PyLong_AsLong(x); } } else { signed long val; @@ -2390,9 +3121,9 @@ "can't convert negative value to signed PY_LONG_LONG"); return (signed PY_LONG_LONG)-1; } - return PyLong_AsUnsignedLongLong(x); + return (signed PY_LONG_LONG)PyLong_AsUnsignedLongLong(x); } else { - return PyLong_AsLongLong(x); + return (signed PY_LONG_LONG)PyLong_AsLongLong(x); } } else { signed PY_LONG_LONG val; @@ -2404,11 +3135,31 @@ } } +static int __Pyx_check_binary_version(void) { + char ctversion[4], rtversion[4]; + PyOS_snprintf(ctversion, 4, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION); + PyOS_snprintf(rtversion, 4, "%s", Py_GetVersion()); + if (ctversion[0] != rtversion[0] || ctversion[2] != rtversion[2]) { + char message[200]; + PyOS_snprintf(message, sizeof(message), + "compiletime version %s of module '%.100s' " + "does not match runtime version %s", + ctversion, __Pyx_MODULE_NAME, rtversion); + #if PY_VERSION_HEX < 0x02050000 + return PyErr_Warn(NULL, message); + #else + return PyErr_WarnEx(NULL, message, 1); + #endif + } + return 0; +} + #include "compile.h" #include "frameobject.h" #include "traceback.h" -static void __Pyx_AddTraceback(const char *funcname) { +static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno, + int __pyx_lineno, const char *__pyx_filename) { PyObject *py_srcfile = 0; PyObject *py_funcname = 0; PyObject *py_globals = 0; diff -Nru twisted-11.1.0/twisted/python/_epoll.pyx twisted-12.1.0/twisted/python/_epoll.pyx --- twisted-11.1.0/twisted/python/_epoll.pyx 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/python/_epoll.pyx 2012-02-19 19:24:21.000000000 +0000 @@ -34,17 +34,17 @@ EPOLL_CTL_MOD = 3 cdef enum EPOLL_EVENTS: - EPOLLIN = 0x001 - EPOLLPRI = 0x002 - EPOLLOUT = 0x004 - EPOLLRDNORM = 0x040 - EPOLLRDBAND = 0x080 - EPOLLWRNORM = 0x100 - EPOLLWRBAND = 0x200 - EPOLLMSG = 0x400 - EPOLLERR = 0x008 - EPOLLHUP = 0x010 - EPOLLET = (1 << 31) + c_EPOLLIN "EPOLLIN" = 0x001 + c_EPOLLPRI "EPOLLPRI" = 0x002 + c_EPOLLOUT "EPOLLOUT" = 0x004 + c_EPOLLRDNORM "EPOLLRDNORM" = 0x040 + c_EPOLLRDBAND "EPOLLRDBAND" = 0x080 + c_EPOLLWRNORM "EPOLLWRNORM" = 0x100 + c_EPOLLWRBAND "EPOLLWRBAND" = 0x200 + c_EPOLLMSG "EPOLLMSG" = 0x400 + c_EPOLLERR "EPOLLERR" = 0x008 + c_EPOLLHUP "EPOLLHUP" = 0x010 + c_EPOLLET "EPOLLET" = (1 << 31) ctypedef union epoll_data_t: void *ptr @@ -65,6 +65,44 @@ cdef extern PyThreadState *PyEval_SaveThread() cdef extern void PyEval_RestoreThread(PyThreadState*) +cdef call_epoll_wait(int fd, unsigned int maxevents, int timeout_msec): + """ + Wait for an I/O event, wrap epoll_wait(2). + + @type fd: C{int} + @param fd: The epoll file descriptor number. + + @type maxevents: C{int} + @param maxevents: Maximum number of events returned. + + @type timeout_msec: C{int} + @param timeout_msec: Maximum time in milliseconds waiting for events. 0 + makes it return immediately whereas -1 makes it wait indefinitely. + + @raise IOError: Raised if the underlying epoll_wait() call fails. + """ + cdef epoll_event *events + cdef int result + cdef int nbytes + cdef PyThreadState *_save + + nbytes = sizeof(epoll_event) * maxevents + events = malloc(nbytes) + memset(events, 0, nbytes) + try: + _save = PyEval_SaveThread() + result = epoll_wait(fd, events, maxevents, timeout_msec) + PyEval_RestoreThread(_save) + + if result == -1: + raise IOError(errno, strerror(errno)) + results = [] + for i from 0 <= i < result: + results.append((events[i].data.fd, events[i].events)) + return results + finally: + free(events) + cdef class epoll: """ Represent a set of file descriptors being monitored for events. @@ -73,7 +111,10 @@ cdef int fd cdef int initialized - def __init__(self, int size): + def __init__(self, int size=1023): + """ + The constructor arguments are compatible with select.poll.__init__. + """ self.fd = epoll_create(size) if self.fd == -1: raise IOError(errno, strerror(errno)) @@ -99,10 +140,79 @@ """ return self.fd + def register(self, int fd, int events): + """ + Add (register) a file descriptor to be monitored by self. + + This method is compatible with select.epoll.register in Python 2.6. + + Wrap epoll_ctl(2). + + @type fd: C{int} + @param fd: File descriptor to modify + + @type events: C{int} + @param events: A bit set of IN, OUT, PRI, ERR, HUP, and ET. + + @raise IOError: Raised if the underlying epoll_ctl() call fails. + """ + cdef int result + cdef epoll_event evt + evt.events = events + evt.data.fd = fd + result = epoll_ctl(self.fd, CTL_ADD, fd, &evt) + if result == -1: + raise IOError(errno, strerror(errno)) + + def unregister(self, int fd): + """ + Remove (unregister) a file descriptor monitored by self. + + This method is compatible with select.epoll.unregister in Python 2.6. + + Wrap epoll_ctl(2). + + @type fd: C{int} + @param fd: File descriptor to modify + + @raise IOError: Raised if the underlying epoll_ctl() call fails. + """ + cdef int result + cdef epoll_event evt + # We don't have to fill evt.events for CTL_DEL. + evt.data.fd = fd + result = epoll_ctl(self.fd, CTL_DEL, fd, &evt) + if result == -1: + raise IOError(errno, strerror(errno)) + + def modify(self, int fd, int events): + """ + Modify the modified state of a file descriptor monitored by self. + + This method is compatible with select.epoll.modify in Python 2.6. + + Wrap epoll_ctl(2). + + @type fd: C{int} + @param fd: File descriptor to modify + + @type events: C{int} + @param events: A bit set of IN, OUT, PRI, ERR, HUP, and ET. + + @raise IOError: Raised if the underlying epoll_ctl() call fails. + """ + cdef int result + cdef epoll_event evt + evt.events = events + evt.data.fd = fd + result = epoll_ctl(self.fd, CTL_MOD, fd, &evt) + if result == -1: + raise IOError(errno, strerror(errno)) + def _control(self, int op, int fd, int events): """ Modify the monitored state of a particular file descriptor. - + Wrap epoll_ctl(2). @type op: C{int} @@ -132,50 +242,44 @@ @param maxevents: Maximum number of events returned. @type timeout: C{int} + @param timeout: Maximum time in milliseconds waiting for events. 0 + makes it return immediately whereas -1 makes it wait indefinitely. + + @raise IOError: Raised if the underlying epoll_wait() call fails. + """ + return call_epoll_wait(self.fd, maxevents, timeout) + + def poll(self, float timeout=-1, unsigned int maxevents=1024): + """ + Wait for an I/O event, wrap epoll_wait(2). + + This method is compatible with select.epoll.poll in Python 2.6. + + @type maxevents: C{int} + @param maxevents: Maximum number of events returned. + + @type timeout: C{int} @param timeout: Maximum time waiting for events. 0 makes it return immediately whereas -1 makes it wait indefinitely. - + @raise IOError: Raised if the underlying epoll_wait() call fails. """ - cdef epoll_event *events - cdef int result - cdef int nbytes - cdef int fd - cdef PyThreadState *_save - - nbytes = sizeof(epoll_event) * maxevents - events = malloc(nbytes) - memset(events, 0, nbytes) - try: - fd = self.fd - - _save = PyEval_SaveThread() - result = epoll_wait(fd, events, maxevents, timeout) - PyEval_RestoreThread(_save) + return call_epoll_wait(self.fd, maxevents, (timeout * 1000.0)) - if result == -1: - raise IOError(errno, strerror(errno)) - results = [] - for i from 0 <= i < result: - results.append((events[i].data.fd, events[i].events)) - return results - finally: - free(events) CTL_ADD = EPOLL_CTL_ADD CTL_DEL = EPOLL_CTL_DEL CTL_MOD = EPOLL_CTL_MOD -IN = EPOLLIN -OUT = EPOLLOUT -PRI = EPOLLPRI -ERR = EPOLLERR -HUP = EPOLLHUP -ET = EPOLLET - -RDNORM = EPOLLRDNORM -RDBAND = EPOLLRDBAND -WRNORM = EPOLLWRNORM -WRBAND = EPOLLWRBAND -MSG = EPOLLMSG - +IN = EPOLLIN = c_EPOLLIN +OUT = EPOLLOUT = c_EPOLLOUT +PRI = EPOLLPRI = c_EPOLLPRI +ERR = EPOLLERR = c_EPOLLERR +HUP = EPOLLHUP = c_EPOLLHUP +ET = EPOLLET = c_EPOLLET + +RDNORM = EPOLLRDNORM = c_EPOLLRDNORM +RDBAND = EPOLLRDBAND = c_EPOLLRDBAND +WRNORM = EPOLLWRNORM = c_EPOLLWRNORM +WRBAND = EPOLLWRBAND = c_EPOLLWRBAND +MSG = EPOLLMSG = c_EPOLLMSG diff -Nru twisted-11.1.0/twisted/python/fakepwd.py twisted-12.1.0/twisted/python/fakepwd.py --- twisted-11.1.0/twisted/python/fakepwd.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/python/fakepwd.py 2011-11-25 01:19:18.000000000 +0000 @@ -7,7 +7,7 @@ """ -__all__ = ['UserDatabase'] +__all__ = ['UserDatabase', 'ShadowDatabase'] class _UserRecord(object): @@ -110,3 +110,110 @@ Return a list of all user records. """ return self._users + + + +class _ShadowRecord(object): + """ + L{_ShadowRecord} holds the shadow user data for a single user in + L{ShadowDatabase}. It corresponds to C{spwd.struct_spwd}. See that class + for attribute documentation. + """ + def __init__(self, username, password, lastChange, min, max, warn, inact, + expire, flag): + self.sp_nam = username + self.sp_pwd = password + self.sp_lstchg = lastChange + self.sp_min = min + self.sp_max = max + self.sp_warn = warn + self.sp_inact = inact + self.sp_expire = expire + self.sp_flag = flag + + + def __len__(self): + return 9 + + + def __getitem__(self, index): + return ( + self.sp_nam, self.sp_pwd, self.sp_lstchg, self.sp_min, + self.sp_max, self.sp_warn, self.sp_inact, self.sp_expire, + self.sp_flag)[index] + + + +class ShadowDatabase(object): + """ + L{ShadowDatabase} holds a shadow user database in memory and makes it + available via the same API as C{spwd}. + + @ivar _users: A C{list} of L{_ShadowRecord} instances holding all user data + added to this database. + + @since: 12.0 + """ + def __init__(self): + self._users = [] + + + def addUser(self, username, password, lastChange, min, max, warn, inact, + expire, flag): + """ + Add a new user record to this database. + + @param username: The value for the C{sp_nam} field of the user record to + add. + @type username: C{str} + + @param password: The value for the C{sp_pwd} field of the user record to + add. + @type password: C{str} + + @param lastChange: The value for the C{sp_lstchg} field of the user + record to add. + @type lastChange: C{int} + + @param min: The value for the C{sp_min} field of the user record to add. + @type min: C{int} + + @param max: The value for the C{sp_max} field of the user record to add. + @type max: C{int} + + @param warn: The value for the C{sp_warn} field of the user record to + add. + @type warn: C{int} + + @param inact: The value for the C{sp_inact} field of the user record to + add. + @type inact: C{int} + + @param expire: The value for the C{sp_expire} field of the user record + to add. + @type expire: C{int} + + @param flag: The value for the C{sp_flag} field of the user record to + add. + @type flag: C{int} + """ + self._users.append(_ShadowRecord( + username, password, lastChange, + min, max, warn, inact, expire, flag)) + + + def getspnam(self, username): + """ + Return the shadow user record corresponding to the given username. + """ + for entry in self._users: + if entry.sp_nam == username: + return entry + raise KeyError + + + def getspall(self): + """ + Return a list of all shadow user records. + """ + return self._users diff -Nru twisted-11.1.0/twisted/python/filepath.py twisted-12.1.0/twisted/python/filepath.py --- twisted-11.1.0/twisted/python/filepath.py 2011-07-01 23:37:45.000000000 +0000 +++ twisted-12.1.0/twisted/python/filepath.py 2012-03-13 23:29:48.000000000 +0000 @@ -36,6 +36,8 @@ from twisted.python.util import FancyEqMixin +from zope.interface import Interface, Attribute, implements + _CREATE_FLAGS = (os.O_EXCL | os.O_CREAT | os.O_RDWR | @@ -79,6 +81,133 @@ randomBytes = getattr(os, 'urandom', _stub_urandom) armor = getattr(base64, 'urlsafe_b64encode', _stub_armor) +class IFilePath(Interface): + """ + File path object. + + A file path represents a location for a file-like-object and can be + organized into a hierarchy; a file path can can children which are + themselves file paths. + + A file path has a name which unique identifies it in the context of its + parent (if it has one); a file path can not have two children with the same + name. This name is referred to as the file path's "base name". + + A series of such names can be used to locate nested children of a file path; + such a series is referred to as the child's "path", relative to the parent. + In this case, each name in the path is referred to as a "path segment"; the + child's base name is the segment in the path. + + When representing a file path as a string, a "path separator" is used to + delimit the path segments within the string. For a file system path, that + would be C{os.sep}. + + Note that the values of child names may be restricted. For example, a file + system path will not allow the use of the path separator in a name, and + certain names (eg. C{"."} and C{".."}) may be reserved or have special + meanings. + + @since: 12.1 + """ + sep = Attribute("The path separator to use in string representations") + + def child(name): + """ + Obtain a direct child of this file path. The child may or may not + exist. + + @param name: the name of a child of this path. C{name} must be a direct + child of this path and may not contain a path separator. + @return: the child of this path with the given C{name}. + @raise InsecurePath: if C{name} describes a file path that is not a + direct child of this file path. + """ + + def open(mode="r"): + """ + Opens this file path with the given mode. + @return: a file-like-object. + @raise Exception: if this file path cannot be opened. + """ + + def changed(): + """ + Clear any cached information about the state of this path on disk. + """ + + def getsize(): + """ + @return: the size of the file at this file path in bytes. + @raise Exception: if the size cannot be obtained. + """ + + def getModificationTime(): + """ + Retrieve the time of last access from this file. + + @return: a number of seconds from the epoch. + @rtype: float + """ + + def getStatusChangeTime(): + """ + Retrieve the time of the last status change for this file. + + @return: a number of seconds from the epoch. + @rtype: float + """ + + def getAccessTime(): + """ + Retrieve the time that this file was last accessed. + + @return: a number of seconds from the epoch. + @rtype: float + """ + + def exists(): + """ + @return: C{True} if the file at this file path exists, C{False} + otherwise. + """ + + def isdir(): + """ + @return: C{True} if the file at this file path is a directory, C{False} + otherwise. + """ + + def isfile(): + """ + @return: C{True} if the file at this file path is a regular file, + C{False} otherwise. + """ + + def children(): + """ + @return: a sequence of the children of the directory at this file path. + @raise Exception: if the file at this file path is not a directory. + """ + + def basename(): + """ + @return: the base name of this file path. + """ + + def parent(): + """ + A file path for the directory containing the file at this file path. + """ + + def sibling(name): + """ + A file path for the directory containing the file at this file path. + @param name: the name of a sibling of this path. C{name} must be a direct + sibling of this path and may not contain a path separator. + + @return: a sibling file path of this one. + """ + class InsecurePath(Exception): """ Error that is raised when the path provided to FilePath is invalid. @@ -136,10 +265,13 @@ -class _PathHelper: +class AbstractFilePath(object): """ - Abstract helper class also used by ZipPath; implements certain utility - methods. + Abstract implementation of an IFilePath; must be completed by a subclass. + + This class primarily exists to provide common implementations of certain + methods in IFilePath. It is *not* a required parent class for IFilePath + implementations, just a useful starting point. """ def getContent(self): @@ -433,7 +565,7 @@ -class FilePath(_PathHelper): +class FilePath(AbstractFilePath): """ I am a path on the filesystem that only permits 'downwards' access. @@ -479,9 +611,13 @@ @type statinfo: C{int} or L{types.NoneType} or L{os.stat_result} """ + implements(IFilePath) + statinfo = None path = None + sep = slash + def __init__(self, path, alwaysCreate=False): """ Convert a path string to an absolute path if necessary and initialize @@ -517,7 +653,7 @@ # Catch paths like C:blah that don't have a slash raise InsecurePath("%r contains a colon." % (path,)) norm = normpath(path) - if slash in norm: + if self.sep in norm: raise InsecurePath("%r contains one or more directory separators" % (path,)) newpath = abspath(joinpath(self.path, norm)) if not newpath.startswith(self.path): @@ -652,6 +788,9 @@ @param reraise: a boolean. If true, re-raise exceptions from L{os.stat}; otherwise, mark this path as not existing, and remove any cached stat information. + + @raise Exception: is C{reraise} is C{True} and an exception occurs while + reloading metadata. """ try: self.statinfo = stat(self.path) @@ -983,7 +1122,12 @@ def touch(self): """ - Update the access and modified times of the L{FilePath}'s file. + Updates the access and last modification times of the file at this + file path to the current time. Also creates the file if it does not + already exist. + + @raise Exception: if unable to create or modify the last modification + time of the file. """ try: self.open('a').close() @@ -996,8 +1140,7 @@ """ Removes the file or directory that is represented by self. If C{self.path} is a directory, recursively remove all its children - before removing the directory. If it's a file or link, just delete - it. + before removing the directory. If it's a file or link, just delete it. """ if self.isdir() and not self.islink(): for child in self.children(): @@ -1023,7 +1166,7 @@ pattern. """ import glob - path = self.path[-1] == '/' and self.path + pattern or slash.join([self.path, pattern]) + path = self.path[-1] == '/' and self.path + pattern or self.sep.join([self.path, pattern]) return map(self.clonePath, glob.glob(path)) diff -Nru twisted-11.1.0/twisted/python/lockfile.py twisted-12.1.0/twisted/python/lockfile.py --- twisted-11.1.0/twisted/python/lockfile.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/python/lockfile.py 2011-11-04 21:39:52.000000000 +0000 @@ -13,17 +13,19 @@ from time import time as _uniquefloat +from twisted.python.runtime import platform + def unique(): return str(long(_uniquefloat() * 1000)) from os import rename -try: +if not platform.isWindows(): from os import kill from os import symlink from os import readlink from os import remove as rmlink _windows = False -except: +else: _windows = True try: diff -Nru twisted-11.1.0/twisted/python/otp.py twisted-12.1.0/twisted/python/otp.py --- twisted-11.1.0/twisted/python/otp.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/python/otp.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,496 +0,0 @@ -# -*- test-case-name: twisted.python.test.test_otp -*- -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -""" -A One-Time Password System based on RFC 2289 - -The class Authenticator contains the hashing-logic, and the parser for the -readable output. It also contains challenge which returns a string describing -the authentication scheme for a client. - -OTP is a password container for an user on a server. - -NOTE: Does not take care of transmitting the shared secret password. - -At the end there's a dict called dict which is dictionary contain 2048 -words for storing pronouncable 11-bit values. Taken from RFC 1760. - -Uses the MD5- and SHA-algorithms for hashing - -Todo: RFC2444, SASL (perhaps), parsing hex-responses - -This module is deprecated. Consider using U{another Python OTP -library} instead. -""" - -import warnings -import string -import random - -warnings.warn( - "twisted.python.otp is deprecated since Twisted 8.3.", - category=DeprecationWarning, - stacklevel=2) - - -def stringToLong(s): - """ Convert digest to long """ - result = 0L - for byte in s: - result = (256 * result) + ord(byte) - return result - -def stringToDWords(s): - """ Convert digest to a list of four 32-bits words """ - result = [] - for a in xrange(len(s) / 4): - tmp = 0L - for byte in s[-4:]: - tmp = (256 * tmp) + ord(byte) - result.append(tmp) - s = s[:-4] - return result - -def longToString(l): - """ Convert long to digest """ - result = "" - while l > 0L: - result = chr(l % 256) + result - l = l / 256L - return result - -from twisted.python.hashlib import md5, sha1 -hashid = {md5: 'md5', sha1: 'sha1'} - -INITIALSEQUENCE = 1000 -MINIMUMSEQUENCE = 50 - -class Unauthorized(Exception): - """the Unauthorized exception - - This exception is raised when an action is not allowed, or a user is not - authenticated properly. - """ - -class OTPAuthenticator: - """ - A One Time Password System - - Based on RFC 2289, which is based on a the S/KEY Authentication-scheme. - It uses the MD5- and SHA-algorithms for hashing - - The variable OTP is at all times a 64bit string. - - @ivar hash: An object which can be used to compute hashes. This is either - L{md5} or L{sha1}. - """ - def __init__(self, hash = md5): - "Set the hash to either md5 or sha1" - self.hash = hash - - - def generateSeed(self): - "Return a 10 char random seed, with 6 lowercase chars and 4 digits" - seed = '' - for x in range(6): - seed = seed + chr(random.randrange(97,122)) - for x in range(4): - seed = seed + chr(random.randrange(48,57)) - return seed - - def foldDigest(self, otp): - if self.hash == md5: - return self.foldDigest128(otp) - if self.hash == sha1: - return self.foldDigest160(otp) - - def foldDigest128(self, otp128): - "Fold a 128 bit digest to 64 bit" - regs = stringToDWords(otp128) - p0 = regs[0] ^ regs[2] - p1 = regs[1] ^ regs[3] - S = '' - for a in xrange(4): - S = chr(p0 & 0xFF) + S - p0 = p0 >> 8 - for a in xrange(4): - S = chr(p1 & 0xFF) + S - p1 = p1 >> 8 - return S - - def foldDigest160(self, otp160): - "Fold a 160 bit digest to 64 bit" - regs = stringToDWords(otp160) - p0 = regs[0] ^ regs[2] - p1 = regs[1] ^ regs[3] - p0 = regs[0] ^ regs[4] - S = '' - for a in xrange(4): - S = chr(p0 & 0xFF) + S - p0 = p0 >> 8 - for a in xrange(4): - S = chr(p1 & 0xFF) + S - p1 = p1 >> 8 - return S - - def hashUpdate(self, digest): - "Run through the hash and fold to 64 bit" - h = self.hash(digest) - return self.foldDigest(h.digest()) - - def generateOTP(self, seed, passwd, sequence): - """Return a 64 bit OTP based on inputs - Run through makeReadable to get a 6 word pass-phrase""" - seed = string.lower(seed) - otp = self.hashUpdate(seed + passwd) - for a in xrange(sequence): - otp = self.hashUpdate(otp) - return otp - - def calculateParity(self, otp): - "Calculate the parity from a 64bit OTP" - parity = 0 - for i in xrange(0, 64, 2): - parity = parity + otp & 0x3 - otp = otp >> 2 - return parity - - def makeReadable(self, otp): - "Returns a 6 word pass-phrase from a 64bit OTP" - digest = stringToLong(otp) - list = [] - parity = self.calculateParity(digest) - for i in xrange(4,-1, -1): - list.append(dict[(digest >> (i * 11 + 9)) & 0x7FF]) - list.append(dict[(digest << 2) & 0x7FC | (parity & 0x03)]) - return string.join(list) - - def challenge(self, seed, sequence): - """Return a challenge in the format otp- """ - return "otp-%s %i %s" % (hashid[self.hash], sequence, seed) - - def parsePhrase(self, phrase): - """Decode the phrase, and return a 64bit OTP - I will raise Unauthorized if the parity is wrong - TODO: Add support for hex (MUST) and the '2nd scheme'(SHOULD)""" - words = string.split(phrase) - for i in xrange(len(words)): - words[i] = string.upper(words[i]) - b = 0L - for i in xrange(0,5): - b = b | ((long(dict.index(words[i])) << ((4-i)*11L+9L))) - tmp = dict.index(words[5]) - b = b | (tmp & 0x7FC ) >> 2 - if (tmp & 3) <> self.calculateParity(b): - raise Unauthorized("Parity error") - digest = longToString(b) - return digest - -class OTP(OTPAuthenticator): - """An automatic version of the OTP-Authenticator - - Updates the sequence and the keeps last approved password on success - On the next authentication, the stored password is hashed and checked - up against the one given by the user. If they match, the sequencecounter - is decreased and the circle is closed. - - This object should be glued to each user - - Note: - It does NOT reset the sequence when the combinations left approach zero, - This has to be done manuelly by instancing a new object - """ - seed = None - sequence = 0 - lastotp = None - - def __init__(self, passwd, sequence = INITIALSEQUENCE, hash=md5): - """Initialize the OTP-Sequence, and discard the password""" - OTPAuthenticator.__init__(self, hash) - seed = self.generateSeed() - # Generate the 'last' password - self.lastotp = OTPAuthenticator.generateOTP(self, seed, passwd, sequence+1) - self.seed = seed - self.sequence = sequence - - def challenge(self): - """Return a challenge string""" - result = OTPAuthenticator.challenge(self, self.seed, self.sequence) - return result - - def authenticate(self, phrase): - """Test the phrase against the last challenge issued""" - try: - digest = self.parsePhrase(phrase) - hasheddigest = self.hashUpdate(digest) - if (self.lastotp == hasheddigest): - self.lastotp = digest - if self.sequence > MINIMUMSEQUENCE: - self.sequence = self.sequence - 1 - return "ok" - else: - raise Unauthorized("Failed") - except Unauthorized, msg: - raise Unauthorized(msg) - -# -# The 2048 word standard dictionary from RFC 1760 -# -dict = ["A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD", -"AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", "AMY", -"AN", "ANA", "AND", "ANN", "ANT", "ANY", "APE", "APS", -"APT", "ARC", "ARE", "ARK", "ARM", "ART", "AS", "ASH", -"ASK", "AT", "ATE", "AUG", "AUK", "AVE", "AWE", "AWK", -"AWL", "AWN", "AX", "AYE", "BAD", "BAG", "BAH", "BAM", -"BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", -"BEN", "BET", "BEY", "BIB", "BID", "BIG", "BIN", "BIT", -"BOB", "BOG", "BON", "BOO", "BOP", "BOW", "BOY", "BUB", -"BUD", "BUG", "BUM", "BUN", "BUS", "BUT", "BUY", "BY", -"BYE", "CAB", "CAL", "CAM", "CAN", "CAP", "CAR", "CAT", -"CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT", -"COW", "COY", "CRY", "CUB", "CUE", "CUP", "CUR", "CUT", -"DAB", "DAD", "DAM", "DAN", "DAR", "DAY", "DEE", "DEL", -"DEN", "DES", "DEW", "DID", "DIE", "DIG", "DIN", "DIP", -"DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", "DUB", -"DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", -"EGG", "EGO", "ELI", "ELK", "ELM", "ELY", "EM", "END", -"EST", "ETC", "EVA", "EVE", "EWE", "EYE", "FAD", "FAN", -"FAR", "FAT", "FAY", "FED", "FEE", "FEW", "FIB", "FIG", -"FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR", -"FRY", "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL", -"GAM", "GAP", "GAS", "GAY", "GEE", "GEL", "GEM", "GET", -"GIG", "GIL", "GIN", "GO", "GOT", "GUM", "GUN", "GUS", -"GUT", "GUY", "GYM", "GYP", "HA", "HAD", "HAL", "HAM", -"HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM", -"HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP", -"HIS", "HIT", "HO", "HOB", "HOC", "HOE", "HOG", "HOP", -"HOT", "HOW", "HUB", "HUE", "HUG", "HUH", "HUM", "HUT", -"I", "ICY", "IDA", "IF", "IKE", "ILL", "INK", "INN", -"IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT", -"ITS", "IVY", "JAB", "JAG", "JAM", "JAN", "JAR", "JAW", -"JAY", "JET", "JIG", "JIM", "JO", "JOB", "JOE", "JOG", -"JOT", "JOY", "JUG", "JUT", "KAY", "KEG", "KEN", "KEY", -"KID", "KIM", "KIN", "KIT", "LA", "LAB", "LAC", "LAD", -"LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE", -"LEG", "LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN", -"LIP", "LIT", "LO", "LOB", "LOG", "LOP", "LOS", "LOT", -"LOU", "LOW", "LOY", "LUG", "LYE", "MA", "MAC", "MAD", -"MAE", "MAN", "MAO", "MAP", "MAT", "MAW", "MAY", "ME", -"MEG", "MEL", "MEN", "MET", "MEW", "MID", "MIN", "MIT", -"MOB", "MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW", -"MUD", "MUG", "MUM", "MY", "NAB", "NAG", "NAN", "NAP", -"NAT", "NAY", "NE", "NED", "NEE", "NET", "NEW", "NIB", -"NIL", "NIP", "NIT", "NO", "NOB", "NOD", "NON", "NOR", -"NOT", "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF", -"OAK", "OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT", -"OH", "OIL", "OK", "OLD", "ON", "ONE", "OR", "ORB", -"ORE", "ORR", "OS", "OTT", "OUR", "OUT", "OVA", "OW", -"OWE", "OWL", "OWN", "OX", "PA", "PAD", "PAL", "PAM", -"PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", "PEG", -"PEN", "PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE", -"PIN", "PIT", "PLY", "PO", "POD", "POE", "POP", "POT", -"POW", "PRO", "PRY", "PUB", "PUG", "PUN", "PUP", "PUT", -"QUO", "RAG", "RAM", "RAN", "RAP", "RAT", "RAW", "RAY", -"REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM", -"RIO", "RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW", -"ROY", "RUB", "RUE", "RUG", "RUM", "RUN", "RYE", "SAC", -"SAD", "SAG", "SAL", "SAM", "SAN", "SAP", "SAT", "SAW", -"SAY", "SEA", "SEC", "SEE", "SEN", "SET", "SEW", "SHE", -"SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY", -"SLY", "SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY", -"SPA", "SPY", "SUB", "SUD", "SUE", "SUM", "SUN", "SUP", -"TAB", "TAD", "TAG", "TAN", "TAP", "TAR", "TEA", "TED", -"TEE", "TEN", "THE", "THY", "TIC", "TIE", "TIM", "TIN", -"TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP", -"TOW", "TOY", "TRY", "TUB", "TUG", "TUM", "TUN", "TWO", -"UN", "UP", "US", "USE", "VAN", "VAT", "VET", "VIE", -"WAD", "WAG", "WAR", "WAS", "WAY", "WE", "WEB", "WED", -"WEE", "WET", "WHO", "WHY", "WIN", "WIT", "WOK", "WON", -"WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE", -"YEA", "YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE", -"ABUT", "ACHE", "ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", -"ADDS", "ADEN", "AFAR", "AFRO", "AGEE", "AHEM", "AHOY", "AIDA", -"AIDE", "AIDS", "AIRY", "AJAR", "AKIN", "ALAN", "ALEC", "ALGA", -"ALIA", "ALLY", "ALMA", "ALOE", "ALSO", "ALTO", "ALUM", "ALVA", -"AMEN", "AMES", "AMID", "AMMO", "AMOK", "AMOS", "AMRA", "ANDY", -"ANEW", "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB", "ARCH", -"AREA", "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", "ASKS", -"ATOM", "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", -"AVOW", "AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE", -"BAIL", "BAIT", "BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", -"BALM", "BAND", "BANE", "BANG", "BANK", "BARB", "BARD", "BARE", -"BARK", "BARN", "BARR", "BASE", "BASH", "BASK", "BASS", "BATE", -"BATH", "BAWD", "BAWL", "BEAD", "BEAK", "BEAM", "BEAN", "BEAR", -"BEAT", "BEAU", "BECK", "BEEF", "BEEN", "BEER", "BEET", "BELA", -"BELL", "BELT", "BEND", "BENT", "BERG", "BERN", "BERT", "BESS", -"BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE", "BIEN", "BILE", -"BILK", "BILL", "BIND", "BING", "BIRD", "BITE", "BITS", "BLAB", -"BLAT", "BLED", "BLEW", "BLOB", "BLOC", "BLOT", "BLOW", "BLUE", -"BLUM", "BLUR", "BOAR", "BOAT", "BOCA", "BOCK", "BODE", "BODY", -"BOGY", "BOHR", "BOIL", "BOLD", "BOLO", "BOLT", "BOMB", "BONA", -"BOND", "BONE", "BONG", "BONN", "BONY", "BOOK", "BOOM", "BOON", -"BOOT", "BORE", "BORG", "BORN", "BOSE", "BOSS", "BOTH", "BOUT", -"BOWL", "BOYD", "BRAD", "BRAE", "BRAG", "BRAN", "BRAY", "BRED", -"BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD", "BUFF", "BULB", -"BULK", "BULL", "BUNK", "BUNT", "BUOY", "BURG", "BURL", "BURN", -"BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST", "BUSY", "BYTE", -"CADY", "CAFE", "CAGE", "CAIN", "CAKE", "CALF", "CALL", "CALM", -"CAME", "CANE", "CANT", "CARD", "CARE", "CARL", "CARR", "CART", -"CASE", "CASH", "CASK", "CAST", "CAVE", "CEIL", "CELL", "CENT", -"CERN", "CHAD", "CHAR", "CHAT", "CHAW", "CHEF", "CHEN", "CHEW", -"CHIC", "CHIN", "CHOU", "CHOW", "CHUB", "CHUG", "CHUM", "CITE", -"CITY", "CLAD", "CLAM", "CLAN", "CLAW", "CLAY", "CLOD", "CLOG", -"CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA", "COCK", "COCO", -"CODA", "CODE", "CODY", "COED", "COIL", "COIN", "COKE", "COLA", -"COLD", "COLT", "COMA", "COMB", "COME", "COOK", "COOL", "COON", -"COOT", "CORD", "CORE", "CORK", "CORN", "COST", "COVE", "COWL", -"CRAB", "CRAG", "CRAM", "CRAY", "CREW", "CRIB", "CROW", "CRUD", -"CUBA", "CUBE", "CUFF", "CULL", "CULT", "CUNY", "CURB", "CURD", -"CURE", "CURL", "CURT", "CUTS", "DADE", "DALE", "DAME", "DANA", -"DANE", "DANG", "DANK", "DARE", "DARK", "DARN", "DART", "DASH", -"DATA", "DATE", "DAVE", "DAVY", "DAWN", "DAYS", "DEAD", "DEAF", -"DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED", "DEEM", "DEER", -"DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK", "DIAL", "DICE", -"DIED", "DIET", "DIME", "DINE", "DING", "DINT", "DIRE", "DIRT", -"DISC", "DISH", "DISK", "DIVE", "DOCK", "DOES", "DOLE", "DOLL", -"DOLT", "DOME", "DONE", "DOOM", "DOOR", "DORA", "DOSE", "DOTE", -"DOUG", "DOUR", "DOVE", "DOWN", "DRAB", "DRAG", "DRAM", "DRAW", -"DREW", "DRUB", "DRUG", "DRUM", "DUAL", "DUCK", "DUCT", "DUEL", -"DUET", "DUKE", "DULL", "DUMB", "DUNE", "DUNK", "DUSK", "DUST", -"DUTY", "EACH", "EARL", "EARN", "EASE", "EAST", "EASY", "EBEN", -"ECHO", "EDDY", "EDEN", "EDGE", "EDGY", "EDIT", "EDNA", "EGAN", -"ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT", "EMMA", "ENDS", -"ERIC", "EROS", "EVEN", "EVER", "EVIL", "EYED", "FACE", "FACT", -"FADE", "FAIL", "FAIN", "FAIR", "FAKE", "FALL", "FAME", "FANG", -"FARM", "FAST", "FATE", "FAWN", "FEAR", "FEAT", "FEED", "FEEL", -"FEET", "FELL", "FELT", "FEND", "FERN", "FEST", "FEUD", "FIEF", -"FIGS", "FILE", "FILL", "FILM", "FIND", "FINE", "FINK", "FIRE", -"FIRM", "FISH", "FISK", "FIST", "FITS", "FIVE", "FLAG", "FLAK", -"FLAM", "FLAT", "FLAW", "FLEA", "FLED", "FLEW", "FLIT", "FLOC", -"FLOG", "FLOW", "FLUB", "FLUE", "FOAL", "FOAM", "FOGY", "FOIL", -"FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL", "FOOT", "FORD", -"FORE", "FORK", "FORM", "FORT", "FOSS", "FOUL", "FOUR", "FOWL", -"FRAU", "FRAY", "FRED", "FREE", "FRET", "FREY", "FROG", "FROM", -"FUEL", "FULL", "FUME", "FUND", "FUNK", "FURY", "FUSE", "FUSS", -"GAFF", "GAGE", "GAIL", "GAIN", "GAIT", "GALA", "GALE", "GALL", -"GALT", "GAME", "GANG", "GARB", "GARY", "GASH", "GATE", "GAUL", -"GAUR", "GAVE", "GAWK", "GEAR", "GELD", "GENE", "GENT", "GERM", -"GETS", "GIBE", "GIFT", "GILD", "GILL", "GILT", "GINA", "GIRD", -"GIRL", "GIST", "GIVE", "GLAD", "GLEE", "GLEN", "GLIB", "GLOB", -"GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD", "GOAL", "GOAT", -"GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG", "GOOD", "GOOF", -"GORE", "GORY", "GOSH", "GOUT", "GOWN", "GRAB", "GRAD", "GRAY", -"GREG", "GREW", "GREY", "GRID", "GRIM", "GRIN", "GRIT", "GROW", -"GRUB", "GULF", "GULL", "GUNK", "GURU", "GUSH", "GUST", "GWEN", -"GWYN", "HAAG", "HAAS", "HACK", "HAIL", "HAIR", "HALE", "HALF", -"HALL", "HALO", "HALT", "HAND", "HANG", "HANK", "HANS", "HARD", -"HARK", "HARM", "HART", "HASH", "HAST", "HATE", "HATH", "HAUL", -"HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR", "HEAT", "HEBE", -"HECK", "HEED", "HEEL", "HEFT", "HELD", "HELL", "HELM", "HERB", -"HERD", "HERE", "HERO", "HERS", "HESS", "HEWN", "HICK", "HIDE", -"HIGH", "HIKE", "HILL", "HILT", "HIND", "HINT", "HIRE", "HISS", -"HIVE", "HOBO", "HOCK", "HOFF", "HOLD", "HOLE", "HOLM", "HOLT", -"HOME", "HONE", "HONK", "HOOD", "HOOF", "HOOK", "HOOT", "HORN", -"HOSE", "HOST", "HOUR", "HOVE", "HOWE", "HOWL", "HOYT", "HUCK", -"HUED", "HUFF", "HUGE", "HUGH", "HUGO", "HULK", "HULL", "HUNK", -"HUNT", "HURD", "HURL", "HURT", "HUSH", "HYDE", "HYMN", "IBIS", -"ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH", "INTO", "IONS", -"IOTA", "IOWA", "IRIS", "IRMA", "IRON", "ISLE", "ITCH", "ITEM", -"IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE", "JAVA", "JEAN", -"JEFF", "JERK", "JESS", "JEST", "JIBE", "JILL", "JILT", "JIVE", -"JOAN", "JOBS", "JOCK", "JOEL", "JOEY", "JOHN", "JOIN", "JOKE", -"JOLT", "JOVE", "JUDD", "JUDE", "JUDO", "JUDY", "JUJU", "JUKE", -"JULY", "JUNE", "JUNK", "JUNO", "JURY", "JUST", "JUTE", "KAHN", -"KALE", "KANE", "KANT", "KARL", "KATE", "KEEL", "KEEN", "KENO", -"KENT", "KERN", "KERR", "KEYS", "KICK", "KILL", "KIND", "KING", -"KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW", "KNIT", "KNOB", -"KNOT", "KNOW", "KOCH", "KONG", "KUDO", "KURD", "KURT", "KYLE", -"LACE", "LACK", "LACY", "LADY", "LAID", "LAIN", "LAIR", "LAKE", -"LAMB", "LAME", "LAND", "LANE", "LANG", "LARD", "LARK", "LASS", -"LAST", "LATE", "LAUD", "LAVA", "LAWN", "LAWS", "LAYS", "LEAD", -"LEAF", "LEAK", "LEAN", "LEAR", "LEEK", "LEER", "LEFT", "LEND", -"LENS", "LENT", "LEON", "LESK", "LESS", "LEST", "LETS", "LIAR", -"LICE", "LICK", "LIED", "LIEN", "LIES", "LIEU", "LIFE", "LIFT", -"LIKE", "LILA", "LILT", "LILY", "LIMA", "LIMB", "LIME", "LIND", -"LINE", "LINK", "LINT", "LION", "LISA", "LIST", "LIVE", "LOAD", -"LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE", "LOIS", "LOLA", -"LONE", "LONG", "LOOK", "LOON", "LOOT", "LORD", "LORE", "LOSE", -"LOSS", "LOST", "LOUD", "LOVE", "LOWE", "LUCK", "LUCY", "LUGE", -"LUKE", "LULU", "LUND", "LUNG", "LURA", "LURE", "LURK", "LUSH", -"LUST", "LYLE", "LYNN", "LYON", "LYRA", "MACE", "MADE", "MAGI", -"MAID", "MAIL", "MAIN", "MAKE", "MALE", "MALI", "MALL", "MALT", -"MANA", "MANN", "MANY", "MARC", "MARE", "MARK", "MARS", "MART", -"MARY", "MASH", "MASK", "MASS", "MAST", "MATE", "MATH", "MAUL", -"MAYO", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK", "MEET", "MELD", -"MELT", "MEMO", "MEND", "MENU", "MERT", "MESH", "MESS", "MICE", -"MIKE", "MILD", "MILE", "MILK", "MILL", "MILT", "MIMI", "MIND", -"MINE", "MINI", "MINK", "MINT", "MIRE", "MISS", "MIST", "MITE", -"MITT", "MOAN", "MOAT", "MOCK", "MODE", "MOLD", "MOLE", "MOLL", -"MOLT", "MONA", "MONK", "MONT", "MOOD", "MOON", "MOOR", "MOOT", -"MORE", "MORN", "MORT", "MOSS", "MOST", "MOTH", "MOVE", "MUCH", -"MUCK", "MUDD", "MUFF", "MULE", "MULL", "MURK", "MUSH", "MUST", -"MUTE", "MUTT", "MYRA", "MYTH", "NAGY", "NAIL", "NAIR", "NAME", -"NARY", "NASH", "NAVE", "NAVY", "NEAL", "NEAR", "NEAT", "NECK", -"NEED", "NEIL", "NELL", "NEON", "NERO", "NESS", "NEST", "NEWS", -"NEWT", "NIBS", "NICE", "NICK", "NILE", "NINA", "NINE", "NOAH", -"NODE", "NOEL", "NOLL", "NONE", "NOOK", "NOON", "NORM", "NOSE", -"NOTE", "NOUN", "NOVA", "NUDE", "NULL", "NUMB", "OATH", "OBEY", -"OBOE", "ODIN", "OHIO", "OILY", "OINT", "OKAY", "OLAF", "OLDY", -"OLGA", "OLIN", "OMAN", "OMEN", "OMIT", "ONCE", "ONES", "ONLY", -"ONTO", "ONUS", "ORAL", "ORGY", "OSLO", "OTIS", "OTTO", "OUCH", -"OUST", "OUTS", "OVAL", "OVEN", "OVER", "OWLY", "OWNS", "QUAD", -"QUIT", "QUOD", "RACE", "RACK", "RACY", "RAFT", "RAGE", "RAID", -"RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE", "RASH", "RATE", -"RAVE", "RAYS", "READ", "REAL", "REAM", "REAR", "RECK", "REED", -"REEF", "REEK", "REEL", "REID", "REIN", "RENA", "REND", "RENT", -"REST", "RICE", "RICH", "RICK", "RIDE", "RIFT", "RILL", "RIME", -"RING", "RINK", "RISE", "RISK", "RITE", "ROAD", "ROAM", "ROAR", -"ROBE", "ROCK", "RODE", "ROIL", "ROLL", "ROME", "ROOD", "ROOF", -"ROOK", "ROOM", "ROOT", "ROSA", "ROSE", "ROSS", "ROSY", "ROTH", -"ROUT", "ROVE", "ROWE", "ROWS", "RUBE", "RUBY", "RUDE", "RUDY", -"RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE", "RUSH", "RUSK", -"RUSS", "RUST", "RUTH", "SACK", "SAFE", "SAGE", "SAID", "SAIL", -"SALE", "SALK", "SALT", "SAME", "SAND", "SANE", "SANG", "SANK", -"SARA", "SAUL", "SAVE", "SAYS", "SCAN", "SCAR", "SCAT", "SCOT", -"SEAL", "SEAM", "SEAR", "SEAT", "SEED", "SEEK", "SEEM", "SEEN", -"SEES", "SELF", "SELL", "SEND", "SENT", "SETS", "SEWN", "SHAG", -"SHAM", "SHAW", "SHAY", "SHED", "SHIM", "SHIN", "SHOD", "SHOE", -"SHOT", "SHOW", "SHUN", "SHUT", "SICK", "SIDE", "SIFT", "SIGH", -"SIGN", "SILK", "SILL", "SILO", "SILT", "SINE", "SING", "SINK", -"SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW", "SKID", "SKIM", -"SKIN", "SKIT", "SLAB", "SLAM", "SLAT", "SLAY", "SLED", "SLEW", -"SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT", "SLOW", "SLUG", -"SLUM", "SLUR", "SMOG", "SMUG", "SNAG", "SNOB", "SNOW", "SNUB", -"SNUG", "SOAK", "SOAR", "SOCK", "SODA", "SOFA", "SOFT", "SOIL", -"SOLD", "SOME", "SONG", "SOON", "SOOT", "SORE", "SORT", "SOUL", -"SOUR", "SOWN", "STAB", "STAG", "STAN", "STAR", "STAY", "STEM", -"STEW", "STIR", "STOW", "STUB", "STUN", "SUCH", "SUDS", "SUIT", -"SULK", "SUMS", "SUNG", "SUNK", "SURE", "SURF", "SWAB", "SWAG", -"SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM", "TACK", "TACT", -"TAIL", "TAKE", "TALE", "TALK", "TALL", "TANK", "TASK", "TATE", -"TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM", "TEEN", "TEET", -"TELL", "TEND", "TENT", "TERM", "TERN", "TESS", "TEST", "THAN", -"THAT", "THEE", "THEM", "THEN", "THEY", "THIN", "THIS", "THUD", -"THUG", "TICK", "TIDE", "TIDY", "TIED", "TIER", "TILE", "TILL", -"TILT", "TIME", "TINA", "TINE", "TINT", "TINY", "TIRE", "TOAD", -"TOGO", "TOIL", "TOLD", "TOLL", "TONE", "TONG", "TONY", "TOOK", -"TOOL", "TOOT", "TORE", "TORN", "TOTE", "TOUR", "TOUT", "TOWN", -"TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG", "TRIM", "TRIO", -"TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE", "TUCK", "TUFT", -"TUNA", "TUNE", "TUNG", "TURF", "TURN", "TUSK", "TWIG", "TWIN", -"TWIT", "ULAN", "UNIT", "URGE", "USED", "USER", "USES", "UTAH", -"VAIL", "VAIN", "VALE", "VARY", "VASE", "VAST", "VEAL", "VEDA", -"VEIL", "VEIN", "VEND", "VENT", "VERB", "VERY", "VETO", "VICE", -"VIEW", "VINE", "VISE", "VOID", "VOLT", "VOTE", "WACK", "WADE", -"WAGE", "WAIL", "WAIT", "WAKE", "WALE", "WALK", "WALL", "WALT", -"WAND", "WANE", "WANG", "WANT", "WARD", "WARM", "WARN", "WART", -"WASH", "WAST", "WATS", "WATT", "WAVE", "WAVY", "WAYS", "WEAK", -"WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR", "WELD", "WELL", -"WELT", "WENT", "WERE", "WERT", "WEST", "WHAM", "WHAT", "WHEE", -"WHEN", "WHET", "WHOA", "WHOM", "WICK", "WIFE", "WILD", "WILL", -"WIND", "WINE", "WING", "WINK", "WINO", "WIRE", "WISE", "WISH", -"WITH", "WOLF", "WONT", "WOOD", "WOOL", "WORD", "WORE", "WORK", -"WORM", "WORN", "WOVE", "WRIT", "WYNN", "YALE", "YANG", "YANK", -"YARD", "YARN", "YAWL", "YAWN", "YEAH", "YEAR", "YELL", "YOGA", -"YOKE"] diff -Nru twisted-11.1.0/twisted/python/randbytes.py twisted-12.1.0/twisted/python/randbytes.py --- twisted-11.1.0/twisted/python/randbytes.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/python/randbytes.py 2012-04-01 20:07:59.000000000 +0000 @@ -33,12 +33,11 @@ You shouldn't have to instantiate this class, use the module level functions instead: it is an implementation detail and could be removed or changed arbitrarily. - - @cvar randomSources: list of file sources used when os.urandom is not - available. - @type randomSources: C{tuple} """ - randomSources = ('/dev/urandom',) + + # This variable is no longer used, and will eventually be removed. + randomSources = () + getrandbits = getrandbits @@ -52,26 +51,6 @@ raise SourceNotAvailable(e) - def _fileUrandom(self, nbytes): - """ - Wrapper around random file sources. - - This method isn't meant to be call out of the class and could be - removed arbitrarily. - """ - for src in self.randomSources: - try: - f = file(src, 'rb') - except (IOError, OSError): - pass - else: - bytes = f.read(nbytes) - f.close() - return bytes - raise SourceNotAvailable("File sources not available: %s" % - (self.randomSources,)) - - def secureRandom(self, nbytes, fallback=False): """ Return a number of secure random bytes. @@ -85,11 +64,11 @@ @return: a string of random bytes. @rtype: C{str} """ - for src in ("_osUrandom", "_fileUrandom"): - try: - return getattr(self, src)(nbytes) - except SourceNotAvailable: - pass + try: + return self._osUrandom(nbytes) + except SourceNotAvailable: + pass + if fallback: warnings.warn( "urandom unavailable - " diff -Nru twisted-11.1.0/twisted/python/reflect.py twisted-12.1.0/twisted/python/reflect.py --- twisted-11.1.0/twisted/python/reflect.py 2011-03-27 01:37:18.000000000 +0000 +++ twisted-12.1.0/twisted/python/reflect.py 2012-03-07 19:55:14.000000000 +0000 @@ -30,7 +30,7 @@ from StringIO import StringIO from twisted.python.util import unsignedID -from twisted.python.deprecate import deprecated +from twisted.python.deprecate import deprecated, deprecatedModuleAttribute from twisted.python.deprecate import _fullyQualifiedName as fullyQualifiedName from twisted.python.versions import Version @@ -44,6 +44,12 @@ where you don't want to name a variable, but you do want to set some attributes; for example, C{X()(y=z,a=b)}. """ + + deprecatedModuleAttribute( + Version("Twisted", 12, 1, 0), + "Settable is old and untested. Please write your own version of this " + "functionality if you need it.", "twisted.python.reflect", "Settable") + def __init__(self, **kw): self(**kw) @@ -54,7 +60,8 @@ class AccessorType(type): - """Metaclass that generates properties automatically. + """ + Metaclass that generates properties automatically. This is for Python 2.2 and up. @@ -75,6 +82,12 @@ """ + deprecatedModuleAttribute( + Version("Twisted", 12, 1, 0), + "AccessorType is old and untested. Please write your own version of " + "this functionality if you need it.", "twisted.python.reflect", + "AccessorType") + def __init__(self, name, bases, d): type.__init__(self, name, bases, d) accessors = {} @@ -111,7 +124,8 @@ class PropertyAccessor(object): - """A mixin class for Python 2.2 that uses AccessorType. + """ + A mixin class for Python 2.2 that uses AccessorType. This provides compatability with the pre-2.2 Accessor mixin, up to a point. @@ -138,6 +152,11 @@ # caused by it. # -- itamar + deprecatedModuleAttribute( + Version("Twisted", 12, 1, 0), + "PropertyAccessor is old and untested. Please write your own version " + "of this functionality if you need it.", "twisted.python.reflect", + "PropertyAccessor") __metaclass__ = AccessorType def reallySet(self, k, v): @@ -159,6 +178,11 @@ This implementation is for Python 2.1. """ + deprecatedModuleAttribute( + Version("Twisted", 12, 1, 0), + "Accessor is an implementation for Python 2.1 which is no longer " + "supported by Twisted.", "twisted.python.reflect", "Accessor") + def __setattr__(self, k,v): kstring='set_%s'%k if hasattr(self.__class__,kstring): @@ -199,6 +223,10 @@ # just in case OriginalAccessor = Accessor +deprecatedModuleAttribute( + Version("Twisted", 12, 1, 0), + "OriginalAccessor is a reference to class twisted.python.reflect.Accessor " + "which is deprecated.", "twisted.python.reflect", "OriginalAccessor") class Summer(Accessor): @@ -214,6 +242,11 @@ incremented, similiarly for the debit versions. """ + deprecatedModuleAttribute( + Version("Twisted", 12, 1, 0), + "Summer is a child class of twisted.python.reflect.Accessor which is " + "deprecated.", "twisted.python.reflect", "Summer") + def reallySet(self, k,v): "This method does the work." for sum in self.sums: @@ -245,7 +278,9 @@ class QueueMethod: - """ I represent a method that doesn't exist yet.""" + """ + I represent a method that doesn't exist yet. + """ def __init__(self, name, calls): self.name = name self.calls = calls @@ -294,7 +329,9 @@ def qual(clazz): - """Return full import path of a class.""" + """ + Return full import path of a class. + """ return clazz.__module__ + '.' + clazz.__name__ @@ -308,8 +345,10 @@ def getClass(obj): - """Return the class or type of object 'obj'. - Returns sensible result for oldstyle and newstyle instances and types.""" + """ + Return the class or type of object 'obj'. + Returns sensible result for oldstyle and newstyle instances and types. + """ if hasattr(obj, '__class__'): return obj.__class__ else: @@ -335,7 +374,9 @@ def namedModule(name): - """Return a module given its name.""" + """ + Return a module given its name. + """ topLevel = __import__(name) packages = name.split(".")[1:] m = topLevel @@ -345,7 +386,8 @@ def namedObject(name): - """Get a fully named module-global object. + """ + Get a fully named module-global object. """ classSplit = name.split('.') module = namedModule('.'.join(classSplit[:-1])) @@ -478,46 +520,6 @@ -def macro(name, filename, source, **identifiers): - """macro(name, source, **identifiers) - - This allows you to create macro-like behaviors in python. - """ - if not identifiers.has_key('name'): - identifiers['name'] = name - source = source % identifiers - codeplace = "<%s (macro)>" % filename - code = compile(source, codeplace, 'exec') - - # shield your eyes! - sm = sys.modules - tprm = "twisted.python.reflect.macros" - if not sm.has_key(tprm): - macros = types.ModuleType(tprm) - sm[tprm] = macros - macros.count = 0 - macros = sm[tprm] - macros.count += 1 - macroname = 'macro_' + str(macros.count) - tprmm = tprm + '.' + macroname - mymod = types.ModuleType(tprmm) - sys.modules[tprmm] = mymod - setattr(macros, macroname, mymod) - dict = mymod.__dict__ - - # Before we go on, I guess I should explain why I just did that. Basically - # it's a gross hack to get epydoc to work right, but the general idea is - # that it will be a useful aid in debugging in _any_ app which expects - # sys.modules to have the same globals as some function. For example, it - # would be useful if you were foolishly trying to pickle a wrapped function - # directly from a class that had been hooked. - - exec code in dict, dict - return dict[name] -macro = deprecated(Version("Twisted", 8, 2, 0))(macro) - - - def _determineClass(x): try: return x.__class__ @@ -576,11 +578,12 @@ -##the following were factored out of usage +## the following were factored out of usage @deprecated(Version("Twisted", 11, 0, 0), "inspect.getmro") def allYourBase(classObj, baseClass=None): - """allYourBase(classObj, baseClass=None) -> list of all base + """ + allYourBase(classObj, baseClass=None) -> list of all base classes that are subclasses of baseClass, unless it is None, in which case all bases will be added. """ @@ -602,7 +605,8 @@ def prefixedMethodNames(classObj, prefix): - """A list of method names with a given prefix in a given class. + """ + A list of method names with a given prefix in a given class. """ dct = {} addMethodNamesToDict(classObj, dct, prefix) @@ -633,7 +637,8 @@ def prefixedMethods(obj, prefix=''): - """A list of methods with a given prefix on a given instance. + """ + A list of methods with a given prefix on a given instance. """ dct = {} accumulateMethods(obj, dct, prefix) @@ -641,7 +646,8 @@ def accumulateMethods(obj, dict, prefix='', curClass=None): - """accumulateMethods(instance, dict, prefix) + """ + accumulateMethods(instance, dict, prefix) I recurse through the bases of instance.__class__, and add methods beginning with 'prefix' to 'dict', in the form of {'methodname':*instance*method_object}. @@ -660,7 +666,8 @@ def accumulateClassDict(classObj, attr, adict, baseClass=None): - """Accumulate all attributes of a given name in a class heirarchy into a single dictionary. + """ + Accumulate all attributes of a given name in a class hierarchy into a single dictionary. Assuming all class attributes of this name are dictionaries. If any of the dictionaries being accumulated have the same key, the @@ -669,23 +676,23 @@ Ex:: - | class Soy: - | properties = {\"taste\": \"bland\"} - | - | class Plant: - | properties = {\"colour\": \"green\"} - | - | class Seaweed(Plant): - | pass - | - | class Lunch(Soy, Seaweed): - | properties = {\"vegan\": 1 } - | - | dct = {} - | - | accumulateClassDict(Lunch, \"properties\", dct) - | - | print dct + class Soy: + properties = {\"taste\": \"bland\"} + + class Plant: + properties = {\"colour\": \"green\"} + + class Seaweed(Plant): + pass + + class Lunch(Soy, Seaweed): + properties = {\"vegan\": 1 } + + dct = {} + + accumulateClassDict(Lunch, \"properties\", dct) + + print dct {\"taste\": \"bland\", \"colour\": \"green\", \"vegan\": 1} """ @@ -696,7 +703,8 @@ def accumulateClassList(classObj, attr, listObj, baseClass=None): - """Accumulate all attributes of a given name in a class heirarchy into a single list. + """ + Accumulate all attributes of a given name in a class heirarchy into a single list. Assuming all class attributes of this name are lists. """ @@ -729,8 +737,9 @@ def objgrep(start, goal, eq=isLike, path='', paths=None, seen=None, showUnknowns=0, maxDepth=None): - '''An insanely CPU-intensive process for finding stuff. - ''' + """ + An insanely CPU-intensive process for finding stuff. + """ if paths is None: paths = [] if seen is None: @@ -810,7 +819,7 @@ 'QueueMethod', 'OriginalAccessor', 'funcinfo', 'fullFuncName', 'qual', 'getcurrent', 'getClass', 'isinst', - 'namedModule', 'namedObject', 'namedClass', 'namedAny', 'macro', + 'namedModule', 'namedObject', 'namedClass', 'namedAny', 'safe_repr', 'safe_str', 'allYourBase', 'accumulateBases', 'prefixedMethodNames', 'addMethodNamesToDict', 'prefixedMethods', 'accumulateClassDict', 'accumulateClassList', 'isSame', 'isLike', diff -Nru twisted-11.1.0/twisted/python/_release.py twisted-12.1.0/twisted/python/_release.py --- twisted-11.1.0/twisted/python/_release.py 2011-03-11 04:34:58.000000000 +0000 +++ twisted-12.1.0/twisted/python/_release.py 2012-02-08 19:50:23.000000000 +0000 @@ -947,7 +947,8 @@ """ from twisted.python.dist import twisted_subprojects as subprojects - def __init__(self, rootDirectory, outputDirectory, apiBaseURL=None): + def __init__(self, rootDirectory, outputDirectory, templatePath=None, + apiBaseURL=None): """ Create a distribution builder. @@ -958,6 +959,10 @@ @param outputDirectory: The directory in which to create the tarballs. @type outputDirectory: L{FilePath} + @param templatePath: Path to the template file that is used for the + howto documentation. + @type templatePath: L{FilePath} + @type apiBaseURL: C{str} or C{NoneType} @param apiBaseURL: A format string which will be interpolated with the fully-qualified Python name for each API link. For example, to @@ -966,6 +971,7 @@ """ self.rootDirectory = rootDirectory self.outputDirectory = outputDirectory + self.templatePath = templatePath self.apiBaseURL = apiBaseURL self.manBuilder = ManBuilder() self.docBuilder = DocBuilder() @@ -985,14 +991,15 @@ @param howtoPath: The "resource path" as L{DocBuilder} describes it. @type howtoPath: L{FilePath} """ - templatePath = self.rootDirectory.child("doc").child("core" - ).child("howto").child("template.tpl") + if self.templatePath is None: + self.templatePath = self.rootDirectory.descendant( + ["doc", "core", "howto", "template.tpl"]) if path.basename() == "man": self.manBuilder.build(path) if path.isdir(): try: self.docBuilder.build(version, howtoPath, path, - templatePath, self.apiBaseURL, True) + self.templatePath, self.apiBaseURL, True) except NoDocumentsFound: pass @@ -1187,13 +1194,15 @@ """ + class NotWorkingDirectory(Exception): """ Raised when a directory does not appear to be an SVN working directory. """ -def buildAllTarballs(checkout, destination): + +def buildAllTarballs(checkout, destination, templatePath=None): """ Build complete tarballs (including documentation) for Twisted and all subprojects. @@ -1206,10 +1215,13 @@ will be exported. @type destination: L{FilePath} @param destination: The directory in which tarballs will be placed. + @type templatePath: L{FilePath} + @param templatePath: Location of the template file that is used for the + howto documentation. - @raise UncleanWorkingDirectory: if there are modifications to the + @raise UncleanWorkingDirectory: If there are modifications to the working directory of C{checkout}. - @raise NotWorkingDirectory: if the checkout path is not an SVN checkout. + @raise NotWorkingDirectory: If the C{checkout} path is not an SVN checkout. """ if not checkout.child(".svn").exists(): raise NotWorkingDirectory( @@ -1218,7 +1230,7 @@ if runCommand(["svn", "st", checkout.path]).strip(): raise UncleanWorkingDirectory( "There are local modifications to the SVN checkout in %s." - % (checkout.path,)) + % (checkout.path,)) workPath = FilePath(mkdtemp()) export = workPath.child("export") @@ -1231,7 +1243,8 @@ versionString) if not destination.exists(): destination.createDirectory() - db = DistributionBuilder(export, destination, apiBaseURL=apiBaseURL) + db = DistributionBuilder(export, destination, templatePath=templatePath, + apiBaseURL=apiBaseURL) db.buildCore(versionString) for subproject in twisted_subprojects: @@ -1295,14 +1308,23 @@ """ Build all release tarballs. - @type args: list of str + @type args: list of C{str} @param args: The command line arguments to process. This must contain - two strings: the checkout directory and the destination directory. - """ - if len(args) != 2: - sys.exit("Must specify two arguments: " - "Twisted checkout and destination path") - self.buildAllTarballs(FilePath(args[0]), FilePath(args[1])) + at least two strings: the checkout directory and the destination + directory. An optional third string can be specified for the website + template file, used for building the howto documentation. If this + string isn't specified, the default template included in twisted + will be used. + """ + if len(args) < 2 or len(args) > 3: + sys.exit("Must specify at least two arguments: " + "Twisted checkout and destination path. The optional third " + "argument is the website template path.") + if len(args) == 2: + self.buildAllTarballs(FilePath(args[0]), FilePath(args[1])) + elif len(args) == 3: + self.buildAllTarballs(FilePath(args[0]), FilePath(args[1]), + FilePath(args[2])) diff -Nru twisted-11.1.0/twisted/python/release.py twisted-12.1.0/twisted/python/release.py --- twisted-11.1.0/twisted/python/release.py 2008-07-29 20:13:54.000000000 +0000 +++ twisted-12.1.0/twisted/python/release.py 2012-02-08 19:50:23.000000000 +0000 @@ -1,3 +1,6 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + """ A release-automation toolkit. @@ -7,19 +10,22 @@ """ import os -import re # errors class DirectoryExists(OSError): - """Some directory exists when it shouldn't.""" + """ + Some directory exists when it shouldn't. + """ pass class DirectoryDoesntExist(OSError): - """Some directory doesn't exist when it should.""" + """ + Some directory doesn't exist when it should. + """ pass @@ -33,9 +39,9 @@ def sh(command, null=True, prompt=False): """ - I'll try to execute `command', and if `prompt' is true, I'll + I'll try to execute C{command}, and if C{prompt} is true, I'll ask before running it. If the command returns something other - than 0, I'll raise CommandFailed(command). + than 0, I'll raise C{CommandFailed(command)}. """ print "--$", command diff -Nru twisted-11.1.0/twisted/python/runtime.py twisted-12.1.0/twisted/python/runtime.py --- twisted-11.1.0/twisted/python/runtime.py 2011-05-05 02:48:02.000000000 +0000 +++ twisted-12.1.0/twisted/python/runtime.py 2012-02-21 00:27:01.000000000 +0000 @@ -49,10 +49,12 @@ """Do we know about this platform?""" return self.type != None + def getType(self): """Return 'posix', 'win32' or 'java'""" return self.type + def isMacOSX(self): """Check if current platform is Mac OS X. @@ -61,6 +63,7 @@ """ return self._platform == "darwin" + def isWinNT(self): """Are we running in Windows NT?""" if self.getType() == 'win32': @@ -75,6 +78,7 @@ # not windows NT return 0 + def isWindows(self): return self.getType() == 'win32' @@ -92,6 +96,16 @@ return False + def isLinux(self): + """ + Check if current platform is Linux. + + @return: C{True} if the current platform has been detected as Linux. + @rtype: C{bool} + """ + return self._platform.startswith("linux") + + def supportsThreads(self): """Can threads be created? """ diff -Nru twisted-11.1.0/twisted/python/sendmsg.c twisted-12.1.0/twisted/python/sendmsg.c --- twisted-11.1.0/twisted/python/sendmsg.c 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/python/sendmsg.c 2012-04-26 15:30:59.000000000 +0000 @@ -0,0 +1,502 @@ +/* + * Copyright (c) Twisted Matrix Laboratories. + * See LICENSE for details. + */ + +#define PY_SSIZE_T_CLEAN 1 +#include + +#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) +/* This may cause some warnings, but if you want to get rid of them, upgrade + * your Python version. */ +typedef int Py_ssize_t; +#endif + +#include +#include +#include + +/* + * As per + * : + * + * "To forestall portability problems, it is recommended that applications + * not use values larger than (2**31)-1 for the socklen_t type." + */ + +#define SOCKLEN_MAX 0x7FFFFFFF + +PyObject *sendmsg_socket_error; + +static PyObject *sendmsg_sendmsg(PyObject *self, PyObject *args, PyObject *keywds); +static PyObject *sendmsg_recvmsg(PyObject *self, PyObject *args, PyObject *keywds); +static PyObject *sendmsg_getsockfam(PyObject *self, PyObject *args, PyObject *keywds); + +static char sendmsg_doc[] = "\ +Bindings for sendmsg(2), recvmsg(2), and a minimal helper for inspecting\n\ +address family of a socket.\n\ +"; + +static char sendmsg_sendmsg_doc[] = "\ +Wrap the C sendmsg(2) function for sending \"messages\" on a socket.\n\ +\n\ +@param fd: The file descriptor of the socket over which to send a message.\n\ +@type fd: C{int}\n\ +\n\ +@param data: Bytes to write to the socket.\n\ +@type data: C{str}\n\ +\n\ +@param flags: Flags to affect how the message is sent. See the C{MSG_}\n\ + constants in the sendmsg(2) manual page. By default no flags are set.\n\ +@type flags: C{int}\n\ +\n\ +@param ancillary: Extra data to send over the socket outside of the normal\n\ + datagram or stream mechanism. By default no ancillary data is sent.\n\ +@type ancillary: C{list} of C{tuple} of C{int}, C{int}, and C{str}.\n\ +\n\ +@raise OverflowError: Raised if too much ancillary data is given.\n\ +@raise socket.error: Raised if the underlying syscall indicates an error.\n\ +\n\ +@return: The return value of the underlying syscall, if it succeeds.\n\ +"; + +static char sendmsg_recvmsg_doc[] = "\ +Wrap the C recvmsg(2) function for receiving \"messages\" on a socket.\n\ +\n\ +@param fd: The file descriptor of the socket over which to receve a message.\n\ +@type fd: C{int}\n\ +\n\ +@param flags: Flags to affect how the message is sent. See the C{MSG_}\n\ + constants in the sendmsg(2) manual page. By default no flags are set.\n\ +@type flags: C{int}\n\ +\n\ +@param maxsize: The maximum number of bytes to receive from the socket\n\ + using the datagram or stream mechanism. The default maximum is 8192.\n\ +@type maxsize: C{int}\n\ +\n\ +@param cmsg_size: The maximum number of bytes to receive from the socket\n\ + outside of the normal datagram or stream mechanism. The default maximum is 4096.\n\ +\n\ +@raise OverflowError: Raised if too much ancillary data is given.\n\ +@raise socket.error: Raised if the underlying syscall indicates an error.\n\ +\n\ +@return: A C{tuple} of three elements: the bytes received using the\n\ + datagram/stream mechanism, flags as an C{int} describing the data\n\ + received, and a C{list} of C{tuples} giving ancillary received data.\n\ +"; + +static char sendmsg_getsockfam_doc[] = "\ +Retrieve the address family of a given socket.\n\ +\n\ +@param fd: The file descriptor of the socket the address family of which\n\ + to retrieve.\n\ +@type fd: C{int}\n\ +\n\ +@raise socket.error: Raised if the underlying getsockname call indicates\n\ + an error.\n\ +\n\ +@return: A C{int} representing the address family of the socket. For\n\ + example, L{socket.AF_INET}, L{socket.AF_INET6}, or L{socket.AF_UNIX}.\n\ +"; + +static PyMethodDef sendmsg_methods[] = { + {"send1msg", (PyCFunction) sendmsg_sendmsg, METH_VARARGS | METH_KEYWORDS, + sendmsg_sendmsg_doc}, + {"recv1msg", (PyCFunction) sendmsg_recvmsg, METH_VARARGS | METH_KEYWORDS, + sendmsg_recvmsg_doc}, + {"getsockfam", (PyCFunction) sendmsg_getsockfam, + METH_VARARGS | METH_KEYWORDS, sendmsg_getsockfam_doc}, + {NULL, NULL, 0, NULL} +}; + + +PyMODINIT_FUNC initsendmsg(void) { + PyObject *module; + + sendmsg_socket_error = NULL; /* Make sure that this has a known value + before doing anything that might exit. */ + + module = Py_InitModule3("sendmsg", sendmsg_methods, sendmsg_doc); + + if (!module) { + return; + } + + /* + The following is the only value mentioned by POSIX: + http://www.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html + */ + + if (-1 == PyModule_AddIntConstant(module, "SCM_RIGHTS", SCM_RIGHTS)) { + return; + } + + + /* BSD, Darwin, Hurd */ +#if defined(SCM_CREDS) + if (-1 == PyModule_AddIntConstant(module, "SCM_CREDS", SCM_CREDS)) { + return; + } +#endif + + /* Linux */ +#if defined(SCM_CREDENTIALS) + if (-1 == PyModule_AddIntConstant(module, "SCM_CREDENTIALS", SCM_CREDENTIALS)) { + return; + } +#endif + + /* Apparently everywhere, but not standardized. */ +#if defined(SCM_TIMESTAMP) + if (-1 == PyModule_AddIntConstant(module, "SCM_TIMESTAMP", SCM_TIMESTAMP)) { + return; + } +#endif + + module = PyImport_ImportModule("socket"); + if (!module) { + return; + } + + sendmsg_socket_error = PyObject_GetAttrString(module, "error"); + if (!sendmsg_socket_error) { + return; + } +} + +static PyObject *sendmsg_sendmsg(PyObject *self, PyObject *args, PyObject *keywds) { + + int fd; + int flags = 0; + Py_ssize_t sendmsg_result; + struct msghdr message_header; + struct iovec iov[1]; + PyObject *ancillary = NULL; + PyObject *iterator = NULL; + PyObject *item = NULL; + PyObject *result_object = NULL; + + static char *kwlist[] = {"fd", "data", "flags", "ancillary", NULL}; + + if (!PyArg_ParseTupleAndKeywords( + args, keywds, "it#|iO:sendmsg", kwlist, + &fd, + &iov[0].iov_base, + &iov[0].iov_len, + &flags, + &ancillary)) { + return NULL; + } + + message_header.msg_name = NULL; + message_header.msg_namelen = 0; + + message_header.msg_iov = iov; + message_header.msg_iovlen = 1; + + message_header.msg_control = NULL; + message_header.msg_controllen = 0; + + message_header.msg_flags = 0; + + if (ancillary) { + + if (!PyList_Check(ancillary)) { + PyErr_Format(PyExc_TypeError, + "send1msg argument 3 expected list, got %s", + ancillary->ob_type->tp_name); + goto finished; + } + + iterator = PyObject_GetIter(ancillary); + + if (iterator == NULL) { + goto finished; + } + + size_t all_data_len = 0; + + /* First we need to know how big the buffer needs to be in order to + have enough space for all of the messages. */ + while ( (item = PyIter_Next(iterator)) ) { + int type, level; + Py_ssize_t data_len; + size_t prev_all_data_len; + char *data; + + if (!PyTuple_Check(item)) { + PyErr_Format(PyExc_TypeError, + "send1msg argument 3 expected list of tuple, " + "got list containing %s", + item->ob_type->tp_name); + goto finished; + } + + if (!PyArg_ParseTuple( + item, "iit#:sendmsg ancillary data (level, type, data)", + &level, &type, &data, &data_len)) { + goto finished; + } + + prev_all_data_len = all_data_len; + all_data_len += CMSG_SPACE(data_len); + + Py_DECREF(item); + item = NULL; + + if (all_data_len < prev_all_data_len) { + PyErr_Format(PyExc_OverflowError, + "Too much msg_control to fit in a size_t: %zu", + prev_all_data_len); + goto finished; + } + } + + Py_DECREF(iterator); + iterator = NULL; + + /* Allocate the buffer for all of the ancillary elements, if we have + * any. */ + if (all_data_len) { + if (all_data_len > SOCKLEN_MAX) { + PyErr_Format(PyExc_OverflowError, + "Too much msg_control to fit in a socklen_t: %zu", + all_data_len); + goto finished; + } + message_header.msg_control = PyMem_Malloc(all_data_len); + if (!message_header.msg_control) { + PyErr_NoMemory(); + goto finished; + } + } else { + message_header.msg_control = NULL; + } + message_header.msg_controllen = (socklen_t) all_data_len; + + iterator = PyObject_GetIter(ancillary); /* again */ + + if (!iterator) { + goto finished; + } + + /* Unpack the tuples into the control message. */ + struct cmsghdr *control_message = CMSG_FIRSTHDR(&message_header); + while ( (item = PyIter_Next(iterator)) ) { + int data_len, type, level; + size_t data_size; + unsigned char *data, *cmsg_data; + + /* We explicitly allocated enough space for all ancillary data + above; if there isn't enough room, all bets are off. */ + assert(control_message); + + if (!PyArg_ParseTuple(item, + "iit#:sendmsg ancillary data (level, type, data)", + &level, + &type, + &data, + &data_len)) { + goto finished; + } + + control_message->cmsg_level = level; + control_message->cmsg_type = type; + data_size = CMSG_LEN(data_len); + + if (data_size > SOCKLEN_MAX) { + PyErr_Format(PyExc_OverflowError, + "CMSG_LEN(%d) > SOCKLEN_MAX", data_len); + goto finished; + } + + control_message->cmsg_len = (socklen_t) data_size; + + cmsg_data = CMSG_DATA(control_message); + memcpy(cmsg_data, data, data_len); + + Py_DECREF(item); + item = NULL; + + control_message = CMSG_NXTHDR(&message_header, control_message); + } + Py_DECREF(iterator); + iterator = NULL; + + if (PyErr_Occurred()) { + goto finished; + } + } + + sendmsg_result = sendmsg(fd, &message_header, flags); + + if (sendmsg_result < 0) { + PyErr_SetFromErrno(sendmsg_socket_error); + goto finished; + } + + result_object = Py_BuildValue("n", sendmsg_result); + + finished: + + if (item) { + Py_DECREF(item); + item = NULL; + } + if (iterator) { + Py_DECREF(iterator); + iterator = NULL; + } + if (message_header.msg_control) { + PyMem_Free(message_header.msg_control); + message_header.msg_control = NULL; + } + return result_object; +} + +static PyObject *sendmsg_recvmsg(PyObject *self, PyObject *args, PyObject *keywds) { + int fd = -1; + int flags = 0; + int maxsize = 8192; + int cmsg_size = 4096; + size_t cmsg_space; + size_t cmsg_overhead; + Py_ssize_t recvmsg_result; + + struct msghdr message_header; + struct cmsghdr *control_message; + struct iovec iov[1]; + char *cmsgbuf; + PyObject *ancillary; + PyObject *final_result = NULL; + + static char *kwlist[] = {"fd", "flags", "maxsize", "cmsg_size", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|iii:recvmsg", kwlist, + &fd, &flags, &maxsize, &cmsg_size)) { + return NULL; + } + + cmsg_space = CMSG_SPACE(cmsg_size); + + /* overflow check */ + if (cmsg_space > SOCKLEN_MAX) { + PyErr_Format(PyExc_OverflowError, + "CMSG_SPACE(cmsg_size) greater than SOCKLEN_MAX: %d", + cmsg_size); + return NULL; + } + + message_header.msg_name = NULL; + message_header.msg_namelen = 0; + + iov[0].iov_len = maxsize; + iov[0].iov_base = PyMem_Malloc(maxsize); + + if (!iov[0].iov_base) { + PyErr_NoMemory(); + return NULL; + } + + message_header.msg_iov = iov; + message_header.msg_iovlen = 1; + + cmsgbuf = PyMem_Malloc(cmsg_space); + + if (!cmsgbuf) { + PyMem_Free(iov[0].iov_base); + PyErr_NoMemory(); + return NULL; + } + + memset(cmsgbuf, 0, cmsg_space); + message_header.msg_control = cmsgbuf; + /* see above for overflow check */ + message_header.msg_controllen = (socklen_t) cmsg_space; + + recvmsg_result = recvmsg(fd, &message_header, flags); + if (recvmsg_result < 0) { + PyErr_SetFromErrno(sendmsg_socket_error); + goto finished; + } + + ancillary = PyList_New(0); + if (!ancillary) { + goto finished; + } + + for (control_message = CMSG_FIRSTHDR(&message_header); + control_message; + control_message = CMSG_NXTHDR(&message_header, + control_message)) { + PyObject *entry; + + /* Some platforms apparently always fill out the ancillary data + structure with a single bogus value if none is provided; ignore it, + if that is the case. */ + + if ((!(control_message->cmsg_level)) && + (!(control_message->cmsg_type))) { + continue; + } + + /* + * Figure out how much of the cmsg size is cmsg structure overhead - in + * other words, how much is not part of the application data. This lets + * us compute the right application data size below. There should + * really be a CMSG_ macro for this. + */ + cmsg_overhead = (char*)CMSG_DATA(control_message) - (char*)control_message; + + entry = Py_BuildValue( + "(iis#)", + control_message->cmsg_level, + control_message->cmsg_type, + CMSG_DATA(control_message), + (Py_ssize_t) (control_message->cmsg_len - cmsg_overhead)); + + if (!entry) { + Py_DECREF(ancillary); + goto finished; + } + + if (PyList_Append(ancillary, entry) < 0) { + Py_DECREF(ancillary); + Py_DECREF(entry); + goto finished; + } else { + Py_DECREF(entry); + } + } + + final_result = Py_BuildValue( + "s#iO", + iov[0].iov_base, + recvmsg_result, + message_header.msg_flags, + ancillary); + + Py_DECREF(ancillary); + + finished: + PyMem_Free(iov[0].iov_base); + PyMem_Free(cmsgbuf); + return final_result; +} + +static PyObject *sendmsg_getsockfam(PyObject *self, PyObject *args, + PyObject *keywds) { + int fd; + struct sockaddr sa; + static char *kwlist[] = {"fd", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, keywds, "i", kwlist, &fd)) { + return NULL; + } + socklen_t sz = sizeof(sa); + if (getsockname(fd, &sa, &sz)) { + PyErr_SetFromErrno(sendmsg_socket_error); + return NULL; + } + return Py_BuildValue("i", sa.sa_family); +} diff -Nru twisted-11.1.0/twisted/python/systemd.py twisted-12.1.0/twisted/python/systemd.py --- twisted-11.1.0/twisted/python/systemd.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/python/systemd.py 2012-04-04 21:03:05.000000000 +0000 @@ -0,0 +1,87 @@ +# -*- test-case-name: twisted.python.test.test_systemd -*- +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Integration with systemd. + +Currently only the minimum APIs necessary for using systemd's socket activation +feature are supported. +""" + +__all__ = ['ListenFDs'] + +from os import getpid + + +class ListenFDs(object): + """ + L{ListenFDs} provides access to file descriptors inherited from systemd. + + Typically L{ListenFDs.fromEnvironment} should be used to construct a new + instance of L{ListenFDs}. + + @cvar _START: File descriptors inherited from systemd are always + consecutively numbered, with a fixed lowest "starting" descriptor. This + gives the default starting descriptor. Since this must agree with the + value systemd is using, it typically should not be overridden. + @type _START: C{int} + + @ivar _descriptors: A C{list} of C{int} giving the descriptors which were + inherited. + """ + _START = 3 + + def __init__(self, descriptors): + """ + @param descriptors: The descriptors which will be returned from calls to + C{inheritedDescriptors}. + """ + self._descriptors = descriptors + + + @classmethod + def fromEnvironment(cls, environ=None, start=None): + """ + @param environ: A dictionary-like object to inspect to discover + inherited descriptors. By default, C{None}, indicating that the + real process environment should be inspected. The default is + suitable for typical usage. + + @param start: An integer giving the lowest value of an inherited + descriptor systemd will give us. By default, C{None}, indicating + the known correct (that is, in agreement with systemd) value will be + used. The default is suitable for typical usage. + + @return: A new instance of C{cls} which can be used to look up the + descriptors which have been inherited. + """ + if environ is None: + from os import environ + if start is None: + start = cls._START + + descriptors = [] + + try: + pid = int(environ['LISTEN_PID']) + except (KeyError, ValueError): + pass + else: + if pid == getpid(): + try: + count = int(environ['LISTEN_FDS']) + except (KeyError, ValueError): + pass + else: + descriptors = range(start, start + count) + del environ['LISTEN_PID'], environ['LISTEN_FDS'] + + return cls(descriptors) + + + def inheritedDescriptors(self): + """ + @return: The configured list of descriptors. + """ + return list(self._descriptors) diff -Nru twisted-11.1.0/twisted/python/test/pullpipe.py twisted-12.1.0/twisted/python/test/pullpipe.py --- twisted-11.1.0/twisted/python/test/pullpipe.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/python/test/pullpipe.py 2012-04-14 10:02:04.000000000 +0000 @@ -0,0 +1,40 @@ +#!/usr/bin/python +# -*- test-case-name: twisted.python.test.test_sendmsg -*- +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +import sys, os +from struct import unpack + +# This makes me sad. Why aren't things nice? +sys.path.insert(0, __file__.rsplit('/', 4)[0]) + +from twisted.python.sendmsg import recv1msg + +def recvfd(socketfd): + """ + Receive a file descriptor from a L{send1msg} message on the given C{AF_UNIX} + socket. + + @param socketfd: An C{AF_UNIX} socket, attached to another process waiting + to send sockets via the ancillary data mechanism in L{send1msg}. + + @param fd: C{int} + + @return: a 2-tuple of (new file descriptor, description). + + @rtype: 2-tuple of (C{int}, C{str}) + """ + data, flags, ancillary = recv1msg(socketfd) + [(cmsg_level, cmsg_type, packedFD)] = ancillary + # cmsg_level and cmsg_type really need to be SOL_SOCKET / SCM_RIGHTS, but + # since those are the *only* standard values, there's not much point in + # checking. + [unpackedFD] = unpack("i", packedFD) + return (unpackedFD, data) + + +if __name__ == '__main__': + fd, description = recvfd(int(sys.argv[1])) + os.write(fd, "Test fixture data: %s.\n" % (description,)) + os.close(fd) diff -Nru twisted-11.1.0/twisted/python/test/test_constants.py twisted-12.1.0/twisted/python/test/test_constants.py --- twisted-11.1.0/twisted/python/test/test_constants.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/python/test/test_constants.py 2012-03-11 09:04:58.000000000 +0000 @@ -0,0 +1,778 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Unit tests for L{twisted.python.constants}. +""" + +from twisted.trial.unittest import TestCase + +from twisted.python.constants import ( + NamedConstant, Names, ValueConstant, Values, FlagConstant, Flags) + + +class NamedConstantTests(TestCase): + """ + Tests for the L{twisted.python.constants.NamedConstant} class which is used + to represent individual values. + """ + def setUp(self): + """ + Create a dummy container into which constants can be placed. + """ + class foo(Names): + pass + self.container = foo + + + def test_name(self): + """ + The C{name} attribute of a L{NamedConstant} refers to the value passed + for the C{name} parameter to C{_realize}. + """ + name = NamedConstant() + name._realize(self.container, "bar", None) + self.assertEqual("bar", name.name) + + + def test_representation(self): + """ + The string representation of an instance of L{NamedConstant} includes + the container the instances belongs to as well as the instance's name. + """ + name = NamedConstant() + name._realize(self.container, "bar", None) + self.assertEqual("", repr(name)) + + + def test_equality(self): + """ + A L{NamedConstant} instance compares equal to itself. + """ + name = NamedConstant() + name._realize(self.container, "bar", None) + self.assertTrue(name == name) + self.assertFalse(name != name) + + + def test_nonequality(self): + """ + Two different L{NamedConstant} instances do not compare equal to each + other. + """ + first = NamedConstant() + first._realize(self.container, "bar", None) + second = NamedConstant() + second._realize(self.container, "bar", None) + self.assertFalse(first == second) + self.assertTrue(first != second) + + + def test_hash(self): + """ + Because two different L{NamedConstant} instances do not compare as equal + to each other, they also have different hashes to avoid collisions when + added to a C{dict} or C{set}. + """ + first = NamedConstant() + first._realize(self.container, "bar", None) + second = NamedConstant() + second._realize(self.container, "bar", None) + self.assertNotEqual(hash(first), hash(second)) + + + +class _ConstantsTestsMixin(object): + """ + Mixin defining test helpers common to multiple types of constants + collections. + """ + def _notInstantiableTest(self, name, cls): + """ + Assert that an attempt to instantiate the constants class raises + C{TypeError}. + + @param name: A C{str} giving the name of the constants collection. + @param cls: The constants class to test. + """ + exc = self.assertRaises(TypeError, cls) + self.assertEqual(name + " may not be instantiated.", str(exc)) + + + +class NamesTests(TestCase, _ConstantsTestsMixin): + """ + Tests for L{twisted.python.constants.Names}, a base class for containers of + related constaints. + """ + def setUp(self): + """ + Create a fresh new L{Names} subclass for each unit test to use. Since + L{Names} is stateful, re-using the same subclass across test methods + makes exercising all of the implementation code paths difficult. + """ + class METHOD(Names): + """ + A container for some named constants to use in unit tests for + L{Names}. + """ + GET = NamedConstant() + PUT = NamedConstant() + POST = NamedConstant() + DELETE = NamedConstant() + + self.METHOD = METHOD + + + def test_notInstantiable(self): + """ + A subclass of L{Names} raises C{TypeError} if an attempt is made to + instantiate it. + """ + self._notInstantiableTest("METHOD", self.METHOD) + + + def test_symbolicAttributes(self): + """ + Each name associated with a L{NamedConstant} instance in the definition + of a L{Names} subclass is available as an attribute on the resulting + class. + """ + self.assertTrue(hasattr(self.METHOD, "GET")) + self.assertTrue(hasattr(self.METHOD, "PUT")) + self.assertTrue(hasattr(self.METHOD, "POST")) + self.assertTrue(hasattr(self.METHOD, "DELETE")) + + + def test_withoutOtherAttributes(self): + """ + As usual, names not defined in the class scope of a L{Names} + subclass are not available as attributes on the resulting class. + """ + self.assertFalse(hasattr(self.METHOD, "foo")) + + + def test_representation(self): + """ + The string representation of a constant on a L{Names} subclass includes + the name of the L{Names} subclass and the name of the constant itself. + """ + self.assertEqual("", repr(self.METHOD.GET)) + + + def test_lookupByName(self): + """ + Constants can be looked up by name using L{Names.lookupByName}. + """ + method = self.METHOD.lookupByName("GET") + self.assertIdentical(self.METHOD.GET, method) + + + def test_notLookupMissingByName(self): + """ + Names not defined with a L{NamedConstant} instance cannot be looked up + using L{Names.lookupByName}. + """ + self.assertRaises(ValueError, self.METHOD.lookupByName, "lookupByName") + self.assertRaises(ValueError, self.METHOD.lookupByName, "__init__") + self.assertRaises(ValueError, self.METHOD.lookupByName, "foo") + + + def test_name(self): + """ + The C{name} attribute of one of the named constants gives that + constant's name. + """ + self.assertEqual("GET", self.METHOD.GET.name) + + + def test_attributeIdentity(self): + """ + Repeated access of an attribute associated with a L{NamedConstant} value + in a L{Names} subclass results in the same object. + """ + self.assertIdentical(self.METHOD.GET, self.METHOD.GET) + + + def test_iterconstants(self): + """ + L{Names.iterconstants} returns an iterator over all of the constants + defined in the class, in the order they were defined. + """ + constants = list(self.METHOD.iterconstants()) + self.assertEqual( + [self.METHOD.GET, self.METHOD.PUT, + self.METHOD.POST, self.METHOD.DELETE], + constants) + + + def test_attributeIterconstantsIdentity(self): + """ + The constants returned from L{Names.iterconstants} are identical to the + constants accessible using attributes. + """ + constants = list(self.METHOD.iterconstants()) + self.assertIdentical(self.METHOD.GET, constants[0]) + self.assertIdentical(self.METHOD.PUT, constants[1]) + self.assertIdentical(self.METHOD.POST, constants[2]) + self.assertIdentical(self.METHOD.DELETE, constants[3]) + + + def test_iterconstantsIdentity(self): + """ + The constants returned from L{Names.iterconstants} are identical on each + call to that method. + """ + constants = list(self.METHOD.iterconstants()) + again = list(self.METHOD.iterconstants()) + self.assertIdentical(again[0], constants[0]) + self.assertIdentical(again[1], constants[1]) + self.assertIdentical(again[2], constants[2]) + self.assertIdentical(again[3], constants[3]) + + + def test_initializedOnce(self): + """ + L{Names._enumerants} is initialized once and its value re-used on + subsequent access. + """ + first = self.METHOD._enumerants + self.METHOD.GET # Side-effects! + second = self.METHOD._enumerants + self.assertIdentical(first, second) + + + +class ValuesTests(TestCase, _ConstantsTestsMixin): + """ + Tests for L{twisted.python.constants.Names}, a base class for containers of + related constaints with arbitrary values. + """ + def setUp(self): + """ + Create a fresh new L{Values} subclass for each unit test to use. Since + L{Values} is stateful, re-using the same subclass across test methods + makes exercising all of the implementation code paths difficult. + """ + class STATUS(Values): + OK = ValueConstant("200") + NOT_FOUND = ValueConstant("404") + + self.STATUS = STATUS + + + def test_notInstantiable(self): + """ + A subclass of L{Values} raises C{TypeError} if an attempt is made to + instantiate it. + """ + self._notInstantiableTest("STATUS", self.STATUS) + + + def test_symbolicAttributes(self): + """ + Each name associated with a L{ValueConstant} instance in the definition + of a L{Values} subclass is available as an attribute on the resulting + class. + """ + self.assertTrue(hasattr(self.STATUS, "OK")) + self.assertTrue(hasattr(self.STATUS, "NOT_FOUND")) + + + def test_withoutOtherAttributes(self): + """ + As usual, names not defined in the class scope of a L{Values} + subclass are not available as attributes on the resulting class. + """ + self.assertFalse(hasattr(self.STATUS, "foo")) + + + def test_representation(self): + """ + The string representation of a constant on a L{Values} subclass includes + the name of the L{Values} subclass and the name of the constant itself. + """ + self.assertEqual("", repr(self.STATUS.OK)) + + + def test_lookupByName(self): + """ + Constants can be looked up by name using L{Values.lookupByName}. + """ + method = self.STATUS.lookupByName("OK") + self.assertIdentical(self.STATUS.OK, method) + + + def test_notLookupMissingByName(self): + """ + Names not defined with a L{ValueConstant} instance cannot be looked up + using L{Values.lookupByName}. + """ + self.assertRaises(ValueError, self.STATUS.lookupByName, "lookupByName") + self.assertRaises(ValueError, self.STATUS.lookupByName, "__init__") + self.assertRaises(ValueError, self.STATUS.lookupByName, "foo") + + + def test_lookupByValue(self): + """ + Constants can be looked up by their associated value, defined by the + argument passed to L{ValueConstant}, using L{Values.lookupByValue}. + """ + status = self.STATUS.lookupByValue("200") + self.assertIdentical(self.STATUS.OK, status) + + + def test_lookupDuplicateByValue(self): + """ + If more than one constant is associated with a particular value, + L{Values.lookupByValue} returns whichever of them is defined first. + """ + class TRANSPORT_MESSAGE(Values): + """ + Message types supported by an SSH transport. + """ + KEX_DH_GEX_REQUEST_OLD = ValueConstant(30) + KEXDH_INIT = ValueConstant(30) + + self.assertIdentical( + TRANSPORT_MESSAGE.lookupByValue(30), + TRANSPORT_MESSAGE.KEX_DH_GEX_REQUEST_OLD) + + + def test_notLookupMissingByValue(self): + """ + L{Values.lookupByValue} raises L{ValueError} when called with a value + with which no constant is associated. + """ + self.assertRaises(ValueError, self.STATUS.lookupByValue, "OK") + self.assertRaises(ValueError, self.STATUS.lookupByValue, 200) + self.assertRaises(ValueError, self.STATUS.lookupByValue, "200.1") + + + def test_name(self): + """ + The C{name} attribute of one of the constants gives that constant's + name. + """ + self.assertEqual("OK", self.STATUS.OK.name) + + + def test_attributeIdentity(self): + """ + Repeated access of an attribute associated with a L{ValueConstant} value + in a L{Values} subclass results in the same object. + """ + self.assertIdentical(self.STATUS.OK, self.STATUS.OK) + + + def test_iterconstants(self): + """ + L{Values.iterconstants} returns an iterator over all of the constants + defined in the class, in the order they were defined. + """ + constants = list(self.STATUS.iterconstants()) + self.assertEqual( + [self.STATUS.OK, self.STATUS.NOT_FOUND], + constants) + + + def test_attributeIterconstantsIdentity(self): + """ + The constants returned from L{Values.iterconstants} are identical to the + constants accessible using attributes. + """ + constants = list(self.STATUS.iterconstants()) + self.assertIdentical(self.STATUS.OK, constants[0]) + self.assertIdentical(self.STATUS.NOT_FOUND, constants[1]) + + + def test_iterconstantsIdentity(self): + """ + The constants returned from L{Values.iterconstants} are identical on + each call to that method. + """ + constants = list(self.STATUS.iterconstants()) + again = list(self.STATUS.iterconstants()) + self.assertIdentical(again[0], constants[0]) + self.assertIdentical(again[1], constants[1]) + + + def test_initializedOnce(self): + """ + L{Values._enumerants} is initialized once and its value re-used on + subsequent access. + """ + first = self.STATUS._enumerants + self.STATUS.OK # Side-effects! + second = self.STATUS._enumerants + self.assertIdentical(first, second) + + +class _FlagsTestsMixin(object): + """ + Mixin defining setup code for any tests for L{Flags} subclasses. + + @ivar FXF: A L{Flags} subclass created for each test method. + """ + def setUp(self): + """ + Create a fresh new L{Flags} subclass for each unit test to use. Since + L{Flags} is stateful, re-using the same subclass across test methods + makes exercising all of the implementation code paths difficult. + """ + class FXF(Flags): + # Implicitly assign three flag values based on definition order + READ = FlagConstant() + WRITE = FlagConstant() + APPEND = FlagConstant() + + # Explicitly assign one flag value by passing it in + EXCLUSIVE = FlagConstant(0x20) + + # Implicitly assign another flag value, following the previously + # specified explicit value. + TEXT = FlagConstant() + + self.FXF = FXF + + + +class FlagsTests(_FlagsTestsMixin, TestCase, _ConstantsTestsMixin): + """ + Tests for L{twisted.python.constants.Flags}, a base class for containers of + related, combinable flag or bitvector-like constants. + """ + def test_notInstantiable(self): + """ + A subclass of L{Flags} raises L{TypeError} if an attempt is made to + instantiate it. + """ + self._notInstantiableTest("FXF", self.FXF) + + + def test_symbolicAttributes(self): + """ + Each name associated with a L{FlagConstant} instance in the definition + of a L{Flags} subclass is available as an attribute on the resulting + class. + """ + self.assertTrue(hasattr(self.FXF, "READ")) + self.assertTrue(hasattr(self.FXF, "WRITE")) + self.assertTrue(hasattr(self.FXF, "APPEND")) + self.assertTrue(hasattr(self.FXF, "EXCLUSIVE")) + self.assertTrue(hasattr(self.FXF, "TEXT")) + + + def test_withoutOtherAttributes(self): + """ + As usual, names not defined in the class scope of a L{Flags} subclass + are not available as attributes on the resulting class. + """ + self.assertFalse(hasattr(self.FXF, "foo")) + + + def test_representation(self): + """ + The string representation of a constant on a L{Flags} subclass includes + the name of the L{Flags} subclass and the name of the constant itself. + """ + self.assertEqual("", repr(self.FXF.READ)) + + + def test_lookupByName(self): + """ + Constants can be looked up by name using L{Flags.lookupByName}. + """ + flag = self.FXF.lookupByName("READ") + self.assertIdentical(self.FXF.READ, flag) + + + def test_notLookupMissingByName(self): + """ + Names not defined with a L{FlagConstant} instance cannot be looked up + using L{Flags.lookupByName}. + """ + self.assertRaises(ValueError, self.FXF.lookupByName, "lookupByName") + self.assertRaises(ValueError, self.FXF.lookupByName, "__init__") + self.assertRaises(ValueError, self.FXF.lookupByName, "foo") + + + def test_lookupByValue(self): + """ + Constants can be looked up by their associated value, defined implicitly + by the position in which the constant appears in the class definition or + explicitly by the argument passed to L{FlagConstant}. + """ + flag = self.FXF.lookupByValue(0x01) + self.assertIdentical(flag, self.FXF.READ) + + flag = self.FXF.lookupByValue(0x02) + self.assertIdentical(flag, self.FXF.WRITE) + + flag = self.FXF.lookupByValue(0x04) + self.assertIdentical(flag, self.FXF.APPEND) + + flag = self.FXF.lookupByValue(0x20) + self.assertIdentical(flag, self.FXF.EXCLUSIVE) + + flag = self.FXF.lookupByValue(0x40) + self.assertIdentical(flag, self.FXF.TEXT) + + + def test_lookupDuplicateByValue(self): + """ + If more than one constant is associated with a particular value, + L{Flags.lookupByValue} returns whichever of them is defined first. + """ + class TIMEX(Flags): + # (timex.mode) + ADJ_OFFSET = FlagConstant(0x0001) # time offset + + # xntp 3.4 compatibility names + MOD_OFFSET = FlagConstant(0x0001) + + self.assertIdentical(TIMEX.lookupByValue(0x0001), TIMEX.ADJ_OFFSET) + + + def test_notLookupMissingByValue(self): + """ + L{Flags.lookupByValue} raises L{ValueError} when called with a value + with which no constant is associated. + """ + self.assertRaises(ValueError, self.FXF.lookupByValue, 0x10) + + + def test_name(self): + """ + The C{name} attribute of one of the constants gives that constant's + name. + """ + self.assertEqual("READ", self.FXF.READ.name) + + + def test_attributeIdentity(self): + """ + Repeated access of an attribute associated with a L{FlagConstant} value + in a L{Flags} subclass results in the same object. + """ + self.assertIdentical(self.FXF.READ, self.FXF.READ) + + + def test_iterconstants(self): + """ + L{Flags.iterconstants} returns an iterator over all of the constants + defined in the class, in the order they were defined. + """ + constants = list(self.FXF.iterconstants()) + self.assertEqual( + [self.FXF.READ, self.FXF.WRITE, self.FXF.APPEND, + self.FXF.EXCLUSIVE, self.FXF.TEXT], + constants) + + + def test_attributeIterconstantsIdentity(self): + """ + The constants returned from L{Flags.iterconstants} are identical to the + constants accessible using attributes. + """ + constants = list(self.FXF.iterconstants()) + self.assertIdentical(self.FXF.READ, constants[0]) + self.assertIdentical(self.FXF.WRITE, constants[1]) + self.assertIdentical(self.FXF.APPEND, constants[2]) + self.assertIdentical(self.FXF.EXCLUSIVE, constants[3]) + self.assertIdentical(self.FXF.TEXT, constants[4]) + + + def test_iterconstantsIdentity(self): + """ + The constants returned from L{Flags.iterconstants} are identical on each + call to that method. + """ + constants = list(self.FXF.iterconstants()) + again = list(self.FXF.iterconstants()) + self.assertIdentical(again[0], constants[0]) + self.assertIdentical(again[1], constants[1]) + self.assertIdentical(again[2], constants[2]) + self.assertIdentical(again[3], constants[3]) + self.assertIdentical(again[4], constants[4]) + + + def test_initializedOnce(self): + """ + L{Flags._enumerants} is initialized once and its value re-used on + subsequent access. + """ + first = self.FXF._enumerants + self.FXF.READ # Side-effects! + second = self.FXF._enumerants + self.assertIdentical(first, second) + + + +class FlagConstantSimpleOrTests(_FlagsTestsMixin, TestCase): + """ + Tests for the C{|} operator as defined for L{FlagConstant} instances, used + to create new L{FlagConstant} instances representing both of two existing + L{FlagConstant} instances from the same L{Flags} class. + """ + def test_value(self): + """ + The value of the L{FlagConstant} which results from C{|} has all of the + bits set which were set in either of the values of the two original + constants. + """ + flag = self.FXF.READ | self.FXF.WRITE + self.assertEqual(self.FXF.READ.value | self.FXF.WRITE.value, flag.value) + + + def test_name(self): + """ + The name of the L{FlagConstant} instance which results from C{|} + includes the names of both of the two original constants. + """ + flag = self.FXF.READ | self.FXF.WRITE + self.assertEqual("{READ,WRITE}", flag.name) + + + def test_representation(self): + """ + The string representation of a L{FlagConstant} instance which results + from C{|} includes the names of both of the two original constants. + """ + flag = self.FXF.READ | self.FXF.WRITE + self.assertEqual("", repr(flag)) + + + +class FlagConstantSimpleAndTests(_FlagsTestsMixin, TestCase): + """ + Tests for the C{&} operator as defined for L{FlagConstant} instances, used + to create new L{FlagConstant} instances representing the common parts of two + existing L{FlagConstant} instances from the same L{Flags} class. + """ + def test_value(self): + """ + The value of the L{FlagConstant} which results from C{&} has all of the + bits set which were set in both of the values of the two original + constants. + """ + readWrite = (self.FXF.READ | self.FXF.WRITE) + writeAppend = (self.FXF.WRITE | self.FXF.APPEND) + flag = readWrite & writeAppend + self.assertEqual(self.FXF.WRITE.value, flag.value) + + + def test_name(self): + """ + The name of the L{FlagConstant} instance which results from C{&} + includes the names of only the flags which were set in both of the two + original constants. + """ + readWrite = (self.FXF.READ | self.FXF.WRITE) + writeAppend = (self.FXF.WRITE | self.FXF.APPEND) + flag = readWrite & writeAppend + self.assertEqual("WRITE", flag.name) + + + def test_representation(self): + """ + The string representation of a L{FlagConstant} instance which results + from C{&} includes the names of only the flags which were set in both + both of the two original constants. + """ + readWrite = (self.FXF.READ | self.FXF.WRITE) + writeAppend = (self.FXF.WRITE | self.FXF.APPEND) + flag = readWrite & writeAppend + self.assertEqual("", repr(flag)) + + + +class FlagConstantSimpleExclusiveOrTests(_FlagsTestsMixin, TestCase): + """ + Tests for the C{^} operator as defined for L{FlagConstant} instances, used + to create new L{FlagConstant} instances representing the uncommon parts of + two existing L{FlagConstant} instances from the same L{Flags} class. + """ + def test_value(self): + """ + The value of the L{FlagConstant} which results from C{^} has all of the + bits set which were set in exactly one of the values of the two original + constants. + """ + readWrite = (self.FXF.READ | self.FXF.WRITE) + writeAppend = (self.FXF.WRITE | self.FXF.APPEND) + flag = readWrite ^ writeAppend + self.assertEqual(self.FXF.READ.value | self.FXF.APPEND.value, flag.value) + + + def test_name(self): + """ + The name of the L{FlagConstant} instance which results from C{^} + includes the names of only the flags which were set in exactly one of + the two original constants. + """ + readWrite = (self.FXF.READ | self.FXF.WRITE) + writeAppend = (self.FXF.WRITE | self.FXF.APPEND) + flag = readWrite ^ writeAppend + self.assertEqual("{APPEND,READ}", flag.name) + + + def test_representation(self): + """ + The string representation of a L{FlagConstant} instance which results + from C{^} includes the names of only the flags which were set in exactly + one of the two original constants. + """ + readWrite = (self.FXF.READ | self.FXF.WRITE) + writeAppend = (self.FXF.WRITE | self.FXF.APPEND) + flag = readWrite ^ writeAppend + self.assertEqual("", repr(flag)) + + + +class FlagConstantNegationTests(_FlagsTestsMixin, TestCase): + """ + Tests for the C{~} operator as defined for L{FlagConstant} instances, used + to create new L{FlagConstant} instances representing all the flags from a + L{Flags} class not set in a particular L{FlagConstant} instance. + """ + def test_value(self): + """ + The value of the L{FlagConstant} which results from C{~} has all of the + bits set which were not set in the original constant. + """ + flag = ~self.FXF.READ + self.assertEqual( + self.FXF.WRITE.value | + self.FXF.APPEND.value | + self.FXF.EXCLUSIVE.value | + self.FXF.TEXT.value, + flag.value) + + flag = ~self.FXF.WRITE + self.assertEqual( + self.FXF.READ.value | + self.FXF.APPEND.value | + self.FXF.EXCLUSIVE.value | + self.FXF.TEXT.value, + flag.value) + + + def test_name(self): + """ + The name of the L{FlagConstant} instance which results from C{~} + includes the names of all the flags which were not set in the original + constant. + """ + flag = ~self.FXF.WRITE + self.assertEqual("{APPEND,EXCLUSIVE,READ,TEXT}", flag.name) + + + def test_representation(self): + """ + The string representation of a L{FlagConstant} instance which results + from C{~} includes the names of all the flags which were not set in the + original constant. + """ + flag = ~self.FXF.WRITE + self.assertEqual("", repr(flag)) diff -Nru twisted-11.1.0/twisted/python/test/test_fakepwd.py twisted-12.1.0/twisted/python/test/test_fakepwd.py --- twisted-11.1.0/twisted/python/test/test_fakepwd.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/python/test/test_fakepwd.py 2011-11-25 01:19:18.000000000 +0000 @@ -10,11 +10,16 @@ except ImportError: pwd = None +try: + import spwd +except ImportError: + spwd = None +import os from operator import getitem from twisted.trial.unittest import TestCase -from twisted.python.fakepwd import UserDatabase +from twisted.python.fakepwd import UserDatabase, ShadowDatabase from twisted.python.compat import set @@ -94,6 +99,7 @@ username, password, uid, gid, gecos, dir, shell = self.getExistingUserInfo() for entry in [db.getpwuid(uid), db.getpwnam(username), db.getpwall()[0]]: self.assertIsInstance(len(entry), int) + self.assertEquals(len(entry), 7) def test_recordIndexable(self): @@ -167,7 +173,8 @@ db = self.database db.addUser(username, password, uid, gid, gecos, home, shell) - for entry in [db.getpwuid(uid), db.getpwnam(username)]: + for [entry] in [[db.getpwuid(uid)], [db.getpwnam(username)], + db.getpwall()]: self.assertEqual(entry.pw_name, username) self.assertEqual(entry.pw_passwd, password) self.assertEqual(entry.pw_uid, uid) @@ -176,15 +183,6 @@ self.assertEqual(entry.pw_dir, home) self.assertEqual(entry.pw_shell, shell) - [entry] = db.getpwall() - self.assertEqual(entry.pw_name, username) - self.assertEqual(entry.pw_passwd, password) - self.assertEqual(entry.pw_uid, uid) - self.assertEqual(entry.pw_gid, gid) - self.assertEqual(entry.pw_gecos, gecos) - self.assertEqual(entry.pw_dir, home) - self.assertEqual(entry.pw_shell, shell) - class PwdModuleTests(TestCase, UserDatabaseTestsMixin): @@ -195,10 +193,10 @@ """ if pwd is None: skip = "Cannot verify UserDatabase against pwd without pwd" - + else: + database = pwd def setUp(self): - self.database = pwd self._users = iter(self.database.getpwall()) self._uids = set() @@ -211,6 +209,178 @@ """ while True: entry = self._users.next() - if entry.pw_uid not in self._uids: - self._uids.add(entry.pw_uid) + uid = entry.pw_uid + if uid not in self._uids: + self._uids.add(uid) return entry + + + +class ShadowDatabaseTestsMixin: + """ + L{ShadowDatabaseTestsMixin} defines tests which apply to any shadow user + database implementation. Subclasses should mix it in, implement C{setUp} to + create C{self.database} bound to a shadow user database instance, and + implement C{getExistingUserInfo} to return information about a user (such + information should be unique per test method). + """ + def test_getspnam(self): + """ + L{getspnam} accepts a username and returns the user record associated + with it. + """ + for i in range(2): + # Get some user which exists in the database. + (username, password, lastChange, min, max, warn, inact, expire, + flag) = self.getExistingUserInfo() + + entry = self.database.getspnam(username) + self.assertEquals(entry.sp_nam, username) + self.assertEquals(entry.sp_pwd, password) + self.assertEquals(entry.sp_lstchg, lastChange) + self.assertEquals(entry.sp_min, min) + self.assertEquals(entry.sp_max, max) + self.assertEquals(entry.sp_warn, warn) + self.assertEquals(entry.sp_inact, inact) + self.assertEquals(entry.sp_expire, expire) + self.assertEquals(entry.sp_flag, flag) + + + def test_noSuchName(self): + """ + I{getspnam} raises L{KeyError} when passed a username which does not + exist in the user database. + """ + self.assertRaises(KeyError, self.database.getspnam, "alice") + + + def test_recordLength(self): + """ + The shadow user record returned by I{getspnam} and I{getspall} has a + length. + """ + db = self.database + username = self.getExistingUserInfo()[0] + for entry in [db.getspnam(username), db.getspall()[0]]: + self.assertIsInstance(len(entry), int) + self.assertEquals(len(entry), 9) + + + def test_recordIndexable(self): + """ + The shadow user record returned by I{getpwnam} and I{getspall} is + indexable, with successive indexes starting from 0 corresponding to the + values of the C{sp_nam}, C{sp_pwd}, C{sp_lstchg}, C{sp_min}, C{sp_max}, + C{sp_warn}, C{sp_inact}, C{sp_expire}, and C{sp_flag} attributes, + respectively. + """ + db = self.database + (username, password, lastChange, min, max, warn, inact, expire, + flag) = self.getExistingUserInfo() + for entry in [db.getspnam(username), db.getspall()[0]]: + self.assertEquals(entry[0], username) + self.assertEquals(entry[1], password) + self.assertEquals(entry[2], lastChange) + self.assertEquals(entry[3], min) + self.assertEquals(entry[4], max) + self.assertEquals(entry[5], warn) + self.assertEquals(entry[6], inact) + self.assertEquals(entry[7], expire) + self.assertEquals(entry[8], flag) + + self.assertEquals(len(entry), len(list(entry))) + self.assertRaises(IndexError, getitem, entry, 9) + + + +class ShadowDatabaseTests(TestCase, ShadowDatabaseTestsMixin): + """ + Tests for L{ShadowDatabase}. + """ + def setUp(self): + """ + Create a L{ShadowDatabase} with no user data in it. + """ + self.database = ShadowDatabase() + self._counter = 0 + + + def getExistingUserInfo(self): + """ + Add a new user to C{self.database} and return its information. + """ + self._counter += 1 + suffix = '_' + str(self._counter) + username = 'username' + suffix + password = 'password' + suffix + lastChange = self._counter + 1 + min = self._counter + 2 + max = self._counter + 3 + warn = self._counter + 4 + inact = self._counter + 5 + expire = self._counter + 6 + flag = self._counter + 7 + + self.database.addUser(username, password, lastChange, min, max, warn, + inact, expire, flag) + return (username, password, lastChange, min, max, warn, inact, + expire, flag) + + + def test_addUser(self): + """ + L{UserDatabase.addUser} accepts seven arguments, one for each field of + a L{pwd.struct_passwd}, and makes the new record available via + L{UserDatabase.getpwuid}, L{UserDatabase.getpwnam}, and + L{UserDatabase.getpwall}. + """ + username = 'alice' + password = 'secr3t' + lastChange = 17 + min = 42 + max = 105 + warn = 12 + inact = 3 + expire = 400 + flag = 3 + + db = self.database + db.addUser(username, password, lastChange, min, max, warn, inact, + expire, flag) + + for [entry] in [[db.getspnam(username)], db.getspall()]: + self.assertEquals(entry.sp_nam, username) + self.assertEquals(entry.sp_pwd, password) + self.assertEquals(entry.sp_lstchg, lastChange) + self.assertEquals(entry.sp_min, min) + self.assertEquals(entry.sp_max, max) + self.assertEquals(entry.sp_warn, warn) + self.assertEquals(entry.sp_inact, inact) + self.assertEquals(entry.sp_expire, expire) + self.assertEquals(entry.sp_flag, flag) + + + +class SPwdModuleTests(TestCase, ShadowDatabaseTestsMixin): + """ + L{SPwdModuleTests} runs the tests defined by L{ShadowDatabaseTestsMixin} + against the built-in C{spwd} module. This serves to verify that + L{ShadowDatabase} is really a fake of that API. + """ + if spwd is None: + skip = "Cannot verify ShadowDatabase against spwd without spwd" + elif os.getuid() != 0: + skip = "Cannot access shadow user database except as root" + else: + database = spwd + + def setUp(self): + self._users = iter(self.database.getspall()) + + + def getExistingUserInfo(self): + """ + Read and return the next record from C{self._users}. + """ + return self._users.next() + diff -Nru twisted-11.1.0/twisted/python/test/test_release.py twisted-12.1.0/twisted/python/test/test_release.py --- twisted-11.1.0/twisted/python/test/test_release.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/python/test/test_release.py 2012-03-07 18:11:45.000000000 +0000 @@ -2169,8 +2169,6 @@ howtoInput, howtoOutput = self.getArbitraryLoreInputAndOutput("8.0.0") specInput, specOutput = self.getArbitraryLoreInputAndOutput( "8.0.0", prefix="../howto/") - upgradeInput, upgradeOutput = self.getArbitraryLoreInputAndOutput( - "8.0.0", prefix="../howto/") tutorialInput, tutorialOutput = self.getArbitraryLoreInputAndOutput( "8.0.0", prefix="../") @@ -2192,7 +2190,6 @@ "tutorial": {"index.xhtml": tutorialInput}}, "specifications": {"index.xhtml": specInput}, - "upgrades": {"index.xhtml": upgradeInput}, "examples": {"foo.py": "foo.py"}, "index.xhtml": indexInput}, "web": {"howto": {"index.xhtml": "webindex"}}}, @@ -2214,7 +2211,6 @@ "index.html": howtoOutput, "tutorial": {"index.html": tutorialOutput}}, "specifications": {"index.html": specOutput}, - "upgrades": {"index.html": upgradeOutput}, "examples": {"foo.py": "foo.py"}, "index.html": indexOutput}, "bin": {"twistd": "TWISTD"}, @@ -2506,18 +2502,25 @@ def test_buildTarballsScript(self): """ L{BuildTarballsScript.main} invokes L{buildAllTarballs} with - L{FilePath} instances representing the paths passed to it. + 2 or 3 L{FilePath} instances representing the paths passed to it. """ builds = [] - def myBuilder(checkout, destination): - builds.append((checkout, destination)) + def myBuilder(checkout, destination, template=None): + builds.append((checkout, destination, template)) tarballBuilder = BuildTarballsScript() tarballBuilder.buildAllTarballs = myBuilder tarballBuilder.main(["checkoutDir", "destinationDir"]) self.assertEqual( builds, - [(FilePath("checkoutDir"), FilePath("destinationDir"))]) + [(FilePath("checkoutDir"), FilePath("destinationDir"), None)]) + + builds = [] + tarballBuilder.main(["checkoutDir", "destinationDir", "templatePath"]) + self.assertEqual( + builds, + [(FilePath("checkoutDir"), FilePath("destinationDir"), + FilePath("templatePath"))]) def test_defaultBuildTarballsScriptBuilder(self): @@ -2536,6 +2539,7 @@ """ tarballBuilder = BuildTarballsScript() self.assertRaises(SystemExit, tarballBuilder.main, []) + self.assertRaises(SystemExit, tarballBuilder.main, ["a", "b", "c", "d"]) def test_badNumberOfArgumentsToBuildNews(self): diff -Nru twisted-11.1.0/twisted/python/test/test_runtime.py twisted-12.1.0/twisted/python/test/test_runtime.py --- twisted-11.1.0/twisted/python/test/test_runtime.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/python/test/test_runtime.py 2012-02-21 00:27:01.000000000 +0000 @@ -5,7 +5,7 @@ Tests for runtime checks. """ - +import sys from twisted.python.runtime import Platform from twisted.trial.unittest import TestCase @@ -39,6 +39,16 @@ self.assertEqual(platform.getType(), 'posix') + def test_isLinuxConsistency(self): + """ + L{Platform.isLinux} can only return C{True} if L{Platform.getType} + returns C{'posix'} and L{sys.platform} starts with C{"linux"}. + """ + platform = Platform() + if platform.isLinux(): + self.assertTrue(sys.platform.startswith("linux")) + + class ForeignPlatformTests(TestCase): """ @@ -66,3 +76,16 @@ self.assertTrue(Platform(None, 'darwin').isMacOSX()) self.assertFalse(Platform(None, 'linux2').isMacOSX()) self.assertFalse(Platform(None, 'win32').isMacOSX()) + + + def test_isLinux(self): + """ + If a system platform name is supplied to L{Platform}'s initializer, it + is used to determine the result of L{Platform.isLinux}, which returns + C{True} for values beginning with C{"linux"}, C{False} otherwise. + """ + self.assertFalse(Platform(None, 'darwin').isLinux()) + self.assertTrue(Platform(None, 'linux').isLinux()) + self.assertTrue(Platform(None, 'linux2').isLinux()) + self.assertTrue(Platform(None, 'linux3').isLinux()) + self.assertFalse(Platform(None, 'win32').isLinux()) diff -Nru twisted-11.1.0/twisted/python/test/test_sendmsg.py twisted-12.1.0/twisted/python/test/test_sendmsg.py --- twisted-11.1.0/twisted/python/test/test_sendmsg.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/python/test/test_sendmsg.py 2012-04-14 10:02:04.000000000 +0000 @@ -0,0 +1,543 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Tests for L{twisted.python.sendmsg}. +""" + +import sys +import errno + +from socket import SOL_SOCKET, AF_INET, AF_INET6, socket, error + +try: + from socket import AF_UNIX, socketpair +except ImportError: + nonUNIXSkip = "Platform does not support AF_UNIX sockets" +else: + nonUNIXSkip = None + +from struct import pack +from os import devnull, pipe, read, close, environ + +from twisted.internet.defer import Deferred +from twisted.internet.error import ProcessDone +from twisted.trial.unittest import TestCase +from twisted.internet.defer import inlineCallbacks +from twisted.internet import reactor +from twisted.python.filepath import FilePath +from twisted.python.runtime import platform + +from twisted.internet.protocol import ProcessProtocol + +if platform.isLinux(): + from socket import MSG_DONTWAIT + dontWaitSkip = None +else: + # It would be nice to be able to test flags on more platforms, but finding a + # flag that works *at all* is somewhat challenging. + dontWaitSkip = "MSG_DONTWAIT is only known to work as intended on Linux" + +try: + from twisted.python.sendmsg import SCM_RIGHTS, send1msg, recv1msg, getsockfam +except ImportError: + importSkip = "Cannot import twisted.python.sendmsg" +else: + importSkip = None + + +class ExitedWithStderr(Exception): + """ + A process exited with some stderr. + """ + + def __str__(self): + """ + Dump the errors in a pretty way in the event of a subprocess traceback. + """ + return '\n'.join([''] + list(self.args)) + + +class StartStopProcessProtocol(ProcessProtocol): + """ + An L{IProcessProtocol} with a Deferred for events where the subprocess + starts and stops. + + @ivar started: A L{Deferred} which fires with this protocol's + L{IProcessTransport} provider when it is connected to one. + + @ivar stopped: A L{Deferred} which fires with the process output or a + failure if the process produces output on standard error. + + @ivar output: A C{str} used to accumulate standard output. + + @ivar errors: A C{str} used to accumulate standard error. + """ + def __init__(self): + self.started = Deferred() + self.stopped = Deferred() + self.output = '' + self.errors = '' + + + def connectionMade(self): + self.started.callback(self.transport) + + + def outReceived(self, data): + self.output += data + + + def errReceived(self, data): + self.errors += data + + + def processEnded(self, reason): + if reason.check(ProcessDone): + self.stopped.callback(self.output) + else: + self.stopped.errback(ExitedWithStderr( + self.errors, self.output)) + + + +class BadList(list): + """ + A list which cannot be iterated sometimes. + + This is a C{list} subclass to get past the type check in L{send1msg}, not as + an example of how real programs might want to interact with L{send1msg} (or + anything else). A custom C{list} subclass makes it easier to trigger + certain error cases in the implementation. + + @ivar iterate: A flag which indicates whether an instance of L{BadList} will + allow iteration over itself or not. If C{False}, an attempt to iterate + over the instance will raise an exception. + """ + iterate = True + + def __iter__(self): + """ + Allow normal list iteration, or raise an exception. + + If C{self.iterate} is C{True}, it will be flipped to C{False} and then + normal iteration will proceed. If C{self.iterate} is C{False}, + L{RuntimeError} is raised instead. + """ + if self.iterate: + self.iterate = False + return super(BadList, self).__iter__() + raise RuntimeError("Something bad happened") + + + +class WorseList(list): + """ + A list which at first gives the appearance of being iterable, but then + raises an exception. + + See L{BadList} for a warning about not writing code like this. + """ + def __iter__(self): + """ + Return an iterator which will raise an exception as soon as C{next} is + called on it. + """ + class BadIterator(object): + def next(self): + raise RuntimeError("This is a really bad case.") + return BadIterator() + + + +class SendmsgTestCase(TestCase): + """ + Tests for sendmsg extension module and associated file-descriptor sending + functionality. + """ + if nonUNIXSkip is not None: + skip = nonUNIXSkip + elif importSkip is not None: + skip = importSkip + + def setUp(self): + """ + Create a pair of UNIX sockets. + """ + self.input, self.output = socketpair(AF_UNIX) + + + def tearDown(self): + """ + Close the sockets opened by setUp. + """ + self.input.close() + self.output.close() + + + def test_sendmsgBadArguments(self): + """ + The argument types accepted by L{send1msg} are: + + 1. C{int} + 2. read-only character buffer + 3. C{int} + 4. sequence + + The 3rd and 4th arguments are optional. If fewer than two arguments or + more than four arguments are passed, or if any of the arguments passed + are not compatible with these types, L{TypeError} is raised. + """ + # Exercise the wrong number of arguments cases + self.assertRaises(TypeError, send1msg) + self.assertRaises(TypeError, send1msg, 1) + self.assertRaises(TypeError, send1msg, 1, "hello world", 2, [], object()) + + # Exercise the wrong type of arguments cases + self.assertRaises(TypeError, send1msg, object(), "hello world", 2, []) + self.assertRaises(TypeError, send1msg, 1, object(), 2, []) + self.assertRaises(TypeError, send1msg, 1, "hello world", object(), []) + self.assertRaises(TypeError, send1msg, 1, "hello world", 2, object()) + + + def test_badAncillaryIter(self): + """ + If iteration over the ancillary data list fails (at the point of the + C{__iter__} call), the exception with which it fails is propagated to + the caller of L{send1msg}. + """ + badList = BadList() + badList.append((1, 2, "hello world")) + badList.iterate = False + + self.assertRaises(RuntimeError, send1msg, 1, "hello world", 2, badList) + + # Hit the second iteration + badList.iterate = True + self.assertRaises(RuntimeError, send1msg, 1, "hello world", 2, badList) + + + def test_badAncillaryNext(self): + """ + If iteration over the ancillary data list fails (at the point of a + C{next} call), the exception with which it fails is propagated to the + caller of L{send1msg}. + """ + worseList = WorseList() + self.assertRaises(RuntimeError, send1msg, 1, "hello world", 2, worseList) + + + def test_sendmsgBadAncillaryItem(self): + """ + The ancillary data list contains three-tuples with element types of: + + 1. C{int} + 2. C{int} + 3. read-only character buffer + + If a tuple in the ancillary data list does not elements of these types, + L{TypeError} is raised. + """ + # Exercise the wrong number of arguments cases + self.assertRaises(TypeError, send1msg, 1, "hello world", 2, [()]) + self.assertRaises(TypeError, send1msg, 1, "hello world", 2, [(1,)]) + self.assertRaises(TypeError, send1msg, 1, "hello world", 2, [(1, 2)]) + self.assertRaises( + TypeError, + send1msg, 1, "hello world", 2, [(1, 2, "goodbye", object())]) + + # Exercise the wrong type of arguments cases + exc = self.assertRaises( + TypeError, send1msg, 1, "hello world", 2, [object()]) + self.assertEqual( + "send1msg argument 3 expected list of tuple, " + "got list containing object", + str(exc)) + self.assertRaises( + TypeError, + send1msg, 1, "hello world", 2, [(object(), 1, "goodbye")]) + self.assertRaises( + TypeError, + send1msg, 1, "hello world", 2, [(1, object(), "goodbye")]) + self.assertRaises( + TypeError, + send1msg, 1, "hello world", 2, [(1, 1, object())]) + + + def test_syscallError(self): + """ + If the underlying C{sendmsg} call fails, L{send1msg} raises + L{socket.error} with its errno set to the underlying errno value. + """ + probe = file(devnull) + fd = probe.fileno() + probe.close() + exc = self.assertRaises(error, send1msg, fd, "hello, world") + self.assertEqual(exc.args[0], errno.EBADF) + + + def test_syscallErrorWithControlMessage(self): + """ + The behavior when the underlying C{sendmsg} call fails is the same + whether L{send1msg} is passed ancillary data or not. + """ + probe = file(devnull) + fd = probe.fileno() + probe.close() + exc = self.assertRaises( + error, send1msg, fd, "hello, world", 0, [(0, 0, "0123")]) + self.assertEqual(exc.args[0], errno.EBADF) + + + def test_roundtrip(self): + """ + L{recv1msg} will retrieve a message sent via L{send1msg}. + """ + message = "hello, world!" + self.assertEqual( + len(message), + send1msg(self.input.fileno(), message, 0)) + + result = recv1msg(fd=self.output.fileno()) + self.assertEquals(result, (message, 0, [])) + + + def test_shortsend(self): + """ + L{send1msg} returns the number of bytes which it was able to send. + """ + message = "x" * 1024 * 1024 + self.input.setblocking(False) + sent = send1msg(self.input.fileno(), message) + # Sanity check - make sure we did fill the send buffer and then some + self.assertTrue(sent < len(message)) + received = recv1msg(self.output.fileno(), 0, len(message)) + self.assertEqual(len(received[0]), sent) + + + def test_roundtripEmptyAncillary(self): + """ + L{send1msg} treats an empty ancillary data list the same way it treats + receiving no argument for the ancillary parameter at all. + """ + send1msg(self.input.fileno(), "hello, world!", 0, []) + + result = recv1msg(fd=self.output.fileno()) + self.assertEquals(result, ("hello, world!", 0, [])) + + + def test_flags(self): + """ + The C{flags} argument to L{send1msg} is passed on to the underlying + C{sendmsg} call, to affect it in whatever way is defined by those flags. + """ + # Just exercise one flag with simple, well-known behavior. MSG_DONTWAIT + # makes the send a non-blocking call, even if the socket is in blocking + # mode. See also test_flags in RecvmsgTestCase + for i in range(1024): + try: + send1msg(self.input.fileno(), "x" * 1024, MSG_DONTWAIT) + except error, e: + self.assertEqual(e.args[0], errno.EAGAIN) + break + else: + self.fail( + "Failed to fill up the send buffer, " + "or maybe send1msg blocked for a while") + if dontWaitSkip is not None: + test_flags.skip = dontWaitSkip + + + def test_wrongTypeAncillary(self): + """ + L{send1msg} will show a helpful exception message when given the wrong + type of object for the 'ancillary' argument. + """ + error = self.assertRaises(TypeError, + send1msg, self.input.fileno(), + "hello, world!", 0, 4321) + self.assertEquals(str(error), + "send1msg argument 3 expected list, got int") + + + def spawn(self, script): + """ + Start a script that is a peer of this test as a subprocess. + + @param script: the module name of the script in this directory (no + package prefix, no '.py') + @type script: C{str} + + @rtype: L{StartStopProcessProtocol} + """ + sspp = StartStopProcessProtocol() + reactor.spawnProcess( + sspp, sys.executable, [ + sys.executable, + FilePath(__file__).sibling(script + ".py").path, + str(self.output.fileno()), + ], + environ, + childFDs={0: "w", 1: "r", 2: "r", + self.output.fileno(): self.output.fileno()} + ) + return sspp + + + @inlineCallbacks + def test_sendSubProcessFD(self): + """ + Calling L{sendsmsg} with SOL_SOCKET, SCM_RIGHTS, and a platform-endian + packed file descriptor number should send that file descriptor to a + different process, where it can be retrieved by using L{recv1msg}. + """ + sspp = self.spawn("pullpipe") + yield sspp.started + pipeOut, pipeIn = pipe() + self.addCleanup(close, pipeOut) + + send1msg( + self.input.fileno(), "blonk", 0, + [(SOL_SOCKET, SCM_RIGHTS, pack("i", pipeIn))]) + + close(pipeIn) + yield sspp.stopped + self.assertEquals(read(pipeOut, 1024), "Test fixture data: blonk.\n") + # Make sure that the pipe is actually closed now. + self.assertEquals(read(pipeOut, 1024), "") + + + +class RecvmsgTestCase(TestCase): + """ + Tests for L{recv1msg} (primarily error handling cases). + """ + if importSkip is not None: + skip = importSkip + + def test_badArguments(self): + """ + The argument types accepted by L{recv1msg} are: + + 1. C{int} + 2. C{int} + 3. C{int} + 4. C{int} + + The 2nd, 3rd, and 4th arguments are optional. If fewer than one + argument or more than four arguments are passed, or if any of the + arguments passed are not compatible with these types, L{TypeError} is + raised. + """ + # Exercise the wrong number of arguments cases + self.assertRaises(TypeError, recv1msg) + self.assertRaises(TypeError, recv1msg, 1, 2, 3, 4, object()) + + # Exercise the wrong type of arguments cases + self.assertRaises(TypeError, recv1msg, object(), 2, 3, 4) + self.assertRaises(TypeError, recv1msg, 1, object(), 3, 4) + self.assertRaises(TypeError, recv1msg, 1, 2, object(), 4) + self.assertRaises(TypeError, recv1msg, 1, 2, 3, object()) + + + def test_cmsgSpaceOverflow(self): + """ + L{recv1msg} raises L{OverflowError} if passed a value for the + C{cmsg_size} argument which exceeds C{SOCKLEN_MAX}. + """ + self.assertRaises(OverflowError, recv1msg, 0, 0, 0, 0x7FFFFFFF) + + + def test_syscallError(self): + """ + If the underlying C{recvmsg} call fails, L{recv1msg} raises + L{socket.error} with its errno set to the underlying errno value. + """ + probe = file(devnull) + fd = probe.fileno() + probe.close() + exc = self.assertRaises(error, recv1msg, fd) + self.assertEqual(exc.args[0], errno.EBADF) + + + def test_flags(self): + """ + The C{flags} argument to L{recv1msg} is passed on to the underlying + C{recvmsg} call, to affect it in whatever way is defined by those flags. + """ + # See test_flags in SendmsgTestCase + reader, writer = socketpair(AF_UNIX) + exc = self.assertRaises( + error, recv1msg, reader.fileno(), MSG_DONTWAIT) + self.assertEqual(exc.args[0], errno.EAGAIN) + if dontWaitSkip is not None: + test_flags.skip = dontWaitSkip + + + +class GetSocketFamilyTests(TestCase): + """ + Tests for L{getsockfam}, a helper which reveals the address family of an + arbitrary socket. + """ + if importSkip is not None: + skip = importSkip + + def _socket(self, addressFamily): + """ + Create a new socket using the given address family and return that + socket's file descriptor. The socket will automatically be closed when + the test is torn down. + """ + s = socket(addressFamily) + self.addCleanup(s.close) + return s.fileno() + + + def test_badArguments(self): + """ + L{getsockfam} accepts a single C{int} argument. If it is called in some + other way, L{TypeError} is raised. + """ + self.assertRaises(TypeError, getsockfam) + self.assertRaises(TypeError, getsockfam, 1, 2) + + self.assertRaises(TypeError, getsockfam, object()) + + + def test_syscallError(self): + """ + If the underlying C{getsockname} call fails, L{getsockfam} raises + L{socket.error} with its errno set to the underlying errno value. + """ + probe = file(devnull) + fd = probe.fileno() + probe.close() + exc = self.assertRaises(error, getsockfam, fd) + self.assertEqual(errno.EBADF, exc.args[0]) + + + def test_inet(self): + """ + When passed the file descriptor of a socket created with the C{AF_INET} + address family, L{getsockfam} returns C{AF_INET}. + """ + self.assertEqual(AF_INET, getsockfam(self._socket(AF_INET))) + + + def test_inet6(self): + """ + When passed the file descriptor of a socket created with the C{AF_INET6} + address family, L{getsockfam} returns C{AF_INET6}. + """ + self.assertEqual(AF_INET6, getsockfam(self._socket(AF_INET6))) + + + def test_unix(self): + """ + When passed the file descriptor of a socket created with the C{AF_UNIX} + address family, L{getsockfam} returns C{AF_UNIX}. + """ + self.assertEqual(AF_UNIX, getsockfam(self._socket(AF_UNIX))) + if nonUNIXSkip is not None: + test_unix.skip = nonUNIXSkip diff -Nru twisted-11.1.0/twisted/python/test/test_systemd.py twisted-12.1.0/twisted/python/test/test_systemd.py --- twisted-11.1.0/twisted/python/test/test_systemd.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/python/test/test_systemd.py 2012-04-04 21:03:05.000000000 +0000 @@ -0,0 +1,173 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Tests for L{twisted.python.systemd}. +""" + +import os + +from twisted.trial.unittest import TestCase +from twisted.python.systemd import ListenFDs + + +class InheritedDescriptorsMixin(object): + """ + Mixin for a L{TestCase} subclass which defines test methods for some kind of + systemd sd-daemon class. In particular, it defines tests for a + C{inheritedDescriptors} method. + """ + def test_inheritedDescriptors(self): + """ + C{inheritedDescriptors} returns a list of integers giving the file + descriptors which were inherited from systemd. + """ + sddaemon = self.getDaemon(7, 3) + self.assertEqual([7, 8, 9], sddaemon.inheritedDescriptors()) + + + def test_repeated(self): + """ + Any subsequent calls to C{inheritedDescriptors} return the same list. + """ + sddaemon = self.getDaemon(7, 3) + self.assertEqual( + sddaemon.inheritedDescriptors(), + sddaemon.inheritedDescriptors()) + + + +class MemoryOnlyMixin(object): + """ + Mixin for a L{TestCase} subclass which creates creating a fake, in-memory + implementation of C{inheritedDescriptors}. This provides verification that + the fake behaves in a compatible way with the real implementation. + """ + def getDaemon(self, start, count): + """ + Invent C{count} new I{file descriptors} (actually integers, attached to + no real file description), starting at C{start}. Construct and return a + new L{ListenFDs} which will claim those integers represent inherited + file descriptors. + """ + return ListenFDs(range(start, start + count)) + + + +class EnvironmentMixin(object): + """ + Mixin for a L{TestCase} subclass which creates a real implementation of + C{inheritedDescriptors} which is based on the environment variables set by + systemd. To facilitate testing, this mixin will also create a fake + environment dictionary and add keys to it to make it look as if some + descriptors have been inherited. + """ + def initializeEnvironment(self, count, pid): + """ + Create a copy of the process environment and add I{LISTEN_FDS} and + I{LISTEN_PID} (the environment variables set by systemd) to it. + """ + result = os.environ.copy() + result['LISTEN_FDS'] = str(count) + result['LISTEN_PID'] = str(pid) + return result + + + def getDaemon(self, start, count): + """ + Create a new L{ListenFDs} instance, initialized with a fake environment + dictionary which will be set up as systemd would have set it up if + C{count} descriptors were being inherited. The descriptors will also + start at C{start}. + """ + fakeEnvironment = self.initializeEnvironment(count, os.getpid()) + return ListenFDs.fromEnvironment(environ=fakeEnvironment, start=start) + + + +class MemoryOnlyTests(MemoryOnlyMixin, InheritedDescriptorsMixin, TestCase): + """ + Apply tests to L{ListenFDs}, explicitly constructed with some fake file + descriptors. + """ + + + +class EnvironmentTests(EnvironmentMixin, InheritedDescriptorsMixin, TestCase): + """ + Apply tests to L{ListenFDs}, constructed based on an environment dictionary. + """ + def test_secondEnvironment(self): + """ + Only a single L{Environment} can extract inherited file descriptors. + """ + fakeEnvironment = self.initializeEnvironment(3, os.getpid()) + first = ListenFDs.fromEnvironment(environ=fakeEnvironment) + second = ListenFDs.fromEnvironment(environ=fakeEnvironment) + self.assertEqual(range(3, 6), first.inheritedDescriptors()) + self.assertEqual([], second.inheritedDescriptors()) + + + def test_mismatchedPID(self): + """ + If the current process PID does not match the PID in the environment, no + inherited descriptors are reported. + """ + fakeEnvironment = self.initializeEnvironment(3, os.getpid() + 1) + sddaemon = ListenFDs.fromEnvironment(environ=fakeEnvironment) + self.assertEqual([], sddaemon.inheritedDescriptors()) + + + def test_missingPIDVariable(self): + """ + If the I{LISTEN_PID} environment variable is not present, no inherited + descriptors are reported. + """ + fakeEnvironment = self.initializeEnvironment(3, os.getpid()) + del fakeEnvironment['LISTEN_PID'] + sddaemon = ListenFDs.fromEnvironment(environ=fakeEnvironment) + self.assertEqual([], sddaemon.inheritedDescriptors()) + + + def test_nonIntegerPIDVariable(self): + """ + If the I{LISTEN_PID} environment variable is set to a string that cannot + be parsed as an integer, no inherited descriptors are reported. + """ + fakeEnvironment = self.initializeEnvironment(3, "hello, world") + sddaemon = ListenFDs.fromEnvironment(environ=fakeEnvironment) + self.assertEqual([], sddaemon.inheritedDescriptors()) + + + def test_missingFDSVariable(self): + """ + If the I{LISTEN_FDS} environment variable is not present, no inherited + descriptors are reported. + """ + fakeEnvironment = self.initializeEnvironment(3, os.getpid()) + del fakeEnvironment['LISTEN_FDS'] + sddaemon = ListenFDs.fromEnvironment(environ=fakeEnvironment) + self.assertEqual([], sddaemon.inheritedDescriptors()) + + + def test_nonIntegerFDSVariable(self): + """ + If the I{LISTEN_FDS} environment variable is set to a string that cannot + be parsed as an integer, no inherited descriptors are reported. + """ + fakeEnvironment = self.initializeEnvironment("hello, world", os.getpid()) + sddaemon = ListenFDs.fromEnvironment(environ=fakeEnvironment) + self.assertEqual([], sddaemon.inheritedDescriptors()) + + + def test_defaultEnviron(self): + """ + If the process environment is not explicitly passed to + L{Environment.__init__}, the real process environment dictionary is + used. + """ + self.patch(os, 'environ', { + 'LISTEN_PID': str(os.getpid()), + 'LISTEN_FDS': '5'}) + sddaemon = ListenFDs.fromEnvironment() + self.assertEqual(range(3, 3 + 5), sddaemon.inheritedDescriptors()) diff -Nru twisted-11.1.0/twisted/python/test/test_util.py twisted-12.1.0/twisted/python/test/test_util.py --- twisted-11.1.0/twisted/python/test/test_util.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/python/test/test_util.py 2012-03-10 15:16:07.000000000 +0000 @@ -119,20 +119,6 @@ "Group Name/GID conversion requires the grp module.") - def test_moduleMovedForSplitDeprecation(self): - """ - Calling L{moduleMovedForSplit} results in a deprecation warning. - """ - util.moduleMovedForSplit("foo", "bar", "baz", "quux", "corge", {}) - warnings = self.flushWarnings( - offendingFunctions=[self.test_moduleMovedForSplitDeprecation]) - self.assertEqual( - warnings[0]['message'], - "moduleMovedForSplit is deprecated since Twisted 9.0.") - self.assertEqual(warnings[0]['category'], DeprecationWarning) - self.assertEqual(len(warnings), 1) - - class SwitchUIDTest(unittest.TestCase): """ @@ -434,26 +420,6 @@ expected=None self.assertEqual(actual, expected) -class Foo: - def __init__(self, x): - self.x = x - -class DSU(unittest.TestCase): - """ - Tests for L{util.dsu} - """ - def test_dsu(self): - L = [Foo(x) for x in range(20, 9, -1)] - L2 = util.dsu(L, lambda o: o.x) - self.assertEqual(range(10, 21), [o.x for o in L2]) - - - def test_deprecation(self): - self.assertWarns(DeprecationWarning, - ("dsu is deprecated since Twisted 10.1. " - "Use the built-in sorted() instead."), - __file__, lambda: util.dsu([], lambda: 0)) - class IntervalDifferentialTestCase(unittest.TestCase): diff -Nru twisted-11.1.0/twisted/python/text.py twisted-12.1.0/twisted/python/text.py --- twisted-11.1.0/twisted/python/text.py 2011-06-08 23:11:41.000000000 +0000 +++ twisted-12.1.0/twisted/python/text.py 2012-03-12 23:05:49.000000000 +0000 @@ -8,9 +8,8 @@ Miscellany of text-munging functions. """ -import string, types - -from twisted.python import deprecate, versions +import string +import types def stringyString(object, indentation=''): @@ -76,49 +75,6 @@ return (s[-len('\n'):] == '\n') - -deprecate.deprecatedModuleAttribute( - versions.Version("Twisted", 10, 2, 0), - "Please use inspect.getdoc instead.", - __name__, "docstringLStrip") - - - -def docstringLStrip(docstring): - """ - Gets rid of unsightly lefthand docstring whitespace residue. - - You'd think someone would have done this already, but apparently - not in 1.5.2. - - BUT since we're all using Python 2.1 now, use L{inspect.getdoc} - instead. I{This function should go away soon.} - """ - - if not docstring: - return docstring - - docstring = string.replace(docstring, '\t', ' ' * 8) - lines = string.split(docstring,'\n') - - leading = 0 - for l in xrange(1,len(lines)): - line = lines[l] - if string.strip(line): - while 1: - if line[leading] == ' ': - leading = leading + 1 - else: - break - if leading: - break - - outlines = lines[0:1] - for l in xrange(1,len(lines)): - outlines.append(lines[l][leading:]) - - return string.join(outlines, '\n') - def greedyWrap(inString, width=80): """Given a string and a column width, return a list of lines. diff -Nru twisted-11.1.0/twisted/python/threadpool.py twisted-12.1.0/twisted/python/threadpool.py --- twisted-11.1.0/twisted/python/threadpool.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/python/threadpool.py 2012-02-11 11:29:31.000000000 +0000 @@ -2,26 +2,19 @@ # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. - """ -twisted.threadpool: a pool of threads to which we dispatch tasks. +twisted.python.threadpool: a pool of threads to which we dispatch tasks. -In most cases you can just use reactor.callInThread and friends +In most cases you can just use C{reactor.callInThread} and friends instead of creating a thread pool directly. """ -# System Imports import Queue import threading import copy -import sys -import warnings - -# Twisted Imports from twisted.python import log, context, failure -from twisted.python.deprecate import deprecatedModuleAttribute -from twisted.python.versions import Version + WorkerStop = object() @@ -31,9 +24,9 @@ This class (hopefully) generalizes the functionality of a pool of threads to which work can be dispatched. - callInThread() and stop() should only be called from - a single thread, unless you make a subclass where stop() and - _startSomeWorkers() are synchronized. + L{callInThread} and L{stop} should only be called from + a single thread, unless you make a subclass where L{stop} and + L{_startSomeWorkers} are synchronized. """ min = 5 max = 20 @@ -50,7 +43,6 @@ Create a new threadpool. @param minthreads: minimum number of threads in the pool - @param maxthreads: maximum number of threads in the pool """ assert minthreads >= 0, 'minimum is negative' @@ -63,6 +55,7 @@ self.threads = [] self.working = [] + def start(self): """ Start the threadpool. @@ -72,6 +65,7 @@ # Start some threads. self.adjustPoolsize() + def startAWorker(self): self.workers += 1 name = "PoolThread-%s-%s" % (self.name or id(self), self.workers) @@ -79,20 +73,24 @@ self.threads.append(newThread) newThread.start() + def stopAWorker(self): self.q.put(WorkerStop) self.workers -= 1 + def __setstate__(self, state): self.__dict__ = state ThreadPool.__init__(self, self.min, self.max) + def __getstate__(self): state = {} state['min'] = self.min state['max'] = self.max return state + def _startSomeWorkers(self): neededSize = self.q.qsize() + len(self.working) # Create enough, but not too many @@ -100,60 +98,48 @@ self.startAWorker() - def dispatch(self, owner, func, *args, **kw): - """ - DEPRECATED: use L{callInThread} instead. - - Dispatch a function to be a run in a thread. - """ - warnings.warn("dispatch() is deprecated since Twisted 8.0, " - "use callInThread() instead", - DeprecationWarning, stacklevel=2) - self.callInThread(func, *args, **kw) - - def callInThread(self, func, *args, **kw): """ Call a callable object in a separate thread. @param func: callable object to be called in separate thread - @param *args: positional arguments to be passed to func + @param *args: positional arguments to be passed to C{func} - @param **kw: keyword args to be passed to func + @param **kw: keyword args to be passed to C{func} """ self.callInThreadWithCallback(None, func, *args, **kw) def callInThreadWithCallback(self, onResult, func, *args, **kw): """ - Call a callable object in a separate thread and call onResult + Call a callable object in a separate thread and call C{onResult} with the return value, or a L{twisted.python.failure.Failure} if the callable raises an exception. - The callable is allowed to block, but the onResult function + The callable is allowed to block, but the C{onResult} function must not block and should perform as little work as possible. - A typical action for onResult for a threadpool used with a - Twisted reactor would be to schedule a Deferred to fire in the - main reactor thread using C{.callFromThread}. Note that - onResult is called inside the separate thread, not inside the - reactor thread. - - @param onResult: a callable with the signature (success, result). - If the callable returns normally, onResult is called with - (True, result) where result is the return value of the callable. - If the callable throws an exception, onResult is called with - (False, failure). + A typical action for C{onResult} for a threadpool used with a + Twisted reactor would be to schedule a + L{twisted.internet.defer.Deferred} to fire in the main + reactor thread using C{.callFromThread}. Note that C{onResult} + is called inside the separate thread, not inside the reactor thread. + + @param onResult: a callable with the signature C{(success, result)}. + If the callable returns normally, C{onResult} is called with + C{(True, result)} where C{result} is the return value of the + callable. If the callable throws an exception, C{onResult} is + called with C{(False, failure)}. - Optionally, onResult may be None, in which case it is not + Optionally, C{onResult} may be C{None}, in which case it is not called at all. @param func: callable object to be called in separate thread - @param *args: positional arguments to be passed to func + @param *args: positional arguments to be passed to C{func} - @param **kwargs: keyword arguments to be passed to func + @param **kwargs: keyword arguments to be passed to C{func} """ if self.joined: return @@ -164,35 +150,9 @@ self._startSomeWorkers() - def _runWithCallback(self, callback, errback, func, args, kwargs): - try: - result = apply(func, args, kwargs) - except: - errback(sys.exc_info()[1]) - else: - callback(result) - - - def dispatchWithCallback(self, owner, callback, errback, func, *args, **kw): - """ - DEPRECATED: use L{twisted.internet.threads.deferToThread} instead. - - Dispatch a function, returning the result to a callback function. - - The callback function will be called in the thread - make sure it is - thread-safe. - """ - warnings.warn("dispatchWithCallback() is deprecated since Twisted 8.0, " - "use twisted.internet.threads.deferToThread() instead.", - DeprecationWarning, stacklevel=2) - self.callInThread( - self._runWithCallback, callback, errback, func, args, kw - ) - - def _worker(self): """ - Method used as target of the created threads: retrieve task to run + Method used as target of the created threads: retrieve a task to run from the threadpool, run it, and proceed to the next task until threadpool is stopped. """ @@ -232,6 +192,7 @@ self.threads.remove(ct) + def stop(self): """ Shutdown the threads in the threadpool. @@ -247,6 +208,7 @@ for thread in threads: thread.join() + def adjustPoolsize(self, minthreads=None, maxthreads=None): if minthreads is None: minthreads = self.min @@ -270,44 +232,9 @@ # Start some threads if there is a need. self._startSomeWorkers() + def dumpStats(self): log.msg('queue: %s' % self.q.queue) log.msg('waiters: %s' % self.waiters) log.msg('workers: %s' % self.working) log.msg('total: %s' % self.threads) - - - -class ThreadSafeList: - """ - In Jython 2.1 lists aren't thread-safe, so this wraps it. Newer versions - of Jython are completely different than 2.1, so this class is deprecated - to make way for future versions of Jython. - """ - - deprecatedModuleAttribute( - Version("Twisted", 10, 1, 0), - "This was an internal implementation detail of support for Jython 2.1," - " which is now obsolete.", - __name__, "ThreadSafeList") - - def __init__(self): - self.lock = threading.Lock() - self.l = [] - - def append(self, i): - self.lock.acquire() - try: - self.l.append(i) - finally: - self.lock.release() - - def remove(self, i): - self.lock.acquire() - try: - self.l.remove(i) - finally: - self.lock.release() - - def __len__(self): - return len(self.l) diff -Nru twisted-11.1.0/twisted/python/util.py twisted-12.1.0/twisted/python/util.py --- twisted-11.1.0/twisted/python/util.py 2011-03-27 01:37:18.000000000 +0000 +++ twisted-12.1.0/twisted/python/util.py 2012-03-10 15:16:07.000000000 +0000 @@ -2,7 +2,7 @@ # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. -import os, sys, hmac, errno, inspect, warnings +import os, sys, errno, inspect, warnings import types try: import pwd, grp @@ -317,11 +317,6 @@ sys.stdin, sys.stdout = old -def dict(*a, **k): - import __builtin__ - warnings.warn('twisted.python.util.dict is deprecated. Use __builtin__.dict instead') - return __builtin__.dict(*a, **k) - def println(*a): sys.stdout.write(' '.join(map(str, a))+'\n') @@ -332,18 +327,10 @@ def str_xor(s, b): return ''.join([chr(ord(c) ^ b) for c in s]) -def keyed_md5(secret, challenge): - """ - Create the keyed MD5 string for the given secret and challenge. - """ - warnings.warn( - "keyed_md5() is deprecated. Use the stdlib module hmac instead.", - DeprecationWarning, stacklevel=2 - ) - return hmac.HMAC(secret, challenge).hexdigest() def makeStatBar(width, maxPosition, doneChar = '=', undoneChar = '-', currentChar = '>'): - """Creates a function that will return a string representing a progress bar. + """ + Creates a function that will return a string representing a progress bar. """ aValue = width / float(maxPosition) def statBar(position, force = 0, last = ['']): @@ -368,8 +355,11 @@ """ % (doneChar * 3, currentChar, undoneChar * 3, width, maxPosition, currentChar) return statBar + def spewer(frame, s, ignored): - """A trace function for sys.settrace that prints every function or method call.""" + """ + A trace function for sys.settrace that prints every function or method call. + """ from twisted.python import reflect if frame.f_locals.has_key('self'): se = frame.f_locals['self'] @@ -386,8 +376,10 @@ frame.f_code.co_filename, frame.f_lineno) + def searchupwards(start, files=[], dirs=[]): - """Walk upwards from start, looking for a directory containing + """ + Walk upwards from start, looking for a directory containing all files and directories given as arguments:: >>> searchupwards('.', ['foo.txt'], ['bar', 'bam']) @@ -447,18 +439,22 @@ """Empty the log""" self.log = [None]*self.size + def raises(exception, f, *args, **kwargs): - """Determine whether the given call raises the given exception""" + """ + Determine whether the given call raises the given exception. + """ try: f(*args, **kwargs) except exception: return 1 return 0 + class IntervalDifferential: """ Given a list of intervals, generate the amount of time to sleep between - \"instants\". + "instants". For example, given 7, 11 and 13, the three (infinite) sequences:: @@ -489,6 +485,7 @@ def __iter__(self): return _IntervalDifferentialIterator(self.intervals, self.default) + class _IntervalDifferentialIterator: def __init__(self, i, d): @@ -529,7 +526,7 @@ class FancyStrMixin: """ Set showAttributes to a sequence of strings naming attributes, OR - sequences of (attributeName, displayName, formatCharacter) + sequences of C{(attributeName, displayName, formatCharacter)}. """ showAttributes = () def __str__(self): @@ -565,19 +562,6 @@ -def dsu(list, key): - """ - decorate-sort-undecorate (aka "Schwartzian transform") - - DEPRECATED. Use the built-in C{sorted()} instead. - """ - warnings.warn(("dsu is deprecated since Twisted 10.1. " - "Use the built-in sorted() instead."), DeprecationWarning, stacklevel=2) - L2 = [(key(e), i, e) for (i, e) in zip(range(len(list)), list)] - L2.sort() - return [e[2] for e in L2] - - try: from twisted.python._initgroups import initgroups as _c_initgroups except ImportError: @@ -718,7 +702,9 @@ class SubclassableCStringIO(object): - """A wrapper around cStringIO to allow for subclassing""" + """ + A wrapper around cStringIO to allow for subclassing. + """ __csio = None def __init__(self, *a, **kw): @@ -767,15 +753,6 @@ def getvalue(self): return self.__csio.getvalue() -def moduleMovedForSplit(origModuleName, newModuleName, moduleDesc, - projectName, projectURL, globDict): - """ - No-op function; only present for backwards compatibility. There is no - reason to call this function. - """ - warnings.warn( - "moduleMovedForSplit is deprecated since Twisted 9.0.", - DeprecationWarning, stacklevel=2) def untilConcludes(f, *a, **kw): @@ -998,10 +975,9 @@ __all__ = [ "uniquify", "padTo", "getPluginDirs", "addPluginDir", "sibpath", - "getPassword", "dict", "println", "keyed_md5", "makeStatBar", - "OrderedDict", "InsensitiveDict", "spewer", "searchupwards", "LineLog", + "getPassword", "println", "makeStatBar", "OrderedDict", + "InsensitiveDict", "spewer", "searchupwards", "LineLog", "raises", "IntervalDifferential", "FancyStrMixin", "FancyEqMixin", - "dsu", "switchUID", "SubclassableCStringIO", "moduleMovedForSplit", - "unsignedID", "mergeFunctionMetadata", "nameToLabel", "uidFromString", - "gidFromString", "runAsEffectiveUser", "moduleMovedForSplit", + "switchUID", "SubclassableCStringIO", "unsignedID", "mergeFunctionMetadata", + "nameToLabel", "uidFromString", "gidFromString", "runAsEffectiveUser", ] diff -Nru twisted-11.1.0/twisted/python/win32.py twisted-12.1.0/twisted/python/win32.py --- twisted-11.1.0/twisted/python/win32.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/python/win32.py 2011-11-07 04:58:37.000000000 +0000 @@ -156,7 +156,7 @@ @rtype: C{str} """ if self.winError is not None: - return self.winError(errorcode)[1] + return self.winError(errorcode).strerror if self.formatMessage is not None: return self.formatMessage(errorcode) if self.errorTab is not None: diff -Nru twisted-11.1.0/twisted/python/zippath.py twisted-12.1.0/twisted/python/zippath.py --- twisted-11.1.0/twisted/python/zippath.py 2011-03-14 21:00:23.000000000 +0000 +++ twisted-12.1.0/twisted/python/zippath.py 2012-03-13 23:29:48.000000000 +0000 @@ -3,9 +3,7 @@ # See LICENSE for details. """ -This module contains partial re-implementations of FilePath, pending some -specification of formal interfaces it is a duck-typing attempt to emulate them -for certain restricted uses. +This module contains implementations of IFilePath for zip files. See the constructor for ZipArchive for use. """ @@ -27,7 +25,9 @@ _USE_ZIPFILE = False from twisted.python.zipstream import ChunkingZipFile -from twisted.python.filepath import FilePath, _PathHelper +from twisted.python.filepath import IFilePath, FilePath, AbstractFilePath + +from zope.interface import implements # using FilePath here exclusively rather than os to make sure that we don't do # anything OS-path-specific here. @@ -36,10 +36,15 @@ # path separator, regardless of platform. -class ZipPath(_PathHelper): +class ZipPath(AbstractFilePath): """ I represent a file or directory contained within a zip file. """ + + implements(IFilePath) + + sep = ZIP_PATH_SEP + def __init__(self, archive, pathInArchive): """ Don't construct me directly. Use ZipArchive.child(). @@ -136,15 +141,25 @@ # less meaningful here. return self.parent().path - def open(self): + def open(self, mode="r"): if _USE_ZIPFILE: - return self.archive.zipfile.open(self.pathInArchive) + return self.archive.zipfile.open(self.pathInArchive, mode=mode) else: + # XXX oh man, is this too much hax? + self.archive.zipfile.mode = mode return self.archive.zipfile.readfile(self.pathInArchive) - def restat(self): + def changed(self): pass + def getsize(self): + """ + Retrieve this file's size. + + @return: file size, in bytes + """ + + return self.archive.zipfile.NameToInfo[self.pathInArchive].file_size def getAccessTime(self): """ diff -Nru twisted-11.1.0/twisted/scripts/__init__.py twisted-12.1.0/twisted/scripts/__init__.py --- twisted-11.1.0/twisted/scripts/__init__.py 2011-10-12 12:08:56.000000000 +0000 +++ twisted-12.1.0/twisted/scripts/__init__.py 2012-02-19 20:39:01.000000000 +0000 @@ -11,10 +11,17 @@ from twisted.python.versions import Version from twisted.python.deprecate import deprecatedModuleAttribute + deprecatedModuleAttribute( Version("Twisted", 11, 1, 0), "Seek unzipping software outside of Twisted.", __name__, "tkunzip") +deprecatedModuleAttribute( + Version("Twisted", 12, 1, 0), + "tapconvert has been deprecated.", + __name__, + "tapconvert") + del Version, deprecatedModuleAttribute diff -Nru twisted-11.1.0/twisted/scripts/tap2rpm.py twisted-12.1.0/twisted/scripts/tap2rpm.py --- twisted-11.1.0/twisted/scripts/tap2rpm.py 2011-10-18 10:31:11.000000000 +0000 +++ twisted-12.1.0/twisted/scripts/tap2rpm.py 2012-03-13 21:08:17.000000000 +0000 @@ -7,8 +7,9 @@ import tempfile import tarfile from StringIO import StringIO +import warnings -from twisted.python import usage, log +from twisted.python import usage, log, versions, deprecate ################################# @@ -36,48 +37,48 @@ # check for required files if [ ! -x /usr/bin/twistd ] then - echo "$0: Aborting, no /usr/bin/twistd found" - exit 0 + echo "$0: Aborting, no /usr/bin/twistd found" + exit 0 fi if [ ! -r "$file" ] then - echo "$0: Aborting, no file $file found." - exit 0 + echo "$0: Aborting, no file $file found." + exit 0 fi # set up run directory if necessary if [ ! -d "${rundir}" ] then - mkdir -p "${rundir}" + mkdir -p "${rundir}" fi case "$1" in - start) - echo -n "Starting %(rpm_file)s: twistd" - daemon twistd \\ - --pidfile=$pidfile \\ - --rundir=$rundir \\ - --%(twistd_option)s=$file \\ - --logfile=$logfile - status %(rpm_file)s - ;; - - stop) - echo -n "Stopping %(rpm_file)s: twistd" - kill `cat "${pidfile}"` - status %(rpm_file)s - ;; - - restart) - "${0}" stop - "${0}" start - ;; + start) + echo -n "Starting %(rpm_file)s: twistd" + daemon twistd \\ + --pidfile=$pidfile \\ + --rundir=$rundir \\ + --%(twistd_option)s=$file \\ + --logfile=$logfile + status %(rpm_file)s + ;; + + stop) + echo -n "Stopping %(rpm_file)s: twistd" + kill `cat "${pidfile}"` + status %(rpm_file)s + ;; + + restart) + "${0}" stop + "${0}" start + ;; *) - echo "Usage: ${0} {start|stop|restart|}" >&2 - exit 1 - ;; + echo "Usage: ${0} {start|stop|restart|}" >&2 + exit 1 + ;; esac exit 0 @@ -106,7 +107,7 @@ %%install [ ! -z "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != '/' ] \ - && rm -rf "$RPM_BUILD_ROOT" + && rm -rf "$RPM_BUILD_ROOT" mkdir -p "$RPM_BUILD_ROOT"/etc/twisted-taps mkdir -p "$RPM_BUILD_ROOT"/etc/init.d mkdir -p "$RPM_BUILD_ROOT"/var/lib/twisted-taps @@ -115,7 +116,7 @@ %%clean [ ! -z "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != '/' ] \ - && rm -rf "$RPM_BUILD_ROOT" + && rm -rf "$RPM_BUILD_ROOT" %%post /sbin/chkconfig --add %(rpm_file)s @@ -138,7 +139,7 @@ ############################### class MyOptions(usage.Options): - optFlags = [["unsigned", "u"], ['quiet', 'q']] + optFlags = [['quiet', 'q']] optParameters = [ ["tapfile", "t", "twistd.tap"], ["maintainer", "m", "tap2rpm"], @@ -177,6 +178,18 @@ self['release-name'] = '%s-%s' % (self['rpmfile'], self['set-version']) + def opt_unsigned(self): + """ + Generate an unsigned rather than a signed RPM. (DEPRECATED; unsigned + is the default) + """ + msg = deprecate.getDeprecationWarningString( + self.opt_unsigned, versions.Version("Twisted", 12, 1, 0)) + warnings.warn(msg, category=DeprecationWarning, stacklevel=2) + + # Maintain the -u short flag + opt_u = opt_unsigned + type_dict = { 'tap': 'file', diff -Nru twisted-11.1.0/twisted/scripts/tapconvert.py twisted-12.1.0/twisted/scripts/tapconvert.py --- twisted-11.1.0/twisted/scripts/tapconvert.py 2011-10-18 10:31:11.000000000 +0000 +++ twisted-12.1.0/twisted/scripts/tapconvert.py 2012-02-19 20:39:01.000000000 +0000 @@ -1,10 +1,12 @@ # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. +import sys, getpass + from twisted.python import usage from twisted.application import app from twisted.persisted import sob -import sys, getpass + class ConvertOptions(usage.Options): synopsis = "Usage: tapconvert [options]" diff -Nru twisted-11.1.0/twisted/scripts/test/test_scripts.py twisted-12.1.0/twisted/scripts/test/test_scripts.py --- twisted-11.1.0/twisted/scripts/test/test_scripts.py 2011-10-21 13:15:37.000000000 +0000 +++ twisted-12.1.0/twisted/scripts/test/test_scripts.py 2012-02-19 20:39:01.000000000 +0000 @@ -147,6 +147,21 @@ self.assertEqual(1, len(warnings)) + def test_deprecatedTapconvert(self): + """ + The entire L{twisted.scripts.tapconvert} module is deprecated. + """ + from twisted.scripts import tapconvert + warnings = self.flushWarnings( + offendingFunctions=[self.test_deprecatedTapconvert]) + self.assertEqual(DeprecationWarning, warnings[0]['category']) + self.assertEqual( + "twisted.scripts.tapconvert was deprecated in Twisted 12.1.0: " + "tapconvert has been deprecated.", + warnings[0]['message']) + self.assertEqual(1, len(warnings)) + + class ZshIntegrationTestCase(TestCase, ZshScriptTestMixin): """ diff -Nru twisted-11.1.0/twisted/scripts/test/test_tap2rpm.py twisted-12.1.0/twisted/scripts/test/test_tap2rpm.py --- twisted-11.1.0/twisted/scripts/test/test_tap2rpm.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/scripts/test/test_tap2rpm.py 2012-03-13 21:08:17.000000000 +0000 @@ -5,8 +5,11 @@ Tests for L{twisted.scripts.tap2rpm}. """ import os + from twisted.trial.unittest import TestCase, SkipTest from twisted.python import procutils +from twisted.python import versions +from twisted.python import deprecate from twisted.python.failure import Failure from twisted.internet import utils from twisted.scripts import tap2rpm @@ -378,3 +381,19 @@ # Try and make an RPM from that tapfile. _makeRPMs(tapfile=tapfile) + + + def test_unsignedFlagDeprecationWarning(self): + """ + The 'unsigned' flag in tap2rpm should be deprecated, and its use + should raise a warning as such. + """ + config = tap2rpm.MyOptions() + config.parseOptions(['--unsigned']) + warnings = self.flushWarnings() + self.assertEqual(DeprecationWarning, warnings[0]['category']) + self.assertEqual( + deprecate.getDeprecationWarningString( + config.opt_unsigned, versions.Version("Twisted", 12, 1, 0)), + warnings[0]['message']) + self.assertEqual(1, len(warnings)) diff -Nru twisted-11.1.0/twisted/scripts/_twistd_unix.py twisted-12.1.0/twisted/scripts/_twistd_unix.py --- twisted-11.1.0/twisted/scripts/_twistd_unix.py 2011-10-18 10:31:11.000000000 +0000 +++ twisted-12.1.0/twisted/scripts/_twistd_unix.py 2012-01-23 22:55:41.000000000 +0000 @@ -7,6 +7,7 @@ from twisted.python import log, syslog, logfile, usage from twisted.python.util import switchUID, uidFromString, gidFromString from twisted.application import app, service +from twisted.internet.interfaces import IReactorDaemonize from twisted import copyright @@ -155,8 +156,26 @@ -def daemonize(): - # See http://www.erlenstar.demon.co.uk/unix/faq_toc.html#TOC16 +def daemonize(reactor, os): + """ + Daemonizes the application on Unix. This is done by the usual double + forking approach. + + @see: U{http://code.activestate.com/recipes/278731/} + @see: W. Richard Stevens, "Advanced Programming in the Unix Environment", + 1992, Addison-Wesley, ISBN 0-201-56317-7 + + @param reactor: The reactor in use. If it provides L{IReactorDaemonize}, + its daemonization-related callbacks will be invoked. + + @param os: An object like the os module to use to perform the daemonization. + """ + + ## If the reactor requires hooks to be called for daemonization, call them. + ## Currently the only reactor which provides/needs that is KQueueReactor. + if IReactorDaemonize.providedBy(reactor): + reactor.beforeDaemonize() + if os.fork(): # launch child and... os._exit(0) # kill off parent os.setsid() @@ -171,6 +190,9 @@ raise os.close(null) + if IReactorDaemonize.providedBy(reactor): + reactor.afterDaemonize() + def launchWithName(name): @@ -265,7 +287,8 @@ if umask is not None: os.umask(umask) if daemon: - daemonize() + from twisted.internet import reactor + daemonize(reactor, os) if pidfile: f = open(pidfile,'wb') f.write(str(os.getpid())) diff -Nru twisted-11.1.0/twisted/spread/pb.py twisted-12.1.0/twisted/spread/pb.py --- twisted-11.1.0/twisted/spread/pb.py 2011-10-11 11:35:34.000000000 +0000 +++ twisted-12.1.0/twisted/spread/pb.py 2011-11-14 18:11:49.000000000 +0000 @@ -34,8 +34,6 @@ # Twisted Imports from twisted.python import log, failure, reflect -from twisted.python.versions import Version -from twisted.python.deprecate import deprecated from twisted.python.hashlib import md5 from twisted.internet import defer, protocol from twisted.cred.portal import Portal @@ -131,10 +129,12 @@ class RemoteMethod: - """This is a translucent reference to a remote message. + """ + This is a translucent reference to a remote message. """ def __init__(self, obj, name): - """Initialize with a L{RemoteReference} and the name of this message. + """ + Initialize with a L{RemoteReference} and the name of this message. """ self.obj = obj self.name = name @@ -149,20 +149,11 @@ def __call__(self, *args, **kw): - """Asynchronously invoke a remote method. """ - return self.obj.broker._sendMessage('',self.obj.perspective, self.obj.luid, self.name, args, kw) - - - -def noOperation(*args, **kw): - """ - Do nothing. - - Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, - consectetur, adipisci velit... - """ -noOperation = deprecated(Version("twisted", 8, 2, 0))(noOperation) + Asynchronously invoke a remote method. + """ + return self.obj.broker._sendMessage('',self.obj.perspective, + self.obj.luid, self.name, args, kw) @@ -171,16 +162,6 @@ -def printTraceback(tb): - """ - Print a traceback (string) to the standard log. - """ - log.msg('Perspective Broker Traceback:' ) - log.msg(tb) -printTraceback = deprecated(Version("twisted", 8, 2, 0))(printTraceback) - - - class IPerspective(Interface): """ per*spec*tive, n. : The relationship of aspects of a subject to each diff -Nru twisted-11.1.0/twisted/spread/refpath.py twisted-12.1.0/twisted/spread/refpath.py --- twisted-11.1.0/twisted/spread/refpath.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/spread/refpath.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,95 +0,0 @@ -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -""" -Path-based references for PB, and other reference-based protocols. - -Maintainer: Glyph Lefkowitz -""" - - -from copy import copy -import os, warnings - -from twisted.python import log -from twisted.spread.flavors import Referenceable, Viewable - -warnings.warn( - "twisted.spread.refpath is deprecated since Twisted 9.0.", - category=DeprecationWarning, stacklevel=2) - -### "Server"-side objects - -class PathReferenceContext: - def __init__(self, path, root): - self.metadata = {} - self.path = path - self.root = root - - def __setitem__(self, key, item): - self.metadata[key] = item - - def __getitem__(self, key): - return self.metadata[key] - - def getObject(self): - o = self.root - for p in self.path: - o = o.getChild(p, self) - return o - -class PathReference: - def __init__(self): - self.children = {} - def getChild(self, child, ctx): - return self.children[child] - -class PathReferenceDirectory(Referenceable): - def __init__(self, root, prefix="remote"): - self.root = root - self.prefix = prefix - def remote_callPath(self, path, name, *args, **kw): - ctx = PathReferenceContext(path, self) - obj = ctx.getObject() - return apply(getattr(obj, "%s_%s" % (self.prefix, name)), args, kw) - -class PathReferenceContextDirectory(Referenceable): - def __init__(self, root, prefix="remote"): - self.root = root - self.prefix = prefix - def remote_callPath(self, path, name, *args, **kw): - ctx = PathReferenceContext(path, self) - obj = ctx.getObject() - return apply(getattr(obj, "%s_%s" % (self.prefix, name)), - (ctx,)+args, kw) - -class PathViewDirectory(Viewable): - def __init__(self, root, prefix="view"): - self.root = root - self.prefix = prefix - def view_callPath(self, perspective, path, name, *args, **kw): - ctx = PathReferenceContext(path, self) - obj = ctx.getObject() - return apply(getattr(obj, "%s_%s" % (self.prefix, name)), - (perspective,)+args, kw) - -class PathViewContextDirectory(Viewable): - def __init__(self, root, prefix="view"): - self.root = root - self.prefix = prefix - def view_callPath(self, perspective, path, name, *args, **kw): - ctx = PathReferenceContext(path, self) - obj = ctx.getObject() - return apply(getattr(obj, "%s_%s" % (self.prefix, name)), - (perspective,ctx)+args, kw) - -### "Client"-side objects - -class RemotePathReference: - def __init__(self, ref, path): - self.ref = ref - self.path = path - - def callRemote(self, name, *args, **kw): - apply(self.ref.callRemote, - ("callPath", self.path, name)+args, kw) diff -Nru twisted-11.1.0/twisted/test/_preamble.py twisted-12.1.0/twisted/test/_preamble.py --- twisted-11.1.0/twisted/test/_preamble.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-12.1.0/twisted/test/_preamble.py 2012-01-23 22:55:41.000000000 +0000 @@ -0,0 +1,17 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +# This makes sure Twisted-using child processes used in the test suite import +# the correct version of Twisted (ie, the version of Twisted under test). + +# This is a copy of the bin/_preamble.py script because it's not clear how to +# use the functionality for both things without having a copy. + +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-11.1.0/twisted/test/proto_helpers.py twisted-12.1.0/twisted/test/proto_helpers.py --- twisted-11.1.0/twisted/test/proto_helpers.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/test/proto_helpers.py 2012-04-10 05:13:02.000000000 +0000 @@ -6,13 +6,15 @@ Assorted functionality which is commonly useful when writing unit tests. """ +from socket import AF_INET, AF_INET6 from StringIO import StringIO from zope.interface import implements -from twisted.internet.interfaces import ITransport, IConsumer, IPushProducer,\ - IConnector -from twisted.internet.interfaces import IReactorTCP, IReactorSSL, IReactorUNIX +from twisted.internet.interfaces import ( + ITransport, IConsumer, IPushProducer, IConnector) +from twisted.internet.interfaces import ( + IReactorTCP, IReactorSSL, IReactorUNIX, IReactorSocket) from twisted.internet.interfaces import IListeningPort from twisted.protocols import basic from twisted.internet import protocol, error, address @@ -304,7 +306,7 @@ """ A fake L{IConnector} that allows us to inspect if it has been told to stop connecting. - + @ivar stoppedConnecting: has this connector's L{FakeConnector.stopConnecting} method been invoked yet? @@ -380,8 +382,11 @@ @ivar unixServers: a list that keeps track of server listen attempts (ie, calls to C{listenUNIX}). @type unixServers: C{list} + + @ivar adoptedPorts: a list that keeps track of server listen attempts (ie, + calls to C{adoptStreamPort}). """ - implements(IReactorTCP, IReactorSSL, IReactorUNIX) + implements(IReactorTCP, IReactorSSL, IReactorUNIX, IReactorSocket) def __init__(self): """ @@ -393,6 +398,23 @@ self.sslServers = [] self.unixClients = [] self.unixServers = [] + self.adoptedPorts = [] + + + def adoptStreamPort(self, fileno, addressFamily, factory): + """ + Fake L{IReactorSocket.adoptStreamPort}, that logs the call and returns + an L{IListeningPort}. + """ + if addressFamily == AF_INET: + addr = IPv4Address('TCP', '0.0.0.0', 1234) + elif addressFamily == AF_INET6: + addr = IPv6Address('TCP', '::', 1234) + else: + raise UnsupportedAddressFamily() + + self.adoptedPorts.append((fileno, addressFamily, factory)) + return _FakePort(addr) def listenTCP(self, port, factory, backlog=50, interface=''): @@ -410,7 +432,9 @@ L{IConnector}. """ self.tcpClients.append((host, port, factory, timeout, bindAddress)) - return _FakeConnector(IPv4Address('TCP', host, port)) + conn = _FakeConnector(IPv4Address('TCP', host, port)) + factory.startedConnecting(conn) + return conn def listenSSL(self, port, factory, contextFactory, @@ -432,7 +456,9 @@ """ self.sslClients.append((host, port, factory, contextFactory, timeout, bindAddress)) - return _FakeConnector(IPv4Address('TCP', host, port)) + conn = _FakeConnector(IPv4Address('TCP', host, port)) + factory.startedConnecting(conn) + return conn def listenUNIX(self, address, factory, @@ -451,7 +477,9 @@ L{IConnector}. """ self.unixClients.append((address, factory, timeout, checkPID)) - return _FakeConnector(UNIXAddress(address)) + conn = _FakeConnector(UNIXAddress(address)) + factory.startedConnecting(conn) + return conn @@ -463,7 +491,7 @@ @ivar _listenException: An instance of an L{Exception} @ivar _connectException: An instance of an L{Exception} """ - implements(IReactorTCP, IReactorSSL, IReactorUNIX) + implements(IReactorTCP, IReactorSSL, IReactorUNIX, IReactorSocket) def __init__(self, listenException=None, connectException=None): """ @@ -477,6 +505,14 @@ self._connectException = connectException + def adoptStreamPort(self, fileno, addressFamily, factory): + """ + Fake L{IReactorSocket.adoptStreamPort}, that raises + L{self._listenException}. + """ + raise self._listenException + + def listenTCP(self, port, factory, backlog=50, interface=''): """ Fake L{reactor.listenTCP}, that raises L{self._listenException}. diff -Nru twisted-11.1.0/twisted/test/stdio_test_consumer.py twisted-12.1.0/twisted/test/stdio_test_consumer.py --- twisted-11.1.0/twisted/test/stdio_test_consumer.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/test/stdio_test_consumer.py 2012-01-23 22:55:41.000000000 +0000 @@ -8,7 +8,7 @@ that process transports implement IConsumer properly. """ -import sys +import sys, _preamble from twisted.python import log, reflect from twisted.internet import stdio, protocol diff -Nru twisted-11.1.0/twisted/test/stdio_test_halfclose.py twisted-12.1.0/twisted/test/stdio_test_halfclose.py --- twisted-11.1.0/twisted/test/stdio_test_halfclose.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/test/stdio_test_halfclose.py 2012-01-23 22:55:41.000000000 +0000 @@ -9,7 +9,7 @@ transports. """ -import sys +import sys, _preamble from zope.interface import implements diff -Nru twisted-11.1.0/twisted/test/stdio_test_hostpeer.py twisted-12.1.0/twisted/test/stdio_test_hostpeer.py --- twisted-11.1.0/twisted/test/stdio_test_hostpeer.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/test/stdio_test_hostpeer.py 2012-01-23 22:55:41.000000000 +0000 @@ -8,7 +8,7 @@ that ITransport.getHost() and ITransport.getPeer() work for process transports. """ -import sys +import sys, _preamble from twisted.internet import stdio, protocol from twisted.python import reflect diff -Nru twisted-11.1.0/twisted/test/stdio_test_lastwrite.py twisted-12.1.0/twisted/test/stdio_test_lastwrite.py --- twisted-11.1.0/twisted/test/stdio_test_lastwrite.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/test/stdio_test_lastwrite.py 2012-01-23 22:55:41.000000000 +0000 @@ -9,7 +9,7 @@ L{twisted.internet.stdio.StandardIO} has finished. """ -import sys +import sys, _preamble from twisted.internet.protocol import Protocol from twisted.internet.stdio import StandardIO diff -Nru twisted-11.1.0/twisted/test/stdio_test_loseconn.py twisted-12.1.0/twisted/test/stdio_test_loseconn.py --- twisted-11.1.0/twisted/test/stdio_test_loseconn.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/test/stdio_test_loseconn.py 2012-01-23 22:55:41.000000000 +0000 @@ -8,7 +8,7 @@ test that ITransport.loseConnection() works for process transports. """ -import sys +import sys, _preamble from twisted.internet.error import ConnectionDone from twisted.internet import stdio, protocol diff -Nru twisted-11.1.0/twisted/test/stdio_test_producer.py twisted-12.1.0/twisted/test/stdio_test_producer.py --- twisted-11.1.0/twisted/test/stdio_test_producer.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/test/stdio_test_producer.py 2012-01-23 22:55:41.000000000 +0000 @@ -8,7 +8,7 @@ that process transports implement IProducer properly. """ -import sys +import sys, _preamble from twisted.internet import stdio, protocol from twisted.python import log, reflect diff -Nru twisted-11.1.0/twisted/test/stdio_test_write.py twisted-12.1.0/twisted/test/stdio_test_write.py --- twisted-11.1.0/twisted/test/stdio_test_write.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/test/stdio_test_write.py 2012-01-23 22:55:41.000000000 +0000 @@ -8,7 +8,7 @@ ITransport.write() works for process transports. """ -import sys +import sys, _preamble from twisted.internet import stdio, protocol from twisted.python import reflect @@ -29,4 +29,3 @@ from twisted.internet import reactor stdio.StandardIO(WriteChild()) reactor.run() - diff -Nru twisted-11.1.0/twisted/test/stdio_test_writeseq.py twisted-12.1.0/twisted/test/stdio_test_writeseq.py --- twisted-11.1.0/twisted/test/stdio_test_writeseq.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/test/stdio_test_writeseq.py 2012-01-23 22:55:41.000000000 +0000 @@ -8,7 +8,7 @@ ITransport.writeSequence() works for process transports. """ -import sys +import sys, _preamble from twisted.internet import stdio, protocol from twisted.python import reflect diff -Nru twisted-11.1.0/twisted/test/test_adbapi.py twisted-12.1.0/twisted/test/test_adbapi.py --- twisted-11.1.0/twisted/test/test_adbapi.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_adbapi.py 2012-01-06 13:16:05.000000000 +0000 @@ -11,9 +11,8 @@ import os, stat import types -from twisted.enterprise.adbapi import ConnectionPool, ConnectionLost, safe +from twisted.enterprise.adbapi import ConnectionPool, ConnectionLost from twisted.enterprise.adbapi import Connection, Transaction -from twisted.enterprise.adbapi import _unreleasedVersion from twisted.internet import reactor, defer, interfaces from twisted.python.failure import Failure @@ -570,23 +569,6 @@ -class DeprecationTestCase(unittest.TestCase): - """ - Test deprecations in twisted.enterprise.adbapi - """ - - def test_safe(self): - """ - Test deprecation of twisted.enterprise.adbapi.safe() - """ - result = self.callDeprecated(_unreleasedVersion, - safe, "test'") - - # make sure safe still behaves like the original - self.assertEqual(result, "test''") - - - class FakePool(object): """ A fake L{ConnectionPool} for tests. diff -Nru twisted-11.1.0/twisted/test/test_amp.py twisted-12.1.0/twisted/test/test_amp.py --- twisted-11.1.0/twisted/test/test_amp.py 2011-09-23 12:30:19.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_amp.py 2012-05-04 19:53:52.000000000 +0000 @@ -9,7 +9,8 @@ import datetime import decimal -from zope.interface.verify import verifyObject +from zope.interface import implements +from zope.interface.verify import verifyClass, verifyObject from twisted.python.util import setIDFunction from twisted.python import filepath @@ -2946,6 +2947,145 @@ +class UNIXStringTransport(object): + """ + An in-memory implementation of L{interfaces.IUNIXTransport} which collects + all data given to it for later inspection. + + @ivar _queue: A C{list} of the data which has been given to this transport, + eg via C{write} or C{sendFileDescriptor}. Elements are two-tuples of a + string (identifying the destination of the data) and the data itself. + """ + implements(interfaces.IUNIXTransport) + + def __init__(self, descriptorFuzz): + """ + @param descriptorFuzz: An offset to apply to descriptors. + @type descriptorFuzz: C{int} + """ + self._fuzz = descriptorFuzz + self._queue = [] + + + def sendFileDescriptor(self, descriptor): + self._queue.append(( + 'fileDescriptorReceived', descriptor + self._fuzz)) + + + def write(self, data): + self._queue.append(('dataReceived', data)) + + + def writeSequence(self, seq): + for data in seq: + self.write(data) + + + def loseConnection(self): + self._queue.append(('connectionLost', Failure(ConnectionLost()))) + + + def getHost(self): + return UNIXAddress('/tmp/some-path') + + + def getPeer(self): + return UNIXAddress('/tmp/another-path') + +# Minimal evidence that we got the signatures right +verifyClass(interfaces.ITransport, UNIXStringTransport) +verifyClass(interfaces.IUNIXTransport, UNIXStringTransport) + + +class DescriptorTests(unittest.TestCase): + """ + Tests for L{amp.Descriptor}, an argument type for passing a file descriptor + over an AMP connection over a UNIX domain socket. + """ + def setUp(self): + self.fuzz = 3 + self.transport = UNIXStringTransport(descriptorFuzz=self.fuzz) + self.protocol = amp.BinaryBoxProtocol( + amp.BoxDispatcher(amp.CommandLocator())) + self.protocol.makeConnection(self.transport) + + + def test_fromStringProto(self): + """ + L{Descriptor.fromStringProto} constructs a file descriptor value by + extracting a previously received file descriptor corresponding to the + wire value of the argument from the L{_DescriptorExchanger} state of the + protocol passed to it. + + This is a whitebox test which involves direct L{_DescriptorExchanger} + state inspection. + """ + argument = amp.Descriptor() + self.protocol.fileDescriptorReceived(5) + self.protocol.fileDescriptorReceived(3) + self.protocol.fileDescriptorReceived(1) + self.assertEqual( + 5, argument.fromStringProto("0", self.protocol)) + self.assertEqual( + 3, argument.fromStringProto("1", self.protocol)) + self.assertEqual( + 1, argument.fromStringProto("2", self.protocol)) + self.assertEqual({}, self.protocol._descriptors) + + + def test_toStringProto(self): + """ + To send a file descriptor, L{Descriptor.toStringProto} uses the + L{IUNIXTransport.sendFileDescriptor} implementation of the transport of + the protocol passed to it to copy the file descriptor. Each subsequent + descriptor sent over a particular AMP connection is assigned the next + integer value, starting from 0. The base ten string representation of + this value is the byte encoding of the argument. + + This is a whitebox test which involves direct L{_DescriptorExchanger} + state inspection and mutation. + """ + argument = amp.Descriptor() + self.assertEqual("0", argument.toStringProto(2, self.protocol)) + self.assertEqual( + ("fileDescriptorReceived", 2 + self.fuzz), self.transport._queue.pop(0)) + self.assertEqual("1", argument.toStringProto(4, self.protocol)) + self.assertEqual( + ("fileDescriptorReceived", 4 + self.fuzz), self.transport._queue.pop(0)) + self.assertEqual("2", argument.toStringProto(6, self.protocol)) + self.assertEqual( + ("fileDescriptorReceived", 6 + self.fuzz), self.transport._queue.pop(0)) + self.assertEqual({}, self.protocol._descriptors) + + + def test_roundTrip(self): + """ + L{amp.Descriptor.fromBox} can interpret an L{amp.AmpBox} constructed by + L{amp.Descriptor.toBox} to reconstruct a file descriptor value. + """ + name = "alpha" + strings = {} + descriptor = 17 + sendObjects = {name: descriptor} + + argument = amp.Descriptor() + argument.toBox(name, strings, sendObjects.copy(), self.protocol) + + receiver = amp.BinaryBoxProtocol( + amp.BoxDispatcher(amp.CommandLocator())) + for event in self.transport._queue: + getattr(receiver, event[0])(*event[1:]) + + receiveObjects = {} + argument.fromBox(name, strings.copy(), receiveObjects, receiver) + + # Make sure we got the descriptor. Adjust by fuzz to be more convincing + # of having gone through L{IUNIXTransport.sendFileDescriptor}, not just + # converted to a string and then parsed back into an integer. + self.assertEqual(descriptor + self.fuzz, receiveObjects[name]) + + + class DateTimeTests(unittest.TestCase): """ Tests for L{amp.DateTime}, L{amp._FixedOffsetTZInfo}, and L{amp.utc}. diff -Nru twisted-11.1.0/twisted/test/test_application.py twisted-12.1.0/twisted/test/test_application.py --- twisted-11.1.0/twisted/test/test_application.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_application.py 2012-04-10 05:13:02.000000000 +0000 @@ -584,7 +584,7 @@ """ reactor = MemoryReactor() - factory = object() + factory = protocol.ClientFactory() t = internet.TCPClient('127.0.0.1', 1234, factory, reactor=reactor) t.startService() self.assertEqual( @@ -598,7 +598,7 @@ """ reactor = MemoryReactor() - factory = object() + factory = protocol.Factory() t = internet.TCPServer(1234, factory, reactor=reactor) t.startService() self.assertEqual(reactor.tcpServers.pop()[:2], (1234, factory)) @@ -614,7 +614,7 @@ """ reactor = MemoryReactor() - factory = object() + factory = protocol.ClientFactory() t = internet.TCPClient('127.0.0.1', 1234, factory, reactor=reactor) t.startService() self.assertEqual( diff -Nru twisted-11.1.0/twisted/test/test_enterprise.py twisted-12.1.0/twisted/test/test_enterprise.py --- twisted-11.1.0/twisted/test/test_enterprise.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_enterprise.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -""" -General tests for twisted.enterprise. -""" - -from twisted.trial import unittest - -from twisted.enterprise import util - -class QuotingTestCase(unittest.TestCase): - - def testQuoting(self): - for value, typ, expected in [ - (12, "integer", "12"), - ("foo'd", "text", "'foo''d'"), - ("\x00abc\\s\xFF", "bytea", "'\\\\000abc\\\\\\\\s\\377'"), - (12, "text", "'12'"), - (u"123'456", "text", u"'123''456'") - ]: - self.assertEqual( - self.callDeprecated(util._deprecatedVersion, util.quote, value, - typ), - expected) - - - def test_safeDeprecation(self): - """ - L{safe} is deprecated. - """ - self.callDeprecated(util._deprecatedVersion, util.safe, "foo") - - - def test_getKeyColumnDeprecation(self): - """ - L{getKeyColumn} is deprecated. - """ - class Row(object): - rowKeyColumns = () - self.callDeprecated(util._deprecatedVersion, util.getKeyColumn, Row, "foo") diff -Nru twisted-11.1.0/twisted/test/test_epoll.py twisted-12.1.0/twisted/test/test_epoll.py --- twisted-11.1.0/twisted/test/test_epoll.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_epoll.py 2012-02-19 19:24:21.000000000 +0000 @@ -80,7 +80,6 @@ self.assertRaises(TypeError, _epoll.epoll, ()) self.assertRaises(TypeError, _epoll.epoll, ['foo']) self.assertRaises(TypeError, _epoll.epoll, {}) - self.assertRaises(TypeError, _epoll.epoll) def test_add(self): diff -Nru twisted-11.1.0/twisted/test/test_ftp.py twisted-12.1.0/twisted/test/test_ftp.py --- twisted-11.1.0/twisted/test/test_ftp.py 2011-09-18 20:01:39.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_ftp.py 2012-01-15 18:31:09.000000000 +0000 @@ -546,6 +546,39 @@ return d + def test_downloadFolder(self): + """ + When RETR is called for a folder, it will fail complaining that + the path is a folder. + """ + # Make a directory in the current working directory + self.dirPath.child('foo').createDirectory() + # Login + d = self._anonymousLogin() + d.addCallback(self._makeDataConnection) + + def retrFolder(downloader): + downloader.transport.loseConnection() + deferred = self.client.queueStringCommand('RETR foo') + return deferred + d.addCallback(retrFolder) + + def failOnSuccess(result): + raise AssertionError('Downloading a folder should not succeed.') + d.addCallback(failOnSuccess) + + def checkError(failure): + failure.trap(ftp.CommandFailed) + self.assertEqual( + ['550 foo: is a directory'], failure.value.message) + current_errors = self.flushLoggedErrors() + self.assertEqual( + 0, len(current_errors), + 'No errors should be logged while downloading a folder.') + d.addErrback(checkError) + return d + + def test_NLSTEmpty(self): """ NLST with no argument returns the directory listing for the current diff -Nru twisted-11.1.0/twisted/test/test_htb.py twisted-12.1.0/twisted/test/test_htb.py --- twisted-11.1.0/twisted/test/test_htb.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_htb.py 2012-01-17 02:37:22.000000000 +0000 @@ -33,7 +33,7 @@ fit = b.add(1000) self.assertEqual(100, fit) - def testBucketDrian(self): + def testBucketDrain(self): """Testing the bucket's drain rate.""" b = SomeBucket() fit = b.add(1000) @@ -41,6 +41,19 @@ fit = b.add(1000) self.assertEqual(20, fit) + def test_bucketEmpty(self): + """ + L{htb.Bucket.drip} returns C{True} if the bucket is empty after that drip. + """ + b = SomeBucket() + b.add(20) + self.clock.set(9) + empty = b.drip() + self.assertFalse(empty) + self.clock.set(10) + empty = b.drip() + self.assertTrue(empty) + class TestBucketNesting(TestBucketBase): def setUp(self): TestBucketBase.setUp(self) diff -Nru twisted-11.1.0/twisted/test/test_import.py twisted-12.1.0/twisted/test/test_import.py --- twisted-11.1.0/twisted/test/test_import.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_import.py 2012-03-07 17:27:04.000000000 +0000 @@ -1,78 +1,75 @@ - # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. - from twisted.trial import unittest from twisted.python.runtime import platformType -class AtLeastImportTestCase(unittest.TestCase): - """I test that there are no syntax errors which will not allow importing. +class AtLeastImportTestCase(unittest.TestCase): + """ + I test that there are no syntax errors which will not allow importing. """ failureException = ImportError def test_misc(self): - """Test importing other misc. modules + """ + Test importing other miscellaneous modules. """ from twisted import copyright def test_persisted(self): - """Test importing persisted + """ + Test importing persisted. """ from twisted.persisted import dirdbm from twisted.persisted import styles def test_internet(self): - """Test importing internet + """ + Test importing internet. """ from twisted.internet import tcp - from twisted.internet import main - # from twisted.internet import ssl + from twisted.internet import main from twisted.internet import abstract from twisted.internet import udp from twisted.internet import protocol from twisted.internet import defer def test_unix(self): - """internet modules for unix.""" + """ + Test internet modules for unix. + """ from twisted.internet import stdio from twisted.internet import process from twisted.internet import unix - + if platformType != "posix": test_unix.skip = "UNIX-only modules" - + def test_spread(self): - """Test importing spreadables + """ + Test importing spreadables. """ from twisted.spread import pb from twisted.spread import jelly from twisted.spread import banana from twisted.spread import flavors - + def test_twistedPython(self): - """Test importing twisted.python + """ + Test importing C{twisted.python}. """ from twisted.python import hook from twisted.python import log from twisted.python import reflect - # from twisted.python import threadable - # from twisted.python import threadpool from twisted.python import usage - from twisted.python import otp - + def test_protocols(self): - """Test importing protocols + """ + Test importing protocols. """ from twisted.protocols import basic from twisted.protocols import ftp from twisted.protocols import telnet from twisted.protocols import policies - - def test_enterprise(self): - from twisted.enterprise import adbapi - from twisted.enterprise import reflector - from twisted.enterprise import sqlreflector - from twisted.enterprise import row diff -Nru twisted-11.1.0/twisted/test/test_journal.py twisted-12.1.0/twisted/test/test_journal.py --- twisted-11.1.0/twisted/test/test_journal.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_journal.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,250 +0,0 @@ -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - - -""" -Testing for twisted.persisted.journal. -""" - -import shutil, os.path, sys - -from twisted.trial import unittest - -from twisted.persisted.journal.base import ICommand, MemoryJournal, serviceCommand, ServiceWrapperCommand, command, Wrappable -from twisted.persisted.journal.picklelog import DirDBMLog -from twisted.python import deprecate, versions -from zope.interface import implements - -from twisted.python.test.modules_helpers import TwistedModulesTestCase - - -class AddTime: - - implements(ICommand) - - def execute(self, svc, cmdtime): - svc.values["time"] = cmdtime - - -class Counter(Wrappable): - - objectType = "counter" - - def __init__(self, uid): - self.uid = uid - self.x = 0 - - - def getUid(self): - return self.uid - - - def _increment(self): - self.x += 1 - - - increment = command("_increment") - - - -class Service: - - def __init__(self, logpath, journalpath): - log = DirDBMLog(logpath) - self.journal = MemoryJournal(log, self, journalpath, self._gotData) - self.journal.updateFromLog() - - - def _gotData(self, result): - if result is None: - self.values = {} - self.counters = {} - else: - self.values, self.counters = result - - - def _makeCounter(self, id): - c = Counter(id) - self.counters[id] = c - return c - - makeCounter = serviceCommand("_makeCounter") - - - def loadObject(self, type, id): - if type != "counter": raise ValueError - return self.counters[id] - - - def _add(self, key, value): - """Add a new entry.""" - self.values[key] = value - - - def _delete(self, key): - """ - Delete an entry. - """ - del self.values[key] - - - def get(self, key): - """ - Return value of an entry. - """ - return self.values[key] - - - def addtime(self, journal): - """ - Set a key 'time' with the current time. - """ - journal.executeCommand(AddTime()) - - # and now the command wrappers - - add = serviceCommand("_add") - - delete = serviceCommand("_delete") - - - -class JournalTestCase(unittest.TestCase): - - def setUp(self): - self.logpath = self.mktemp() - self.journalpath = self.mktemp() - self.svc = Service(self.logpath, self.journalpath) - - - def tearDown(self): - if hasattr(self, "svc"): - del self.svc - # delete stuff? ... - if os.path.isdir(self.logpath): - shutil.rmtree(self.logpath) - if os.path.exists(self.logpath): - os.unlink(self.logpath) - if os.path.isdir(self.journalpath): - shutil.rmtree(self.journalpath) - if os.path.exists(self.journalpath): - os.unlink(self.journalpath) - - - def testCommandExecution(self): - svc = self.svc - svc.add(svc.journal, "foo", "bar") - self.assertEqual(svc.get("foo"), "bar") - - svc.delete(svc.journal, "foo") - self.assertRaises(KeyError, svc.get, "foo") - - - def testLogging(self): - svc = self.svc - log = self.svc.journal.log - j = self.svc.journal - svc.add(j, "foo", "bar") - svc.add(j, 1, "hello") - svc.delete(j, "foo") - - commands = [ServiceWrapperCommand("_add", ("foo", "bar")), - ServiceWrapperCommand("_add", (1, "hello")), - ServiceWrapperCommand("_delete", ("foo",))] - - self.assertEqual(log.getCurrentIndex(), 3) - for i in range(1, 4): - for a, b in zip(commands[i-1:], [c for t, c in log.getCommandsSince(i)]): - self.assertEqual(a, b) - - - def testRecovery(self): - svc = self.svc - j = svc.journal - svc.add(j, "foo", "bar") - svc.add(j, 1, "hello") - # we sync *before* delete to make sure commands get executed - svc.journal.sync((svc.values, svc.counters)) - svc.delete(j, "foo") - d = svc.makeCounter(j, 1) - d.addCallback(lambda c, j=j: c.increment(j)) - del svc, self.svc - - # first, load from snapshot - svc = Service(self.logpath, self.journalpath) - self.assertEqual(svc.values, {1: "hello"}) - self.assertEqual(svc.counters[1].x, 1) - del svc - - # now, tamper with log, and then try - f = open(self.journalpath, "w") - f.write("sfsdfsdfsd") - f.close() - svc = Service(self.logpath, self.journalpath) - self.assertEqual(svc.values, {1: "hello"}) - self.assertEqual(svc.counters[1].x, 1) - - - def testTime(self): - svc = self.svc - svc.addtime(svc.journal) - t = svc.get("time") - - log = self.svc.journal.log - (t2, c), = log.getCommandsSince(1) - self.assertEqual(t, t2) - - - -class JournalDeprecationTest(TwistedModulesTestCase): - """ - Tests for twisted.persisted.journal being deprecated. - """ - - def setUp(self): - """ - Prepare for the deprecation test, by making sure that - twisted.persisted.journal isn't imported. - """ - self.replaceSysModules(sys.modules.copy()) - mods = [] - for mod in sys.modules: - if mod.startswith("twisted.persisted.journal"): - mods.append(mod) - for mod in mods: - del(sys.modules[mod]) - - - def uniquify(self, listOfStuff): - """ - Remove duplicate items from a list - """ - for i in range(len(listOfStuff)): - j = i+1; - while j < len(listOfStuff): - if listOfStuff[j] == listOfStuff[i]: - del(listOfStuff[j]) - else: - j += 1 - - - def test_deprecated(self): - """ - Make sure that twisted.persisted.journal is deprecated, and - check the text of its deprecation warning. - """ - from twisted.persisted import journal - warnings = self.flushWarnings([self.test_deprecated]) - - # because for some reason deprecate.deprecatedModuleAttribute causes a warning to be - # emitted twice in this case. Bug will be filed - self.uniquify(warnings) - - self.assertEqual(len(warnings), 1) - self.assertEqual(warnings[0]['category'], DeprecationWarning) - self.assertEqual( - warnings[0]['message'], - deprecate.getDeprecationWarningString(journal, - versions.Version('twisted', 11, 0, 0)) + - ": Use a different persistence library. This one is no longer maintained.") - diff -Nru twisted-11.1.0/twisted/test/test_log.py twisted-12.1.0/twisted/test/test_log.py --- twisted-11.1.0/twisted/test/test_log.py 2011-08-14 01:01:36.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_log.py 2012-04-08 13:17:05.000000000 +0000 @@ -5,7 +5,7 @@ Tests for L{twisted.python.log}. """ -import os, sys, time, logging, warnings +import os, sys, time, logging, warnings, calendar from cStringIO import StringIO from twisted.trial import unittest @@ -391,9 +391,7 @@ Test the method of L{FileLogObserver} which turns a timestamp into a human-readable string. """ - # There is no function in the time module which converts a UTC time - # tuple to a timestamp. - when = time.mktime((2001, 2, 3, 4, 5, 6, 7, 8, 0)) - time.timezone + when = calendar.timegm((2001, 2, 3, 4, 5, 6, 7, 8, 0)) # Pretend to be in US/Eastern for a moment self.flo.getTimezoneOffset = lambda when: 18000 diff -Nru twisted-11.1.0/twisted/test/test_paths.py twisted-12.1.0/twisted/test/test_paths.py --- twisted-11.1.0/twisted/test/test_paths.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_paths.py 2012-03-13 23:29:48.000000000 +0000 @@ -15,6 +15,8 @@ from twisted.trial import unittest +from zope.interface.verify import verifyObject + class AbstractFilePathTestCase(unittest.TestCase): @@ -68,7 +70,8 @@ ["a", "b", "c"]) def test_segmentsFromNegative(self): - """Verify that segmentsFrom notices when the ancestor isn't an ancestor. + """ + Verify that segmentsFrom notices when the ancestor isn't an ancestor. """ self.assertRaises( ValueError, @@ -103,7 +106,8 @@ def test_validSubdir(self): - """Verify that a valid subdirectory will show up as a directory, but not as a + """ + Verify that a valid subdirectory will show up as a directory, but not as a file, not as a symlink, and be listable. """ sub1 = self.path.child('sub1') @@ -273,7 +277,7 @@ def zipit(dirname, zfname): """ - create a zipfile on zfname, containing the contents of dirname' + Create a zipfile on zfname, containing the contents of dirname' """ zf = zipfile.ZipFile(zfname, "w") for root, ignored, files, in os.walk(dirname): @@ -299,6 +303,14 @@ self.all = [x.replace(self.cmn, self.cmn + '.zip') for x in self.all] + def test_verifyObject(self): + """ + ZipPaths implement IFilePath. + """ + + self.assertTrue(verifyObject(filepath.IFilePath, self.path)) + + def test_zipPathRepr(self): """ Make sure that invoking ZipPath's repr prints the correct class name @@ -643,6 +655,15 @@ Test various L{FilePath} path manipulations. """ + + def test_verifyObject(self): + """ + FilePaths implement IFilePath. + """ + + self.assertTrue(verifyObject(filepath.IFilePath, self.path)) + + def test_chmod(self): """ L{FilePath.chmod} modifies the permissions of @@ -926,10 +947,11 @@ self.assertRaises(filepath.InsecurePath, self.path.child, r"C:randomfile") if platform.getType() != 'win32': - testInsecureWin32.skip = "Consider yourself lucky." + testInsecureWin32.skip = "Test will run only on Windows." def testInsecureWin32Whacky(self): - """Windows has 'special' filenames like NUL and CON and COM1 and LPR + """ + Windows has 'special' filenames like NUL and CON and COM1 and LPR and PRN and ... god knows what else. They can be located anywhere in the filesystem. For obvious reasons, we do not wish to normally permit access to these. @@ -939,7 +961,7 @@ self.assertRaises(filepath.InsecurePath, self.path.child, r"C:\CON") if platform.getType() != 'win32': - testInsecureWin32Whacky.skip = "Consider yourself lucky." + testInsecureWin32Whacky.skip = "Test will run only on Windows." def testComparison(self): self.assertEqual(filepath.FilePath('a'), @@ -1558,8 +1580,8 @@ test_statinfoNumbersAreValid.skip = True test_getPermissions_POSIX.skip = True else: - test_statinfoBitsNotImplementedInWindows.skip = True - test_getPermissions_Windows.skip = True + test_statinfoBitsNotImplementedInWindows.skip = "Test will run only on Windows." + test_getPermissions_Windows.skip = "Test will run only on Windows." diff -Nru twisted-11.1.0/twisted/test/test_pb.py twisted-12.1.0/twisted/test/test_pb.py --- twisted-11.1.0/twisted/test/test_pb.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_pb.py 2011-11-14 18:11:49.000000000 +0000 @@ -16,14 +16,12 @@ from cStringIO import StringIO from zope.interface import implements, Interface -from twisted.python.versions import Version from twisted.trial import unittest from twisted.spread import pb, util, publish, jelly from twisted.internet import protocol, main, reactor from twisted.internet.error import ConnectionRefusedError from twisted.internet.defer import Deferred, gatherResults, succeed from twisted.protocols.policies import WrappingFactory -from twisted.protocols import loopback from twisted.python import failure, log from twisted.cred.error import UnauthorizedLogin, UnhandledCredentials from twisted.cred import portal, checkers, credentials @@ -1846,27 +1844,3 @@ factory = pb.PBServerFactory(Echoer(), security=security) broker = factory.buildProtocol(None) self.assertIdentical(broker.security, security) - - - -class DeprecationTests(unittest.TestCase): - """ - Tests for certain deprecations of free-functions in L{twisted.spread.pb}. - """ - def test_noOperationDeprecated(self): - """ - L{pb.noOperation} is deprecated. - """ - self.callDeprecated( - Version("twisted", 8, 2, 0), - pb.noOperation, 1, 2, x=3, y=4) - - - def test_printTraceback(self): - """ - L{pb.printTraceback} is deprecated. - """ - self.callDeprecated( - Version("twisted", 8, 2, 0), - pb.printTraceback, - "printTraceback deprecation fake traceback value") diff -Nru twisted-11.1.0/twisted/test/test_process.py twisted-12.1.0/twisted/test/test_process.py --- twisted-11.1.0/twisted/test/test_process.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_process.py 2012-05-15 12:40:55.000000000 +0000 @@ -201,13 +201,14 @@ if childFD == 1: self.stages.append(2) if self.data != "abcd": - raise RuntimeError + raise RuntimeError( + "Data was %r instead of 'abcd'" % (self.data,)) self.transport.write("1234") elif childFD == 2: self.stages.append(3) if self.err != "1234": - print 'err != 1234: ' + repr(self.err) - raise RuntimeError() + raise RuntimeError( + "Err was %r instead of '1234'" % (self.err,)) self.transport.write("abcd") self.stages.append(4) elif childFD == 0: @@ -1162,7 +1163,7 @@ # This script runs until we disconnect its transport. pythonExecutable = sys.executable - scriptPath = util.sibpath(__file__, "process_twisted.py") + scriptPath = util.sibpath(__file__, "process_echoer.py") class ErrorInProcessEnded(protocol.ProcessProtocol): """ diff -Nru twisted-11.1.0/twisted/test/test_randbytes.py twisted-12.1.0/twisted/test/test_randbytes.py --- twisted-11.1.0/twisted/test/test_randbytes.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_randbytes.py 2012-04-01 20:07:59.000000000 +0000 @@ -77,25 +77,12 @@ self._check(self.factory._osUrandom) - def test_fileUrandom(self): - """ - L{RandomFactory._fileUrandom} should work as a random source whenever - C{/dev/urandom} is available. - """ - try: - self._check(self.factory._fileUrandom) - except randbytes.SourceNotAvailable: - # The test should only fail in /dev/urandom doesn't exist - self.assertFalse(os.path.exists('/dev/urandom')) - - def test_withoutAnything(self): """ Remove all secure sources and assert it raises a failure. Then try the fallback parameter. """ self.factory._osUrandom = self.errorFactory - self.factory._fileUrandom = self.errorFactory self.assertRaises(randbytes.SecureRandomNotAvailable, self.factory.secureRandom, 18) def wrapper(): diff -Nru twisted-11.1.0/twisted/test/test_reflector.py twisted-12.1.0/twisted/test/test_reflector.py --- twisted-11.1.0/twisted/test/test_reflector.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_reflector.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,401 +0,0 @@ -# Copyright (c) Twisted Matrix Laboratories. -# See LICENSE for details. - -""" -Tests for twisted.enterprise reflectors. -""" - -import random - -from twisted.internet import reactor, interfaces, defer -from twisted.enterprise.row import RowObject -from twisted.enterprise.reflector import EQUAL -from twisted.enterprise.sqlreflector import SQLReflector -from twisted.enterprise import util -from twisted.test.test_adbapi import makeSQLTests -from twisted.trial.util import suppress as suppressWarning -from twisted.trial import unittest - - -tableName = "testTable" -childTableName = "childTable" - - -class TestRow(RowObject): - rowColumns = [("key_string", "varchar"), - ("col2", "int"), - ("another_column", "varchar"), - ("Column4", "varchar"), - ("column_5_", "int")] - rowKeyColumns = [("key_string", "varchar")] - rowTableName = tableName - - -class ChildRow(RowObject): - rowColumns = [("childId", "int"), - ("foo", "varchar"), - ("test_key", "varchar"), - ("stuff", "varchar"), - ("gogogo", "int"), - ("data", "varchar")] - rowKeyColumns = [("childId", "int")] - rowTableName = childTableName - rowForeignKeys = [(tableName, - [("test_key","varchar")], - [("key_string","varchar")], - None, 1)] - - -main_table_schema = """ -CREATE TABLE testTable ( - key_string varchar(64), - col2 integer, - another_column varchar(64), - Column4 varchar(64), - column_5_ integer -) -""" - -child_table_schema = """ -CREATE TABLE childTable ( - childId integer, - foo varchar(64), - test_key varchar(64), - stuff varchar(64), - gogogo integer, - data varchar(64) -) -""" - - -def randomizeRow(row, nulls_ok=True, trailing_spaces_ok=True): - values = {} - for name, type in row.rowColumns: - if util.getKeyColumn(row, name): - values[name] = getattr(row, name) - continue - elif nulls_ok and random.randint(0, 9) == 0: - value = None # null - elif type == 'int': - value = random.randint(-10000, 10000) - else: - if random.randint(0, 9) == 0: - value = '' - else: - value = ''.join(map(lambda i:chr(random.randrange(32,127)), - xrange(random.randint(1, 64)))) - if not trailing_spaces_ok: - value = value.rstrip() - setattr(row, name, value) - values[name] = value - return values - - -def rowMatches(row, values): - for name, type in row.rowColumns: - if getattr(row, name) != values[name]: - print ("Mismatch on column %s: |%s| (row) |%s| (values)" % - (name, getattr(row, name), values[name])) - return False - return True - - -rowObjectSuppression = suppressWarning( - message="twisted.enterprise.row is deprecated since Twisted 8.0", - category=DeprecationWarning) - - -reflectorSuppression = suppressWarning( - message="twisted.enterprise.reflector is deprecated since Twisted 8.0", - category=DeprecationWarning) - - -class ReflectorTestBase: - """ - Base class for testing reflectors. - - @ivar reflector: The reflector created during setup. - """ - - if interfaces.IReactorThreads(reactor, None) is None: - skip = "No thread support, no reflector tests" - - count = 100 # a parameter used for running iterative tests - - def randomizeRow(self, row): - return randomizeRow(row, self.nulls_ok, self.trailing_spaces_ok) - - def extraSetUp(self): - """ - Create and store a reference to a SQL reflector for use by the tests. - """ - d = self.createReflector() - d.addCallback(self._cbSetUp) - return d - - def _cbSetUp(self, reflector): - self.reflector = reflector - - def tearDown(self): - return self.destroyReflector() - - def destroyReflector(self): - pass - - def test_reflector(self): - """ - Full featured tests of reflector. - """ - # create one row to work with - row = TestRow() - row.assignKeyAttr("key_string", "first") - values = self.randomizeRow(row) - - # save it - d = self.reflector.insertRow(row) - - def _loadBack(_): - # now load it back in - whereClause = [("key_string", EQUAL, "first")] - d = self.reflector.loadObjectsFrom(tableName, - whereClause=whereClause) - return d.addCallback(self.gotData) - - def _getParent(_): - # make sure it came back as what we saved - self.failUnless(len(self.data) == 1, "no row") - parent = self.data[0] - self.failUnless(rowMatches(parent, values), "no match") - return parent - - d.addCallback(_loadBack) - d.addCallback(_getParent) - d.addCallback(self._cbTestReflector) - return d - test_reflector.suppress = [rowObjectSuppression, reflectorSuppression] - - def _cbTestReflector(self, parent): - # create some child rows - test_values = {} - inserts = [] - child_values = {} - for i in range(0, self.num_iterations): - row = ChildRow() - row.assignKeyAttr("childId", i) - values = self.randomizeRow(row) - values['test_key'] = row.test_key = "first" - child_values[i] = values - inserts.append(self.reflector.insertRow(row)) - row = None - #del inserts - d = defer.gatherResults(inserts) - values = [None] - - def _loadObjects(_): - d = self.reflector.loadObjectsFrom(childTableName, parentRow=parent) - return d.addCallback(self.gotData) - - def _checkLoadObjects(_): - self.failUnless(len(self.data) == self.num_iterations, - "no rows on query") - self.failUnless(len(parent.childRows) == self.num_iterations, - "did not load child rows: %d" % len(parent.childRows)) - for child in parent.childRows: - self.failUnless(rowMatches(child, child_values[child.childId]), - "child %d does not match" % child.childId) - - def _checkLoadObjects2(_): - self.failUnless(len(self.data) == self.num_iterations, - "no rows on query") - self.failUnless(len(parent.childRows) == self.num_iterations, - "child rows added twice!: %d" % len(parent.childRows)) - - def _changeParent(_): - # now change the parent - values[0] = self.randomizeRow(parent) - return self.reflector.updateRow(parent) - - def _loadBack(_): - # now load it back in - whereClause = [("key_string", EQUAL, "first")] - d = self.reflector.loadObjectsFrom(tableName, whereClause=whereClause) - return d.addCallback(self.gotData) - - def _checkLoadBack(_): - # make sure it came back as what we saved - self.failUnless(len(self.data) == 1, "no row") - parent = self.data[0] - self.failUnless(rowMatches(parent, values[0]), "no match") - # save parent - test_values[parent.key_string] = values[0] - parent = None - - def _saveMoreTestRows(_): - # save some more test rows - ds = [] - for i in range(0, self.num_iterations): - row = TestRow() - row.assignKeyAttr("key_string", "bulk%d"%i) - test_values[row.key_string] = self.randomizeRow(row) - ds.append(self.reflector.insertRow(row)) - return defer.gatherResults(ds) - - def _loadRowsBack(_): - # now load them all back in - d = self.reflector.loadObjectsFrom("testTable") - return d.addCallback(self.gotData) - - def _checkRowsBack(_): - # make sure they are the same - self.failUnless(len(self.data) == self.num_iterations + 1, - "query did not get rows") - for row in self.data: - self.failUnless(rowMatches(row, test_values[row.key_string]), - "child %s does not match" % row.key_string) - - def _changeRows(_): - # now change them all - ds = [] - for row in self.data: - test_values[row.key_string] = self.randomizeRow(row) - ds.append(self.reflector.updateRow(row)) - d = defer.gatherResults(ds) - return d.addCallback(_cbChangeRows) - - def _cbChangeRows(_): - self.data = None - - def _deleteRows(_): - # now delete them - ds = [] - for row in self.data: - ds.append(self.reflector.deleteRow(row)) - d = defer.gatherResults(ds) - return d.addCallback(_cbChangeRows) - - def _checkRowsDeleted(_): - self.failUnless(len(self.data) == 0, "rows were not deleted") - - d.addCallback(_loadObjects) - d.addCallback(_checkLoadObjects) - d.addCallback(_loadObjects) - d.addCallback(_checkLoadObjects2) - d.addCallback(_changeParent) - d.addCallback(_loadBack) - d.addCallback(_checkLoadBack) - d.addCallback(_saveMoreTestRows) - d.addCallback(_loadRowsBack) - d.addCallback(_checkRowsBack) - d.addCallback(_changeRows) - d.addCallback(_loadRowsBack) - d.addCallback(_checkRowsBack) - d.addCallback(_deleteRows) - d.addCallback(_loadRowsBack) - d.addCallback(_checkRowsDeleted) - return d - - - def test_saveAndDelete(self): - """ - Create a row and then try to delete it. - """ - # create one row to work with - row = TestRow() - row.assignKeyAttr("key_string", "first") - values = self.randomizeRow(row) - # save it - d = self.reflector.insertRow(row) - def _deleteRow(_): - # delete it - return self.reflector.deleteRow(row) - d.addCallback(_deleteRow) - return d - test_saveAndDelete.suppress = [rowObjectSuppression, reflectorSuppression] - - - def gotData(self, data): - self.data = data - - -ReflectorTestBase.timeout = 30.0 - - -class SQLReflectorTestBase(ReflectorTestBase): - """ - Base class for the SQL reflector. - """ - - def createReflector(self): - self.startDB() - self.dbpool = self.makePool() - self.dbpool.start() - - if self.can_clear: - d = self.dbpool.runOperation('DROP TABLE testTable') - d.addCallback(lambda _: - self.dbpool.runOperation('DROP TABLE childTable')) - d.addErrback(lambda _: None) - else: - d = defer.succeed(None) - - d.addCallback(lambda _: self.dbpool.runOperation(main_table_schema)) - d.addCallback(lambda _: self.dbpool.runOperation(child_table_schema)) - reflectorClass = self.escape_slashes and SQLReflector \ - or NoSlashSQLReflector - d.addCallback(lambda _: - reflectorClass(self.dbpool, [TestRow, ChildRow])) - return d - - def destroyReflector(self): - d = self.dbpool.runOperation('DROP TABLE testTable') - d.addCallback(lambda _: - self.dbpool.runOperation('DROP TABLE childTable')) - def close(_): - self.dbpool.close() - self.stopDB() - d.addCallback(close) - return d - - -class DeprecationTestCase(unittest.TestCase): - """ - Test various deprecations of twisted.enterprise. - """ - - def test_rowDeprecation(self): - """ - Test deprecation of L{RowObject}. - """ - def wrapper(): - return TestRow() - self.assertWarns(DeprecationWarning, - "twisted.enterprise.row is deprecated since Twisted 8.0", - __file__, - wrapper) - - def test_reflectorDeprecation(self): - """ - Test deprecation of L{SQLReflector}. - """ - def wrapper(): - return SQLReflector(None, ()) - from twisted.enterprise import sqlreflector - self.assertWarns(DeprecationWarning, - "twisted.enterprise.reflector is deprecated since Twisted 8.0", - sqlreflector.__file__, - wrapper) - - -# GadflyReflectorTestCase SQLiteReflectorTestCase PyPgSQLReflectorTestCase -# PsycopgReflectorTestCase MySQLReflectorTestCase FirebirdReflectorTestCase -makeSQLTests(SQLReflectorTestBase, 'ReflectorTestCase', globals()) - - -class NoSlashSQLReflector(SQLReflector): - """ - An sql reflector that only escapes single quotes. - """ - - def escape_string(self, text): - return text.replace("'", "''") - diff -Nru twisted-11.1.0/twisted/test/test_reflect.py twisted-12.1.0/twisted/test/test_reflect.py --- twisted-11.1.0/twisted/test/test_reflect.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_reflect.py 2012-03-07 19:55:14.000000000 +0000 @@ -731,43 +731,137 @@ "twisted.python.reflect.fullyQualifiedName") - def test_method(self): + def test_boundMethod(self): """ - L{reflect.fullyQualifiedName} returns the name of a method inside its - class and its module. + L{reflect.fullyQualifiedName} returns the name of a bound method inside + its class and its module. """ - self._checkFullyQualifiedName(reflect.PropertyAccessor.reallyDel, + self._checkFullyQualifiedName( + reflect.PropertyAccessor().reallyDel, "twisted.python.reflect.PropertyAccessor.reallyDel") - self._checkFullyQualifiedName(reflect.PropertyAccessor().reallyDel, + + + def test_unboundMethod(self): + """ + L{reflect.fullyQualifiedName} returns the name of an unbound method + inside its class and its module. + """ + self._checkFullyQualifiedName( + reflect.PropertyAccessor.reallyDel, "twisted.python.reflect.PropertyAccessor.reallyDel") + class DeprecationTestCase(unittest.TestCase): """ Test deprecations in twisted.python.reflect """ - def test_macro(self): - """ - Test deprecation of L{reflect.macro}. - """ - result = self.callDeprecated(Version("Twisted", 8, 2, 0), - reflect.macro, "test", __file__, "test = 1") - self.assertEqual(result, 1) - def test_allYourBase(self): """ - Test deprecation of L{reflect.allYourBase}. + Test deprecation of L{reflect.allYourBase}. See #5481 for removal. """ self.callDeprecated( (Version("Twisted", 11, 0, 0), "inspect.getmro"), reflect.allYourBase, DeprecationTestCase) + def test_accumulateBases(self): """ - Test deprecation of L{reflect.accumulateBases}. + Test deprecation of L{reflect.accumulateBases}. See #5481 for removal. """ l = [] self.callDeprecated( (Version("Twisted", 11, 0, 0), "inspect.getmro"), reflect.accumulateBases, DeprecationTestCase, l, None) + + + def lookForDeprecationWarning(self, testMethod, attributeName, warningMsg): + """ + Test deprecation of attribute 'reflect.attributeName' by calling + 'reflect.testMethod' and verifying the warning message + 'reflect.warningMsg' + + @param testMethod: Name of the offending function to be used with + flushWarnings + @type testmethod: C{str} + + @param attributeName: Name of attribute to be checked for deprecation + @type attributeName: C{str} + + @param warningMsg: Deprecation warning message + @type warningMsg: C{str} + """ + warningsShown = self.flushWarnings([testMethod]) + self.assertEqual(len(warningsShown), 1) + self.assertIdentical(warningsShown[0]['category'], DeprecationWarning) + self.assertEqual( + warningsShown[0]['message'], + "twisted.python.reflect." + attributeName + " " + "was deprecated in Twisted 12.1.0: " + warningMsg + ".") + + + def test_settable(self): + """ + Test deprecation of L{reflect.Settable}. + """ + reflect.Settable() + self.lookForDeprecationWarning( + self.test_settable, "Settable", + "Settable is old and untested. Please write your own version of this " + "functionality if you need it") + + + def test_accessorType(self): + """ + Test deprecation of L{reflect.AccessorType}. + """ + reflect.AccessorType(' ', ( ), { }) + self.lookForDeprecationWarning( + self.test_accessorType, "AccessorType", + "AccessorType is old and untested. Please write your own version of " + "this functionality if you need it") + + + def test_propertyAccessor(self): + """ + Test deprecation of L{reflect.PropertyAccessor}. + """ + reflect.PropertyAccessor() + self.lookForDeprecationWarning( + self.test_propertyAccessor, "PropertyAccessor", + "PropertyAccessor is old and untested. Please write your own " + "version of this functionality if you need it") + + + def test_accessor(self): + """ + Test deprecation of L{reflect.Accessor}. + """ + reflect.Accessor() + self.lookForDeprecationWarning( + self.test_accessor, "Accessor", + "Accessor is an implementation for Python 2.1 which is no longer " + "supported by Twisted") + + + def test_originalAccessor(self): + """ + Test deprecation of L{reflect.OriginalAccessor}. + """ + reflect.OriginalAccessor() + self.lookForDeprecationWarning( + self.test_originalAccessor, "OriginalAccessor", + "OriginalAccessor is a reference to class " + "twisted.python.reflect.Accessor which is deprecated") + + + def test_summer(self): + """ + Test deprecation of L{reflect.Summer}. + """ + reflect.Summer() + self.lookForDeprecationWarning( + self.test_summer, "Summer", + "Summer is a child class of twisted.python.reflect.Accessor which " + "is deprecated") diff -Nru twisted-11.1.0/twisted/test/test_stdio.py twisted-12.1.0/twisted/test/test_stdio.py --- twisted-11.1.0/twisted/test/test_stdio.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_stdio.py 2012-05-04 18:49:18.000000000 +0000 @@ -364,37 +364,8 @@ ''.join(map(str, range(howMany)))) onConnLost.addCallback(cbLost) return onConnLost - if reactor.__class__.__name__ == 'EPollReactor': - test_normalFileStandardOut.skip = ( - "epoll(7) does not support normal files. See #4429. " - "This should be a todo but technical limitations prevent " - "this.") - elif platform.isWindows(): + + if platform.isWindows(): test_normalFileStandardOut.skip = ( "StandardIO does not accept stdout as an argument to Windows. " "Testing redirection to a file is therefore harder.") - - - def test_normalFileStandardOutGoodEpollError(self): - """ - Using StandardIO with epollreactor with stdout redirected to a - normal file fails with a comprehensible error (until it is - supported, when #4429 is resolved). See also #2259 and #3442. - """ - path = filepath.FilePath(self.mktemp()) - normal = path.open('w') - fd = normal.fileno() - self.addCleanup(normal.close) - exc = self.assertRaises( - RuntimeError, - stdio.StandardIO, protocol.Protocol(), stdout=fd) - - self.assertEqual( - str(exc), - "This reactor does not support this type of file descriptor (fd " - "%d, mode %d) (for example, epollreactor does not support normal " - "files. See #4429)." % (fd, os.fstat(fd).st_mode)) - if reactor.__class__.__name__ != 'EPollReactor': - test_normalFileStandardOutGoodEpollError.skip = ( - "Only epollreactor is expected to fail with stdout redirected " - "to a normal file.") diff -Nru twisted-11.1.0/twisted/test/test_strcred.py twisted-12.1.0/twisted/test/test_strcred.py --- twisted-11.1.0/twisted/test/test_strcred.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_strcred.py 2012-03-12 21:35:11.000000000 +0000 @@ -53,7 +53,8 @@ """ iat = getInvalidAuthType() self.assertRaises(strcred.InvalidAuthType, strcred.makeChecker, iat) - self.assertRaises(strcred.InvalidAuthType, strcred.findCheckerFactory, iat) + self.assertRaises( + strcred.InvalidAuthType, strcred.findCheckerFactory, iat) def test_invalidAuthType(self): @@ -62,7 +63,8 @@ """ iat = getInvalidAuthType() self.assertRaises(strcred.InvalidAuthType, strcred.makeChecker, iat) - self.assertRaises(strcred.InvalidAuthType, strcred.findCheckerFactory, iat) + self.assertRaises( + strcred.InvalidAuthType, strcred.findCheckerFactory, iat) @@ -337,6 +339,32 @@ +class TestSSHChecker(unittest.TestCase): + """ + Tests for the --auth=sshkey:... checker. The majority of the tests for the + ssh public key database checker are in + L{twisted.conch.test.test_checkers.SSHPublicKeyDatabaseTestCase}. + """ + + try: + import Crypto + import pyasn1 + except ImportError: + skip = "PyCrypto is not available" + + + def test_isChecker(self): + """ + Verifies that strcred.makeChecker('sshkey') returns an object + that implements the L{ICredentialsChecker} interface. + """ + sshChecker = strcred.makeChecker('sshkey') + self.assertTrue(checkers.ICredentialsChecker.providedBy(sshChecker)) + self.assertIn( + credentials.ISSHPrivateKey, sshChecker.credentialInterfaces) + + + class DummyOptions(usage.Options, strcred.AuthOptionMixin): """ Simple options for testing L{strcred.AuthOptionMixin}. @@ -502,7 +530,8 @@ self.filename = self.mktemp() file(self.filename, 'w').write('admin:asdf\nalice:foo\n') self.goodChecker = checkers.FilePasswordDB(self.filename) - self.badChecker = checkers.FilePasswordDB(self.filename, hash=self._hash) + self.badChecker = checkers.FilePasswordDB( + self.filename, hash=self._hash) self.anonChecker = checkers.AllowAnonymousAccess() @@ -523,7 +552,8 @@ self.assertFalse( options.supportsInterface(credentials.IAnonymous)) self.assertRaises( - strcred.UnsupportedInterfaces, options.addChecker, self.anonChecker) + strcred.UnsupportedInterfaces, options.addChecker, + self.anonChecker) def test_supportsAllInterfaces(self): @@ -559,7 +589,8 @@ options.addChecker(self.goodChecker) iface = options.supportedInterfaces[0] # Test that we did get IUsernamePassword - self.assertIdentical(options['credInterfaces'][iface][0], self.goodChecker) + self.assertIdentical( + options['credInterfaces'][iface][0], self.goodChecker) self.assertIdentical(options['credCheckers'][0], self.goodChecker) # Test that we didn't get IUsernameHashedPassword self.assertEqual(len(options['credInterfaces'][iface]), 1) @@ -624,4 +655,3 @@ self.assertRaises(SystemExit, options.parseOptions, ['--help-auth-type', 'anonymous']) self.assertIn(strcred.notSupportedWarning, newStdout.getvalue()) - diff -Nru twisted-11.1.0/twisted/test/test_strerror.py twisted-12.1.0/twisted/test/test_strerror.py --- twisted-11.1.0/twisted/test/test_strerror.py 2011-02-14 04:45:15.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_strerror.py 2012-02-05 14:13:05.000000000 +0000 @@ -14,6 +14,12 @@ from twisted.python.runtime import platform +class _MyWindowsException(OSError): + """ + An exception type like L{ctypes.WinError}, but available on all platforms. + """ + + class ErrorFormatingTestCase(TestCase): """ @@ -81,7 +87,7 @@ winCalls = [] def winError(errorCode): winCalls.append(errorCode) - return (errorCode, self.probeMessage) + return _MyWindowsException(errorCode, self.probeMessage) formatter = _ErrorFormatter( winError, lambda error: 'formatMessage: wrong message', @@ -101,7 +107,7 @@ from ctypes import WinError self.assertEqual( formatter.formatError(self.probeErrorCode), - WinError(self.probeErrorCode)[1]) + WinError(self.probeErrorCode).strerror) formatter.winError = None if formatter.formatMessage is not None: @@ -118,7 +124,7 @@ errorTab[self.probeErrorCode]) if platform.getType() != "win32": - test_fromEnvironment.skip = "This error lookup only works on Windows" + test_fromEnvironment.skip = "Test will run only on Windows." def test_correctLookups(self): @@ -130,7 +136,7 @@ acceptable = [socket.errorTab[ECONNABORTED]] try: from ctypes import WinError - acceptable.append(WinError(ECONNABORTED)[1]) + acceptable.append(WinError(ECONNABORTED).strerror) except ImportError: pass try: @@ -142,4 +148,4 @@ self.assertIn(formatError(ECONNABORTED), acceptable) if platform.getType() != "win32": - test_correctLookups.skip = "This error lookup only works on Windows" + test_correctLookups.skip = "Test will run only on Windows." diff -Nru twisted-11.1.0/twisted/test/test_tcp.py twisted-12.1.0/twisted/test/test_tcp.py --- twisted-11.1.0/twisted/test/test_tcp.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_tcp.py 2012-03-27 12:27:04.000000000 +0000 @@ -602,6 +602,10 @@ started = 0 stopped = 0 + def __init__(self, *a, **kw): + MyClientFactory.__init__(self, *a, **kw) + self.whenStopped = defer.Deferred() + def startFactory(self): if self.started or self.stopped: raise RuntimeError @@ -611,6 +615,7 @@ if not self.started or self.stopped: raise RuntimeError self.stopped = 1 + self.whenStopped.callback(True) class FactoryTestCase(unittest.TestCase): @@ -677,99 +682,6 @@ -class ConnectorTestCase(unittest.TestCase): - - def test_connectorIdentity(self): - """ - L{IReactorTCP.connectTCP} returns an object which provides - L{IConnector}. The destination of the connector is the address which - was passed to C{connectTCP}. The same connector object is passed to - the factory's C{startedConnecting} method as to the factory's - C{clientConnectionLost} method. - """ - serverFactory = ClosingFactory() - tcpPort = reactor.listenTCP(0, serverFactory, interface="127.0.0.1") - serverFactory.port = tcpPort - self.addCleanup(serverFactory.cleanUp) - portNumber = tcpPort.getHost().port - - seenConnectors = [] - seenFailures = [] - - clientFactory = ClientStartStopFactory() - clientFactory.clientConnectionLost = ( - lambda connector, reason: (seenConnectors.append(connector), - seenFailures.append(reason))) - clientFactory.startedConnecting = seenConnectors.append - - connector = reactor.connectTCP("127.0.0.1", portNumber, clientFactory) - self.assertTrue(interfaces.IConnector.providedBy(connector)) - dest = connector.getDestination() - self.assertEqual(dest.type, "TCP") - self.assertEqual(dest.host, "127.0.0.1") - self.assertEqual(dest.port, portNumber) - - d = loopUntil(lambda: clientFactory.stopped) - def clientFactoryStopped(ignored): - seenFailures[0].trap(error.ConnectionDone) - self.assertEqual(seenConnectors, [connector, connector]) - d.addCallback(clientFactoryStopped) - return d - - - def test_userFail(self): - """ - Calling L{IConnector.stopConnecting} in C{Factory.startedConnecting} - results in C{Factory.clientConnectionFailed} being called with - L{error.UserError} as the reason. - """ - serverFactory = MyServerFactory() - tcpPort = reactor.listenTCP(0, serverFactory, interface="127.0.0.1") - self.addCleanup(tcpPort.stopListening) - portNumber = tcpPort.getHost().port - - def startedConnecting(connector): - connector.stopConnecting() - - clientFactory = ClientStartStopFactory() - clientFactory.startedConnecting = startedConnecting - reactor.connectTCP("127.0.0.1", portNumber, clientFactory) - - d = loopUntil(lambda: clientFactory.stopped) - def check(ignored): - self.assertEqual(clientFactory.failed, 1) - clientFactory.reason.trap(error.UserError) - return d.addCallback(check) - - - def test_reconnect(self): - """ - Calling L{IConnector.connect} in C{Factory.clientConnectionLost} causes - a new connection attempt to be made. - """ - serverFactory = ClosingFactory() - tcpPort = reactor.listenTCP(0, serverFactory, interface="127.0.0.1") - serverFactory.port = tcpPort - self.addCleanup(serverFactory.cleanUp) - portNumber = tcpPort.getHost().port - - clientFactory = MyClientFactory() - - def clientConnectionLost(connector, reason): - connector.connect() - clientFactory.clientConnectionLost = clientConnectionLost - reactor.connectTCP("127.0.0.1", portNumber, clientFactory) - - d = loopUntil(lambda: clientFactory.failed) - def reconnectFailed(ignored): - p = clientFactory.protocol - self.assertEqual((p.made, p.closed), (1, 1)) - clientFactory.reason.trap(error.ConnectionRefusedError) - self.assertEqual(clientFactory.stopped, 1) - return d.addCallback(reconnectFailed) - - - class CannotBindTestCase(unittest.TestCase): """ Tests for correct behavior when a reactor cannot bind to the required TCP diff -Nru twisted-11.1.0/twisted/test/test_text.py twisted-12.1.0/twisted/test/test_text.py --- twisted-11.1.0/twisted/test/test_text.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_text.py 2012-03-12 23:05:49.000000000 +0000 @@ -155,24 +155,4 @@ -class DeprecationTest(unittest.TestCase): - """ - Tests for deprecations in L{twisted.python.text} - """ - - def test_docstringLStrip(self): - """ - L{docstringLStrip} is deprecated as of 10.2.0 - """ - text.docstringLStrip("") - warningsShown = self.flushWarnings([self.test_docstringLStrip]) - self.assertEqual(1, len(warningsShown)) - self.assertIdentical(warningsShown[0]['category'], DeprecationWarning) - self.assertEqual(warningsShown[0]['message'], - "twisted.python.text.docstringLStrip was " - "deprecated in Twisted 10.2.0: Please use " - "inspect.getdoc instead.") - - - testCases = [WrapTest, SplitTest, StrFileTest] diff -Nru twisted-11.1.0/twisted/test/test_threadpool.py twisted-12.1.0/twisted/test/test_threadpool.py --- twisted-11.1.0/twisted/test/test_threadpool.py 2011-07-14 19:05:14.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_threadpool.py 2012-02-11 11:29:31.000000000 +0000 @@ -7,7 +7,7 @@ import pickle, time, weakref, gc, threading -from twisted.trial import unittest, util +from twisted.trial import unittest from twisted.python import threadpool, threadable, failure, context from twisted.internet import reactor from twisted.internet.defer import Deferred @@ -249,19 +249,6 @@ (actor.failures,)) - def test_dispatch(self): - """ - Call C{_threadpoolTest} with C{dispatch}. - """ - return self._threadpoolTest( - lambda tp, actor: tp.dispatch(actor, actor.run)) - - test_dispatch.suppress = [util.suppress( - message="dispatch\(\) is deprecated since Twisted 8.0, " - "use callInThread\(\) instead", - category=DeprecationWarning)] - - def test_callInThread(self): """ Call C{_threadpoolTest} with C{callInThread}. @@ -471,44 +458,6 @@ tp.stop() - def test_dispatchDeprecation(self): - """ - Test for the deprecation of the dispatch method. - """ - tp = threadpool.ThreadPool() - tp.start() - self.addCleanup(tp.stop) - - def cb(): - return tp.dispatch(None, lambda: None) - - self.assertWarns(DeprecationWarning, - "dispatch() is deprecated since Twisted 8.0, " - "use callInThread() instead", - __file__, cb) - - - def test_dispatchWithCallbackDeprecation(self): - """ - Test for the deprecation of the dispatchWithCallback method. - """ - tp = threadpool.ThreadPool() - tp.start() - self.addCleanup(tp.stop) - - def cb(): - return tp.dispatchWithCallback( - None, - lambda x: None, - lambda x: None, - lambda: None) - - self.assertWarns(DeprecationWarning, - "dispatchWithCallback() is deprecated since Twisted 8.0, " - "use twisted.internet.threads.deferToThread() instead.", - __file__, cb) - - class RaceConditionTestCase(unittest.TestCase): def setUp(self): @@ -575,25 +524,3 @@ loopDeferred.addCallback(cbLoop) submit(10) return loopDeferred - - - -class ThreadSafeListDeprecationTestCase(unittest.TestCase): - """ - Test deprecation of threadpool.ThreadSafeList in twisted.python.threadpool - """ - - def test_threadSafeList(self): - """ - Test deprecation of L{threadpool.ThreadSafeList}. - """ - threadpool.ThreadSafeList() - - warningsShown = self.flushWarnings([self.test_threadSafeList]) - self.assertEqual(len(warningsShown), 1) - self.assertIdentical(warningsShown[0]['category'], DeprecationWarning) - self.assertEqual( - warningsShown[0]['message'], - "twisted.python.threadpool.ThreadSafeList was deprecated in " - "Twisted 10.1.0: This was an internal implementation detail of " - "support for Jython 2.1, which is now obsolete.") diff -Nru twisted-11.1.0/twisted/test/test_twistd.py twisted-12.1.0/twisted/test/test_twistd.py --- twisted-11.1.0/twisted/test/test_twistd.py 2011-10-04 20:16:52.000000000 +0000 +++ twisted-12.1.0/twisted/test/test_twistd.py 2012-03-12 07:01:11.000000000 +0000 @@ -23,6 +23,7 @@ from zope.interface.verify import verifyObject from twisted.trial import unittest +from twisted.test.test_process import MockOS from twisted import plugin from twisted.application.service import IServiceMaker @@ -34,6 +35,7 @@ from twisted.python.versions import Version from twisted.python.components import Componentized from twisted.internet.defer import Deferred +from twisted.internet.interfaces import IReactorDaemonize from twisted.python.fakepwd import UserDatabase try: @@ -616,7 +618,7 @@ self.runner = UnixApplicationRunner({}) - def daemonize(self): + def daemonize(self, reactor, os): """ Indicate that daemonization has happened and change the PID so that the value written to the pidfile can be tested in the daemonization case. @@ -806,6 +808,76 @@ +class FakeNonDaemonizingReactor(object): + """ + A dummy reactor, providing C{beforeDaemonize} and C{afterDaemonize} methods, + but not announcing this, and logging whether the methods have been called. + + @ivar _beforeDaemonizeCalled: if C{beforeDaemonize} has been called or not. + @type _beforeDaemonizeCalled: C{bool} + @ivar _afterDaemonizeCalled: if C{afterDaemonize} has been called or not. + @type _afterDaemonizeCalled: C{bool} + """ + + def __init__(self): + self._beforeDaemonizeCalled = False + self._afterDaemonizeCalled = False + + def beforeDaemonize(self): + self._beforeDaemonizeCalled = True + + def afterDaemonize(self): + self._afterDaemonizeCalled = True + + + +class FakeDaemonizingReactor(FakeNonDaemonizingReactor): + """ + A dummy reactor, providing C{beforeDaemonize} and C{afterDaemonize} methods, + announcing this, and logging whether the methods have been called. + """ + + implements(IReactorDaemonize) + + + +class ReactorDaemonizationTests(unittest.TestCase): + """ + Tests for L{_twistd_unix.daemonize} and L{IReactorDaemonize}. + """ + if _twistd_unix is None: + skip = "twistd unix not available" + + + def test_daemonizationHooksCalled(self): + """ + L{_twistd_unix.daemonize} indeed calls + L{IReactorDaemonize.beforeDaemonize} and + L{IReactorDaemonize.afterDaemonize} if the reactor implements + L{IReactorDaemonize}. + """ + reactor = FakeDaemonizingReactor() + os = MockOS() + _twistd_unix.daemonize(reactor, os) + self.assertTrue(reactor._beforeDaemonizeCalled) + self.assertTrue(reactor._afterDaemonizeCalled) + + + def test_daemonizationHooksNotCalled(self): + """ + L{_twistd_unix.daemonize} does NOT call + L{IReactorDaemonize.beforeDaemonize} or + L{IReactorDaemonize.afterDaemonize} if the reactor does NOT + implement L{IReactorDaemonize}. + """ + reactor = FakeNonDaemonizingReactor() + os = MockOS() + _twistd_unix.daemonize(reactor, os) + self.assertFalse(reactor._beforeDaemonizeCalled) + self.assertFalse(reactor._afterDaemonizeCalled) + + + class DummyReactor(object): """ A dummy reactor, only providing a C{run} method and checking that it @@ -1475,20 +1547,3 @@ - -class DeprecationTests(unittest.TestCase): - """ - Tests for deprecated features. - """ - - def test_initialLog(self): - """ - L{app.initialLog} is deprecated. - """ - logs = [] - log.addObserver(logs.append) - self.addCleanup(log.removeObserver, logs.append) - self.callDeprecated(Version("Twisted", 8, 2, 0), app.initialLog) - self.assertEqual(len(logs), 2) - self.assertIn("starting up", logs[0]["message"][0]) - self.assertIn("reactor class", logs[1]["message"][0]) diff -Nru twisted-11.1.0/twisted/_version.py twisted-12.1.0/twisted/_version.py --- twisted-11.1.0/twisted/_version.py 2011-11-15 16:39:18.000000000 +0000 +++ twisted-12.1.0/twisted/_version.py 2012-06-02 07:04:01.000000000 +0000 @@ -1,3 +1,3 @@ # This is an auto-generated file. Do not edit it. from twisted.python import versions -version = versions.Version('twisted', 11, 1, 0) +version = versions.Version('twisted', 12, 1, 0)